All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups
CCDDigitizer.cc
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 #include "CCDDigitizer.h"
3 #include <iostream>
4 #include <EVENT/LCCollection.h>
5 #include <IMPL/LCRelationImpl.h>
6 #include <EVENT/SimTrackerHit.h>
7 #include <EVENT/MCParticle.h>
8 #include <IMPL/LCFlagImpl.h>
9 #include "random.h"
10 #include "gsl/gsl_sf_erf.h"
11 #include "CLHEP/Random/RandGauss.h"
12 #include "CLHEP/Random/RandPoisson.h"
13 #include "CLHEP/Random/RandFlat.h"
14 
15 
16 // STUFF needed for GEAR
17 #include <marlin/Global.h>
18 #include <gear/GEAR.h>
19 #include <gear/VXDParameters.h>
20 #include <gear/VXDLayerLayout.h>
21 
22 
23 namespace CLHEP{} // declare namespace CLHEP for backward compatibility
24 using namespace CLHEP ;
25 
26 using namespace lcio ;
27 using namespace marlin ;
28 using namespace std ;
29 
30 typedef std::vector<SimTrackerHit*> SimTrackerHitVec;
31 
32 
34 
35 
36 CCDDigitizer::CCDDigitizer() : Processor("CCDDigitizer") {
37 
38  // modify processor description
39  _description = "CCDDigitizer should create VTX TrackerHits from SimTrackerHits" ;
40 
41 
42  // register steering parameters: name, description, class-variable, default value
43 
44 
45  // name of input SimTrackerHit collection
46  // (default parameter value : "vxd01_VXD", taken from Mokka)
47  registerInputCollection( LCIO::SIMTRACKERHIT,
48  "CollectionName" ,
49  "Name of the SimTrackerHit collection" ,
50  _colName ,
51  std::string("vxd01_VXD") ) ;
52 
53 
54  registerOutputCollection( LCIO::TRACKERHIT,
55  "OutputCollectionName" ,
56  "Name of the output TrackerHit collection" ,
58  std::string("VTXTrackerHits") ) ;
59 
60  registerOutputCollection( LCIO::LCRELATION,
61  "RelationColName" ,
62  "Name of the output VTX trackerhit relation collection" ,
64  std::string("VTXRelation") ) ;
65 
66 
67  // cut on the energy of delta-electrons (in MeV)
68  // (default parameter value : 0.03)
69  registerProcessorParameter("CutOnDeltaRays",
70  "Cut on delta-ray energy (MeV)",
72  (double)0.030);
73 
74 
75  // pixel size along direction perpendicular to beam axis (in mm)
76  registerProcessorParameter("PixelSizeX",
77  "Pixel Size X",
79  (double)0.020);
80 
81 
82  // pixel size along beam axis (in mm) <br>
83  registerProcessorParameter("PixelSizeY",
84  "Pixel Size Y",
86  (double)0.020);//0.025
87 
88 
89 
90  registerProcessorParameter("Debug",
91  "Debug option",
92  _debug,
93  int(0));
94 
95 
96  // number of electrons produced per MeV of deposited energy
97  // (default parameter value : 270.3)
98  registerProcessorParameter("ElectronsPerKeV",
99  "Electrons per keV",
101  (double)270.3);
102 
103 
104 
105  std::vector<float> bkgdHitsInLayer;
106  bkgdHitsInLayer.push_back(34400.);
107  bkgdHitsInLayer.push_back(23900.);
108  bkgdHitsInLayer.push_back(9600.);
109  bkgdHitsInLayer.push_back(5500.);
110  bkgdHitsInLayer.push_back(3100.);
111  registerProcessorParameter("BackgroundHitsPerLayer",
112  "Background Hits per Layer",
114  bkgdHitsInLayer);
115 
116 
117  // segment length along track path which is used to subdivide track into segments (in mm).
118  // The number of track subsegments is calculated as int(TrackLengthWithinActiveLayer/SegmentLength)+1
119  //acoording to first tests the default value should be set smaller or at least equal to 0.003
120  registerProcessorParameter("SegmentLength",
121  "Segment Length",
123  double(0.003));
124 
125 
126  // flag to switch on smearing of signal (signal noise)
127  registerProcessorParameter("PoissonSmearing",
128  "Apply Poisson smearing of electrons collected on pixels",
130  1);
131 
132  // flag to switch on gaussian smearing of signal (electronic noise)
133  registerProcessorParameter("ElectronicEffects",
134  "Apply Electronic Effects",
136  int(1));
137 
138 
139  registerProcessorParameter("ElectronicNoise",
140  "electronic noise in electrons",
142  double(100));
143 
144  registerProcessorParameter("Saturation",
145  "maximum number of electrons, which can be stroed in a pixel",
146  _saturation,
147  double(10000));
148 
149 
150  // registerProcessorParameter("AdditionalCollections",
151 // "Additional Collections to store hit position in the local ladder frame",
152 // _produceFullPattern,
153 // int(0));
154 
155  //mean energy loss of MIP per tracklength
156  //(default parameter value 280)
157  registerProcessorParameter("EnergyLoss",
158  "Energy Loss keV/mm",
159  _energyLoss,
160  double(280.0));
161 
162 
163  // flag to switch on additional background signals
164  registerProcessorParameter("GenerateBackground",
165  "Generate Background",
167  int(0));
168 
169 
170  registerProcessorParameter("depletedDepth",
171  "Thickness of depleted zone",
172  depdep,
173  double(0.01));
174 
175 
176  registerProcessorParameter("undepletedDepth",
177  "Thickness of undepleted zone",
178  undep,
179  double(0.01)); // 0.03744 layerthickness
180 
181 
182 
183  registerProcessorParameter("BField",
184  "BField in Tesla",
185  _bfield,
186  (double)4);
187 
188  //Voltage applied on the n layer is used to calculate electric field in depleted zone,this parameter is used only when parameter Electric Field is set to be negative
189  registerProcessorParameter("BiasVolt",
190  "BiasVoltage in V",
191  _biasvolt,
192  (double)10);
193 
194  //electric field in depleted zone
195  //(default parameter value: 10000)
196  registerProcessorParameter("ElectricField",
197  "Electric Field in V/cm",
198  _efield,
199  (double)10000);//when using input biasvoltage, set efield negative
200 
201 
202  registerProcessorParameter("mu",
203  "electrons mobility in depleted zoneat low elcectric fields, in cm^2*V^-1*S^-1",
204  _mu,
205  (double)1400);//value from sinevs code:1340;the paper mentioned in void settanlorentzangle suggested 1417
206 
207 
208  registerProcessorParameter("Temperatur",
209  "Temperatur in Kelvin",
210  _T,
211  (double)250);//220-270 according to Konstantin
212 
213 
214 //default parameter value from sinevs code: 34; value in "Vertex Detectors:The State of the Art and Future Prospect",by Damerell,Dec 95: 34.6 cm^2/s at room temperature
215  registerProcessorParameter("diffusioncoefficient",
216  "diffcoeff in depleted zone in cm^2*S^-1",
217  _difcoef,
218  (double)34);
219 
220 
221 // flag to choose reconstruction method;
222 // method 0: centre of gravity finder for all pixels above threshold
223 // method 1: centre of gravity finder for all pixels within certain distance to the pixel with highest amplitude
224  registerProcessorParameter("reconstructmethod",
225  "reconstruction method",
226  _recmethod,
227  (int)1);//
228 
229  //threshold on charge deposited on one pixel (in electons),only needed reconstruction method 0
230  registerProcessorParameter("Threshold",
231  "Cell Threshold in electrons",
232  _threshold,
233  200.);
234 
235 
236  //maximum distance between pixel within the considered frame and the pixel with highest amplitude
237  //only needed reconstruction method 1
238  registerProcessorParameter("framesize",
239  "size of cluster in reconstruction",
240  _framesize,
241  (int)2);
242 }
243 
244 
245 
246 
247 
248 
250 
251  // usually a good idea to
252  printParameters();
253  // internal parameters
254  PI = (double)acos((double)(-1.0));
255  TWOPI = (double)(2.0)*PI;
256  PI2 = 0.5*PI;
257  _nRun = 0 ;
258  _nEvt = 0 ;
260 
261  sigmacoefficient=0.6;//coefficient for diffusion in undepleted layer; Sinevs default parameter value 0.6
262  epitaxdep=depdep+undep;//thickness of epitaxel layer
263  midpixx=(maxpixx-1)/2;
264  midpixy=(maxpixy-1)/2;
265  stepx= _pixelSizeX / Numstepx;//distance between points at which amplitude of diffusion is calculated within one pixel in x direction
266  stepy= _pixelSizeY / Numstepy;//distance between points at which amplitude of diffusion is calculated within one pixel in y direction
267  xobsoffset= stepx/2;
268  yobsoffset= stepy/2;//offset for positions, so that positions are arranged symmetrically in the pixel
269  maxnionpoint=10000;//maximum number of ionisationpoionts per track
270 
271  if(_efield<0) _efield=_biasvolt/(depdep*0.1);
273  // settanlorentzangleb(_bfield,_efield,_mu,_T);//lorentzangle according to the paper Christian found
274 
275 
276 
277 #ifdef CCD_diagnostics
278  AIDA::IHistogramFactory* pHistogramFactory=marlin::AIDAProcessor::histogramFactory( this );
279 
280  histdist= pHistogramFactory->createHistogram1D( "dist","distance (mm) between rawhits and reconstructed hits",100, 0, 0.05 );
281  histcluster= pHistogramFactory->createHistogram1D("clustersize","number of fired pixels in cluster",20, 0, 20 );
282  histclustxy= pHistogramFactory->createHistogram2D("clustxy","width and heigth of cluster",30,0,15 , 30,0,15 );
283  histcharge= pHistogramFactory->createHistogram1D( "clustcharge","number of electrons per hit",120,0,12000);
284  histdistxy= pHistogramFactory->createHistogram2D("distxy","distance(mm) between rawhits and reconstructed hit (x,y- direction in local coordinates of ladder)",100,-0.05,0.05 , 100,-0.05,0.05 );
285  histNionpoint= pHistogramFactory->createHistogram1D( "numberofionpoints","number of ionisationpoints per hit",30,0,30);
286  // histzcoord= pHistogramFactory->createHistogram1D( "locraw-z-coordinate","locraw-z-coordinate",100,-0.01,+0.01);
287 
288  histenergy= pHistogramFactory->createHistogram1D( "energyloss","energy loss per hit",100,0,10);
289 
290  histsignal= pHistogramFactory->createHistogram1D( "signal","electronnumber per pixel",100,0,500);
291  histsignalframe= pHistogramFactory->createHistogram1D( "signalframe","electronnumber per pixel",100,0,1000);
292 
293  histenergycentre= pHistogramFactory->createHistogram1D( "signalcentre","electronnumber per pixel",100,0,5000);
294 #endif
295 
296 
297  //table
298  // sigmin=0;//minimum sigma for diffusion,is sigma smaller than sigmin, the total charge is stored in the central pixel
299  // sigstep=0.005;
300  // settable();
301  //table//
302 
303  //------Get the geometry from the gear file-----//
304 
305  const gear::VXDParameters& gearVXD = Global::GEAR->getVXDParameters() ;
306  const gear::VXDLayerLayout& layerVXD = gearVXD.getVXDLayerLayout();
307 
308  //number of layers
309  _numberOfLayers = layerVXD.getNLayers();
310 
311  //the number of ladders within layers
313 
314  //Azimuthal offset of the whole structure of each layer.
316 
317  //layer thickness and half-thickness
320 
321  //Distance from the middle of the Si sensor to IP in each layer.
323 
324  //The length of the Si sensor in each layer
326 
327  //The width and half-width of the Si sensor in each layer
330 
331  //The offset of the sensitive area in ladder in each layer
333 
334  // The gaps in z between two subladders within each layer
335  const gear::GearParameters& gearVXDInfra = Global::GEAR->getGearParameters("VXDInfra") ;
336  const std::vector<double> laddergaps = gearVXDInfra.getDoubleVals("LadderGaps");
337  std::cout<<"laddergaps size "<<laddergaps.size()<<std::endl;
338  _layerLadderGap.resize(laddergaps.size());
339 
340  //ladder offset in phi
342 
343  for(int layer = 0; layer < _numberOfLayers; layer++)
344  {
345  _laddersInLayer[layer] = layerVXD.getNLadders(layer);
346 
347 
348  //should half phi be replaced by this from Alexei's original code?
349  _layerHalfPhi[layer] = PI/((double)_laddersInLayer[layer]);
350 
351  _layerThickness[layer] =layerVXD.getSensitiveThickness(layer);
352  _layerHalfThickness[layer] = 0.5*_layerThickness[layer];
353  _layerRadius[layer] =layerVXD.getSensitiveDistance(layer) + 0.5 * _layerThickness[layer];
354  _layerLadderLength[layer] = 2*layerVXD.getSensitiveLength(layer);
355  _layerLadderWidth[layer] = layerVXD.getSensitiveWidth(layer);
356  _layerLadderHalfWidth[layer] = _layerLadderWidth[layer]/2.;
357  _layerActiveSiOffset[layer] = - (layerVXD.getSensitiveOffset(layer));
358  _layerLadderGap[layer] = laddergaps[layer];
359  _layerPhiOffset[layer] = layerVXD.getPhi0(layer);
360  }
361 
362 
363 
364  cout<<" _numberOfLayers "<<_numberOfLayers<<endl;
365  cout<<" _pixelSizeX "<<_pixelSizeX<<endl;
366  cout<<" _pixelSizeY "<<_pixelSizeY<<endl;
367  cout<<" _electronsPerKeV "<<_electronsPerKeV<<endl;
368  cout<<" _segmentDepth "<<_segmentDepth<<endl;
369  cout<<" _currentTotalCharge "<<_currentTotalCharge<<endl;
370  for (int i=0; i<_numberOfLayers; ++i)
371  {
372  cout<<"layer "<<i<<endl;
373  cout<<" _laddersInLayer "<<_laddersInLayer[i]<<endl;
374  cout<<" _layerRadius "<<_layerRadius[i]<<endl;
375  cout<<" _layerLadderLength "<<_layerLadderLength[i]<<endl;
376  cout<<" _layerLadderHalfWidth "<<_layerLadderHalfWidth[i]<<endl;
377  cout<<" _layerPhiOffset "<<_layerPhiOffset[i]<<endl;
378  cout<<" _layerActiveSiOffset "<< _layerActiveSiOffset[i]<<endl;
379  cout<<" _layerHalfPhi "<<_layerHalfPhi[i]<<endl;
380  cout<<" _layerLadderGap "<<_layerLadderGap[i]<<endl;
381  cout<<" _bkgdHitsInLayer "<<_bkgdHitsInLayer[i]<<endl;
382  cout<<" _layerLadderWidth "<<_layerLadderWidth[i]<<endl;
383  cout<<" _layerThickness "<<_layerThickness[i]<<endl;
384 
385  cout<<" _layerHalfThickness "<<_layerHalfThickness[i]<<endl;
386 
387  }
388 
389 }
390 
391 void CCDDigitizer::processRunHeader( LCRunHeader* /*run*/) {
392  _nRun++ ;
393 
394 
395 }
396 
397 void CCDDigitizer::processEvent( LCEvent * evt ) {
398 
399  try{
400  LCCollection * STHcol = evt->getCollection( _colName ) ;
401  // LCFlagImpl flag;
402 // flag.setBit(LCIO::THBIT_MOMENTUM);
403 // STHcol->setFlag(flag.getFlag());
404  LCCollectionVec * THcol = new LCCollectionVec(LCIO::TRACKERHIT);
405  LCCollectionVec * RelCol = new LCCollectionVec(LCIO::LCRELATION);
406  LCCollectionVec * STHLocCol = NULL;
407  LCCollectionVec * THLocCol = NULL;
408  LCCollectionVec * RelLocCol = NULL;
409  if (_produceFullPattern == 1) {
410  STHLocCol = new LCCollectionVec(LCIO::SIMTRACKERHIT);
411  THLocCol = new LCCollectionVec(LCIO::TRACKERHIT);
412  RelLocCol = new LCCollectionVec(LCIO::LCRELATION);
413 
414  }
415 
416 
417  int nSTH = STHcol->getNumberOfElements();
418  // Loop over sim tracker hits;
419 
420  for (int i=0; i<nSTH; ++i) {
421 
422  // std::cout << "Hit number : " << i << std::endl;
423  SimTrackerHit * simTrkHit =
424  dynamic_cast<SimTrackerHit*>(STHcol->getElementAt(i));
425 
426 
427  // do digitization for one SimTrackerHit
428  // Produce ionisation points along track
429 
430 
431  ProduceIonisationPoints( simTrkHit );
432 
433  // std::cout << "End of ProduceIonisationPoints( ) " << std::endl;
434  // std::cout << "Current layer = " << _currentLayer << std::endl;
435  // std::cout << "Total particle momentum = " << totPartMomentum << std::endl;
436 
437  bool accept = _currentLayer >= 0 && _currentLayer < int(_layerRadius.size());
438 
439  if ( accept ) {
440 
441  SimTrackerHitImplVec simTrkHitVec;
442  // Produce fired pixels,ionpoint diffuses to plane
443  ProduceHits( simTrkHitVec );
444 
445  // for (int iHit=0; iHit<int(simTrkHitVec.size()); ++iHit) {
446 // SimTrackerHit * hit = simTrkHitVec[iHit];
447 // //cout<<"hit 1"<<iHit <<" "<<hit->getEDep()<<endl;
448 // }
449 
450 
451 
452  // std::cout << "End of ProduceHits( ) " << std::endl;
453  // Apply Poisson Smearing to deposited charges
454  if (_PoissonSmearing != 0) PoissonSmearer( simTrkHitVec );
455  if (_electronicEffects != 0) GainSmearer( simTrkHitVec );
456  //std::cout << "Amplitude 6 = " << _ampl << std::endl;
457 
458  TrackerHitImpl * recoHit = ReconstructTrackerHit( simTrkHitVec );
459 
460  // std::cout << "End of ReconstructTrackerHit( ) " << std::endl;
461  // if (_produceFullPattern == 1 && recoHit !=0 ) {
462 // SimTrackerHitImpl * sth = new SimTrackerHitImpl();
463 // sth->setCellID(simTrkHit->getCellID0());
464 // sth->setEDep(simTrkHit->getEDep());
465 // double currentPosition[3];
466 // for (int j=0; j<3; ++j)
467 // currentPosition[j] = 0.5*(_currentExitPoint[j] + _currentEntryPoint[j]);
468 // sth->setPosition(currentPosition);
469 // TrackerHitImpl * th = new TrackerHitImpl();
470 // th->setEDep(recoHit->getEDep());
471 // double xp[3];
472 // for (int j=0; j<3; ++j)
473 // xp[j] = recoHit->getPosition()[j];
474 // th->setPosition(xp);
475 // STHLocCol->addElement(sth);
476 // THLocCol->addElement(th);
477 // LCRelationImpl * rel = new LCRelationImpl(th,sth,float(1.0));
478 // RelLocCol->addElement(rel);
479 // }
480 
481  if (recoHit != NULL) {
482  TrackerHitToLab( recoHit );
483  }
484 
485  if (_debug != 0) {
486  if (recoHit == NULL)
487  std::cout << "Number of pixels above threshold = 0 " << std::endl;
488  else
489  PrintInfo( simTrkHit, recoHit );
490  }
491 
492 
493  if ( recoHit != NULL) {
494 
495 
496  recoHit->rawHits().push_back(simTrkHit);
497 
498 
499  float pointResoRPhi=0.004;
500  float pointResoZ=0.004;
501  float covMat[TRKHITNCOVMATRIX]={0.,0.,pointResoRPhi*pointResoRPhi,0.,0.,pointResoZ*pointResoZ};
502  recoHit->setCovMatrix(covMat);
503 
504 
505  recoHit->setType(100+simTrkHit->getCellID0());
506  THcol->addElement( recoHit );
507  // std::cout << "Hit is added to collection " << _nEvt << std::endl;
508  LCRelationImpl * rel = new LCRelationImpl(recoHit,simTrkHit,float(1.0));
509  RelCol->addElement(rel);
510  }
511 // Clean Up
512  for (int i=0; i < int(simTrkHitVec.size()); ++i) {
513  SimTrackerHit * hit = simTrkHitVec[i];
514  delete hit;
515  }
516  }
517  }
518  if (_generateBackground == 1)
519  generateBackground( THcol );
520 
521  evt->addCollection(THcol,_outputCollectionName.c_str());
522  evt->addCollection(RelCol, _colVTXRelation );
523  if (_produceFullPattern == 1) {
524  evt->addCollection(STHLocCol,"VTXLocalSimTrackerHits");
525  evt->addCollection(THLocCol,"VTXLocalTrackerHits");
526  evt->addCollection(RelLocCol,"VTXLocalRelation");
527  }
528  }
529  catch(DataNotAvailableException &e){}
530 
531 
532  _nEvt ++ ;
533 
534  if (_nEvt % 100 == 0)
535  std::cout << "Processed " << _nEvt << "events " << std::endl;
536 
537 }
538 
539 
540 
541 void CCDDigitizer::check( LCEvent * /*evt*/ ) {
542 
543 }
544 
545 
547 
548  delete _fluctuate;
549 
550  std::cout << "CCDDigitizer::end() " << name()
551  << " processed " << _nEvt << " events in " << _nRun << " runs "
552  << std::endl ;
553 }
554 
555 void CCDDigitizer::FindLocalPosition(SimTrackerHit * hit,
556  double * localPosition,
557  double * localDirection) {
558  /** Function calculates local coordinates of the sim hit
559  * in the given ladder and local momentum of particle.
560  * Also returns module number and ladder
561  * number.
562  * Local coordinate system within the ladder
563  * is defined as following : <br>
564  * - x (0) axis lies in the ladder plane and orthogonal to the beam axis <br>
565  * - y (1) axis lies in the ladder plane parallel to beam
566  * - z (2) axis is perpendicular to the ladder plane <br>
567 
568 
569  * Encoding of modules: <br>
570  * ====================== <br>
571  * - 0 = left endcap <br>
572  * - 1 = left ladder in the barrel <br>
573  * - 2 = right ladder in the barrel <br>
574  * - 3 = right endcap <br>
575  *
576  */
577 
578 
579  double xLab[3] = { hit->getPosition()[0],
580  hit->getPosition()[1],
581  hit->getPosition()[2]};
582 
583 
584 
585 
586  int layer = -1;
587 
588 // FIXME : Assume for the moment only barrel in VDX
589 
590 // Find layer number by coordinates
591 
592  double RXY = sqrt(xLab[0]*xLab[0]+
593  xLab[1]*xLab[1]);
594 
595 
596 // layer is encoded in CellID;
597  layer = hit->getCellID0() - 1;
598 
599  _currentLayer = layer;
600 
601 // Check boundary of layers
602  if (layer < 0 || layer > _numberOfLayers-1)
603  return;
604 
605 // Find module by z coordinate
606 // -z : module 1
607 // +z : module 2
608  int module;
609  if (xLab[2] < 0.0 ) {
610  module = 1;
611  }
612  else {
613  module = 2;
614  }
615  _currentModule = module;
616 
617  double Momentum[3];
618 
619  if (hit->getMCParticle()) {
620  for (int j=0; j<3; ++j)
621  Momentum[j] = hit->getMCParticle()->getMomentum()[j];
622  }
623  else {
624  for (int j=0; j<3; ++j) {
625  Momentum[j] = hit->getMomentum()[j];
626  }
627  }
628 
629 
631  if (hit->getMCParticle())
632  _currentParticleMass = hit->getMCParticle()->getMass();
633  if (_currentParticleMass < 0.510e-3)
634  _currentParticleMass = 0.510e-3;
636  for (int i=0; i<3; ++i)
637  _currentParticleMomentum += Momentum[i]*Momentum[i];
639 
640  if(_currentParticleMomentum==0.){
641  for (int i=0; i<3; ++i){
642  Momentum[i] = 0.001;
643  _currentParticleMomentum += Momentum[i]*Momentum[i];
644  }
646 
647  }
648 
649  double PXY = sqrt(Momentum[0]*Momentum[0]+
650  Momentum[1]*Momentum[1]);
651 
652  double PhiInLab = (double)atan2(xLab[1],xLab[0]);
653  if (PhiInLab < 0.0) PhiInLab += TWOPI;
654  double PhiInLabMom = atan2(Momentum[1],Momentum[0]);
655  if (PhiInLabMom < 0.0) PhiInLabMom += TWOPI;
656  double Radius = _layerRadius[layer];
657  // << " Radius = " << Radius << std::endl;
658 
659  double Phi0 = _layerPhiOffset[layer];
660 
661  int nLadders = _laddersInLayer[layer];
662 
663  double dPhi = 2.0*_layerHalfPhi[layer];
664  // And now compute local coordinates
665  // and local momentum of particle
666 
667  double PhiLadder=0;
668  double PhiInLocal=0;
669  //cout<<"nLadders "<<nLadders<<" "<<dPhi<<" "<<Phi0<<" "<<endl;
670 
671 
672  int iLadder=0;
673  for (int ic=0; ic<nLadders; ++ic) {
674  PhiLadder = double(ic)*dPhi + Phi0;
675  PhiInLocal = PhiInLab - PhiLadder;
676  //cout<<"Phi "<<PhiLadder<<" "<<PhiInLocal<<" "<<PhiInLab<<" "<<_layerThickness[layer]<<" "<<Radius<<endl;
677  if (RXY*cos(PhiInLocal)-Radius > -_layerThickness[layer] &&
678  RXY*cos(PhiInLocal)-Radius < _layerThickness[layer]) {
679  iLadder = ic;
680  break;
681  }
682  //cout<<"phi ladder "<<PhiLadder<<endl;
683  }
684  double PhiLocalMom = PhiInLabMom - PhiLadder;
685  localPosition[0] = RXY*sin(PhiInLocal);
686  localPosition[1] = xLab[2];
687  localPosition[2] = RXY*cos(PhiInLocal)-Radius;
688  //geant sometimes (about 1 from 10 times) produces a z coordinate, which is not in the exact centre of the active layer, but which is still in the active layer.
689 
690  localDirection[0]=PXY*sin(PhiLocalMom);
691  localDirection[1]=Momentum[2];
692  localDirection[2]=PXY*cos(PhiLocalMom);
693  _currentPhi = PhiLadder;
694 
695 // if(_debug){
696 // cout<<"x: "<<localPosition[0]<<" ";
697 // cout<<"y: "<<localPosition[1]<<" ";
698 // cout<<"z: "<<localPosition[2]<<" "<<endl;
699 
700 #ifdef CCD_diagnostics
701  for(int i=0;i<3;i++){
702  dirraw[i]=localDirection[i];
703  posraw[i]=localPosition[i];
704  }
705 #endif
706 
707 }
708 
709 
710 
711 
712 
713 void CCDDigitizer::TransformToLab(double * xLoc, double * xLab) {
714  /** Function transforms local coordinates in the ladder
715  * into global coordinates
716  */
717 
718  int layer = _currentLayer;
719  double Phi = _currentPhi;
720  double Radius = _layerRadius[layer];
721 
722 
723  double baseLine = Radius + xLoc[2];
724  double PhiInLab = Phi + atan2(xLoc[0],baseLine);
725  double RXY = sqrt(baseLine*baseLine+xLoc[0]*xLoc[0]);
726  xLab[2] = xLoc[1];
727  xLab[0] = RXY*cos(PhiInLab);
728  xLab[1] = RXY*sin(PhiInLab);
729 
730 }
731 
732 void CCDDigitizer::ProduceIonisationPoints( SimTrackerHit * hit) {
733  /** Produces ionisation points along track segment within active Silicon layer.
734  */
735  //std::cout << "Amplitude 1 = " << _ampl << std::endl;
736  // Position of hit in the Lab frame
737  double pos[3];
738  double dir[3];
739  // double dir[3];
740 
741 
742  // Find local position in the ladder frame
743  FindLocalPosition( hit, pos, dir);
744  // std::cout << "End of FindLocalPosition" << std::endl;
745 
746  // check layer boundaries
747  if (_currentLayer < 0 || _currentLayer > _numberOfLayers)
748  return;
749 
750 
751 
752 
753  double tanx = dir[0]/dir[2];
754  double tany = dir[1]/dir[2];
755  double trackLength = min(10.,epitaxdep*sqrt(1.0+tanx*tanx+tany*tany));
756  // double trackLength = min(1.0e+3,_layerThickness[_currentLayer]*sqrt(1.0+tanx*tanx+tany*tany));//code without bulk
757 
758  double dEmean = 1e-6*_energyLoss * trackLength;
759 
760 
761  // dEmean = hit->getEDep()/((double)_numberOfSegments);
762 
763 
764  _numberOfSegments = int(trackLength/_segmentLength) + 1;
765 
766  dEmean = dEmean/((double)_numberOfSegments);
767 // if(_numberOfSegments>1000) cout <<"check1000,ionpointnumber: "<< _numberOfSegments<<endl;
768 // if(_numberOfSegments>500) cout <<"check500,ionpointnumber: "<< _numberOfSegments<<endl;
769 // if(_numberOfSegments>100) cout <<"check100,ionpointnumber: "<< _numberOfSegments<<endl;
772  dEmean = hit->getEDep()/((double)_numberOfSegments)*epitaxdep/_layerThickness[_currentLayer];
773  }
774 
775 
776 #ifdef CCD_diagnostics
779 #endif
780 
781 
782 
784 
785  double segmentLength = trackLength/((double)_numberOfSegments);
787  //_segmentDepth =_layerThickness[_currentLayer]/((double)_numberOfSegments);//code without bulk
788 
789 #ifdef CCD_diagnostics
790  double energy=0;
791 #endif
792 
793 
794 
795  for (int i=0; i<_numberOfSegments; ++i) {
796  double z = (_layerHalfThickness[_currentLayer]-epitaxdep) + ((double)(i)+0.5)*_segmentDepth;
797  // double z = - _layerHalfThickness[_currentLayer] + ((double)(i)+0.5)*_segmentDepth;//code without bulk
798  double x = pos[0]+dir[0]*(z-pos[2])/dir[2];
799  double y = pos[1]+dir[1]*(z-pos[2])/dir[2];
800  IonisationPoint ipoint;
801  double de = _fluctuate->SampleFluctuations(double(1000.*_currentParticleMomentum),
802  double(1000.*_currentParticleMass),
803  _cutOnDeltaRays,segmentLength,
804  double(1000.*dEmean))/1000.;
805  // if(_debug) std::cout << "segment " << i << " dE = " << de << std::endl;
806 #ifdef CCD_diagnostics
807  energy+=1e+6*de;
808 #endif
809 
810  ipoint.eloss = de;
811  ipoint.x = x;
812  ipoint.y = y;
813  ipoint.z = z;
814  _ionisationPoints[i] = ipoint;
815  }
816 
817 
818 #ifdef CCD_diagnostics
819  energy=energy/(trackLength)*epitaxdep;
820  histenergy->fill(energy,1);
821 #endif
822 
823  //std::cout << "Amplitude = " << _ampl << std::endl;
824 
825 }
826 
827 
829  // Produces signal points on the collection plane.
830 
831  double TanLorentzX = TanLorentzAngle;
832  double TanLorentzY = 0;
833 
834  //loop over all ionisisationpoints of the hit
835  for(int i=0; i<_numberOfSegments; i++) {
837  double z = ipoint.z;
838  double x = ipoint.x;
839  double y = ipoint.y;
840  double energy=ipoint.eloss;
841  // if(_debug)cout<<"x: "<<x<<" y: "<<y<< "z: "<<z<<" energy "<< energy<<endl;
842 
843 
844 
845  //distance to plane,where charge is accumulated
846  double distancetoplane;
847  distancetoplane = _layerHalfThickness[_currentLayer] - z;
848 
849 
850  double xdif, ydif;//distance between position of hit and edge of pixel
851  int xcell, ycell;//number of rows and columns of pixel,in which the ionpoint is located
852 
853  //check in which area ionpoint is located
854 
855  // // //if the ionpoint is in the bulk, no charge is deposited in detector
856 // if(distancetoplane>epitaxdep){
857 // continue;
858 // }
859 
860 
861  //in undepleted zone: reflected and direct part contributes to charge in pixel, both parts are weighted by a factor depending on distance to the undepleted zone
862  // the diffusion in the depleted zone is neglected for that part
863  if(distancetoplane<=epitaxdep && distancetoplane>depdep){
864 
865  x+= TanLorentzX*depdep;//magnetic effects in undepleted zone are neglected
866  y+= TanLorentzY*depdep;
867 
868  double sigmadirect= sigmacoefficient*(distancetoplane-depdep);
869  double sigmareflect=sigmacoefficient*(2*undep-(distancetoplane-depdep));
870  double weight=(distancetoplane-depdep)/undep;
871  //assuming a linear relation between distance to plane and probability that charge reaches reflecting plane first
872  //reflectionprocesses of higher order are neglected
873 
874 
875  // double ** spxl;
876 // spxl= new double* [maxpixx];
877 // for(int i=0;i<maxpixx;i++) spxl[i]=new double [maxpixy];
878  double spxl[maxpixx][maxpixy];
879  //array for summation of direct and reflected parts
880 
881  TransformXYToCellID(x, y, xcell, ycell, xdif, ydif);
882 
883  diffusion(xdif, ydif,sigmadirect);
884  //diffusiontable(xdif, ydif,sigmadirect);
885 
886  for(int i=0;i<maxpixx;i++){
887  for(int k=0;k<maxpixy;k++){
888 
889  spxl[i][k]= (1-weight) * pxl[i][k];
890  }
891  }
892 
893  diffusion(xdif, ydif,sigmareflect);
894  //diffusiontable(xdif, ydif,sigmareflect);
895  for(int i=0;i<maxpixx;i++){
896  for(int k=0;k<maxpixy;k++){
897  pxl[i][k]= spxl[i][k]+ weight * pxl[i][k];
898  }
899  }
900  // delete spxl;
901  }
902 
903  //in undepleted zone the width of the diffusion depends on the traveltime of the charge
904  if(distancetoplane<=depdep){
905 
906  x+= TanLorentzX*distancetoplane;
907  y+= TanLorentzY*distancetoplane;
908 
909  double trt=(distancetoplane*0.1)/(_mu*_efield);// trt in s,convert distance into cm
910 
911  // double sigma=1.375*sqrt(_difcoef*trt)*10;// convert in mm with a factor 10, according to gear data;Sinevs formular
912  double sigma=sqrt(2*_difcoef*trt)*10;// convert in mm with a factor 10, according to gear data;formular taken from "Vertex Detectors:The State of the Art and Future Prospects",by Damerell,Dec 95
913 
914  TransformXYToCellID(x, y, xcell, ycell, xdif, ydif);
915 
916  diffusion(xdif, ydif,sigma);
917  //diffusiontable(xdif, ydif,sigma);
918  }
919 
920 
921  //the values of the charge distribution are stored in pxl
922  // now add the values of pxl to the list of fired pixel
923 
924  double ladderwidth = _layerLadderWidth[_currentLayer];
925  double Numladderpixx=(int)(ladderwidth/_pixelSizeX);
926  double ladderlength = _layerLadderLength[_currentLayer];
927  double Numladderpixy=(int)(ladderlength/_pixelSizeY);
928 
929 
930  for (int i = 0; i<maxpixx; i++) {
931  int ix=i+xcell-midpixx;
932  // if(_debug)cout<<ix<<","<<endl;
933 
934  if (ix >= 0 && ix<=Numladderpixx) {//test, whether pixel exists
935 
936  for (int k = 0; k<maxpixy; k++) {
937  int iy=k+ycell-midpixy;
938  if (iy >=0 && iy<=Numladderpixy) {
939 
940 
941  double charge=(1e+6*energy*_electronsPerKeV) *pxl[i][k];
942  // if(_debug)cout<<"charge " <<i<<" "<<k<<" "<<charge<<endl;
943  int iexist = 0;
944 
945  // double xCurrent,yCurrent;
946  // TransformCellIDToXY(ix,iy,xCurrent,yCurrent);
947 
948  int currentcellid = 100000*ix + iy;
949  SimTrackerHitImpl * existingHit = 0;
950 
951  for (int iHits=0; iHits<int(vectorOfHits.size()); ++iHits) {
952  existingHit = vectorOfHits[iHits];
953  int cellid = existingHit->getCellID0();
954  if (cellid == currentcellid) {
955  iexist = 1;
956  break;
957  }
958  }
959  if (iexist == 1) {
960  float edep = existingHit->getEDep();
961  edep += charge;
962  existingHit->setEDep( edep );
963  }
964  else {
965  SimTrackerHitImpl * hit = new SimTrackerHitImpl();
966 
967  // double pos[3] = {xCurrent, yCurrent, 0};
968  // hit->setPosition( pos );
969 
970  hit->setCellID0( currentcellid );
971  hit->setEDep( charge );
972  vectorOfHits.push_back( hit );
973  }
974  }
975  }
976  }
977  }
978  }
979 }
980 
981 
982 void CCDDigitizer::TransformXYToCellID(double x, double y,
983  int & ix,
984  int & iy,double & xdif, double & ydif) {
985  /**
986  * Function calculates position in pixel matrix based on the
987  * local coordinates of point in the ladder. Also calculates
988  * the position within this pixel.
989  */
990 
991  int layer = _currentLayer;
992  double ladderGap = _layerLadderGap[layer];
993  double ladderLength = _layerLadderLength[layer];
994 
995  double yInLadder = 0.0;
996  if (y < 0.0) {
997  yInLadder = y + ladderLength;
998  }
999  else {
1000  yInLadder = y - ladderGap;
1001  }
1002 
1003 
1004  iy = int(yInLadder/_pixelSizeY);//position in pixelmatrix
1005  ydif= yInLadder-(((double)iy)*_pixelSizeY); // position within the pixel
1006 
1007  double xInLadder = 0.0;
1008 
1009  xInLadder = x + _layerLadderHalfWidth[layer] + _layerActiveSiOffset[layer];
1010 
1011  ix = int(xInLadder/_pixelSizeX);
1012  xdif= xInLadder-(((double)ix)*_pixelSizeX);
1013 
1014 }
1015 
1017  double & x, double & y) {
1018 
1019  /**
1020  Function calculates position in the local frame
1021  based on the index of pixel in the ladder.
1022  */
1023 
1024  int layer = _currentLayer;
1025  int module = _currentModule;
1026  double ladderGap = _layerLadderGap[layer];
1027  double ladderLength = _layerLadderLength[layer];
1028 
1029  y = (0.5+double(iy))*_pixelSizeY;
1030 
1031  if (module == 1)
1032  y = -ladderLength + y;
1033  else
1034  y = ladderGap + y;
1035 
1036  x = (0.5+double(ix))*_pixelSizeX;
1037 
1038  x = x - _layerLadderHalfWidth[layer] - _layerActiveSiOffset[layer];
1039 
1040 }
1041 
1042 
1044 /**
1045  * Function that fluctuates charge (in units of electrons)
1046  * deposited on the fired pixels according to the Poisson
1047  * distribution...
1048  */
1049 
1050  for (int ihit=0; ihit<int(simTrkVec.size()); ++ihit) {
1051  SimTrackerHitImpl * hit = simTrkVec[ihit];
1052  double charge = hit->getEDep();
1053  double rng;
1054  if (charge > 1000.) { // assume Gaussian
1055  double sigma = sqrt(charge);
1056  rng = double(RandGauss::shoot(charge,sigma));
1057  hit->setEDep(rng);
1058  }
1059  else { // assume Poisson
1060  rng = double(RandPoisson::shoot(charge));
1061  }
1062  hit->setEDep(float(rng));
1063  }
1064 }
1065 
1067 /**
1068  * Simulation of electronic noise.
1069  */
1070 
1071  int nPixels = int( simTrkVec.size() );
1072  // std::cout << "Gain smearer applied" << std::endl;
1073 
1074  for (int i=0;i<nPixels;++i) {
1075  double Noise = RandGauss::shoot(0.,_electronicNoise);
1076  SimTrackerHitImpl * hit = simTrkVec[i];
1077  double charge = hit->getEDep() + Noise ;
1078  if (charge> _saturation) charge = _saturation;
1079  hit->setEDep( charge );
1080  }
1081 
1082 }
1083 
1084 
1086  /**
1087  * Emulates reconstruction of Tracker Hit
1088  * Position is corrected for Lorentz shift.
1089  */
1090 
1091  // new Tracker Hit
1092  double pos[3] = {0,0,0};
1093  double charge = 0;
1094 
1095 
1096  //generic centre of gravity finder for all pixels above threshold
1097  if(_recmethod==0){
1098  for (int iHit=0; iHit<int(simTrkVec.size()); ++iHit) {
1099  SimTrackerHit * hit = simTrkVec[iHit];
1100 
1101  // if(_debug) cout<<"hit "<<iHit <<" "<<hit->getEDep()<<endl;
1102  // if(_debug) cout<< "edep: "<< hit->getEDep()<<endl;
1103  //istsignal->fill(hit->getEDep(),1);
1104 
1105  if (hit->getEDep() > _threshold) {
1106  charge+= hit->getEDep();
1107 
1108 
1109  int cellID = hit->getCellID0();
1110  int ix = cellID / 100000 ;
1111  int iy = cellID - 100000 * ix;
1112  double xCurrent,yCurrent;
1113  TransformCellIDToXY(ix,iy,xCurrent,yCurrent);
1114  pos[0]+=xCurrent* hit->getEDep();
1115  pos[1]+=yCurrent* hit->getEDep();
1116 
1117  // for (int j=0; j<2; ++j){
1118  // pos[j] += hit->getEDep()*hit->getPosition()[j];
1119  }
1120 
1121  }
1122  }
1123 
1124  //looks for the pixel with highest amplitude and computes centre of gravity within a certain grid around this pixel
1125  if(_recmethod==1){
1126 
1127  int xcentre=-10000;
1128  int ycentre=-10000;
1129  double emax=0;
1130 
1131  for (int iHit=0; iHit<int(simTrkVec.size()); ++iHit) {
1132  SimTrackerHit * hit = simTrkVec[iHit];
1133 
1134  if (hit->getEDep() > emax) {
1135  emax=hit->getEDep();
1136  int cellID = hit->getCellID0();
1137  xcentre = cellID / 100000 ;
1138  ycentre = cellID - 100000 * xcentre;
1139  }
1140  }
1141 #ifdef CCD_diagnostics
1142  histenergycentre->fill(emax,1);//number of electrons in pixel with highest amplitude
1143 #endif
1144 
1145  for (int iHit=0; iHit<int(simTrkVec.size()); ++iHit) {
1146  SimTrackerHit * hit = simTrkVec[iHit];
1147 
1148  int cellID = hit->getCellID0();
1149  int ix = cellID / 100000 ;
1150  int iy = cellID - 100000 * ix;
1151 
1152  bool inframe = (abs(ix-xcentre) < _framesize) && (abs(iy-ycentre) < _framesize);
1153  if (inframe) {
1154 
1155  charge+= hit->getEDep();
1156  double xCurrent,yCurrent;
1157  TransformCellIDToXY(ix,iy,xCurrent,yCurrent);
1158  pos[0]+=xCurrent* hit->getEDep();
1159  pos[1]+=yCurrent* hit->getEDep();
1160 
1161 #ifdef CCD_diagnostics
1162  double a=hit->getEDep();
1163  histsignalframe->fill(a,1);
1164 #endif
1165  }
1166 
1167  }
1168 
1169  }
1170 
1171 
1172  if(charge>0){
1173  TrackerHitImpl * recoHit = new TrackerHitImpl();
1174  recoHit->setEDep( charge );
1175  for (int j=0; j<2; ++j)
1176  pos[j]/=charge;
1177 
1178 
1179 
1180 
1181  //correction due to magnetic effects (shift of depdep weighted by undep,shift of depdep/2 is weighted by depdep)
1182  double tanXLorentz = TanLorentzAngle;
1183  double meanlorentzdepth= ((undep*depdep)+depdep*(depdep/2))/(undep+depdep);
1184 
1185  pos[0] = pos[0] - meanlorentzdepth * tanXLorentz;
1186 
1187 
1188  // cout<<"xuncor: "<<pos[0]<<" ";
1189 // cout<<"yuncor: "<<pos[1]<<" ";
1190 // cout<<"zuncor: "<<pos[2]<<" "<<endl;
1191 
1192 
1193  // correction of z coordinate,because of the bulk:
1194  double bulkthickness= _layerThickness[_currentLayer] - epitaxdep;
1195  pos[2] += bulkthickness/2;
1196 
1197 
1198 #ifdef CCD_diagnostics
1199  //shift along the track back to direction initial interaction plane to make results comparable
1200  double shift[3];
1201  shift[2]=-bulkthickness/2;
1202 
1203  for (int i=0; i<2; ++i) {
1204  if (dirraw[2]!=0)
1205  shift[i]=(dirraw[i]/dirraw[2])*shift[2];
1206  }
1207 
1208  for (int i=0;i<3;i++){
1209  pos[i]+=shift[i];
1210  }
1211 
1212  // cout<<"xcor: "<<pos[0]<<" ";
1213 // cout<<"ycor: "<<pos[1]<<" ";
1214 // cout<<"zcor: "<<pos[2]<<" "<<endl;
1215 
1216 
1217  int ixmin = 1000000;
1218  int ixmax = -1000000;
1219  int iymin = 1000000;
1220  int iymax = -1000000;
1221  int nPixels=0;
1222 
1223 
1224  for (int iHit=0; iHit<int(simTrkVec.size()); ++iHit) {
1225  SimTrackerHit * hit = simTrkVec[iHit];
1226  if (hit->getEDep() > _threshold) {
1227  nPixels++;
1228 
1229  int cellID = hit->getCellID0();
1230  int ix = cellID / 100000 ;
1231  int iy = cellID - 100000 * ix ;
1232 
1233  if (ix > ixmax)
1234  ixmax = ix;
1235  if (ix < ixmin)
1236  ixmin = ix;
1237  if (iy > iymax)
1238  iymax = iy;
1239  if (iy < iymin)
1240  iymin = iy;
1241 
1242  }
1243  }
1244 
1245  int xwidth=ixmax-ixmin+1;
1246  int ywidth=iymax-iymin+1;
1247 
1248  // cout<<"xmin "<< ixmin<<" xmax "<<ixmax<<endl;
1249 // cout <<"xwidth: "<<xwidth<<" "<<"ywidth "<<ywidth<<endl;
1250 
1251 
1252 
1253 // cout<<"npixels:" << nPixels<<endl;
1254 // cout<<"charge: " <<charge<<endl;
1255  // cout<<"posraw: " <<posraw[0]<<" ,"<<posraw[1]<<", "<<posraw[2]<<endl
1256  // <<"posreco: "<<pos[0]<<" ,"<<pos[1]<<", "<<pos[2]<<endl
1257  // <<"numberofionpoints: "<<Nionpoint<<endl;
1258 
1259 
1260 
1261  // cout<<"clustxy: "<<xwidth<<", "<<ywidth<<endl;
1262  histclustxy->fill(xwidth,ywidth,1);//maximum distance between two pixels above threshold
1263  // cout<<"firedpixelnumber: "<<nPixels<<endl;
1264  histcluster->fill(nPixels,1);//number of pixels above threshold
1265  // cout<<"charge: "<<charge<<endl;
1266  histcharge->fill(charge,1);//collected electrons per hit
1267  double dist=sqrt(pow(posraw[0]-pos[0],2)
1268  +pow(posraw[1]-pos[1],2)
1269  +pow(posraw[2]-pos[2],2));
1270  // cout<<"dist: "<<dist<<endl;
1271  histdist->fill(dist,1);
1272 
1273  double distx=posraw[0]-pos[0];
1274  double disty=posraw[1]-pos[1];
1275  //cout<<"histdistxy: "<<distx<<" ,"<<disty<<endl;
1276  histdistxy->fill(distx,disty,1);
1277  // histzcoord->fill(posraw[2],1);
1278 
1279 
1280 
1281  // if(dist>0.1){
1282 // cout<<" dist>0.1"<<endl;
1283 
1284 // cout<<"dist "<<dist<<endl<<"ionpoints "<<Nionpoint<<endl;
1285 // cout<<"modul "<<_currentModule<<endl;
1286 // cout<<"clustxy: "<<xwidth<<", "<<ywidth<<endl;
1287 // cout<<"xcor: "<<pos[0]<<" ";
1288 // cout<<"ycor: "<<pos[1]<<" ";
1289 // cout<<"zcor: "<<pos[2]<<" "<<endl;
1290 // cout<<"xuncor: "<<pos[0]<<" ";
1291 // cout<<"yuncor: "<<pos[1]<<" ";
1292 // cout<<"zuncor: "<<pos[2]<<" "<<endl;
1293 // cout<<"posraw: " <<posraw[0]<<" ,"<<posraw[1]<<", "<<posraw[2]<<endl;
1294  // char q = getchar();
1295  // }
1296 
1297 #endif
1298 
1299 
1300  recoHit->setPosition( pos );
1301  return recoHit;
1302  }
1303 
1304  else
1305  return NULL;
1306 
1307 }
1308 
1309 
1310 void CCDDigitizer::TrackerHitToLab( TrackerHitImpl * recoHit) {
1311 
1312  double pos[3];
1313  for (int i=0; i<3; ++i)
1314  pos[i] = recoHit->getPosition()[i];
1315 
1316  double xLab[3];
1317  TransformToLab( pos, xLab);
1318 
1319  recoHit->setPosition( xLab );
1320 
1321 
1322 }
1323 
1324 void CCDDigitizer::PrintInfo( SimTrackerHit * simHit, TrackerHitImpl * recoHit) {
1325 
1326  std::cout << std::endl;
1327 
1328  std::cout << "Simulated hit position = "
1329  << " " << simHit->getPosition()[0]
1330  << " " << simHit->getPosition()[1]
1331  << " " << simHit->getPosition()[2] << std::endl;
1332 
1333  std::cout << "Reconstructed hit position = "
1334  << " " << recoHit->getPosition()[0]
1335  << " " << recoHit->getPosition()[1]
1336  << " " << recoHit->getPosition()[2]
1337  << " total number of electrons " << recoHit->getEDep() <<std::endl;
1338 
1339 
1340  std::cout << std::endl;
1341  std::cout << "Type Q to exit display mode" << std::endl;
1342  char q = getchar();
1343  if (q=='q' || q=='Q')
1344  _debug = 0;
1345 }
1346 
1347 
1349 
1350  for (int ilayer=0;ilayer<_numberOfLayers;++ilayer) {
1351  double mean = _bkgdHitsInLayer[ilayer];
1352  int nHits = int(RandPoisson::shoot(mean));
1353  for (int ihit=0;ihit<nHits;++ihit) {
1354  double pos[3];
1355  pos[0] = RandFlat::shoot(_layerLadderWidth[ilayer]);
1356  pos[1] = _layerLadderGap[ilayer] + RandFlat::shoot(_layerLadderLength[ilayer]);
1357  pos[2] = 0.0;
1358  if (RandFlat::shoot(double(1.)) > 0.5) {
1359  pos[1] = -pos[1];
1360  }
1361  pos[0] = pos[0] - _layerLadderHalfWidth[ilayer] - _layerActiveSiOffset[ilayer];
1362  _currentLayer = ilayer;
1363  double xLadders = _laddersInLayer[ilayer];
1364  double Phi0 = _layerPhiOffset[ilayer];
1365  double dPhi = 2.0*_layerHalfPhi[ilayer];
1366  int nPhi = int(RandFlat::shoot(xLadders));
1367  _currentPhi = - PI2 + double(nPhi)*dPhi + Phi0;
1368  double xLab[3];
1369  TransformToLab(pos,xLab);
1370  TrackerHitImpl * trkHit = new TrackerHitImpl();
1371  trkHit->setPosition( xLab );
1372  trkHit->setEDep(1000.);
1373  trkHit->setType(ilayer+1);
1374  col->addElement( trkHit );
1375  }
1376 
1377  }
1378 
1379 }
1380 
1381 void CCDDigitizer::diffusion(double xdif,double ydif, double sigma){
1382 
1383  //function computes the part of charge, which diffuses in each pixel of a maxpixx*maxpixy- array
1384  //it computes a dampfactor(dependent on the distance between ionpoint and observatiopoint (in the xy plane) and the functionparameter sigma) (sinev) for Numstepx*Numstepy observationpoints in each pixel and summarizes them (the distribution is approximated by discrete points); after that values are normed
1385 
1386  double xobs0,yobs0,xobs,yobs,sum,damp,dist,distsquare;
1387 
1388  double xhit=xdif+(midpixx * _pixelSizeX);
1389  double yhit=ydif+(midpixy * _pixelSizeY);
1390  double norm=0;
1391  double twosigmasquare=2*sigma*sigma;
1392 
1393  for(int xpix=0;xpix<maxpixx;xpix++){
1394  xobs0=xpix* _pixelSizeX + xobsoffset;
1395 
1396  for(int ypix=0;ypix<maxpixy;ypix++){
1397  yobs0=ypix*_pixelSizeY+ yobsoffset;
1398  sum=0;
1399 
1400  for(int i=0;i<Numstepx;i++){
1401  xobs=xobs0+i*stepx;
1402 
1403  for(int k=0;k<Numstepx;k++){
1404  yobs=yobs0+k*stepy;
1405 
1406  distsquare=(xobs-xhit)*(xobs-xhit)+(yobs-yhit)*(yobs-yhit);
1407  dist=sqrt(distsquare);
1408  damp=exp(-distsquare/twosigmasquare)/dist;
1409  sum+=damp;
1410  }
1411 
1412  }
1413 
1414  pxl[xpix][ypix]=sum;
1415  norm+=sum;
1416  // cout<<"norm: "<<norm<<endl;
1417 
1418  }
1419 
1420  }
1421  for (int i=0;i<maxpixx;i++){
1422  for(int k=0;k<maxpixy;k++){
1423  pxl[i][k]/=norm;
1424  // if(_debug)cout <<"pxl "<<i<<k<<" "<<pxl[i][k]<<endl;
1425  }
1426 
1427  }
1428 
1429 }
1430 
1431 
1432 
1433 void CCDDigitizer::settanlorentzangleb (double B,double E,double mu,double T){
1434 
1435 
1436 /* sets lorentzangle for depleted zone
1437 
1438  taken from sinevs code:
1439  Lorentz angle is calculated according to parametrisation given by
1440  T.Lari (INFN, ATLAS Pixel Collaboration) in February of 2003 talk
1441  Strictly speaking this parametrization is valid only for the
1442  silicon with cariers mobility cited in the above talk
1443  ( 1920. cm**2V**-1S**-1)
1444 
1445 
1446 
1447  B - b field in Tesla
1448  E - electric field in V/cm
1449  mu - initial carriers mobility in cm**2 x V**-1 x S**-1
1450  T - temperature (in Kelvin)
1451 */
1452 
1453  double exp2=1.55;
1454  double exp3=0.66;
1455  double Ec0 = 6030.;
1456  double r = 1.13 + 0.0008 * (T - 273.);
1457  double beta = 1.04 * pow(T/273.0 ,exp3);
1458 
1459  double Ec = Ec0 * pow(T/273.0 ,exp2);
1460  double mud = mu / pow((1.+pow(E/Ec,beta)),1./beta);
1461  TanLorentzAngle = 0.0001 * r * mud *B;
1462  // cout<<"beta"<<beta<<endl;
1463 // cout<<"Ec= "<<Ec<<endl;
1464  cout<<"lorentzangle"<<TanLorentzAngle<<endl;
1465 
1466 }
1467 
1468 void CCDDigitizer::settanlorentzangle (double B,double E,double mu,double T){
1469 
1470 
1471 /* sets lorentzangle for depleted zone
1472 
1473  //according to a paper Kristian Harder found
1474 
1475 
1476  B - b field in Tesla
1477  E - electric field in V/cm
1478  mu - initial carriers mobility(at low electric field) in cm**2 x V**-1 x S**-1
1479  T - temperature (in Kelvin)
1480 */
1481 
1482  double exp2=0.87;
1483  double exp3=0.66;//equal to sinevs value
1484  double r = 1.15;//similar to sinev value
1485  double beta = 1.109 * pow(T/300.0 ,exp3);//similar to sinevs formular
1486  // double mulow=1417*pow((T/300),-2.2);
1487 
1488  double vsat =1.07e+7 * pow((T/300),exp2);
1489  double mud = mu / pow((1.+pow(E*mu/vsat,beta)),1./beta);
1490  TanLorentzAngle = 0.0001 * r * mud *B;
1491  // double Ec=vsat/mu;
1492  // cout<<"Ec= vsat/mu= "<<Ec<<endl;
1493 // cout<<"beta"<<beta<<endl;
1494  cout<<"lorentzangle "<<TanLorentzAngle<<endl;
1495 
1496 }
1497 
1498 /*
1499 
1500 I started to create a lookuptable to decrease computing time. this part is not debugged. it should reduce computing time to 70% of the time needed without.
1501 void CCDDigitizer::settable(){
1502 
1503  //creates a lookuptable for diffusionprocess
1504 
1505  int maxx= ((midpixx+2)* Numstepx)+1;
1506  int maxy= ((midpixy+2)* Numstepy)+1;
1507 
1508  for(int isigma=0; isigma<numsigstep;isigma++){
1509 
1510  double norm=0;
1511  double sigma= sigmin+sigstep*isigma;
1512  double twosigmasquare=2*sigma*sigma;
1513 
1514  double ** htable;
1515  htable= new double* [maxx];
1516  for(int i=0;i<maxx;i++) htable[i]=new double [maxy];
1517 
1518  for(int i=0;i<maxx;i++){
1519  for(int k=0;k<maxy;k++){
1520 
1521  double distsquare=pow(( i* stepx)-xobsoffset,2)+pow(( k* stepy-yobsoffset),2);
1522  double dist=sqrt(distsquare);
1523  htable[i][k]=exp(-distsquare/twosigmasquare)/dist;
1524  }
1525  }
1526 
1527  for(int i=0; i<numhitstepx ;i++){
1528  for(int k=0 ;i<numhitstepy ;k++){
1529  for(int ipixx=0;ipixx<maxpixx;ipixx++){
1530  for(int ipixy=0;ipixy<maxpixy;ipixy++){
1531 
1532  double sum=0;
1533 
1534  cout<<"t " <<i +( (ipixx-midpixx)*Numstepx)<< "y "<<k + (ipixy-midpixy) * Numstepy <<endl;
1535 
1536  for(int x=0;x<Numstepx;x++){
1537  for(int y=0;y<Numstepy;y++){
1538  // cout<<"t " <<i +( (ipixx-midpixx)*Numstepx) +x<< "y "<<k + (ipixy-midpixy) * Numstepy + y<<endl;
1539  sum+=htable[abs(i +( (ipixx-midpixx)*Numstepx) +x)][abs(k +( (ipixy-midpixy) * Numstepy) + y)];
1540 
1541  }
1542  }
1543  table[isigma][i][k][ipixx][ipixy]=sum;
1544  norm+=sum;
1545  }
1546 
1547  }
1548  for (int ipixx=0;ipixx<maxpixx;ipixx++){
1549  for(int ipixy=0;ipixy<maxpixy;ipixy++){
1550  table[isigma][i][k][ipixx][ipixy]/=norm;
1551  }
1552  }
1553  }
1554  }
1555  delete htable;
1556  }
1557 }
1558 
1559 void CCDDigitizer::diffusiontable(double xdif, double ydif,double sigma){
1560 
1561 
1562  //the diffusionprocess using the lookuptable
1563 
1564  if(sigma<sigmin){
1565  for (int i=0;i<maxpixx;i++){
1566  for(int k=0;k<maxpixy;k++){
1567  pxl[i][k]=0;
1568  }
1569  }
1570  pxl[midpixx][midpixy]=1;
1571  }
1572  else{
1573 
1574  bool mirrowx=0;
1575  bool mirrowy=0;
1576  double pix [maxpixx][maxpixy];
1577  //double ** pix;
1578  //pix= new double* [maxpixx];
1579  //for(int i=0;i<maxpixx;i++) pix[i]=new double [maxpixy];
1580 
1581  if(xdif> 0.5*_pixelSizeX){
1582  mirrowx=1;
1583  xdif=_pixelSizeX-xdif;
1584  }
1585  if(ydif> 0.5*_pixelSizeY){
1586  mirrowy=1;
1587  ydif=_pixelSizeY-ydif;
1588  }
1589 
1590  int xhit=(int)(xdif/stepx);
1591  double xweight=(xdif-xhit)/stepx;
1592  int yhit=(int)(ydif/stepy);
1593  double yweight=(xdif-xhit)/stepx;
1594 
1595  int isigma=(int)((sigma-sigmin)/sigstep);
1596  double sigweight= sigma-(isigma*sigstep);
1597  // if (sigma<sigmin){
1598  // isigma=0;
1599  // }
1600 
1601  if (sigma>(sigmin+(numsigstep*sigstep))){
1602  isigma=numsigstep;
1603  sigweight=0;
1604  }
1605 
1606  for(int x=0;x<maxpixx;x++){
1607  for(int y=0;y<maxpixy;y++){
1608 
1609  double x_y =table[isigma][xhit] [yhit] [x][y];
1610  double xp_y =table[isigma][xhit+1][yhit] [x][y];
1611  double x_yp =table[isigma][xhit] [yhit+1][x][y];
1612  double xp_yp=table[isigma][xhit+1][yhit+1][x][y];
1613  double xsum_y =(1-xweight) *x_y + xweight * xp_y;
1614  double xsum_yp=(1-xweight) *x_yp + xweight * xp_yp;
1615  double xsum_ysum_d=(1-yweight)*xsum_y+ yweight * xsum_yp;
1616 
1617  x_y =table[isigma+1][xhit] [yhit] [x][y];
1618  xp_y =table[isigma+1][xhit+1][yhit] [x][y];
1619  x_yp =table[isigma+1][xhit] [yhit+1][x][y];
1620  xp_yp =table[isigma+1][xhit+1][yhit+1][x][y];
1621  xsum_y =(1-xweight)*x_y+ xweight * xp_y;
1622  xsum_yp=(1-xweight)*x_yp+ xweight * xp_yp;
1623  double xsum_ysum_u=(1-yweight)*xsum_y+ yweight * xsum_yp;
1624 
1625  pix[x][y]= (1-sigweight)*xsum_ysum_d+ sigweight * xsum_ysum_u;
1626  }
1627  }
1628 
1629  for(int x=0;x<maxpixx;x++){
1630  double ix=x;
1631  if(mirrowx) ix=maxpixx-1-x;
1632 
1633  for(int y=0;x<maxpixy;y++){
1634  double iy=y;
1635  if(mirrowy) iy=maxpixy-1-y;
1636  pxl[x][y]=pix[x][y];
1637  }
1638  }
1639  // delete pix;
1640  }
1641 }
1642 */
1643 
std::vector< float > _layerActiveSiOffset
Definition: CCDDigitizer.h:168
AIDA::IHistogram1D * histsignal
Definition: CCDDigitizer.h:273
std::vector< float > _layerHalfPhi
Definition: CCDDigitizer.h:169
std::vector< float > _layerLadderHalfWidth
Definition: CCDDigitizer.h:166
std::vector< float > _bkgdHitsInLayer
Definition: CCDDigitizer.h:171
double _biasvolt
Definition: CCDDigitizer.h:255
double _electronicNoise
Definition: CCDDigitizer.h:198
void PoissonSmearer(SimTrackerHitImplVec &simTrkVec)
double posraw[3]
Definition: CCDDigitizer.h:264
void diffusion(double xdif, double ydif, double sigma)
AIDA::IHistogram1D * histcharge
Definition: CCDDigitizer.h:268
double _threshold
Definition: CCDDigitizer.h:192
void TransformXYToCellID(double x, double y, int &ix, int &iy, double &xdif, double &ydif)
AIDA::IHistogram1D * histsignalframe
Definition: CCDDigitizer.h:274
virtual void end()
Termination member function.
std::vector< float > _layerLadderGap
Definition: CCDDigitizer.h:170
void settanlorentzangleb(double B, double E, double mu, double T)
double _currentTotalCharge
Definition: CCDDigitizer.h:159
IonisationPointVec _ionisationPoints
Definition: CCDDigitizer.h:201
double _pixelSizeY
Definition: CCDDigitizer.h:156
static const float k
void ProduceHits(SimTrackerHitImplVec &simTrkVec)
int _numberOfSegments
Definition: CCDDigitizer.h:185
double sigmacoefficient
Definition: CCDDigitizer.h:251
virtual void processEvent(LCEvent *evt)
Processing of one event.
AIDA::IHistogram1D * histenergy
Definition: CCDDigitizer.h:272
double _efield
Definition: CCDDigitizer.h:254
double _currentParticleMomentum
Definition: CCDDigitizer.h:177
AIDA::IHistogram1D * histenergycentre
Definition: CCDDigitizer.h:275
int _PoissonSmearing
Definition: CCDDigitizer.h:187
virtual void processRunHeader(LCRunHeader *run)
Processing of run header.
double _electronsPerKeV
Definition: CCDDigitizer.h:157
AIDA::IHistogram1D * histcluster
Definition: CCDDigitizer.h:266
AIDA::IHistogram2D * histclustxy
Definition: CCDDigitizer.h:267
double dirraw[3]
Definition: CCDDigitizer.h:263
int _generateBackground
Definition: CCDDigitizer.h:176
void TransformToLab(double *xLoc, double *xLab)
double yobsoffset
Definition: CCDDigitizer.h:249
static const float T
std::vector< float > _layerHalfThickness
Definition: CCDDigitizer.h:164
virtual void init()
Initialisation member function.
void FindLocalPosition(SimTrackerHit *hit, double *localPosition, double *localDirection)
void PrintInfo(SimTrackerHit *simTrkHit, TrackerHitImpl *recoHit)
CCDDigitizer aCCDDigitizer
Definition: CCDDigitizer.cc:33
void GainSmearer(SimTrackerHitImplVec &simTrkVec)
void generateBackground(LCCollectionVec *col)
double TanLorentzAngle
Definition: CCDDigitizer.h:259
std::vector< int > _laddersInLayer
Definition: CCDDigitizer.h:161
std::vector< SimTrackerHitImpl * > SimTrackerHitImplVec
Definition: CCDDigitizer.h:73
double epitaxdep
Definition: CCDDigitizer.h:241
static const float e
double _currentPhi
Definition: CCDDigitizer.h:180
AIDA::IHistogram1D * histNionpoint
Definition: CCDDigitizer.h:270
std::vector< float > _layerLadderLength
Definition: CCDDigitizer.h:165
std::vector< EVENT::SimTrackerHit * > SimTrackerHitVec
Definition: SiStripDigi.h:139
double _saturation
Definition: CCDDigitizer.h:193
void TransformCellIDToXY(int ix, int iy, double &x, double &y)
std::vector< float > _layerPhiOffset
Definition: CCDDigitizer.h:167
std::string _colName
Input collection name.
Definition: CCDDigitizer.h:133
void ProduceIonisationPoints(SimTrackerHit *hit)
double _cutOnDeltaRays
tangent of Lorentz angle
Definition: CCDDigitizer.h:147
int _electronicEffects
Definition: CCDDigitizer.h:188
std::vector< float > _layerLadderWidth
Definition: CCDDigitizer.h:172
std::vector< LCCollection * > LCCollectionVec
Definition: SiStripClus.h:55
double _bfield
Definition: CCDDigitizer.h:256
virtual void check(LCEvent *evt)
Produces check plots.
double _difcoef
Definition: CCDDigitizer.h:253
double SampleFluctuations(const double momentum, const double mass, double &tmax, const double length, const double meanLoss)
double xobsoffset
Definition: CCDDigitizer.h:248
AIDA::IHistogram1D * histdist
Definition: CCDDigitizer.h:265
void settanlorentzangle(double B, double E, double mu, double T)
int _produceFullPattern
Definition: CCDDigitizer.h:184
double _segmentLength
Definition: CCDDigitizer.h:199
std::string _outputCollectionName
Definition: CCDDigitizer.h:134
double _segmentDepth
Definition: CCDDigitizer.h:158
double _energyLoss
Definition: CCDDigitizer.h:236
std::vector< float > _layerRadius
Definition: CCDDigitizer.h:162
std::string _colVTXRelation
Definition: CCDDigitizer.h:135
std::vector< float > _layerThickness
Definition: CCDDigitizer.h:163
double _currentParticleMass
Definition: CCDDigitizer.h:179
AIDA::IHistogram2D * histdistxy
Definition: CCDDigitizer.h:269
TrackerHitImpl * ReconstructTrackerHit(SimTrackerHitImplVec &simTrkVec)
int _nRun
Run number.
Definition: CCDDigitizer.h:139
MyG4UniversalFluctuationForSi * _fluctuate
Definition: CCDDigitizer.h:204
void TrackerHitToLab(TrackerHitImpl *recoHit)
double _pixelSizeX
Definition: CCDDigitizer.h:155
double pxl[maxpixx][maxpixy]
Definition: CCDDigitizer.h:243
int _nEvt
Event number.
Definition: CCDDigitizer.h:143