All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups
FPCCDDigitizer.cc
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 #include "FPCCDDigitizer.h"
3 #include "FPCCDPixelHit.h"
4 #include "FPCCDData.h"
5 
6 #include <iostream>
7 #include <cstring>
8 #include <cstdio>
9 
10 #include <EVENT/LCCollection.h>
11 #include <IMPL/LCCollectionVec.h>
12 #include <IMPL/SimTrackerHitImpl.h>
13 #include <EVENT/SimTrackerHit.h>
14 #include <IMPL/TrackerHitImpl.h>
15 #include <IMPL/TrackerHitPlaneImpl.h>
16 #include <EVENT/MCParticle.h>
17 #include <UTIL/CellIDEncoder.h>
18 #include "UTIL/LCTrackerConf.h"
19 #include <UTIL/ILDConf.h>
20 #include "UTIL/LCTOOLS.h"
21 
22 #include <cmath>
23 #include <algorithm>
24 #include <sstream>
25 #include <map>
26 #include <TRandom.h>
27 
28 using namespace lcio ;
29 using namespace marlin ;
30 using namespace std ;
31 
32 namespace
33 {
34  template<class T1,class T2,class T3>
35  class SortByPosX
36  {
37  public:
38  bool operator()( const T1& object1, const T1& object2 )
39  {
40  return object1.first->x() < object2.first->x();
41  }
42  };
43 }
44 
45 
47 
48 
49 
50 // =====================================================================
51 FPCCDDigitizer::FPCCDDigitizer() : Processor("FPCCDDigitizer") {
52 
53  // modify processor description
54  _description = "FPCCDDigitizer should create FPCCD's VTXPixelHits from SimTrackerHits" ;
55 
56  // register steering parameters: name, description, class-variable, default value
57 
58  registerProcessorParameter( "CutOption_mode",
59  "true make the Cut option active.",
60  _cutMode,
61  bool(false));
62 
63  registerProcessorParameter( "CutOption_theta_From",
64  "from",
66  double(0));
67 
68  registerProcessorParameter( "CutOption_theta_To",
69  "To",
71  double(0));
72 
73  registerProcessorParameter( "CutOption_phi_From",
74  "phi From",
76  double(0));
77 
78  registerProcessorParameter( "CutOption_phi_To",
79  "phi To",
80  _cutPhiTo,
81  double(0));
82 
83  registerProcessorParameter( "isSignalEvent_isBGEvent_forLinkerInClustering",
84  "1:SignalEvent 0:BGEvent for FPCCDOverlayBX process and linker in FPCCDClustering.",
86  int(1));
87 
88  registerProcessorParameter( "Debug",
89  "Debugging option",
90  _debug,
91  int(0));
92 
93  registerProcessorParameter( "modifySimTrackerHit",
94  "Modify SimTrackerHit into layer",
96  bool(true));
97 
98  registerProcessorParameter( "OccupancyStudyMode" ,
99  "OccupancyStudyMode==1: We discreminate direct and backscatter. 0:NormalMode for tracking. Make sure HitQuality Option for discreminating signal and BG " ,
101  int(0) ) ;
102 
103  registerProcessorParameter( "FPCCD_pixelSize(mm)" ,
104  "Pixel size of FPCCD (unit:mm) (default: 0.005)" ,
105  _pixelSize ,
106  float(0.005) ) ;
107 
108  FloatVec pixelSizeVec; // This is a temporary variable. Each ladder's PixelSize are different.
109  for(int i=0;i<6;i++){pixelSizeVec.push_back(0.005);}
110 
111  registerProcessorParameter( "Each_FPCCD_pixelSize(mm)",
112  "Each ladder's Pixel size of FPCCD (unit:mm) (default:0.005)",
114  pixelSizeVec );
115 
116  registerProcessorParameter( "PixelHeight(mm)" ,
117  "Pixel Height(mm).",
118  _pixelheight ,
119  float(0.015));
120 
121  registerProcessorParameter("sigmaConstant",
122  "ration of sigma of Landau distribution and path length",
123  _sigmaConst,
124  double(1600/0.05));
125 
126  registerProcessorParameter("HitQuality",
127  "If OccupancyStydyMode == 0, this becomes active. Then, true: digitize evt as signal. false: digitize as bkg. Then TrackerHit output from FPCCDClustering has a quality identifying signal hit or bkg hit. If you use FPCCDOverlayBX, I recommend to differentiate inputfile by this option.",
128  _isSignal,
129  bool(true));
130 
131  registerProcessorParameter( "HelixTMomentumCriteria(MeV)" ,
132  "Transverse momentum criteria for helix approximation (MeV)",
133  _momCut ,
134  float(100.0));//old:1.0
135 
136  registerProcessorParameter( "Ladder_Number_encoded_in_cellID" ,
137  "Mokka has encoded the ladder number in the cellID" ,
139  bool(true));//old:false
140 
141  registerProcessorParameter( "EnergyLoss_almostOFF" ,
142  "false : normal mode, true : for computing Spatial Resolution." ,
143  _EL_almostOFF ,
144  bool(false));
145 
146  // Input collections
147  registerInputCollection( LCIO::SIMTRACKERHIT,
148  "VTXCollectionName" ,
149  "Name of the VTX SimTrackerHit collection" ,
150  _colNameVTX ,
151  std::string("VXDCollection") ) ;
152 
153 
154  // Output collections
155  registerOutputCollection( LCIO::LCGENERICOBJECT,
156  "VTXPixelHitCollection" ,
157  "Name of the VXD PixelHit output collection" ,
159  std::string("VTXPixelHits") ) ;
160 
161 }
162 
163 
164 // =====================================================================
166 
167  // usually a good idea to
168  printParameters() ;
169 
170  _nRun = 0 ;
171  _nEvt = 0 ;
172 
173  InitGeometry();
174 }
175 
176 // =====================================================================
178 {
179  // Save frequently used parameters.
180  const gear::ZPlanarParameters &gearVXD = Global::GEAR->getVXDParameters();
181  const gear::ZPlanarLayerLayout &layerVXD = gearVXD.getVXDLayerLayout();
182  _nLayer = layerVXD.getNLayers() ;
183  _geodata.resize(_nLayer);
184  _maxLadder = 0;
185 
186  for(int ly=0;ly<_nLayer;ly++){
187  _geodata[ly].nladder = layerVXD.getNLadders(ly); // Number of ladders in this layer
188  if( _maxLadder < _geodata[ly].nladder ) { _maxLadder = _geodata[ly].nladder; }
189  _geodata[ly].rmin = layerVXD.getSensitiveDistance(ly); // Distance of sensitive area from
190  _geodata[ly].dphi = (2*M_PI)/(double)_geodata[ly].nladder;
191  _geodata[ly].phi0 = layerVXD.getPhi0(ly); // phi offset.
192  _geodata[ly].sthick = layerVXD.getSensitiveThickness(ly);
193  _geodata[ly].sximin = -layerVXD.getSensitiveOffset(ly)
194  -layerVXD.getSensitiveWidth(ly)/2.0;
195  _geodata[ly].sximax = -layerVXD.getSensitiveOffset(ly)
196  +layerVXD.getSensitiveWidth(ly)/2.0;
197  _geodata[ly].hlength = layerVXD.getSensitiveLength(ly);
198  _geodata[ly].cosphi.resize( _geodata[ly].nladder );
199  _geodata[ly].sinphi.resize( _geodata[ly].nladder );
200  for(int ld = 0;ld<_geodata[ly].nladder;ld++) {
201  double phi = _geodata[ly].phi0 + _geodata[ly].dphi*ld;
202  _geodata[ly].cosphi[ld] = cos(phi);
203  _geodata[ly].sinphi[ld] = sin(phi);
204  }
205  }
206 }
207 
208 
209 // =====================================================================
210 void FPCCDDigitizer::processRunHeader( LCRunHeader* /*run*/) {
211  _nRun++ ;
212 }
213 
214 // =====================================================================
215 void FPCCDDigitizer::modifyEvent( LCEvent * evt )
216 {
217 
218  col = 0 ;
219 
220  try{ col = evt->getCollection( _colNameVTX ) ; }
221  catch(DataNotAvailableException &e){
222  if (_debug == 1) { std::cout << "Collection " << _colNameVTX.c_str() << " is unavailable in event " << _nEvt << std::endl; }
223  }
224  if( col != 0 ){
225  LCCollectionVec* fpccdDataVec = new LCCollectionVec( LCIO::LCGENERICOBJECT ) ;
226  FPCCDData theData(_nLayer, _maxLadder); // prepare object to make pixelhits
227  //mori: _maxLadder is number of ladders which belong to the n-th(in FPCCD case, 5 or 6th.00) layer with most number of ladders.
228  //--> In case of default setteing, _nLayer = 6 and _maxLadder = 17.
229  // Constructor does only resize matrix whose element is _pxHits derived from std::vector< std::vector<std::map<unsigned int, FPCCDPixelHit*>> >
230 
231  int nSimHits = col->getNumberOfElements() ;
232  // Loop over all VXD hits
233 
234 /************************area D1 *****function of BG Cut******************/
235  if(_debug == 1) { std::cout << "Now Range shows " << std::endl
236  << "theta from , to" << _cutThetaFrom << " , " << _cutThetaTo << std::endl
237  << "phi from , to" << _cutPhiFrom << " , " << _cutPhiTo << std::endl;}
238 #if 1
239  for(int i=0; i< nSimHits; i++){
240  SimTrackerHitImpl* SimTHitImpl = dynamic_cast<SimTrackerHitImpl*>( col->getElementAt( i ) ) ;
241  double pos_x = SimTHitImpl->getPosition()[0]; double pos_y = SimTHitImpl->getPosition()[1]; double pos_z = SimTHitImpl->getPosition()[2];
242  double length_pos = sqrt(pow(pos_x,2) + pow(pos_y,2) + pow(pos_z,2));
243  double theta = 180/M_PI* acos( pos_z / length_pos ); //from 0 to pi
244  double phi = 180/M_PI* atan2( pos_y ,pos_x); // from -pi to pi
245 
246  if(_debug==2){std::cout << "3-pos = " << pos_x <<" , "<< pos_y <<" , "<< pos_z << std::endl;
247  std::cout << "then Calc theta, phi = " << theta << " , " << phi << std::endl;
248  std::cout << "theta Cut = " << "from " << _cutThetaFrom << " to " << _cutThetaTo << std::endl;
249  std::cout << "phi Cut = " << "from " << _cutPhiFrom << " to " << _cutPhiTo << std::endl;
250  }
251  if(_cutMode == false || ((_cutThetaFrom < theta && theta < _cutThetaTo ) && (_cutPhiFrom < phi && phi < _cutPhiTo ) ) ){
252  //makePixelHits(SimTHitImpl, theData);//Mainly, _pxHits (the member valiable of FPCCDData.) will be set.
253  if(_signalProperty == 1){
254  makePixelHits(SimTHitImpl, theData, i);//New Version. Put nth of simthit in 3rd argument.
255  } //Mainly, _pxHits (the member valiable of FPCCDData.) will be set.
256  else if(_signalProperty == 0){
257  makePixelHits(SimTHitImpl, theData, -1);//From 2013_01_25, -1 is regarded as Background data.
258  }
259  else std::cout << "something wrong at FPCCDDigitizer at line 246 to 256" << std::endl;
260  if(_debug==2) std::cout << "accepted." << std::endl;
261  }
262  else{
263  // makePixelHits(SimTHitImpl, theData);
264  // std::cout << "exclusion occurs." << std::endl;
265  }
266  } // End of loop over all SimTrackerHits
267 #endif
268 
269 /*===================area D1 end=============================================*/
270 
271  theData.packPixelHits( *fpccdDataVec );// Save _pxHits info in *LCCollectionVec ( in this case the elements of LCCollectionVec have LCGenericObject)
272 
273  evt->addCollection( fpccdDataVec , _outColNameVTX ) ;
274  if(_debug == 1){
275  std::cout << "dumpEvent Digitizer" << std::endl;
276  LCTOOLS::dumpEvent( evt ) ;
277  }
278  } // End of process when VXD has hits
279  _nEvt ++ ;
280 }
281 
282 // =====================================================================
283 void FPCCDDigitizer::makePixelHits(SimTrackerHitImpl *SimTHit, FPCCDData &hitVec, int nth_simthit)
284 {//The type of FPCCDData is not Vector. So the word "&hitVec" is confusing. Pay attention to it.
285  //nth_simthit is the number of the element of STHcol. Namely, it is the nth_simthit of STHcol->getElementAt(nth_simthit).
286  //This makes data remember which simthit a pixel hit is originated from.
287  gear::Vector3D* HitPosInMokka = new gear::Vector3D(SimTHit->getPosition()[0],SimTHit->getPosition()[1],SimTHit->getPosition()[2]);
288  /************get basic info.**************/
289  const gear::BField& gearBField = Global::GEAR->getBField();
290  double posphi = HitPosInMokka->phi();
291  if(HitPosInMokka->y()<0) posphi += 2*M_PI;
292  int layer = 0 ; int ladderID = 0 ;
293  const int cellId = SimTHit->getCellID0();
294 
296  streamlog_out( DEBUG3 ) << "Get Layer Number using StandardILD Encoding from ILDConf.h : cellId = " << cellId << std::endl;
297  UTIL::BitField64 encoder( lcio::LCTrackerCellID::encoding_string() ) ;
298  encoder.setValue(cellId) ;
299  layer = encoder[lcio::LCTrackerCellID::layer()] ; ladderID = encoder[lcio::LCTrackerCellID::module()] ;
300  streamlog_out( DEBUG3 ) << "layer Number = " << layer << std::endl; streamlog_out( DEBUG3 ) << "ladder Number = " << ladderID << std::endl;
301  }
302  else{ layer = cellId - 1 ; }
303  /*********** check which ladder hit on*************************************/
304  if( !_ladder_Number_encoded_in_cellID ) { ladderID = getLadderID( HitPosInMokka, layer); }
305  _pixelSize = _pixelSizeVec[layer];
306  /*********** get hit dir(mom) at hit points and other info.****************/
307  gear::Vector3D* MomAtHitPos = new gear::Vector3D(SimTHit->getMomentum()[0],SimTHit->getMomentum()[1],SimTHit->getMomentum()[2]);
308  double momphi = MomAtHitPos->phi();
309  if(MomAtHitPos->y()<0) momphi += 2*M_PI;
310  gear::Vector3D origin;
311  gear::Vector3D bfield = gearBField.at(origin);
312  gear::Vector3D* BField = new gear::Vector3D(bfield.x(),bfield.y(),bfield.z());
313  MCParticle* mcp = SimTHit -> getMCParticle();
314  if( mcp == 0 ) return ;
315  float charge = mcp->getCharge();
316  /*********** get local pos and dir on each ladder **************************/
317  gear::Vector3D* LocalHitPos = getLocalPos(HitPosInMokka, layer, ladderID);
318  gear::Vector3D* MomAtLocalHitPos = new gear::Vector3D(MomAtHitPos->x()*_geodata[layer].sinphi[ladderID]-MomAtHitPos->y()*_geodata[layer].cosphi[ladderID],
319  MomAtHitPos->z(),
320  MomAtHitPos->x()*_geodata[layer].cosphi[ladderID]+MomAtHitPos->y()*_geodata[layer].sinphi[ladderID]);
321  gear::Vector3D* LocalBField = new gear::Vector3D( _geodata[layer].sinphi[ladderID]*BField->x()-_geodata[layer].cosphi[ladderID]*BField->y(),
322  BField->z(),
323  _geodata[layer].cosphi[ladderID]*BField->x()+_geodata[layer].sinphi[ladderID]*BField->y());
324  gear::Vector3D* PosOutFromLadder = new gear::Vector3D(0,0,0);
325  gear::Vector3D* PosInToLadder = new gear::Vector3D(0,0,0);
326  /*********** get the intersections with the surface of sensitive region**********************/
327  if( sqrt(MomAtLocalHitPos->x()*MomAtLocalHitPos->x() + MomAtLocalHitPos->z()*MomAtLocalHitPos->z()) < _momCut*1e-03){ // transvers momentum criteria for helix approximation
328  if( _debug == 1 ) cout << "========== Track of this hit is trated as a helix ==========" << endl;
329  getInOutPosOfHelixOnLadder(layer, PosOutFromLadder, PosInToLadder, LocalHitPos, MomAtLocalHitPos, LocalBField,charge);
330  }
331  else{
332  getInOutPosOnLadder(layer, PosOutFromLadder,PosInToLadder,LocalHitPos,MomAtLocalHitPos);
333  if(_debug == 1){
334  std::cout <<" layer = " << layer << " : PosIntoLadder = "<< PosInToLadder->x() << "," << PosInToLadder->y() << "," << PosInToLadder->z() << std::endl;
335  std::cout <<" layer = " << layer << " : PosOutFromLadder = "<< PosOutFromLadder->x() << "," << PosOutFromLadder->y() << "," << PosOutFromLadder->z() << std::endl;
336  }
337  }
338 
339  if( inSensitiveRegion( PosOutFromLadder, layer) && inSensitiveRegion( PosInToLadder, layer) ){ // check if the particle through the sensitive region.
340 
341  /********* make new SimTrackerHit for seinsitive thickness of FPCCD***************/
342  if(_modifySimTHit){
343  gear::Vector3D Path(PosOutFromLadder->x()-PosInToLadder->x(), PosOutFromLadder->y()-PosInToLadder->y(),
344  PosOutFromLadder->z()-PosInToLadder->z());
345  double PathLength = Path.r();
346  makeNewSimTHit(SimTHit, LocalHitPos, MomAtLocalHitPos, layer, ladderID, PathLength);
347  }
348  /******** get hit points incoming and outgoiong each pixel (@ edge of pixel)************/
349  std::vector<std::pair<const gear::Vector3D*,int> >EdgeOfPixel = getIntersectionOfTrkAndPix(layer,PosOutFromLadder,PosInToLadder);
350  /*********calculate length that particle pass through pixel & central point of pixel*********/
351  sort( EdgeOfPixel.begin(), EdgeOfPixel.end(), SortByPosX<std::pair<const gear::Vector3D*, int>, const gear::Vector3D*, int >() );
352  std::map< std::pair< int, int>*, double> pixel_local = getLocalPixel(SimTHit,EdgeOfPixel);
353  std::map< std::pair< int, int>*, double>::iterator i_pixel_local = pixel_local.begin();
354 
355  while( i_pixel_local != pixel_local.end() ){
356  int xiID = (*i_pixel_local).first->first;
357  int zetaID = (*i_pixel_local).first->second;
358  float dE = (float)(*i_pixel_local).second; // [mm]
359  FPCCDPixelHit::HitQuality_t quality;
360  if(_OccupancyStudy == 0){
361  if( _isSignal && mcp->getParents().size() == 0 ){ quality = FPCCDPixelHit::kSingle; }
362  else{ quality = FPCCDPixelHit::kBKG;}
363  }
364  else{
365  if( SimTHit->getTime() >10 ){ quality = FPCCDPixelHit::kSingle; }
366  else{ quality = FPCCDPixelHit::kBKG; }
367  }
368  FPCCDPixelHit aHit(layer, ladderID, xiID, zetaID, dE, quality, mcp);
369  if(nth_simthit > -1){ aHit.setOrderID(nth_simthit); }
370  else if(nth_simthit == -1){ aHit.setOrderID(-1); }// From 2013_01_25, -1 is regarded as Background data.
371  else{std::cout << "3rd argument in makepixelhit is something wrong. Please set nth_simthit value. wrong number is " << nth_simthit << std::endl;}
372 
373  hitVec.addPixelHit(aHit,quality);//The type of "hitVec" is FPCCDData.
374 
375  if(_debug == 1 ) aHit.print();
376  i_pixel_local++;
377  }
378 
379  }
380  else{
381  if(_debug == 1) cout << "This particle didn't through the sensitive region." << endl;
382  }
383 
384  delete HitPosInMokka;
385  delete LocalHitPos;
386  delete MomAtLocalHitPos;
387  delete LocalBField;
388  delete PosOutFromLadder;
389  delete PosInToLadder;
390 
391  return ;
392 }
393 
394 
395 
396 // =====================================================================
397 void FPCCDDigitizer::check( LCEvent * /*evt*/ ) {
398  // nothing to check here - could be used to fill checkplots in reconstruction processor
399 }
400 
401 // =====================================================================
403 
404  streamlog_out(MESSAGE) << " end() " << name()
405  << " processed " << _nEvt << " events in " << _nRun << " runs "
406  << endl ;
407 }
408 
409 
410 
411 
412 // =====================================================================
413 // =====================================================================
414 int FPCCDDigitizer::getLadderID(const gear::Vector3D* pos, const int layer){
415 
416  std::cout << "layer is " << layer << std::endl;
417  double layerthickness = _geodata[layer].sthick;
418  double radius = _geodata[layer].rmin+0.5*layerthickness;
419  int nladder = _geodata[layer].nladder;
420  double dphi = _geodata[layer].dphi;
421  double offset_phi = _geodata[layer].phi0;
422  double posphi = pos->phi();
423  double posR = pos->rho();
424 
425  int ladderID = 50;
426  double local_phi = 50.;
427  for(int j=0; j<nladder; j++){
428  local_phi = posphi - dphi*j - offset_phi;
429  if((posR*cos(local_phi)-radius >= -layerthickness) && (posR*cos(local_phi)-radius <= layerthickness)){
430  ladderID = j;
431  break;
432  }
433  }
434  if(ladderID>100) cout << "LADDERID>100!: " << ladderID << endl;
435  local_phi = posphi - dphi*(ladderID+1) - offset_phi;
436  if((posR*cos(local_phi)-radius >= -layerthickness) && (posR*cos(local_phi)-radius <= layerthickness)){
437  ladderID++;
438  }
439  if(ladderID==50){
440  for(int j=0; j<nladder; j++){
441  local_phi = posphi - dphi*j - offset_phi;
442  if((posR*cos(local_phi)-radius >= -1.*layerthickness) && (posR*cos(local_phi)-radius <= 1.*layerthickness)){
443  ladderID = j;
444  break;
445  }
446  }
447  }
448  if(ladderID==50) cout << "LADDERID==50!" << endl;
449  if(ladderID>100) cout << "LADDERID>100!..." << ladderID << endl;
450 
451  return ladderID;
452 }
453 
454 // =====================================================================
455 gear::Vector3D* FPCCDDigitizer::getLocalPos(const gear::Vector3D* pos, const int layer, const int ladder){
456  double posR = pos->rho();
457  double posphi = pos->phi();
458  double radius = _geodata[layer].rmin+0.5*_pixelheight + (layer%2)*(_geodata[layer].sthick-_pixelheight);
459  gear::Vector3D* LocalPos = new gear::Vector3D(
460  posR*(cos(posphi)*_geodata[layer].sinphi[ladder]-sin(posphi)*_geodata[layer].cosphi[ladder]),
461  pos->z(),
462  posR*(cos(posphi)*_geodata[layer].cosphi[ladder]+sin(posphi)*_geodata[layer].sinphi[ladder])-radius
463  );
464  return LocalPos;
465 }
466 
467 // =====================================================================
469  double f_z = 0.5 * _pixelheight;
470 
471  double top_y = (mom->y()/mom->z())*(f_z-pos->z())+pos->y();
472  double top_x = (mom->x()/mom->z())*(f_z-pos->z())+pos->x();
473 
474  double bottom_y = (mom->y()/mom->z())*(-f_z-pos->z())+pos->y();
475  double bottom_x = (mom->x()/mom->z())*(-f_z-pos->z())+pos->x();
476 
477  if( (mom->x() > 0 && top_x > bottom_x) || (mom->x() < 0 && top_x < bottom_x ) ) {
478  *outpos = gear::Vector3D( top_x, top_y, f_z);
479  *inpos = gear::Vector3D( bottom_x, bottom_y, -f_z);
480  }
481  else{
482  *inpos = gear::Vector3D( top_x, top_y, f_z);
483  *outpos = gear::Vector3D( bottom_x, bottom_y, -f_z);
484  }
485 
486  ModifyIntoLadder( inpos, layer, inpos, mom);
487  ModifyIntoLadder( outpos, layer, outpos, mom);
488 
489  *pos = gear::Vector3D((outpos->x()+inpos->x())/2 ,
490  (outpos->y()+inpos->y())/2 ,
491  (outpos->z()+inpos->z())/2);
492 
493  return ;
494 }
495 
496 // =====================================================================
497 void FPCCDDigitizer::ModifyIntoLadder(gear::Vector3D* bemodifiedpos,const int f_layer,gear::Vector3D* pos,gear::Vector3D* mom){
498  double sximin = _geodata[f_layer].sximin;
499  double sximax = _geodata[f_layer].sximax;
500  double szetamin = -_geodata[f_layer].hlength;
501  double szetamax = _geodata[f_layer].hlength;
502 
503  double preposx = bemodifiedpos->x();
504  double preposy = bemodifiedpos->y();
505  double preposz = bemodifiedpos->z();
506 
507  if(preposx < sximin){
508  if(_debug ==1 ) cout << "this hit was modified Sx" << endl;
509  preposx = sximin;
510  preposy = (mom->y()/mom->x())*(preposx-pos->x())+pos->y();
511  preposz = (mom->z()/mom->x())*(preposx-pos->x())+pos->z();
512  }else if(preposx > sximax){
513  if(_debug ==1 ) cout << "this hit was modified Ex" << endl;
514  preposx = sximax;
515  preposy = (mom->y()/mom->x())*(preposx-pos->x())+pos->y();
516  preposz = (mom->z()/mom->x())*(preposx-pos->x())+pos->z();
517  }
518  if(preposy < szetamin){
519  if(_debug ==1 ) cout << "this hit was modified Sy" << endl;
520  preposy = szetamin;
521  preposx = (mom->x()/mom->y())*(preposy-pos->y())+pos->x();
522  preposz = (mom->z()/mom->y())*(preposy-pos->y())+pos->z();
523  }else if(preposy > szetamax){
524  if(_debug ==1 ) cout << "this hit was modified Ey" << endl;
525  preposy = szetamax;
526  preposx = (mom->x()/mom->y())*(preposy-pos->y())+pos->x();
527  preposz = (mom->z()/mom->y())*(preposy-pos->y())+pos->z();
528  }
529  gear::Vector3D prepos(preposx,preposy,preposz);
530  *bemodifiedpos = prepos;
531 
532  return ;
533 }
534 
535 // =====================================================================
537  double out[3];
538  double in[3];
539 
540  double outerZ = 0.5*_pixelheight;
541  double innerZ = -0.5*_pixelheight;
542  double sximin = _geodata[layer].sximin;
543  double sximax = _geodata[layer].sximax;
544  double szetamin = -_geodata[layer].hlength;
545  double szetamax = _geodata[layer].hlength;
546  gear::Vector3D tmom(mom->x(),0,mom->z());
547  // gear::Vector3D* tmom = new gear::Vector3D((1-BField->x()/BField->r())*mom->x(),
548  // (1-BField->y()/BField->r())*mom->y(),
549  // (1-BField->z()/BField->r())*mom->z());
550  double PI = M_PI;
551 
552  double radius = (tmom.r()/(0.29979*BField->r()*fabs(Charge)))*1e+03;
553  if( radius/2 < _pixelheight ){
554  *outpos = gear::Vector3D( pos->x(), pos->y(), outerZ);
555  *inpos = gear::Vector3D( pos->x(), pos->y(), innerZ);
556  *pos = gear::Vector3D( pos->x(), pos->y(), 0);
557  return ;
558  }
559  double init_pos[3] = {pos->x(),pos->y(),pos->z()};
560  double init_dir[3] = {mom->x()/tmom.r(),
561  mom->y()/tmom.r(),
562  mom->z()/tmom.r()};
563  double v_y = radius*init_dir[1];
564 
565  double offset_pos[3];
566  double offset_phi;
567  double asin_offset = -(1/Charge)*asin(init_dir[0]/(Charge));
568  double acos_offset = (1/Charge)*acos(init_dir[2]/(Charge));
569 
570  asin_offset*Charge >= 0 ? offset_phi = acos_offset : offset_phi = -acos_offset;
571  int sign;
572  fabs(acos_offset*Charge) > PI/2 ? sign = -1 : sign = 1;
573 
574  offset_pos[0] = init_pos[0]-radius*cos(Charge*offset_phi);
575  offset_pos[1] = init_pos[1]-v_y*offset_phi;
576  offset_pos[2] = init_pos[2]-radius*sin(Charge*offset_phi);
577 
578  double outerZ_phi = 0;
579  double innerZ_phi = 0;
580  //Check if the track intesects with x-y plane.
581  if( fabs((outerZ-offset_pos[2])/radius) <= 1. ) outerZ_phi = 1 / Charge*asin((outerZ-offset_pos[2])/radius) - asin_offset;
582  if( fabs((innerZ-offset_pos[2])/radius) <= 1. ) innerZ_phi = 1 / Charge*asin((innerZ-offset_pos[2])/radius) - asin_offset;
583 
584  double outphi = sign*outerZ_phi ;
585  double inphi = sign*innerZ_phi ;
586 
587  int flag = 0;
588  if( radius*cos(Charge*(outphi + offset_phi)) + offset_pos[0] <= sximin
589  || radius*cos(Charge*(outphi + offset_phi)) + offset_pos[0] >= sximax
590  || v_y*(outphi + offset_phi) + offset_pos[1] <= szetamin
591  || v_y*(outphi + offset_phi) + offset_pos[1] >= szetamax ) flag = flag + 1; // outerZ_phi will be modified.
592 
593  if( radius*cos(Charge*(inphi + offset_phi)) + offset_pos[0] <= sximin
594  || radius*cos(Charge*(inphi + offset_phi)) + offset_pos[0] >= sximax
595  || v_y*(inphi + offset_phi) + offset_pos[1] <= szetamin
596  || v_y*(inphi + offset_phi) + offset_pos[1] >= szetamax ) flag = flag + 2; // innerZ_phi will be modified.
597 
598  if(flag != 0){
599 
600  double tmpphi;
601  double sximin_phi = 1e+8;
602  double sximax_phi = 1e+8;
603  if(fabs((sximin-offset_pos[0])/radius) <= 1.) sximin_phi = sign*(1 / Charge*acos((sximin - offset_pos[0])/radius) - acos_offset);
604  if(fabs((sximax-offset_pos[0])/radius) <= 1.) sximax_phi = sign*(1 / Charge*acos((sximax - offset_pos[0])/radius) - acos_offset);
605  double szetamin_phi = (szetamin - offset_pos[1]) / v_y - offset_phi;
606  double szetamax_phi = (szetamax - offset_pos[1]) / v_y - offset_phi;
607 
608  if(fabs(sximin_phi) <= fabs(sximax_phi) && fabs(sximin_phi) <= fabs(szetamin_phi) && fabs(sximin_phi) <= fabs(szetamax_phi)){
609  tmpphi = sximin_phi;
610  sximin_phi = 1e+8;
611  }
612  else if(fabs(sximax_phi) <= fabs(szetamin_phi) && fabs(sximax_phi) <= fabs(szetamax_phi)){
613  tmpphi = sximax_phi;
614  sximax_phi = 1e+8;
615  }
616  else if(fabs(szetamin_phi) <= fabs(szetamax_phi)){
617  tmpphi = szetamin_phi;
618  szetamin_phi = 1e+8;
619  }
620  else{
621  tmpphi = szetamax_phi;
622  szetamax_phi = 1e+8;
623  }
624  if(flag == 1) outphi = tmpphi;
625  if(flag == 2) inphi = tmpphi;
626  if(flag == 3){
627  inphi = tmpphi;
628  if(fabs(sximin_phi) <= fabs(sximax_phi) && fabs(sximin_phi) <= fabs(szetamin_phi) && fabs(sximin_phi) <= fabs(szetamax_phi)) tmpphi = sximin_phi;
629  else if(fabs(sximax_phi) <= fabs(szetamin_phi) && fabs(sximax_phi) <= fabs(szetamax_phi)) tmpphi = sximax_phi;
630  else if(fabs(szetamin_phi) <= fabs(szetamax_phi))tmpphi = szetamin_phi;
631  else tmpphi = szetamax_phi;
632  outphi = tmpphi;
633  }
634  }
635  out[0] = radius*cos(Charge*(outphi+offset_phi)) + offset_pos[0];
636  out[1] = v_y * (outphi+offset_phi)+ offset_pos[1];
637  out[2] = radius*sin(Charge*(outphi+offset_phi)) + offset_pos[2];
638 
639  in[0] = radius*cos(Charge*(inphi+offset_phi)) + offset_pos[0];
640  in[1] = v_y * (inphi+offset_phi)+ offset_pos[1];
641  in[2] = radius*sin(Charge*(inphi+offset_phi)) + offset_pos[2];
642 
643  double center_phi = (outphi+inphi)/2;
644  *pos = gear::Vector3D(radius*cos(Charge*(center_phi+offset_phi)) + offset_pos[0],
645  v_y*(center_phi+offset_phi) + offset_pos[1],
646  radius*sin(Charge*(center_phi+offset_phi)) + offset_pos[2]);
647  *mom = gear::Vector3D(-radius*sin(Charge*(center_phi+offset_phi)),
648  v_y ,
649  radius*cos(Charge*(center_phi+offset_phi)));
650  *outpos = gear::Vector3D(out[0], out[1], out[2]);
651  *inpos = gear::Vector3D( in[0], in[1], in[2]);
652 
653  return ;
654 }
655 
656 // =====================================================================
657 std::vector<std::pair<const gear::Vector3D*, int> > FPCCDDigitizer::getIntersectionOfTrkAndPix(const int f_layer, gear::Vector3D* top,gear::Vector3D* bottom){
658  std::vector<std::pair<const gear::Vector3D*, int> > EdgeOfPixel;
659  double sximin = _geodata[f_layer].sximin;
660  double szetamin = -_geodata[f_layer].hlength;
661  double small_localx;
662  double large_localx;
663  double small_localy;
664  double large_localy;
665  if(top->x()>=bottom->x()){ large_localx = top->x(); small_localx = bottom->x(); }
666  else { large_localx = bottom->x(); small_localx = top->x(); }
667  if(top->y()>=bottom->y()) {large_localy = top->y(); small_localy = bottom->y(); }
668  else { large_localy = bottom->y(); small_localy = top->y(); }
669 
670 
671  int sloopx = (int)ceil((small_localx-sximin)/_pixelSize) ;
672  int eloopx = (int)ceil((large_localx-sximin)/_pixelSize) - 1;
673  int sloopy = (int)ceil((small_localy-szetamin)/_pixelSize) ;
674  int eloopy = (int)ceil((large_localy-szetamin)/_pixelSize) - 1;
675 
676  int nloopx = eloopx - sloopx + 1;
677  int nloopy = eloopy - sloopy + 1;
678  if(_debug == 1){
679  std::cout << "check sximin,szetamin = " << sximin << " , " << szetamin << std::endl;
680  std::cout << "check small_localx, large_localx = " << small_localx << " , " << large_localx << std::endl;
681  std::cout << "check small_localy, large_localy = " << small_localy << " , " << large_localy << std::endl;
682  std::cout << "check sloopx, eloopx = " << sloopx << " , " << eloopx << std::endl;
683  std::cout << "check sloopy, eloopy = " << sloopy << " , " << eloopy << std::endl;
684  std::cout << "check nloopx, nloopy = " << nloopx << " , " << nloopy << std::endl;
685  }
686 
687  for(int j=0; j<nloopx; j++){
688  double XEdgeOfPixelZ = ((top->z()-bottom->z())/(top->x()-bottom->x()))*(sximin+(sloopx+j)*_pixelSize-(top->x()+bottom->x())/2.)+(top->z()+bottom->z())/2.;
689  double XEdgeOfPixelX = sximin+(sloopx+j)*_pixelSize;
690  double XEdgeOfPixelY = ((top->y()-bottom->y())/(top->x()-bottom->x()))*(sximin+(sloopx+j)*_pixelSize-(top->x()+bottom->x())/2.)+(top->y()+bottom->y())/2.;
691 
692  gear::Vector3D* XEdgeOfPixel = new gear::Vector3D(XEdgeOfPixelX,XEdgeOfPixelY,XEdgeOfPixelZ);
693  EdgeOfPixel.push_back(std::pair<gear::Vector3D*,int>(XEdgeOfPixel,1));
694  }
695  for(int j=0; j<nloopy; j++){
696  double YEdgeOfPixelZ = ((top->z()-bottom->z())/(top->y()-bottom->y()))*(szetamin+(sloopy+j)*_pixelSize-(top->y()+bottom->y())/2.)+(top->z()+bottom->z())/2.;
697  double YEdgeOfPixelX = ((top->x()-bottom->x())/(top->y()-bottom->y()))*(szetamin+(sloopy+j)*_pixelSize-(top->y()+bottom->y())/2.)+(top->x()+bottom->x())/2.;
698  double YEdgeOfPixelY = szetamin+(sloopy+j)*_pixelSize;
699 
700  gear::Vector3D* YEdgeOfPixel = new gear::Vector3D(YEdgeOfPixelX,YEdgeOfPixelY,YEdgeOfPixelZ);
701  EdgeOfPixel.push_back(std::pair<gear::Vector3D*,int>(YEdgeOfPixel,2));
702  }
703  EdgeOfPixel.push_back(std::pair<gear::Vector3D*,int>(top,0));
704  EdgeOfPixel.push_back(std::pair<gear::Vector3D*,int>(bottom,0));
705  return EdgeOfPixel;
706 }
707 
708 // =====================================================================
709 std::map< pair<int, int>*, double> FPCCDDigitizer::getLocalPixel(SimTrackerHitImpl* simthit, vector<std::pair<const gear::Vector3D*,int> > edgeofpixel){
710  std::map<pair< int, int>*, double> pixel_local;
711  UTIL::BitField64 encoder( lcio::LCTrackerCellID::encoding_string() ) ;
712  encoder.setValue(simthit->getCellID0()) ;
713  int f_layer = encoder[lcio::LCTrackerCellID::layer()] ;
714  double dEdx = 0.0;
715  if(_EL_almostOFF == false){
716  dEdx = simthit->getEDep()*1e+9; // Energy deposit of 50um thickness ladder. [eV]
717  }
718  else{
719  dEdx = 23290;
720  /** Energy deposit of 50um thickness ladder. [eV]
721  If you want to inspect position resolution of clusters with energy loss almost zero,
722  set _EL_almostOff : true */
723  }
724 
725 
726  double path_length = simthit->getPathLength(); // Path length of 50um thickness ladder. [mm]
727 
728  double mpv = 0.;
729  double dE = 0.;
730  double sigma = 0.;
731  std::vector<std::pair<const gear::Vector3D*,int> >::iterator nxt = edgeofpixel.begin();
732  while( nxt != edgeofpixel.end()-1 ){
733  std::vector<std::pair<const gear::Vector3D*,int> >::iterator fst = nxt;
734  nxt++;
735 
736  double diffx = (*nxt).first->x() - (*fst).first->x();
737  double diffy = (*nxt).first->y() - (*fst).first->y();
738  double diffz = (*nxt).first->z() - (*fst).first->z();
739  double L_through_pixel = sqrt(diffx*diffx + diffy*diffy + diffz*diffz);
740 
741  mpv = (dEdx/path_length)*L_through_pixel;
742  sigma = (_sigmaConst)*L_through_pixel;
743 
744  dE = gRandom->Landau( mpv, sigma)*1e-9; // Energy deposit is smeared by Landau distribution. [GeV]
745 
746  std::pair< int, int>* pixID = FindPixel((*fst),(*nxt),f_layer); // estimate central point of pixels
747  pixel_local.insert(std::map< std::pair<int, int>*, double>::value_type( pixID, dE));
748  }
749  return pixel_local;
750 }
751 
752 // =====================================================================
753 std::pair< int, int>* FPCCDDigitizer::FindPixel(std::pair<const gear::Vector3D*,int> fst, std::pair<const gear::Vector3D*,int> nxt, int layer){
754 
755  std::pair<int,int> fst_array[4] ;
756  std::pair<int,int> nxt_array[4] ;
757 
758  makeCandidates(fst, fst_array, layer);
759  makeCandidates(nxt, nxt_array, layer);
760 
761  std::pair<int,int>* pixID = new std::pair< int, int>(0,0);
762  for(int i=0; i<4; i++){
763  for(int j=0; j<4; j++){
764  if(fst_array[i].first >= 0 && fst_array[i] == nxt_array[j] ){
765  pixID->first = fst_array[i].first;
766  pixID->second = fst_array[i].second;
767  goto GotPixID;
768  }
769  }
770  }
771  GotPixID:
772 
773  return pixID;
774 }
775 // =====================================================================
776 void FPCCDDigitizer::makeCandidates( std::pair<const gear::Vector3D*,int> edge, std::pair<int,int>* cand_array, int layer){
777 
778  std::pair<int,int> candID1(-1,-1);
779  std::pair<int,int> candID2(-1,-1);
780  std::pair<int,int> candID3(-1,-1);
781  std::pair<int,int> candID4(-1,-1);
782 
783  double hlength = _geodata[layer].hlength;
784  double sximin = _geodata[layer].sximin;
785 
786  double quotient_x = (edge.first->x()-sximin)/_pixelSize ;
787  double quotient_y = (edge.first->y()+hlength)/_pixelSize ;
788 
789  double mergin = 1e-5;
790 
791  switch(edge.second)
792  {
793  case 0 : // intersection with ladder surface.
794  candID1.first = (int)floor(quotient_x);
795  if ( quotient_x - candID1.first < mergin/_pixelSize ) candID2.first = candID1.first - 1;
796  else if( quotient_x - candID1.first > 1 - mergin/_pixelSize ) candID2.first = candID1.first + 1;
797  else candID2.first = candID1.first;
798 
799  candID1.second = (int)floor(quotient_y);
800  if ( quotient_y - candID1.second < mergin/_pixelSize ) candID2.second = candID1.second - 1;
801  else if( quotient_y - candID1.second > 1 - mergin/_pixelSize )candID2.second = candID1.second + 1;
802  else candID2.second = candID1.second;
803  break;
804 
805  case 1 : // intersection with pixel border in xi
806  candID1.first = (int)floor(quotient_x + 0.5);
807  candID2.first = candID1.first - 1;
808  candID1.second = (int)floor(quotient_y);
809  candID2.second = candID1.second;
810 
811  if ( quotient_y - candID1.second < mergin/_pixelSize){
812  candID3.first = candID1.first;
813  candID3.second = candID1.second - 1;
814  candID4.first = candID2.first;
815  candID4.second = candID2.second - 1;
816  }
817  else if( quotient_y - candID1.second > 1 - mergin/_pixelSize){
818  candID3.first = candID1.first;
819  candID3.second = candID1.second + 1;
820  candID4.first = candID2.first;
821  candID4.second = candID2.second + 1;
822  }
823  break;
824 
825  case 2 : // intersection with pixel border in zeta
826  candID1.first = (int)floor(quotient_x);
827  candID2.first = candID1.first;
828  candID1.second = (int)floor(quotient_y + 0.5);
829  candID2.second = candID1.second - 1;
830 
831  if ( quotient_x - candID1.first < mergin/_pixelSize){
832  candID3.first = candID1.first - 1;
833  candID3.second = candID1.second;
834  candID4.first = candID2.first - 1;
835  candID4.second = candID2.second;
836  }
837  else if( quotient_x - candID1.first > 1 - mergin/_pixelSize){
838  candID3.first = candID1.first + 1;
839  candID3.second = candID1.second;
840  candID4.first = candID2.first + 1;
841  candID4.second = candID2.second;
842  }break;
843 
844  default :
845  if(_debug == 1) std::cout << "pixel candidates cannot found. : " << edge.second << std::endl;
846  break;
847  }
848  *cand_array = candID1;
849  *(cand_array+1) = candID2;
850  *(cand_array+2) = candID3;
851  *(cand_array+3) = candID4;
852 
853  return ;
854 }
855 
856 // =====================================================================
857 void FPCCDDigitizer::makeNewSimTHit(SimTrackerHitImpl* simthit, gear::Vector3D* newpos, gear::Vector3D* newmom, int layer, int ladder, double newPathLength){
858 
859  float newdEdx = simthit->getEDep()*newPathLength/simthit->getPathLength();
860  double eta0 = _geodata[layer].rmin+0.5*_pixelheight + ((layer)%2)*(_geodata[layer].sthick-_pixelheight);
861  double pos[3] = {newpos->x()*_geodata[layer].sinphi[ladder]+eta0*_geodata[layer].cosphi[ladder],
862  -newpos->x()*_geodata[layer].cosphi[ladder]+eta0*_geodata[layer].sinphi[ladder],
863  newpos->y()};
864  float mom[3] = {(float)(newmom->x()*_geodata[layer].cosphi[ladder] - newmom->z()*_geodata[layer].sinphi[ladder]),
865  (float)(newmom->x()*_geodata[layer].sinphi[ladder] + newmom->z()*_geodata[layer].cosphi[ladder]),
866  (float)newmom->y()};
867 
868  CellIDEncoder<SimTrackerHitImpl> cellid_encoder( lcio::LCTrackerCellID::encoding_string() , col) ;
869  cellid_encoder[ lcio::LCTrackerCellID::subdet() ] = lcio::ILDDetID::VXD ;
870  cellid_encoder[ lcio::LCTrackerCellID::side() ] = 0 ;
871  cellid_encoder[ lcio::LCTrackerCellID::layer() ] = layer ;
872  cellid_encoder[ lcio::LCTrackerCellID::module() ] = ladder ;
873  cellid_encoder[ lcio::LCTrackerCellID::sensor() ] = 0 ;
874  cellid_encoder.setCellID( simthit );
875  simthit->setEDep( newdEdx );
876  simthit->setPathLength( (float)newPathLength );
877  simthit->setPosition( pos );
878  simthit->setMomentum( mom );
879  return ;
880 }
881 
882 // =====================================================================
884  if(fabs(pos->z()) > 0.5*_pixelheight + 1e-5
885  || fabs(pos->y()) > _geodata[layer].hlength + 1e-5
886  || pos->x() > _geodata[layer].sximax + 1e-5
887  || pos->x() < _geodata[layer].sximin - 1e-5){
888  return false;
889  }
890  else return true;
891 }
std::string _outColNameVTX
std::vector< std::pair< const gear::Vector3D *, int > > getIntersectionOfTrkAndPix(const int layer, gear::Vector3D *top, gear::Vector3D *bottom)
FPCCDDigitizer aFPCCDDigitizer
void getInOutPosOfHelixOnLadder(int layer, gear::Vector3D *outpos, gear::Vector3D *inpos, gear::Vector3D *pos, gear::Vector3D *mom, gear::Vector3D *BField, float charge)
int getLadderID(const gear::Vector3D *pos, const int layer)
virtual void modifyEvent(LCEvent *evt)
CLHEP::Hep3Vector Vector3D
std::map< std::pair< int, int > *, double > getLocalPixel(IMPL::SimTrackerHitImpl *simthit, std::vector< std::pair< const gear::Vector3D *, int > > edgeofpixel)
bool inSensitiveRegion(gear::Vector3D *pos, int layer)
std::vector< GeoData_t > _geodata
virtual void end()
Called after data processing for clean up.
virtual void init()
Called at the begin of the job before anything is read.
void makePixelHits(IMPL::SimTrackerHitImpl *simHit, FPCCDData &pxHits)
bool _ladder_Number_encoded_in_cellID
std::string _colNameVTX
void makeCandidates(std::pair< const gear::Vector3D *, int > edge, std::pair< int, int > *cand_array, int layer)
virtual void processRunHeader(LCRunHeader *run)
Called for every run.
void ModifyIntoLadder(gear::Vector3D *bemodifiedpos, const int layer, gear::Vector3D *pos, gear::Vector3D *mom)
gear::Vector3D * getLocalPos(const gear::Vector3D *pos, const int layer, const int ladder)
int xiID[_ARRAY_NUM]
static const float e
std::pair< int, int > * FindPixel(std::pair< const gear::Vector3D *, int > f_fst, std::pair< const gear::Vector3D *, int > f_nxt, int f_layer)
void makeNewSimTHit(IMPL::SimTrackerHitImpl *simthit, gear::Vector3D *newpos, gear::Vector3D *newmom, int layer, int ladder, double newPathLength)
MCParticle * getMCParticle(ReconstructedParticle *recPart, LCCollection *colMCTL)
Definition: Utilities.cc:30
int zetaID[_ARRAY_NUM]
LCCollection * col
std::vector< LCCollection * > LCCollectionVec
Definition: SiStripClus.h:55
void getInOutPosOnLadder(int layer, gear::Vector3D *outpos, gear::Vector3D *inpos, gear::Vector3D *pos, gear::Vector3D *mom)
FloatVec _pixelSizeVec
virtual const std::string & name() const
int nloopx[_ARRAY_NUM]
virtual void check(LCEvent *evt)
Called for every event - the working horse.
int nloopy[_ARRAY_NUM]