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