FairRoot/PandaRoot
PndSdsCalcStrip.cxx
Go to the documentation of this file.
1 //______________________________________________________________________________
2 //
3 // C++ Implementation: PndSdsCalcStrip
4 //
5 // Description:
6 //
7 //
8 // Author: HG Zaunick <hg.zaunick@physik.tu-dresden.de>, (C) 2007
9 //
10 // Copyright: See COPYING file that comes with this distribution
11 //
12 //
13 #include <cmath>
14 #include <exception>
15 
16 #include "PndSdsCalcStrip.h"
17 #include "TRandom.h"
18 
19 //______________________________________________________________________________
21  fPitch(0.),
22  fOrient(0.),
23  fNrStrips(0),
24  fNrFeChannels(0),
25  fAnchor(0.,0.),
26  fThreshold(0.),
27  fNoise(0.),
28  fCSigma(0.),
29  fStripDir(0.,0.),
30  fOrthoDir(0.,0.),
31  fVerboseLevel(0)
32 {}
33 
34 //______________________________________________________________________________
36  Int_t nrStrips, Int_t nrFeChannels,
37  const TVector2& firstStripAnchor,
39 : fPitch(pitch), fOrient(orient),
40 fNrStrips(nrStrips), fNrFeChannels(nrFeChannels),
41 fAnchor(firstStripAnchor),
42 fThreshold(threshold), fNoise(noise), fCSigma(csigma),
43 fStripDir(0.,0.), fOrthoDir(0.,0.), fVerboseLevel(0)
44 {
47  //Print();
48 }
49 
50 //______________________________________________________________________________
52 : fPitch(0.),
53  fOrient(0.),
54  fNrStrips(0),
55  fNrFeChannels(0),
56  fAnchor(0.,0.),
57  fThreshold(0.),
58  fNoise(0.),
59  fCSigma(0.),
60  fStripDir(0.,0.),
61  fOrthoDir(0.,0.),
62  fVerboseLevel(0)
63 {
64  if(side == kTOP)
65  {
66  fPitch = digipar->GetTopPitch();
67  fOrient = digipar->GetOrient();
68  fAnchor = digipar->GetTopAnchor();
69  fNrStrips = digipar->GetNrTopFE()*digipar->GetNrFECh();
70  }
71  else if(side == kBOTTOM)
72  {
73  fPitch = digipar->GetBotPitch();
74  fOrient = digipar->GetOrient() + digipar->GetSkew();
75  fAnchor = digipar->GetBotAnchor();
76  fNrStrips = digipar->GetNrBotFE()*digipar->GetNrFECh();
77  }
78  fNrFeChannels = digipar->GetNrFECh();
79  fThreshold = digipar->GetThreshold();
80  fNoise = digipar->GetNoise();
81  fCSigma = digipar->GetQCloudSigma();
82 
85  fVerboseLevel = 0;
86  if (fVerboseLevel > 0) Print();
87 }
88 
89 
90 //______________________________________________________________________________
91 std::vector<PndSdsStrip>
92 PndSdsCalcStrip::GetStrips(Double_t inx, Double_t iny, Double_t , //inz //[R.K.03/2017] unused variable(s)
93  Double_t outx, Double_t outy, Double_t , // outz //[R.K.03/2017] unused variable(s)
94  Double_t eLoss)
95 {
96  if (fVerboseLevel > 2) std::cout<<"-I- PndSdsCalcStrip::GetStrips "<<std::endl;
97 
98  // 2d-Projection of trajectory
99  TVector2 in(inx,iny);
100  TVector2 out(outx,outy);
101  TVector2 path=out-in;
102 
103  if (fVerboseLevel > 2){
104  std::cout<<" InPoint: ("<<in.X()<<","<<in.Y()<<")"<<std::endl;
105  std::cout<<" OutPoint: ("<<out.X()<<","<<out.Y()<<")"<<std::endl;
106  }
107 
108  //if (path.Mod()<1E-18) {
109  //std::cout<<"-W- PndSdsCalcStrip::GetStrips : No Trajectory inside Sensor! (out-in).Mod() = "<<path.Mod()<<std::endl;
110  //std::vector<PndSdsStrip> strips;
111  //return strips;
112  //}
113 
114  if (fVerboseLevel > 1) std::cout<<" pathlength: "<<path.Mod()<<std::endl;
115 
116  Double_t nuIn = CalcStripFromPoint(inx,iny);
117  Double_t nuOut = CalcStripFromPoint(outx,outy);
118 
119  if (fVerboseLevel > 2) std::cout<<" nuIn = "<<nuIn<<" ; nuOut = "<<nuOut<<std::endl;
120 
121  Double_t Q = ChargeFromEloss(eLoss);//*1E9/3.61; // 3.6 eV/Electron in Silicon
122  if (fVerboseLevel > 1) std::cout<<" integral charge = "<<Q<<std::endl;
123  if (fVerboseLevel > 1) std::cout<<"Charge cloud sigma="<<fCSigma<<std::endl;
124  // Do charge distribution
125  if(fCSigma>0) return GetStripsDif(nuIn,nuOut,Q);
126  else return GetStripsNoDif(nuIn,nuOut,Q);
127 
128 }
129 
130 
131 //______________________________________________________________________________
132 std::vector<PndSdsStrip> PndSdsCalcStrip::GetStripsNoDif(Double_t nuIn, Double_t nuOut, Double_t Q)
133 {
134  // Charge distributed equally along a path.
135 
136  if (fVerboseLevel > 2) std::cout<<"-I- PndSdsCalcStrip::GetStripsNoDif "<<std::endl;
137  std::vector<PndSdsStrip> strips;
138 
139  if (fVerboseLevel > 2) std::cout<<" nuIn = "<<nuIn<<" ; nuOut = "<<nuOut<<std::endl;
140  if (fVerboseLevel > 1) std::cout<<" integral charge = "<<Q<<std::endl;
141 
142  // did we hit the active area ?
143  // if ( (nuIn<0.5 && nuOut<0.5) || (((nuIn+0.5) > Double_t(fNrStrips-1)) && ((nuOut+0.5) > Double_t(fNrStrips-1)))){
144  if ( (nuIn<0. && nuOut<0.) || ((nuIn > Double_t(fNrStrips)) && (nuOut > Double_t(fNrStrips))) )
145  {
146  if (fVerboseLevel > 1) std::cout<<"-W- PndSdsCalcStrip::GetStripsNoDif: Hit outside active area."<<std::endl;
147  return strips;
148  }
149 
150  // is the In-Point inside active area ?
151  // only charge fraction inside active area taken
152  if (nuIn<0.){
153  Q *= (nuOut)/(nuOut-nuIn);
154  nuIn = 0.;
155  } else if (nuIn > (Double_t(fNrStrips))){
156  Q *= ((Double_t)fNrStrips-nuOut)/(-nuOut+nuIn);
157  nuIn = Double_t(fNrStrips);
158  }
159 
160  // is the Out-Point inside active area ?
161  if (nuOut<0.){
162  Q *= (nuIn)/(-nuOut+nuIn);
163  nuOut = 0.;
164  } else if (nuOut > (Double_t(fNrStrips))){
165  Q *= ((Double_t)fNrStrips-nuIn)/(nuOut-nuIn);
166  nuOut = Double_t(fNrStrips);
167  }
168 
169  // only one strip hit ?
170  if (Int_t(nuIn) == Int_t(nuOut)){
171  // this strip collected the entire charge
172  InjectStripCharge(strips,(Int_t)nuOut,Q);
173  return strips;
174 
175  } else
176  { // more than one strip is hit
177  Double_t dQ=Q/std::fabs(nuOut-nuIn);
178  Double_t dir = (nuOut>nuIn) ? 1. : -1.;
179  Int_t nrHits = 0;
180 
181  // calculate portion of track in first strip
182  Int_t nextIn = Int_t(nuIn + 0.5+0.5*dir);
183  Double_t Q1 = dQ*std::fabs(nextIn-nuIn);
184  if (fVerboseLevel > 2){
185  std::cout<<" part of first strip : "<<nextIn-nuIn<<std::endl ;
186  std::cout<<" charge : "<<Q1<<std::endl ;
187  std::cout<<" next strip : "<<nextIn<<std::endl ;
188  }
189  InjectStripCharge(strips,(Int_t)nuIn,Q1);
190  nrHits++;
191  Q -= Q1;
192 
193  // calculate portion of track in last strip
194  Int_t prevOut = Int_t(nuOut + 0.5-0.5*dir);
195  Double_t Q2 = dQ*std::fabs(nuOut-prevOut);
196  if (fVerboseLevel > 2){
197  std::cout<<" part of last strip : "<<(nuOut-prevOut)<<std::endl ;
198  std::cout<<" charge : "<<Q2<<std::endl ;
199  std::cout<<" end of previous strip : "<<prevOut<<std::endl ;
200  }
201  InjectStripCharge(strips,(Int_t)nuOut,Q2);
202  nrHits++;
203  Q -= Q2;
204 
205  // Distribute the charge amongst the intermediate strips
206  nextIn = Int_t(nextIn - 0.5 + 0.5*dir);
207  prevOut = Int_t(prevOut - 0.5 + 0.5*dir);
208  if (fVerboseLevel > 2) {
209  std::cout<<" dir="<<Int_t(dir)<<std::endl;
210  std::cout<<" begin="<<nextIn<<" end="<<prevOut<<std::endl;
211  }
212 
213  for (Int_t n = nextIn ; n != prevOut; n += Int_t(dir) )
214  {
215  if (fVerboseLevel > 2) std::cout<<" n = "<<n<<std::endl;
216  InjectStripCharge(strips,n,dQ);
217  nrHits++;
218  Q -= dQ;
219  }
220  if (fVerboseLevel > 2) if (fabs(Q)>1.) std::cout<<" charge Q = "<<Q<<" not detected!"<<std::endl;
221  if (fVerboseLevel > 1) std::cout<<" -> "<<nrHits<<" strips hit."<<std::endl;
222  }
223 
224  return strips;
225 }
226 
227 //______________________________________________________________________________
228 std::vector<PndSdsStrip> PndSdsCalcStrip::GetStripsDif(Double_t pathstart, Double_t pathend, Double_t Q)
229 {
230  // Do charge diffusion integrated analytically over a path length
231  // 0.5*(1+erf(x)) is the integral over a gauss from -inf to x
232  // factor 0.5 is applied last, the +1 terms cancel in the difference
233 
234  if(pathend<pathstart){ // sort for direction
235  Double_t tmp=pathstart;
236  pathstart=pathend;
237  pathend=tmp;
238  }
239  std::vector<PndSdsStrip> array;
240  Double_t DQ = 0.;
241  // sigma_str = sigma_um/pitch_str-per-um
242  Double_t sigma_str=fCSigma/fPitch;
243  // TODO how much extra bins to fill?, minimum 1...
244  // how about 2sigma? shall be collected
245  Int_t xtra = (Int_t)ceil(2.*sigma_str);
246  for(Int_t i=(Int_t)pathstart-xtra;i<(Int_t)pathend+1+xtra;i++)
247  {
248  DQ=0;
249  if(fabs(pathstart-pathend) < 1e-6) { // too small path, don't integrate over path
250  DQ+=TMath::Erf(i+1-0.5*(pathstart+pathend))/(sqrt(2)*sigma_str);
251  DQ-=TMath::Erf(i-0.5*(pathstart+pathend))/(sqrt(2)*sigma_str);
252  } else {
253  DQ+=CalcFk(i,pathend,sigma_str);
254  DQ-=CalcFk(i+1,pathend,sigma_str);
255  DQ-=CalcFk(i,pathstart,sigma_str);
256  DQ+=CalcFk(i+1,pathstart,sigma_str);
257  DQ/=(pathend-pathstart);
258  }
259  DQ*=0.5*Q;
260  InjectStripCharge(array,i,DQ);
261  }
262  return array;
263 }
264 
265 //______________________________________________________________________________
267 {
268  const Double_t t=(strip-x)/(sqrt(2)*sig);
269  return ( (strip-x)*TMath::Erf(t) + sqrt(2/TMath::Pi())*sig*exp(-t*t) );
270 }
271 
272 //______________________________________________________________________________
273 Int_t PndSdsCalcStrip::GetStripsAlternative(Double_t nuIn, Double_t nuOut, Double_t Q, Int_t mode, std::vector<Int_t>& indice, std::vector<Double_t>& charges)
274 {
275  if(fVerboseLevel>2)Info("GetStripsAlternative()","begin with in=%f, out=%f, Q=%f",nuIn,nuOut,Q);
276  std::vector<PndSdsStrip> strips;
277  if(mode == 0) strips = GetStripsNoDif(nuIn,nuOut,Q);
278  if(mode == 1) strips = GetStripsDif(nuIn,nuOut,Q);
279  Int_t nstr=strips.size();
280  for(Int_t i=0;i<nstr;i++)
281  {
282  if(fVerboseLevel>2) Info("GetStripsAlternative()","pass this strip: i=%i, s=%i, q=%f",i,strips[i].GetIndex(),strips[i].GetCharge());
283  indice.push_back(strips[i].GetIndex());
284  charges.push_back(strips[i].GetCharge());
285  }
286  return nstr;
287 }
288 
289 //______________________________________________________________________________
291 {
292  // fOrthoDir is already set to magnitude == 1., makes it cheaper here.
293  return ((x-fAnchor.X())*fOrthoDir.X() + (y-fAnchor.Y())*fOrthoDir.Y())/fPitch;
294 }
295 
296 //______________________________________________________________________________
298 {
299  point = fPitch*(strip+0.5)*fOrthoDir + fAnchor;
300 }
301 
302 //______________________________________________________________________________
303 Int_t PndSdsCalcStrip::CalcFEfromStrip(Int_t stripNr) const { return (stripNr/fNrFeChannels); }
304 
305 //______________________________________________________________________________
306 Int_t PndSdsCalcStrip::CalcChannelfromStrip(Int_t stripNr) const { return (stripNr%fNrFeChannels); }
307 
308 //______________________________________________________________________________
309 void PndSdsCalcStrip::CalcFeChToStrip(Int_t fe, Int_t channel, Int_t& strip, enum SensorSide& side) const
310 {
311  //Caution! The top side s always the reference side!
312  Int_t nr = fe * fNrFeChannels + channel;
313  if (nr < fNrStrips) {
314  side = kTOP;
315  } else {
316  nr -= fNrStrips;
317  side = kBOTTOM;
318  }
319  strip = nr;
320 }
321 
322 //______________________________________________________________________________
323 void PndSdsCalcStrip::InjectStripCharge(std::vector<PndSdsStrip>& array, Int_t istrip, Double_t charge)
324 {
325  if(istrip<0) {if(fVerboseLevel>2)Warning("InjectStripCharge","Invalid strip number: %i < 0",istrip); return;}
326  if(istrip>fNrStrips) {if(fVerboseLevel>2)Warning("InjectStripCharge","Invalid strip number: %i > %i",istrip,fNrStrips); return;}
327  if(charge==0) return; // cut zero electron charge now, real threshold later
328  Double_t smearedQ = SmearCharge(charge);
329  if(smearedQ < fThreshold) {if(fVerboseLevel>3)Info("InjectStripCharge","Strip %i, charge %f below threshold %f",istrip,smearedQ,fThreshold); return;}
330  if(fVerboseLevel>3) Info("InjectStripCharge","istrip=%i,charge=%f,smearedCharge=%f",istrip,charge,smearedQ);
331  array.push_back( PndSdsStrip(Int_t(istrip),smearedQ) );
332  return;
333 }
334 
335 //______________________________________________________________________________
337 {
338  Double_t smeared = gRandom->Gaus(charge,fNoise);
339  if (fVerboseLevel > 3) Info("SmearCharge:"," charge = %f, smeared = %f",charge,smeared);
340  return smeared;
341 }
342 
343 
345 {
346  std::cout<<"-I- PndSdsCalcStrip Info :"<<std::endl;
347  std::cout<<" pitch = "<<fPitch*10000.<<" um"<<std::endl;
348  std::cout<<" orientation angle = "<<fOrient/TMath::Pi()*180.<<" deg"<<std::endl;
349  std::cout<<" nr of strips = "<<fNrStrips<<std::endl;
350  std::cout<<" nr of channels per FE = "<<fNrFeChannels<<std::endl;
351  std::cout<<" nr of frontends = "<<fNrStrips/fNrFeChannels<<std::endl;
352  std::cout<<" anchor point = ("<<fAnchor.X()<<","<<fAnchor.Y()<<")"<<std::endl;
353  std::cout<<" strip-direction vector = ("<<fStripDir.X()<<","<<fStripDir.Y()<<")"<<std::endl;
354 }
355 
356 
357 
358 
359 
Double_t SmearCharge(Double_t charge)
friend F32vec4 cos(const F32vec4 &a)
Definition: P4_F32vec4.h:112
Int_t fNrStrips
strip orientation angle to x axis
TVector2 GetBotAnchor() const
friend F32vec4 exp(const F32vec4 &a)
Definition: P4_F32vec4.h:109
Int_t i
Definition: run_full.C:25
void Print() const
Int_t CalcFEfromStrip(Int_t stripNr) const
friend F32vec4 sqrt(const F32vec4 &a)
Definition: P4_F32vec4.h:29
friend F32vec4 sin(const F32vec4 &a)
Definition: P4_F32vec4.h:111
int n
Double_t GetNoise() const
Class representing strips on wafer-scale.
Definition: PndSdsStrip.h:15
int nrStrips
Definition: anaLmdDigi.C:76
Double_t GetThreshold() const
Int_t fNrFeChannels
Nr. of strips on active area.
Double_t GetOrient() const
Double_t fCSigma
ENC.
std::vector< PndSdsStrip > GetStripsDif(Double_t nuIn, Double_t nuOut, Double_t Q)
Int_t fVerboseLevel
vector orthogonal to strip direction
Int_t GetStripsAlternative(Double_t nuIn, Double_t nuOut, Double_t Q, Int_t mode, std::vector< Int_t > &indice, std::vector< Double_t > &charges)
Int_t mode
Definition: autocutx.C:47
int strip
Definition: anaMvdDigi.C:135
Double_t GetSkew() const
Double_t
int nrFeChannels
Definition: anaLmdDigi.C:75
Digitization Parameter Class for MVD-Strip part.
SensorSide
std::vector< PndSdsStrip > GetStripsNoDif(Double_t nuIn, Double_t nuOut, Double_t Q)
Double_t CalcFk(Double_t strip, Double_t x, Double_t sig)
friend F32vec4 fabs(const F32vec4 &a)
Definition: P4_F32vec4.h:47
TFile * out
Definition: reco_muo.C:20
double threshold
Int_t CalcChannelfromStrip(Int_t stripNr) const
TVector2 fOrthoDir
vector perpendicular to strip direction
void InjectStripCharge(std::vector< PndSdsStrip > &array, Int_t istrip, Double_t charge)
void CalcFeChToStrip(Int_t fe, Int_t channel, Int_t &strip, enum SensorSide &side) const
Double_t x
Int_t GetNrFECh() const
Double_t GetBotPitch() const
Double_t fOrient
strip pitch (cm)
int fe
Definition: anaLmdDigi.C:67
Double_t GetQCloudSigma() const
double orient
TTree * t
Definition: bump_analys.C:13
Int_t GetNrTopFE() const
Double_t CalcStripFromPoint(Double_t x, Double_t y)
Int_t GetNrBotFE() const
Double_t y
TVector2 fStripDir
Charge diffusion.
TVector2 GetTopAnchor() const
Double_t fThreshold
anchor point on first strip
Double_t Pi
Double_t fNoise
charge threshold
double noise
std::vector< PndSdsStrip > GetStrips(Double_t inx, Double_t iny, Double_t inz, Double_t outx, Double_t outy, Double_t outz, Double_t eLoss)
Double_t GetTopPitch() const
TVector2 fAnchor
Nr of Channels per FE.
Double_t ChargeFromEloss(Double_t eloss) const
PndSdsMCPoint * point
Definition: anaLmdCluster.C:72
void CalcStripPointOnLine(const Double_t strip, TVector2 &point) const