]> git.uio.no Git - u/mrichter/AliRoot.git/blame - ITS/UPGRADE/AliITSUSimulationPix.cxx
When applying random noise do this also for sdigits with real signal
[u/mrichter/AliRoot.git] / ITS / UPGRADE / AliITSUSimulationPix.cxx
CommitLineData
451f5018 1/*
2 questions to experts: why RemoveDeadPixels should be called before FrompListToDigits ?
3
4
5*/
6
7/**************************************************************************
8* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
9* *
10* Author: The ALICE Off-line Project. *
11* Contributors are mentioned in the code where appropriate. *
12* *
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**************************************************************************/
21
451f5018 22#include <TGeoGlobalMagField.h>
23#include <TH1.h>
29ad4146 24#include <TH2.h>
451f5018 25#include <TString.h>
26#include "AliITSU.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"
34#include "AliLog.h"
35#include "AliRun.h"
36#include "AliMagF.h"
37#include "AliMathBase.h"
38#include "AliITSUSimuParam.h"
39#include "AliITSUSDigit.h"
29ad4146 40#include "AliITSUParamList.h"
451f5018 41
e61afb80 42using std::cout;
43using std::endl;
a11ef2e4 44using namespace TMath;
e61afb80 45
451f5018 46ClassImp(AliITSUSimulationPix)
47////////////////////////////////////////////////////////////////////////
48// Version: 1
49// Modified by D. Elia, G.E. Bruno, H. Tydesjo
50// Fast diffusion code by Bjorn S. Nilsen
51// March-April 2006
52// October 2007: GetCalibrationObjects() removed
53//
54// Version: 0
55// Written by Boris Batyunya
56// December 20 1999
57//
58// Adapted for pixels of ITS upgrade July 2012, ruben.shahoyan@cern.ch
59//
60// AliITSUSimulationPix is to do the simulation of pixels
61//
29ad4146 62// 2013 Feb: Added MonoPix response and nois calculation al la MIMOSA32 (levente.molnar@cern.ch)
63//
451f5018 64////////////////////////////////////////////////////////////////////////
65
66//______________________________________________________________________
67AliITSUSimulationPix::AliITSUSimulationPix()
68: fTanLorAng(0)
0ebc85cf 69 ,fReadOutCycleLength(25e-6)
70 ,fReadOutCycleOffset(0)
29ad4146 71 ,fGlobalChargeScale(1.0)
72 ,fSpread2DHisto(0)
c92b1537 73 ,fSpreadFun(0)
0ebc85cf 74 ,fROTimeFun(0)
451f5018 75{
76 // Default constructor.
c92b1537 77 SetUniqueID(AliITSUGeomTGeo::kDetTypePix);
451f5018 78}
79
80//______________________________________________________________________
81AliITSUSimulationPix::AliITSUSimulationPix(AliITSUSimuParam* sim,AliITSUSensMap* map)
82 :AliITSUSimulation(sim,map)
83 ,fTanLorAng(0)
0ebc85cf 84 ,fReadOutCycleLength(25e-6)
85 ,fReadOutCycleOffset(0)
29ad4146 86 ,fGlobalChargeScale(1.0)
87 ,fSpread2DHisto(0)
c92b1537 88 ,fSpreadFun(0)
0ebc85cf 89 ,fROTimeFun(0)
451f5018 90{
91 // standard constructor
c92b1537 92 SetUniqueID(AliITSUGeomTGeo::kDetTypePix);
451f5018 93 Init();
94}
95
96//______________________________________________________________________
97AliITSUSimulationPix::AliITSUSimulationPix(const AliITSUSimulationPix &s)
98 :AliITSUSimulation(s)
99 ,fTanLorAng(s.fTanLorAng)
0ebc85cf 100 ,fReadOutCycleLength(s.fReadOutCycleLength)
101 ,fReadOutCycleOffset(s.fReadOutCycleOffset)
29ad4146 102 ,fGlobalChargeScale(s.fGlobalChargeScale)
103 ,fSpread2DHisto(s.fSpread2DHisto)
c92b1537 104 ,fSpreadFun(s.fSpreadFun)
0ebc85cf 105 ,fROTimeFun(s.fROTimeFun)
451f5018 106{
107 // Copy Constructor
108}
109
110
111//______________________________________________________________________
112AliITSUSimulationPix::~AliITSUSimulationPix()
113{
114 // destructor
115 // only the sens map is owned and it is deleted by ~AliITSUSimulation
116}
117
118//______________________________________________________________________
119AliITSUSimulationPix& AliITSUSimulationPix::operator=(const AliITSUSimulationPix &s)
120{
121 // Assignment operator
122 if (&s == this) return *this;
123 AliITSUSimulation::operator=(s);
0ebc85cf 124 fReadOutCycleLength = s.fReadOutCycleLength;
125 fReadOutCycleOffset = s.fReadOutCycleOffset;
29ad4146 126 fSpread2DHisto = s.fSpread2DHisto;
127 fGlobalChargeScale = s.fGlobalChargeScale;
c92b1537 128 fSpreadFun = s.fSpreadFun;
0ebc85cf 129 fROTimeFun = s.fROTimeFun;
c92b1537 130 //
451f5018 131 return *this;
132}
133
134//______________________________________________________________________
135void AliITSUSimulationPix::Init()
136{
137 // Initilization
4fa9d550 138 if (fSimuParam->GetPixLorentzDrift()) SetTanLorAngle(fSimuParam->GetPixLorentzHoleWeight());
451f5018 139}
140
141//______________________________________________________________________
142Bool_t AliITSUSimulationPix::SetTanLorAngle(Double_t weightHole)
143{
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
148 //
149 if (weightHole<0) {
150 weightHole=0.;
151 AliWarning("You have asked for negative Hole weight");
152 AliWarning("I'm going to use only electrons");
153 }
154 if (weightHole>1) {
155 weightHole=1.;
156 AliWarning("You have asked for weight > 1");
157 AliWarning("I'm going to use only holes");
158 }
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();
a11ef2e4 163 fTanLorAng = Tan(weightHole*fSimuParam->LorentzAngleHole(bz) +
451f5018 164 weightEle*fSimuParam->LorentzAngleElectron(bz));
165 return kTRUE;
166}
167
168//_____________________________________________________________________
c92b1537 169void AliITSUSimulationPix::SDigitiseModule()
451f5018 170{
171 // This function begins the work of creating S-Digits.
29ad4146 172
173 AliDebug(10,Form("In event %d module %d there are %d hits returning.", fEvent, fModule->GetIndex(),fModule->GetNHits()));
174
61ac1a02 175 if (fModule->GetNHits()) Hits2SDigitsFast();
c92b1537 176 //
4fa9d550 177 if (fSimuParam->GetPixAddNoisyFlag()) AddNoisyPixels();
61ac1a02 178 if (fSimuParam->GetPixRemoveDeadFlag()) RemoveDeadPixels();
179 if (!fSensMap->GetEntries()) return;
451f5018 180 WriteSDigits();
181 ClearMap();
61ac1a02 182 //
451f5018 183}
184
185//______________________________________________________________________
186void AliITSUSimulationPix::WriteSDigits()
187{
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);
195 }
196 return;
197}
198
199//______________________________________________________________________
200void AliITSUSimulationPix::FinishSDigitiseModule()
201{
202 // This function calls SDigitsToDigits which creates Digits from SDigits
203 FrompListToDigits();
204 ClearMap();
205 return;
206}
207
208//______________________________________________________________________
c92b1537 209void AliITSUSimulationPix::DigitiseModule()
451f5018 210{
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
214 //
c92b1537 215 // pick charge spread function
216 Hits2SDigitsFast();
451f5018 217 //
4fa9d550 218 if (fSimuParam->GetPixAddNoisyFlag()) AddNoisyPixels();
219 if (fSimuParam->GetPixRemoveDeadFlag()) RemoveDeadPixels();
451f5018 220 FrompListToDigits();
221 ClearMap();
222}
223
224//______________________________________________________________________
c92b1537 225void AliITSUSimulationPix::Hits2SDigits()
451f5018 226{
227 // Does the charge distributions using Gaussian diffusion charge charing.
c92b1537 228 Int_t nhits = fModule->GetNHits();
451f5018 229 if (!nhits) return;
230 //
231 Int_t h,ix,iz,i;
232 Int_t idtrack;
4fa9d550 233 Float_t x,y,z; // keep coordinates float (required by AliSegmentation)
0ebc85cf 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;
c92b1537 235 Double_t t,tp,st,dt=0.2,el;
29f5e263 236 Double_t thick = 0.5*fSeg->Dy(); // Half Thickness
c92b1537 237
451f5018 238 //
239 for (h=0;h<nhits;h++) {
451f5018 240 //
0ebc85cf 241 if (!fModule->LineSegmentL(h,x0,x1,y0,y1,z0,z1,de,tof,idtrack)) continue;
a11ef2e4 242 st = Sqrt(x1*x1+y1*y1+z1*z1);
451f5018 243 if (st>0.0) {
29f5e263 244 st = (Double_t)((Int_t)(st*1e4)); // number of microns
451f5018 245 if (st<=1.0) st = 1.0;
29f5e263 246 dt = 1.0/st; // RS TODO: do we need 1 micron steps?
c92b1537 247 double dy = dt*thick;
248 y = -0.5*dy;
451f5018 249 for (t=0.0;t<1.0;t+=dt) { // Integrate over t
250 tp = t+0.5*dt;
251 x = x0+x1*tp;
c92b1537 252 y += dy;
451f5018 253 z = z0+z1*tp;
254 if (!(fSeg->LocalToDet(x,z,ix,iz))) continue; // outside
255 el = dt * de / fSimuParam->GetGeVToCharge();
256 //
c92b1537 257 if (fSimuParam->GetPixLorentzDrift()) x += y*fTanLorAng;
0ebc85cf 258 // Check if the hit is inside readout window
259 if ( !(((AliITSUSimulationPix*)this)->*AliITSUSimulationPix::fROTimeFun)(ix,iz,tof) ) continue;
c92b1537 260 SpreadCharge2D(x,z,y,ix,iz,el,idtrack,h);
451f5018 261 } // end for t
262 } else { // st == 0.0 deposit it at this point
263 x = x0;
c92b1537 264 y = y0 + 0.5*thick;
451f5018 265 z = z0;
266 if (!(fSeg->LocalToDet(x,z,ix,iz))) continue; // outside
267 el = de / fSimuParam->GetGeVToCharge();
c92b1537 268 if (fSimuParam->GetPixLorentzDrift()) x += y*fTanLorAng;
0ebc85cf 269 // Check if the hit is inside readout window
270 if ( !(((AliITSUSimulationPix*)this)->*AliITSUSimulationPix::fROTimeFun)(ix,iz,tof) ) continue;
c92b1537 271 SpreadCharge2D(x,z,y,ix,iz,el,idtrack,h);
451f5018 272 } // end if st>0.0
273 } // Loop over all hits h
274 //
275 // Coupling
276 int nd = fSensMap->GetEntriesUnsorted(); // use unsorted access when possible, since it is faster
277 AliITSUSDigit* dg = 0;
4fa9d550 278 switch (fSimuParam->GetPixCouplingOption()) {
279 case AliITSUSimuParam::kNewCouplingPix :
451f5018 280 for (i=nd;i--;) {
281 dg = (AliITSUSDigit*)fSensMap->AtUnsorted(i);
282 if (fSensMap->IsDisabled(dg)) continue;
283 SetCoupling(dg,idtrack,h);
284 }
285 break;
4fa9d550 286 case AliITSUSimuParam::kOldCouplingPix:
451f5018 287 for (i=nd;i--;) {
288 dg = (AliITSUSDigit*)fSensMap->AtUnsorted(i);
289 if (fSensMap->IsDisabled(dg)) continue;
290 SetCouplingOld(dg,idtrack,h);
291 }
292 break;
293 default:
294 break;
295
296 } // end switch
4fa9d550 297 if (GetDebug(2)) AliInfo(Form("Finished fCoupling=%d",fSimuParam->GetPixCouplingOption()));
451f5018 298}
299
300//______________________________________________________________________
c92b1537 301void AliITSUSimulationPix::Hits2SDigitsFast()
451f5018 302{
303 // Does the charge distributions using Gaussian diffusion charge charing. // Inputs:
304 // AliITSUModule *mod Pointer to this module
c92b1537 305 //
c92b1537 306 TObjArray *hits = fModule->GetHits();
451f5018 307 Int_t nhits = hits->GetEntriesFast();
308 if (nhits<=0) return;
309 //
310 Int_t h,ix,iz,i;
311 Int_t idtrack;
4fa9d550 312 Float_t x,y,z; // keep coordinates float (required by AliSegmentation)
0ebc85cf 313 Double_t tof,x0=0.0,x1=0.0,y0=0.0,y1=0.0,z0=0.0,z1=0.0;
e0dbadec 314 Double_t step,st,el,de=0.0;
81f2107f 315 Double_t minDim = Min(fSeg->Dpx(1),fSeg->Dpz(1)); // RStmp: smallest pitch
c92b1537 316 Double_t thick = fSeg->Dy();
451f5018 317 //
318 for (h=0;h<nhits;h++) {
451f5018 319 //
0ebc85cf 320 if (!fModule->LineSegmentL(h,x0,x1,y0,y1,z0,z1,de,tof,idtrack)) continue;
321 //
81f2107f 322 st = Sqrt(x1*x1+y1*y1+z1*z1);
323 if (st>0.0) {
0ebc85cf 324 int np = int(1.5*st/minDim); //RStmp: inject the points in such a way that there is ~1.5 point per cell
29ad4146 325 np = TMath::Max(1.0*np,fResponseParam->GetParameter(kSpreadFunMinSteps));
326 AliDebug(10,Form(" Number of charge injection steps is set to %d ",np));
0ebc85cf 327 double dstep = 1./np;
e0dbadec 328 double dy = dstep*thick;
c92b1537 329 y = -0.5*dy;
0ebc85cf 330 step = -0.5*dstep;
81f2107f 331 for (i=0;i<np;i++) { //RStmp Integrate over t
332 // for (i=0;i<kn10;i++) { // Integrate over t
0ebc85cf 333 step += dstep; // RStmp kti[i];
334 x = x0+x1*step;
c92b1537 335 y += dy;
0ebc85cf 336 z = z0+z1*step;
451f5018 337 if (!(fSeg->LocalToDet(x,z,ix,iz))) continue; // outside
29ad4146 338 el = fGlobalChargeScale * dstep * de/fSimuParam->GetGeVToCharge();
c92b1537 339 if (fSimuParam->GetPixLorentzDrift()) x += y*fTanLorAng;
0ebc85cf 340 // Check if the hit is inside readout window
341 if ( !(((AliITSUSimulationPix*)this)->*AliITSUSimulationPix::fROTimeFun)(ix,iz,tof) ) continue;
c92b1537 342 SpreadCharge2D(x,z,y,ix,iz,el,idtrack,h);
451f5018 343 } // end for i // End Integrate over t
81f2107f 344 }
451f5018 345 else { // st == 0.0 deposit it at this point
346 x = x0;
c92b1537 347 y = y0+0.5*thick;
451f5018 348 z = z0;
349 if (!(fSeg->LocalToDet(x,z,ix,iz))) continue; // outside
350 el = de / fSimuParam->GetGeVToCharge();
c92b1537 351 if (fSimuParam->GetPixLorentzDrift()) x += y*fTanLorAng;
0ebc85cf 352 // Check if the hit is inside readout window
353 if ( !(((AliITSUSimulationPix*)this)->*AliITSUSimulationPix::fROTimeFun)(ix,iz,tof) ) continue;
c92b1537 354 SpreadCharge2D(x,z,y,ix,iz,el,idtrack,h);
451f5018 355 } // end if st>0.0
356
357 } // Loop over all hits h
358
359 // Coupling
360 int nd = fSensMap->GetEntriesUnsorted(); // use unsorted access when possible, since it is faster
361 AliITSUSDigit* dg = 0;
4fa9d550 362 switch (fSimuParam->GetPixCouplingOption()) {
363 case AliITSUSimuParam::kNewCouplingPix :
451f5018 364 for (i=nd;i--;) {
365 dg = (AliITSUSDigit*)fSensMap->AtUnsorted(i);
366 if (fSensMap->IsDisabled(dg)) continue;
367 SetCoupling(dg,idtrack,h);
368 }
4fa9d550 369 case AliITSUSimuParam::kOldCouplingPix:
451f5018 370 for (i=nd;i--;) {
371 dg = (AliITSUSDigit*)fSensMap->AtUnsorted(i);
372 if (fSensMap->IsDisabled(dg)) continue;
373 SetCouplingOld(dg,idtrack,h);
374 }
375 break;
376 default:
377 break;
378 } // end switch
4fa9d550 379 if (GetDebug(2)) AliInfo(Form("Finished fCoupling=%d",fSimuParam->GetPixCouplingOption()));
451f5018 380}
381
382//______________________________________________________________________
c92b1537 383void AliITSUSimulationPix::SpreadCharge2D(Double_t x0,Double_t z0, Double_t dy, Int_t ix0,Int_t iz0,
384 Double_t el, Int_t tID, Int_t hID)
451f5018 385{
386 // Spreads the charge over neighboring cells. Assume charge is distributed
387 // as charge(x,z) = (el/2*pi*sigx*sigz)*exp(-arg)
388 // arg=((x-x0)*(x-x0)/2*sigx*sigx)+((z-z0*z-z0)/2*sigz*sigz)
451f5018 389 // Defined this way, the integral over all x and z is el.
390 // Inputs:
c92b1537 391 // Double_t x0 x position of point where charge is liberated (local)
392 // Double_t z0 z position of point where charge is liberated (local)
393 // Double_t dy distance from the entrance surface (diffusion sigma may depend on it)
451f5018 394 // Int_t ix0 row of cell corresponding to point x0
395 // Int_t iz0 columb of cell corresponding to point z0
396 // Double_t el number of electrons liberated in this step
397 // Double_t sigx Sigma difusion along x for this step (y0 dependent)
4fa9d550 398 // Double_t sigz Sigma difusion along z for this step (z0 dependent)
c92b1537 399 // Int_t tID track number
400 // Int_t hID hit "hit" index number
401 //
451f5018 402 Int_t ix,iz,ixs,ixe,izs,ize;
4fa9d550 403 Float_t x,z; // keep coordinates float (required by AliSegmentation)
29ad4146 404 Float_t xdioshift = 0 , zdioshift = 0 ;
c92b1537 405 Double_t s,dtIn[kNDtSpread]; // data transfered to spread function for integral calculation
451f5018 406 //
29ad4146 407 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));
c92b1537 408 //
409 Double_t &x1 = dtIn[kCellX1];
410 Double_t &x2 = dtIn[kCellX2];
411 Double_t &z1 = dtIn[kCellZ1];
412 Double_t &z2 = dtIn[kCellZ2];
413 //
414 int nx = GetResponseParam()->GetParameter(kSpreadFunParamNXoffs);
415 int nz = GetResponseParam()->GetParameter(kSpreadFunParamNZoffs);
416 //
417 dtIn[kCellYDepth] = dy;
418 ixs = Max(-nx+ix0,0);
419 ixe = Min( nx+ix0,fSeg->Npx()-1);
420 izs = Max(-nz+iz0,0);
421 ize = Min( nz+iz0,fSeg->Npz()-1);
451f5018 422 for (ix=ixs;ix<=ixe;ix++)
423 for (iz=izs;iz<=ize;iz++) {
424 fSeg->DetToLocal(ix,iz,x,z); // pixel center
29ad4146 425 xdioshift = zdioshift = 0;
426 CalcDiodeShiftInPixel(ix,iz,xdioshift,zdioshift); // Check and apply diode shift if needed
29f5e263 427 double dxi = 0.5*fSeg->Dpx(ix);
428 double dzi = 0.5*fSeg->Dpz(iz);
29ad4146 429 x1 = (x + xdioshift) - x0; // calculate distance of cell boundaries from injection center
430 z1 = (z + zdioshift) - z0;
4fa9d550 431 x2 = x1 + dxi; // Upper
432 x1 -= dxi; // Lower
433 z2 = z1 + dzi; // Upper
434 z1 -= dzi; // Lower
c92b1537 435 s = el* (((AliITSUSimulationPix*)this)->*AliITSUSimulationPix::fSpreadFun)(dtIn);
c92b1537 436 if (s>fSimuParam->GetPixMinElToAdd()) UpdateMapSignal(iz,ix,tID,hID,s);
451f5018 437 } // end for ix, iz
438 //
439}
440
c92b1537 441//______________________________________________________________________
442Double_t AliITSUSimulationPix::SpreadFunDoubleGauss2D(const Double_t *dtIn)
443{
444 // calculate integral of charge in the cell with boundaries at X=dtIn[kCellX1]:dtIn[kCellX2]
445 // and Z=dtIn[kCellZ1]:dtIn[kCellZ2]
446 // The spread function is assumed to be double gaussian in 2D
447 // Parameters should be: mean0,sigma0, mean1,sigma1, relative strenght of 2nd gaussian wrt 1st one
448 //
c92b1537 449 // 1st gaussian
69e0f089 450 double intg1 = GausInt2D(fResponseParam->GetParameter(kG2SigX0), // sigX
69e0f089 451 dtIn[kCellX1]-fResponseParam->GetParameter(kG2MeanX0), // x1-xmean
452 dtIn[kCellX2]-fResponseParam->GetParameter(kG2MeanX0), // x2-xmean
268bb76f 453 fResponseParam->GetParameter(kG2SigZ0), // sigZ
69e0f089 454 dtIn[kCellZ1]-fResponseParam->GetParameter(kG2MeanZ0), // z1-zmean
455 dtIn[kCellZ2]-fResponseParam->GetParameter(kG2MeanZ0)); // z2-zmean
c92b1537 456 // 2nd gaussian
69e0f089 457 double intg2 = GausInt2D(fResponseParam->GetParameter(kG2SigX1), // sigX
69e0f089 458 dtIn[kCellX1]-fResponseParam->GetParameter(kG2MeanX1), // x1-xmean
459 dtIn[kCellX2]-fResponseParam->GetParameter(kG2MeanX1), // x2-xmean
268bb76f 460 fResponseParam->GetParameter(kG2SigZ1), // sigZ
69e0f089 461 dtIn[kCellZ1]-fResponseParam->GetParameter(kG2MeanZ1), // z1-zmean
462 dtIn[kCellZ2]-fResponseParam->GetParameter(kG2MeanZ1)); // z2-zmean
463 double scl = fResponseParam->GetParameter(kG2ScaleG2);
c92b1537 464 return (intg1+intg2*scl)/(1+scl);
465 //
466}
467
29ad4146 468
469//______________________________________________________________________
470Double_t AliITSUSimulationPix::SpreadFrom2DHisto(const Double_t *dtIn)
471{
472 // calculate integral of charge in the cell with boundaries at X=dtIn[kCellX1]:dtIn[kCellX2]
473 // and Z=dtIn[kCellZ1]:dtIn[kCellZ2]
474 // The spread function integral is taken from fSpread2DHisto extracted from the sensor response parameters
475 // list in the method SetResponseParam. The histo must return the fraction of charge integrates in the
476 // cell whose center is on the distance X=(dtIn[kCellX1]+dtIn[kCellX2])/2 and Z=(dtIn[kCellZ1]+dtIn[kCellZ2])/2
477 // from the injection point.
478 //
479 Double_t qpixfrac = 0;
480 Double_t xintp = 1e4*(dtIn[kCellX1]+dtIn[kCellX2])/2.0;
481 Double_t zintp = 1e4*(dtIn[kCellZ1]+dtIn[kCellZ2])/2.0;
482 //
483 qpixfrac = fSpread2DHisto->Interpolate(xintp,zintp); //the PSF map is given in um but the dtIn is in cm so we need to convert it
484 //
485 return qpixfrac;
486}
487
c92b1537 488//______________________________________________________________________
489Double_t AliITSUSimulationPix::SpreadFunGauss2D(const Double_t *dtIn)
490{
491 // calculate integral of charge in the cell with boundaries at X=dtIn[kCellX1]:dtIn[kCellX2]
492 // and Z=dtIn[kCellZ1]:dtIn[kCellZ2]
493 // The spread function is assumed to be gaussian in 2D
494 // Parameters should be: mean0,sigma0
69e0f089 495 return GausInt2D(fResponseParam->GetParameter(kG1SigX), // sigX
496 fResponseParam->GetParameter(kG1SigZ), // sigZ
497 dtIn[kCellX1]-fResponseParam->GetParameter(kG1MeanX), // x1-xmean
498 dtIn[kCellX2]-fResponseParam->GetParameter(kG1MeanX), // x2-xmean
499 dtIn[kCellZ1]-fResponseParam->GetParameter(kG1MeanZ), // z1-zmean
500 dtIn[kCellZ2]-fResponseParam->GetParameter(kG1MeanZ)); // z2-zmean
c92b1537 501 //
502}
503
451f5018 504//______________________________________________________________________
505void AliITSUSimulationPix::RemoveDeadPixels()
506{
507 // Removes dead pixels on each module (ladder)
508 // This should be called before going from sdigits to digits (FrompListToDigits)
509
510 AliITSUCalibrationPix* calObj = (AliITSUCalibrationPix*) GetCalibDead();
511 if (!calObj) return;
512 //
513 if (calObj->IsBad()) {ClearMap(); return;} // whole module is masked
514 //
515 // remove single bad pixels one by one
516 int nsingle = calObj->GetNrBadSingle();
517 UInt_t col,row;
518 for (int i=nsingle;i--;) {
519 calObj->GetBadPixelSingle(i,row,col);
520 fSensMap->DeleteItem(col,row);
521 }
522 int nsd = fSensMap->GetEntriesUnsorted();
523 for (int isd=nsd;isd--;) {
524 AliITSUSDigit* sd = (AliITSUSDigit*)fSensMap->AtUnsorted(isd);
525 if (fSensMap->IsDisabled(sd)) continue;
526 fSensMap->GetMapIndex(sd->GetUniqueID(),col,row);
527 int chip = fSeg->GetChipFromChannel(0,col);
528 // if (calObj->IsChipMarkedBad(chip)) fSensMap->Disable(sd); // this will simple mark the hit as bad
529 if (calObj->IsChipMarkedBad(chip)) fSensMap->DeleteItem(sd); // this will suppress hit in the sorted list
530 }
531 //
532}
533
534//______________________________________________________________________
535void AliITSUSimulationPix::AddNoisyPixels()
536{
537 // Adds noisy pixels on each module (ladder)
538 // This should be called before going from sdigits to digits (FrompListToDigits)
539 AliITSUCalibrationPix* calObj = (AliITSUCalibrationPix*) GetCalibNoisy();
29ad4146 540 if (!calObj) { AliDebug(10,Form(" No Calib Object for Noise!!! ")); return;}
451f5018 541 for (Int_t i=calObj->GetNrBad(); i--;) UpdateMapNoise(calObj->GetBadColAt(i), calObj->GetBadRowAt(i),
c92b1537 542 10*fSimuParam->GetPixThreshold(fModule->GetIndex()));
451f5018 543 //
544}
545
546//______________________________________________________________________
547void AliITSUSimulationPix::FrompListToDigits()
548{
549 // add noise and electronics, perform the zero suppression and add the
550 // digit to the list
551 static AliITSU *aliITS = (AliITSU*)gAlice->GetModule("ITS");
552 UInt_t ix,iz;
553 Double_t sig;
554 const Int_t knmaxtrk=AliITSdigit::GetNTracks();
555 static AliITSUDigitPix dig;
556 // RS: in principle:
557 // 1) for every pixel w/o hit we have to generate a noise and activate the pixel if the noise exceeds the threshold.
558 // 2) for every pixel with hit we should add random noise and check if the total signal exceeds the threshold
559 // With many channels this will be too time consuming, hence I do the following
29ad4146 560 // 1) Precalculate the probability that the nois alone will exceed the threshold (probnoisy).
561 // 2) Chose randomly empty pixels according to fakes rate
451f5018 562 // 3) For pixels having a hits apply the usual noise and compare with threshold
563 //
564 // RS may use for ordered random sample generation dl.acm.org/ft_gateway.cfm?id=356313&type=pdf
565 //
566 int maxInd = fSensMap->GetMaxIndex();
c92b1537 567 int modId = fModule->GetIndex();
451f5018 568 //
569 int nsd = fSensMap->GetEntries();
570 Int_t prevID=0,curID=0;
571 TArrayI ordSampleInd(100),ordSample(100);
572 //
c92b1537 573 double probNoisy,noiseSig,noiseMean,thresh = fSimuParam->GetPixThreshold(modId);
574 fSimuParam->GetPixNoise(modId, noiseSig, noiseMean);
451f5018 575 probNoisy = AliITSUSimuParam::CalcProbNoiseOverThreshold(noiseMean,noiseSig,thresh); // prob. to have noise above threshold
576 //
577 for (int i=0;i<nsd;i++) {
578 AliITSUSDigit* sd = (AliITSUSDigit*)fSensMap->At(i); // ordered in index
579 if (fSensMap->IsDisabled(sd)) continue;
580 curID = (int)sd->GetUniqueID();
581 //
29ad4146 582 if ( fSimuParam->GetPixAddNoisyFlag() ) {
451f5018 583 CreateNoisyDigits(prevID,curID,probNoisy, noiseSig, noiseMean);
584 prevID = curID+1;
970bfd2e 585 //
586 // add noise also to sdigit with signal
587 sd->AddNoise(AliITSUSimuParam::GenerateNoiseQFunction(0,noiseMean,noiseSig));
451f5018 588 }
589 //
c92b1537 590 if ((sig=sd->GetSumSignal())<=fSimuParam->GetPixThreshold(modId)) continue;
a11ef2e4 591 if (Abs(sig)>2147483647.0) { //RS?
451f5018 592 //PH 2147483647 is the max. integer
593 //PH This apparently is a problem which needs investigation
594 AliWarning(Form("Too big or too small signal value %f",sig));
595 }
596 fSensMap->GetMapIndex(sd->GetUniqueID(),iz,ix);
597 dig.SetCoord1(iz);
598 dig.SetCoord2(ix);
29ad4146 599 dig.SetSignal((Int_t)sig);
451f5018 600 dig.SetSignalPix((Int_t)sig);
601 int ntr = sd->GetNTracks();
602 for (int j=0;j<ntr;j++) {
603 dig.SetTrack(j,sd->GetTrack(j));
604 dig.SetHit(j,sd->GetHit(j));
605 }
606 for (int j=ntr;j<knmaxtrk;j++) {
607 dig.SetTrack(j,-3);
608 dig.SetHit(j,-1);
609 }
02d6eccc 610 aliITS->AddSimDigit(AliITSUGeomTGeo::kDetTypePix, &dig);
451f5018 611 }
612 // if needed, add noisy pixels with id from last real hit to maxID
29ad4146 613 if (fSimuParam->GetPixAddNoisyFlag() &&
614 (nsd>0 || ( nsd==0 && fSimuParam->GetPixNoiseInAllMod()) )) {
615 AliDebug(10,Form("CreateNoisyDigits2( %d ,%d) module %d",prevID,maxInd,modId));
616 CreateNoisyDigits(prevID,maxInd,probNoisy, noiseSig, noiseMean);
617 }
451f5018 618 //
619}
620
621//______________________________________________________________________
622Int_t AliITSUSimulationPix::CreateNoisyDigits(Int_t minID,Int_t maxID,double probNoisy, double noise, double base)
29ad4146 623{//RS PAYATT2
451f5018 624 // create random noisy digits above threshold within id range [minID,maxID[
625 // see FrompListToDigits for details
626 //
627 static AliITSU *aliITS = (AliITSU*)gAlice->GetModule("ITS");
628 UInt_t ix,iz;
629 static AliITSUDigitPix dig;
630 static TArrayI ordSampleInd(100),ordSample(100); //RS!!! static is not thread-safe!!!
631 const Int_t knmaxtrk=AliITSdigit::GetNTracks();
632 //
633 Int_t ncand = 0;
634 int npix = maxID-minID;
29ad4146 635 if (npix<1 || (ncand=gRandom->Poisson(npix * fSimuParam->GetPixFakeRate() ))<1) return ncand; // decide how many noisy pixels will be added
451f5018 636 ncand = GenOrderedSample(npix,ncand,ordSample,ordSampleInd);
637 int* ordV = ordSample.GetArray();
638 int* ordI = ordSampleInd.GetArray();
639 for (int j=0;j<ncand;j++) {
640 fSensMap->GetMapIndex((UInt_t)ordV[ordI[j]],iz,ix); // create noisy digit
641 dig.SetCoord1(iz);
642 dig.SetCoord2(ix);
643 dig.SetSignal(1);
644 dig.SetSignalPix((Int_t)AliITSUSimuParam::GenerateNoiseQFunction(probNoisy,base,noise));
645 for (int k=knmaxtrk;k--;) {
646 dig.SetTrack(k,-3);
647 dig.SetHit(k,-1);
648 }
02d6eccc 649 aliITS->AddSimDigit(AliITSUGeomTGeo::kDetTypePix,&dig);
29ad4146 650 AliDebug(10,Form("Add noisy pixel %d(%d/%d) Noise=%d",ordV[ordI[j]],iz,ix,dig.GetSignalPix()));
451f5018 651 }
652 return ncand;
653}
654
655//______________________________________________________________________
656void AliITSUSimulationPix::SetCoupling(AliITSUSDigit* old, Int_t ntrack, Int_t idhit)
657{
658 // Take into account the coupling between adiacent pixels.
659 // The parameters probcol and probrow are the probability of the
660 // signal in one pixel shared in the two adjacent pixels along
661 // the column and row direction, respectively.
662 // Note pList is goten via GetMap() and module is not need any more.
663 // Otherwise it is identical to that coded by Tiziano Virgili (BSN).
664 //Begin_Html
665 /*
666 <img src="picts/ITS/barimodel_3.gif">
667 </pre>
668 <br clear=left>
669 <font size=+2 color=red>
670 <a href="mailto:tiziano.virgili@cern.ch"></a>.
671 </font>
672 <pre>
673 */
674 //End_Html
675 // Inputs:
676 // old existing AliITSUSDigit
677 // Int_t ntrack track incex number
678 // Int_t idhit hit index number
679 UInt_t col,row;
680 Double_t pulse1,pulse2;
681 Double_t couplR=0.0,couplC=0.0;
682 Double_t xr=0.;
683 //
684 fSensMap->GetMapIndex(old->GetUniqueID(),col,row);
4fa9d550 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));
451f5018 688 pulse2 = pulse1 = old->GetSignal();
4fa9d550 689 if (pulse1<fSimuParam->GetPixMinElToAdd()) return; // too small signal
451f5018 690 for (Int_t isign=-1;isign<=1;isign+=2) {
691 //
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);
696 //
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);
701 }
702 //
703}
704
705//______________________________________________________________________
706void AliITSUSimulationPix::SetCouplingOld(AliITSUSDigit* old, Int_t ntrack,Int_t idhit)
707{
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.
712 //Begin_Html
713 /*
714 <img src="picts/ITS/barimodel_3.gif">
715 </pre>
716 <br clear=left>
717 <font size=+2 color=red>
718 <a href="mailto:Rocco.Caliandro@ba.infn.it"></a>.
719 </font>
720 <pre>
721 */
722 //End_Html
723 // Inputs:
724 // old existing AliITSUSDigit
725 // ntrack track incex number
726 // idhit hit index number
727 // module module number
728 //
729 UInt_t col,row;
c92b1537 730 Int_t modId = fModule->GetIndex();
451f5018 731 Double_t pulse1,pulse2;
732 Double_t couplR=0.0,couplC=0.0;
733 //
734 fSensMap->GetMapIndex(old->GetUniqueID(),col,row);
4fa9d550 735 fSimuParam->GetPixCouplingParam(couplC,couplR);
736 if (GetDebug(3)) AliInfo(Form("(col=%d,row=%d,ntrack=%d,idhit=%d) couplC=%e couplR=%e",
737 col,row,ntrack,idhit,couplC,couplR));
738 //
739 if (old->GetSignal()<fSimuParam->GetPixMinElToAdd()) return; // too small signal
740 for (Int_t isign=-1;isign<=1;isign+=2) {// loop in col direction
741 pulse2 = pulse1 = old->GetSignal();
742 //
743 int j1 = int(col)+isign;
744 pulse1 *= couplC;
c92b1537 745 if ((j1<0)||(j1>fSeg->Npz()-1)||(pulse1<fSimuParam->GetPixThreshold(modId))) pulse1 = old->GetSignal();
4fa9d550 746 else UpdateMapSignal(UInt_t(j1),row,ntrack,idhit,pulse1);
747
748 // loop in row direction
749 int j2 = int(row) + isign;
750 pulse2 *= couplR;
c92b1537 751 if ((j2<0)||(j2>(fSeg->Npx()-1))||(pulse2<fSimuParam->GetPixThreshold(modId))) pulse2 = old->GetSignal();
4fa9d550 752 else UpdateMapSignal(col,UInt_t(j2),ntrack,idhit,pulse2);
753 } // for isign
451f5018 754}
755
756//______________________________________________________________________
0ebc85cf 757void AliITSUSimulationPix::GenerateReadOutCycleOffset()
451f5018 758{
759 // Generate randomly the strobe
760 // phase w.r.t to the LHC clock
0ebc85cf 761 fReadOutCycleOffset = fReadOutCycleLength*gRandom->Rndm();
29ad4146 762 // 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?!
763 // 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
764 // collision will be lost) untill real number is specified
765 //
451f5018 766}
767
c92b1537 768//______________________________________________________________________
29ad4146 769void AliITSUSimulationPix::SetResponseParam(AliITSUParamList* resp)
c92b1537 770{
771 // attach response parameterisation data
772 fResponseParam = resp;
29ad4146 773 //
774 int spreadID = Nint(fResponseParam->GetParameter(AliITSUSimulationPix::kChargeSpreadType));
775 const char* hname = 0;
776 fSpread2DHisto = 0;
777 //
778 switch (spreadID) {
779 //
780 case kSpreadFunHisto:
781 fSpreadFun = &AliITSUSimulationPix::SpreadFrom2DHisto;
782 hname = fResponseParam->GetParName(AliITSUSimulationPix::kChargeSpreadType);
783 if (!(fSpread2DHisto=(TH2*)fResponseParam->GetParamObject(hname)))
784 AliFatal(Form("Did not find 2D histo %s for charge spread parameterization",hname));
c92b1537 785 break;
29ad4146 786 //
787 case kSpreadFunDoubleGauss2D:
788 fSpreadFun = &AliITSUSimulationPix::SpreadFunDoubleGauss2D;
789 break;
790 //
791 case kSpreadFunGauss2D:
792 fSpreadFun = &AliITSUSimulationPix::SpreadFunGauss2D;
c92b1537 793 break;
29ad4146 794 //
795 default: AliFatal(Form("Did not find requested spread function id=%d",spreadID));
c92b1537 796 }
797 //
0ebc85cf 798 int readoutType = Nint(fResponseParam->GetParameter(kReadOutSchemeType));
799 switch (readoutType) {
29ad4146 800 case kReadOutStrobe:
801 fROTimeFun = &AliITSUSimulationPix::IsHitInReadOutWindow;
0ebc85cf 802 break;
29ad4146 803 case kReadOutRollingShutter:
804 fROTimeFun = &AliITSUSimulationPix::IsHitInReadOutWindowRollingShutter;
0ebc85cf 805 break;
806 default: AliFatal(Form("Did not find requested readout time type id=%d",readoutType));
807 }
29ad4146 808 //___ Set the Rolling Shutter read-out window
0ebc85cf 809 fReadOutCycleLength = fResponseParam->GetParameter(kReadOutCycleLength);
29ad4146 810 //___ Pixel discrimination threshold, and the S/N cut
811 fSimuParam->SetPixThreshold(fResponseParam->GetParameter(kPixNoiseMPV) *fResponseParam->GetParameter(kPixSNDisrcCut) , fResponseParam->GetParameter(kPixSNDisrcCut),-1); //for all modules
812 //___ Minimum number of electrons to add
813 fSimuParam->SetPixMinElToAdd(fResponseParam->GetParameter(kPixMinElToAdd));
814 //___ Set the Pixel Noise MPV and Sigma (the noise distribution is Landau not Gauss due to RTN)
815 fSimuParam->SetPixNoise( fResponseParam->GetParameter(kPixNoiseMPV), fResponseParam->GetParameter(kPixNoiseSigma), -1); //for all modules
816 //___ Pixel fake hit rate
817 fSimuParam->SetPixFakeRate( fResponseParam->GetParameter(kPixFakeRate) );
818 //___ To apply the noise or not
819 if ( fResponseParam->GetParameter(kPixNoiseIsOn) > 0.01) fSimuParam->SetPixAddNoisyFlag(kTRUE);
820 else fSimuParam->SetPixAddNoisyFlag(kFALSE);
821 //
822 if(fResponseParam->GetParameter(kPixNoiseInAllMod) > 0.01 ) fSimuParam->SetPixNoiseInAllMod(kTRUE);
823 else fSimuParam->SetPixNoiseInAllMod(kFALSE);
824 //
825 // Double_t vGeVToQ = fSimuParam->GetGeVToCharge();
826 fGlobalChargeScale = fResponseParam->GetParameter(kSpreadFunGlobalQScale);
827
828 AliDebug(10,Form("=============== Setting the response start ============================"));
829 AliDebug(10,Form("=============== RO type: %d",readoutType));
830 AliDebug(10,Form("=============== RO cycle lenght: %lf",fReadOutCycleLength));
831 AliDebug(10,Form("=============== Noise MPV: %lf",fResponseParam->GetParameter(kPixNoiseMPV)));
832 AliDebug(10,Form("=============== Noise Sigma: %lf",fResponseParam->GetParameter(kPixNoiseSigma)));
833 AliDebug(10,Form("=============== Fake rate: %lf",fResponseParam->GetParameter(kPixFakeRate)));
834 AliDebug(10,Form("=============== Noise On/Off: %d",fSimuParam->GetPixAddNoisyFlag()));
835 AliDebug(10,Form("=============== Noise in all mod on/off: %d",fSimuParam->GetPixNoiseInAllMod()));
836 AliDebug(10,Form("=============== Global Charge scale: %lf",fGlobalChargeScale));
837 AliDebug(10,Form("=============== Setting the response done ============================"));
838
839
840
c92b1537 841}
0ebc85cf 842
843//______________________________________________________________________
29ad4146 844Bool_t AliITSUSimulationPix::IsHitInReadOutWindowRollingShutter(Int_t row, Int_t col, Double_t hitTime)
0ebc85cf 845{
846 //
847 // Check whether the hit is in the read out window of the given column/row of the sensor
848 // hitTime is the time of the subhit (hit is divided to nstep charge deposit) in seconds
849 // globalPhaseShift gives the start of the RO for the cycle in pixel wrt the LHC clock
850 // GetRollingShutterWindow give the with of the rolling shutter read out window
851 //
852 double timePerRow = fReadOutCycleLength / fSeg->Npx();
853 double tmax = fReadOutCycleOffset + timePerRow*(row+1);
854 double tmin = tmax - fReadOutCycleLength;
855 AliDebug(3,Form("Rolling shutter at row%d/col%d: particle time: %e, tmin: %e : %e",row,col,hitTime,tmin,tmax));
856 return (hitTime<tmin || hitTime>tmax) ? kFALSE : kTRUE;
857 //
858}
859
860//______________________________________________________________________
861Bool_t AliITSUSimulationPix::IsHitInReadOutWindow(Int_t row, Int_t col, Double_t hitTime)
862{
863 //
864 // Check whether the hit is in the read out window of the given column/row of the sensor
865 //
866 AliDebug(3,Form("Strobe readout: row%d/col%d: particle time: %e, tmin: %e, tmax %e",
867 row,col,hitTime,fReadOutCycleOffset,fReadOutCycleOffset+fReadOutCycleLength));
e822b25e 868 hitTime -= fReadOutCycleOffset+0.5*fReadOutCycleLength;
0ebc85cf 869 return (hitTime<0 || hitTime>fReadOutCycleLength) ? kFALSE : kTRUE;
870 //
871}
872
29ad4146 873//_______________________________________________________________________
874void AliITSUSimulationPix::CalcDiodeShiftInPixel(Int_t xlin, Int_t zcol, Float_t &x, Float_t &)
875{
876 //
877 // Calculates the shift of the diode wrt the geometric center of the pixel.
878 // It is needed for staggerred pixel layout or double diode pixels with assymetric center
879 // The shift can depend on the column or line or both...
880 // The x and z are passed in cm
881 //
882
883 TString parTitle = fResponseParam->GetTitle();
884
885 // M32terP31 is staggered the diode shift within pixel depends on the column
886 if ( parTitle.Contains("M32terP31") )
887 {
888 if ( zcol%2 == 0 ) x += 0.30 * fSeg->Dpx(xlin);
889 else x -= 0.19 * fSeg->Dpx(xlin);
890 }
891
892
893}
894//_______________________________________________________________________