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>
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"
17 #include <marlin/Global.h>
18 #include <gear/GEAR.h>
19 #include <gear/VXDParameters.h>
20 #include <gear/VXDLayerLayout.h>
23 using namespace CLHEP ;
25 using namespace lcio ;
26 using namespace marlin ;
37 _description =
"VTXDigitizer should create VTX TrackerHits from SimTrackerHits" ;
42 registerInputCollection( LCIO::SIMTRACKERHIT,
44 "Name of the SimTrackerHit collection" ,
46 std::string(
"VXDCollection") ) ;
48 registerOutputCollection( LCIO::TRACKERHIT,
49 "OutputCollectionName" ,
50 "Name of the output TrackerHit collection" ,
52 std::string(
"VTXTrackerHits") ) ;
54 registerOutputCollection( LCIO::LCRELATION,
56 "Name of the output VTX trackerhit relation collection" ,
58 std::string(
"VTXRelation") ) ;
60 registerProcessorParameter(
"TanLorentz",
61 "Tangent of Lorentz Angle",
65 registerProcessorParameter(
"CutOnDeltaRays",
66 "Cut on delta-ray energy (MeV)",
70 registerProcessorParameter(
"Diffusion",
71 "Diffusion coefficient (in mm) for layer thickness",
77 registerProcessorParameter(
"PixelSizeX",
83 registerProcessorParameter(
"PixelSizeY",
88 registerProcessorParameter(
"Debug",
95 registerProcessorParameter(
"ElectronsPerKeV",
104 std::vector<float> bkgdHitsInLayer;
105 bkgdHitsInLayer.push_back(34400.);
106 bkgdHitsInLayer.push_back(23900.);
107 bkgdHitsInLayer.push_back(9600.);
108 bkgdHitsInLayer.push_back(5500.);
109 bkgdHitsInLayer.push_back(3100.);
110 registerProcessorParameter(
"BackgroundHitsPerLayer",
111 "Background Hits per Layer",
115 registerProcessorParameter(
"SegmentLength",
120 registerProcessorParameter(
"WidthOfCluster",
126 registerProcessorParameter(
"Threshold",
127 "Cell Threshold in electrons",
131 registerProcessorParameter(
"PoissonSmearing",
132 "Apply Poisson smearing of electrons collected on pixels",
136 registerProcessorParameter(
"ElectronicEffects",
137 "Apply Electronic Effects",
141 registerProcessorParameter(
"ElectronicNoise",
142 "electronic noise in electrons",
146 registerProcessorParameter(
"StoreFiredPixels",
147 "Store fired pixels",
151 registerProcessorParameter(
"UseMCPMomentum",
152 "Use Particle Momentum",
156 registerProcessorParameter(
"EnergyLoss",
157 "Energy Loss keV/mm",
161 registerProcessorParameter(
"RemoveDRayPixels",
162 "Remove D-Ray Pixels",
166 registerProcessorParameter(
"GenerateBackground",
167 "Generate Background",
181 PI = (double)acos((
double)(-1.0));
196 const gear::VXDParameters& gearVXD = Global::GEAR->getVXDParameters() ;
197 const gear::VXDLayerLayout& layerVXD = gearVXD.getVXDLayerLayout();
226 const gear::GearParameters& gearVXDInfra = Global::GEAR->getGearParameters(
"VXDInfra") ;
227 const std::vector<double> laddergaps = gearVXDInfra.getDoubleVals(
"LadderGaps");
228 std::cout<<
"laddergaps size "<<laddergaps.size()<<std::endl;
255 cout<<
" _numberOfLayers "<<_numberOfLayers<<endl;
263 cout<<
"layer "<<i<<endl;
288 LCCollection * STHcol = evt->getCollection(
_colName ) ;
306 int nSTH = STHcol->getNumberOfElements();
308 for (
int i=0; i<nSTH; ++i) {
310 SimTrackerHit * simTrkHit =
311 dynamic_cast<SimTrackerHit*
>(STHcol->getElementAt(i));
349 if (recoHit != NULL) {
354 std::cout <<
"Number of pixels above threshold = 0 " << std::endl;
359 if ( recoHit != NULL) {
362 recoHit->rawHits().push_back(simTrkHit);
364 recoHit->rawHits().push_back(simTrkHit);
367 int nSimHits = int( simTrkHitVec.size() );
368 for (
int iS=0;iS<nSimHits;++iS) {
369 SimTrackerHitImpl * sth = simTrkHitVec[iS];
370 float charge = sth->getEDep();
372 SimTrackerHitImpl * newsth =
new SimTrackerHitImpl();
375 for (
int iC=0;iC<3;++iC)
376 spos[iC] = sth->getPosition()[iC];
378 newsth->setPosition(sLab);
379 newsth->setEDep(charge);
380 STHLocCol->addElement(newsth);
381 recoHit->rawHits().push_back( newsth );
386 float pointResoRPhi=0.004;
387 float pointResoZ=0.004;
388 float covMat[TRKHITNCOVMATRIX]={0.,0.,pointResoRPhi*pointResoRPhi,0.,0.,pointResoZ*pointResoZ};
389 recoHit->setCovMatrix(covMat);
392 recoHit->setType(100+simTrkHit->getCellID0());
393 THcol->addElement( recoHit );
398 for (
int i=0; i < int(simTrkHitVec.size()); ++i) {
399 SimTrackerHit * hit = simTrkHitVec[i];
411 evt->addCollection(STHLocCol,
"VTXPixels");
416 catch(DataNotAvailableException &
e){}
421 if (
_nEvt % 100 == 0)
422 std::cout <<
"Processed " <<
_nEvt <<
"events " << std::endl;
435 std::cout <<
"VTXDigitizer::end() " << name()
436 <<
" processed " <<
_nEvt <<
" events in " <<
_nRun <<
" runs "
444 double * localPosition,
445 double * localDirection) {
466 double xLab[3] = { hit->getPosition()[0],
467 hit->getPosition()[1],
468 hit->getPosition()[2]};
476 double RXY = sqrt(xLab[0]*xLab[0]+
499 layer = hit->getCellID0() - 1;
511 if (xLab[2] < 0.0 ) {
520 if (hit->getMCParticle()) {
521 for (
int j=0; j<3; ++j)
522 Momentum[j] = hit->getMCParticle()->getMomentum()[j];
525 for (
int j=0; j<3; ++j) {
526 Momentum[j] = hit->getMomentum()[j];
532 if (hit->getMCParticle())
537 for (
int i=0; i<3; ++i)
543 double PXY = sqrt(Momentum[0]*Momentum[0]+
544 Momentum[1]*Momentum[1]);
546 double PhiInLab = (double)atan2(xLab[1],xLab[0]);
547 if (PhiInLab < 0.0) PhiInLab +=
TWOPI;
548 double PhiInLabMom = atan2(Momentum[1],Momentum[0]);
549 if (PhiInLabMom < 0.0) PhiInLabMom +=
TWOPI;
568 for (
int ic=0; ic<nLadders; ++ic) {
570 PhiLadder = double(ic)*dPhi + Phi0;
571 PhiInLocal = PhiInLab - PhiLadder;
580 double PhiLocalMom = PhiInLabMom - PhiLadder;
581 localPosition[0] = RXY*sin(PhiInLocal);
582 localPosition[1] = xLab[2];
583 localPosition[2] = RXY*cos(PhiInLocal)-Radius;
584 localDirection[0]=PXY*sin(PhiLocalMom);
585 localDirection[1]=Momentum[2];
586 localDirection[2]=PXY*cos(PhiLocalMom);
593 localPosition[0]=0.0;
594 localPosition[1]=xLab[2];
595 localPosition[2]=RXY-Radius;
596 double PhiLocalMom = PhiInLabMom - PhiInLab;
597 localDirection[0]=PXY*sin(PhiLocalMom);
598 localDirection[1]=Momentum[2];
599 localDirection[2]=PXY*cos(PhiLocalMom);
617 double baseLine = Radius + xLoc[2];
618 double PhiInLab = Phi + atan2(xLoc[0],baseLine);
619 double RXY = sqrt(baseLine*baseLine+xLoc[0]*xLoc[0]);
621 xLab[0] = RXY*cos(PhiInLab);
622 xLab[1] = RXY*sin(PhiInLab);
625 double baseLine = Radius + xLoc[2];
626 double PhiInLab = Phi + xLoc[0]/baseLine;
627 xLab[0] = baseLine*cos(PhiInLab);
628 xLab[1] = baseLine*sin(PhiInLab);
661 for (
int i=0; i<2; ++i) {
662 entry[i]=pos[i]+dir[i]*(entry[2]-pos[2])/dir[2];
663 exit[i]=pos[i]+dir[i]*(exit[2]-pos[2])/dir[2];
666 for (
int i=0; i<3; ++i) {
673 double tanx = dir[0]/dir[2];
674 double tany = dir[1]/dir[2];
698 double x = pos[0]+dir[0]*(z-pos[2])/dir[2];
699 double y = pos[1]+dir[1]*(z-pos[2])/dir[2];
704 double(1000.*dEmean))/1000.;
723 double TanLorentzX = 0;
724 double TanLorentzY = 0;
730 double inverseCosLorentzX = sqrt(1.0+TanLorentzX*TanLorentzX);
731 double inverseCosLorentzY = sqrt(1.0+TanLorentzY*TanLorentzY);
741 double de = ipoint.
eloss;
743 double xOnPlane = x + TanLorentzX*DistanceToPlane;
744 double yOnPlane = y + TanLorentzY*DistanceToPlane;
745 double DriftLength = DistanceToPlane*sqrt(1.0+TanLorentzX*TanLorentzX+TanLorentzY*TanLorentzY);
747 double SigmaX = SigmaDiff*inverseCosLorentzX;
748 double SigmaY = SigmaDiff*inverseCosLorentzY;
770 vectorOfHits.clear();
778 double xCentre = spoint.
x;
779 double yCentre = spoint.
y;
780 double sigmaX = spoint.
sigmaX;
781 double sigmaY = spoint.
sigmaY;
793 int ixLo, ixUp, iyLo, iyUp;
806 for (
int ix = ixLo; ix<ixUp+1; ++ix) {
808 for (
int iy = iyLo; iy<iyUp+1; ++iy) {
810 double xCurrent,yCurrent;
812 gsl_sf_result result;
813 int status = gsl_sf_erf_Q_e(
float((xCurrent - 0.5*
_pixelSizeX - xCentre)/sigmaX), &result);
814 float LowerBound = 1 - result.val;
815 status = gsl_sf_erf_Q_e(
float((xCurrent + 0.5*
_pixelSizeX - xCentre)/sigmaX), &result);
816 float UpperBound = 1 - result.val;
817 float integralX = UpperBound - LowerBound;
818 status = gsl_sf_erf_Q_e(
float((yCurrent - 0.5*
_pixelSizeY - yCentre)/sigmaY), &result);
819 LowerBound = 1 - result.val;
820 status = gsl_sf_erf_Q_e(
float((yCurrent + 0.5*
_pixelSizeY - yCentre)/sigmaY), &result);
821 UpperBound = 1 - result.val;
822 float integralY = UpperBound - LowerBound;
823 float totCharge = float(spoint.
charge)*integralX*integralY;
825 int cellID = 100000*ix + iy;
826 SimTrackerHitImpl * existingHit = 0;
827 for (
int iHits=0; iHits<int(vectorOfHits.size()); ++iHits) {
828 existingHit = vectorOfHits[iHits];
829 int cellid = existingHit->getCellID0();
830 if (cellid == cellID) {
836 float edep = existingHit->getEDep();
838 existingHit->setEDep( edep );
841 SimTrackerHitImpl * hit =
new SimTrackerHitImpl();
843 hit->setPosition( pos );
844 hit->setCellID0( cellID );
845 hit->setEDep( totCharge );
846 vectorOfHits.push_back( hit );
873 double yInLadder = 0.0;
875 yInLadder = y + ladderLength;
878 yInLadder = y - ladderGap;
881 if (yInLadder < 0.0) {
889 double xInLadder = 0.0;
897 if (xInLadder < 0.0) {
909 double & xCell,
double & yCell) {
916 double yInLadder = 0.0;
918 yInLadder = -y - ladderGap;
921 yInLadder = y - ladderGap;
924 if (yInLadder < 0.0) {
933 double xInLadder = 0.0;
941 if (xInLadder < 0.0) {
953 double & x,
double & y) {
970 y = -ladderLength + y;
993 for (
int ihit=0; ihit<int(simTrkVec.size()); ++ihit) {
994 SimTrackerHitImpl * hit = simTrkVec[ihit];
995 double charge = hit->getEDep();
997 if (charge > 1000.) {
998 double sigma = sqrt(charge);
999 rng = double(RandGauss::shoot(charge,sigma));
1003 rng = double(RandPoisson::shoot(charge));
1005 hit->setEDep(
float(rng));
1014 int nPixels = int( simTrkVec.size() );
1017 for (
int i=0;i<nPixels;++i) {
1019 SimTrackerHitImpl * hit = simTrkVec[i];
1020 double charge = hit->getEDep() + Noise ;
1021 hit->setEDep( charge );
1035 double pos[3] = {0,0,0};
1038 int ixmin = 1000000;
1039 int ixmax = -1000000;
1040 int iymin = 1000000;
1041 int iymax = -1000000;
1047 for (
int iHit=0; iHit<int(simTrkVec.size()); ++iHit) {
1048 SimTrackerHit * hit = simTrkVec[iHit];
1052 _amplC[nPixels] = hit->getEDep();
1054 charge += hit->getEDep();
1055 int cellID = hit->getCellID0();
1056 int ix = cellID / 100000 ;
1057 int iy = cellID - 100000 * ix;
1072 for (
int j=0; j<2; ++j)
1073 pos[j] += hit->getEDep()*hit->getPosition()[j];
1079 for (
int j=0; j<2; ++j)
1091 double tanYLorentz = 0;
1108 if (charge > 0. && nPixels > 0) {
1109 TrackerHitImpl * recoHit =
new TrackerHitImpl();
1110 recoHit->setEDep( charge );
1111 for (
int iY=0;iY<20;++iY) {
1115 for (
int iHit=0; iHit<int(simTrkVec.size()); ++iHit) {
1116 SimTrackerHit * hit = simTrkVec[iHit];
1118 float deltaX = hit->getPosition()[0]-pos[0];
1120 deltaX = hit->getPosition()[1]-pos[1];
1122 int cellID = hit->getCellID0();
1123 int ix = cellID / 100000 ;
1124 int iy = cellID - 100000 * ix;
1125 if ((iy - iymin) < 20)
1127 if ((ix - ixmin) < 20)
1129 bool frame = abs(ix-ixSeed) < 2;
1130 frame = frame && abs(iy-iySeed) < 2;
1135 frame = abs(ix-ixSeed) < 3;
1136 frame = frame && abs(iy-iySeed) < 3;
1141 frame = abs(ix-ixSeed) < 4;
1142 frame = frame && abs(iy-iySeed) < 4;
1151 double aXCentre = 0;
1152 double aYCentre = 0;
1153 for (
int i=ixmin+1;i<ixmax;++i) {
1154 aXCentre +=
_amplX[i-ixmin];
1156 for (
int i=iymin+1;i<iymax;++i) {
1157 aYCentre +=
_amplY[i-iymin];
1159 aXCentre = aXCentre/max(1,ixmax-ixmin-1);
1160 aYCentre = aYCentre/max(1,iymax-iymin-1);
1164 for (
int i=ixmin;i<ixmax+1;++i) {
1168 if (i != ixmin && i != ixmax) {
1169 _xRecoS += xx*aXCentre;
1172 _xRecoS += xx*
_amplX[i-ixmin];
1175 _xRecoS = _xRecoS / aTot;
1178 for (
int i=iymin;i<iymax+1;++i) {
1182 if (i != iymin && i != iymax) {
1183 _yRecoS += yy*aYCentre;
1186 _yRecoS += yy*
_amplY[i-iymin];
1189 _yRecoS = _yRecoS / aTot;
1198 recoHit->setPosition( pos );
1210 for (
int i=0; i<3; ++i)
1211 pos[i] = recoHit->getPosition()[i];
1216 recoHit->setPosition( xLab );
1223 std::cout << std::endl;
1225 std::cout <<
"Simulated hit position = "
1226 <<
" " << simHit->getPosition()[0]
1227 <<
" " << simHit->getPosition()[1]
1228 <<
" " << simHit->getPosition()[2] << std::endl;
1230 std::cout <<
"Reconstructed hit position = "
1231 <<
" " << recoHit->getPosition()[0]
1232 <<
" " << recoHit->getPosition()[1]
1233 <<
" " << recoHit->getPosition()[2] << std::endl;
1236 std::cout << std::endl;
1237 std::cout <<
"Type Q to exit display mode" << std::endl;
1239 if (q==
'q' || q==
'Q')
1248 int nHits = int(RandPoisson::shoot(mean));
1249 for (
int ihit=0;ihit<nHits;++ihit) {
1254 if (RandFlat::shoot(
double(1.)) > 0.5) {
1262 int nPhi = int(RandFlat::shoot(xLadders));
1266 TrackerHitImpl * trkHit =
new TrackerHitImpl();
1267 trkHit->setPosition( xLab );
1268 trkHit->setEDep(1000.);
1269 trkHit->setType(ilayer+1);
1270 col->addElement( trkHit );
double _diffusionCoefficient
Diffusion coefficient in mm for nominla layer thickness.
void ProduceHits(SimTrackerHitImplVec &simTrkVec)
std::string _colVTXRelation
std::string _outputCollectionName
double _currentParticleMass
void TransformToLab(double *xLoc, double *xLab)
std::vector< int > _laddersInLayer
void TransformXYToCellID(double x, double y, int &ix, int &iy)
virtual void init()
Initialisation member function.
void GainSmearer(SimTrackerHitImplVec &simTrkVec)
void ProduceSignalPoints()
double _currentLocalPosition[3]
std::vector< float > _layerHalfThickness
std::vector< float > _layerThickness
std::vector< float > _bkgdHitsInLayer
std::vector< float > _layerLadderHalfWidth
MyG4UniversalFluctuationForSi * _fluctuate
virtual void processRunHeader(LCRunHeader *run)
Processing of run header.
std::vector< float > _layerPhiOffset
double _cutOnDeltaRays
cut in MeV on delta electrons used in simulation of charge for each ionisation point ...
double _currentTotalCharge
void PositionWithinCell(double x, double y, int &ix, int &iy, double &xCell, double &yCell)
int _numberOfLayers
layer thickness
void ProduceIonisationPoints(SimTrackerHit *hit)
void TransformCellIDToXY(int ix, int iy, double &x, double &y)
std::vector< float > _layerLadderWidth
void PrintInfo(SimTrackerHit *simTrkHit, TrackerHitImpl *recoHit)
double _currentExitPoint[3]
std::vector< float > _layerActiveSiOffset
SignalPointVec _signalPoints
void TrackerHitToLab(TrackerHitImpl *recoHit)
void generateBackground(LCCollectionVec *col)
std::string _colName
Input collection name.
double _currentParticleMomentum
void PoissonSmearer(SimTrackerHitImplVec &simTrkVec)
std::vector< float > _layerLadderGap
std::vector< SimTrackerHitImpl * > SimTrackerHitImplVec
double _tanLorentzAngle
tangent of Lorentz angle
std::vector< EVENT::SimTrackerHit * > SimTrackerHitVec
IonisationPointVec _ionisationPoints
void FindLocalPosition(SimTrackerHit *hit, double *localPosition, double *localDirection)
Finds coordinates.
TrackerHitImpl * ReconstructTrackerHit(SimTrackerHitImplVec &simTrkVec)
std::vector< LCCollection * > LCCollectionVec
std::vector< float > _layerHalfPhi
double SampleFluctuations(const double momentum, const double mass, double &tmax, const double length, const double meanLoss)
std::vector< float > _layerRadius
virtual void check(LCEvent *evt)
Produces check plots.
virtual void end()
Termination member function.
VTXDigitizer aVTXDigitizer
std::vector< float > _layerLadderLength
double _currentEntryPoint[3]
virtual void processEvent(LCEvent *evt)
Processing of one event.