7 #define _USE_MATH_DEFINES
11 #include <marlin/Global.h>
12 #include <marlin/Processor.h>
13 #include <marlin/AIDAProcessor.h>
16 #include <EVENT/LCCollection.h>
17 #include <EVENT/Track.h>
18 #include <EVENT/TrackerHit.h>
19 #include <IMPL/TrackImpl.h>
21 #include <DD4hep/Detector.h>
22 #include <DDRec/DetectorData.h>
23 #include <DD4hep/DD4hepUnits.h>
25 #include <UTIL/BitField64.h>
26 #include "UTIL/LCTrackerConf.h"
29 #include "LCGeometryTypes.h"
30 #include "SimpleHelix.h"
31 #include "HelixClass.h"
42 : Processor(
"Compute_dEdxProcessor") {
45 _description =
"dE/dx calculation using truncation method" ;
47 registerInputCollection(LCIO::TRACK,
49 "LDC track collection name",
51 std::string(
"MarlinTrkTracks"));
53 registerProcessorParameter(
"Write_dEdx",
54 "If set, the calculated dEdx value will be attached to its corresponding track (default: true).",
58 registerProcessorParameter(
"EnergyLossErrorTPC",
59 "Fractional error of dEdx in the TPC",
63 registerProcessorParameter(
"LowerTruncationFraction",
64 "Lower truncation fraction, default: 0.08 (8%)",
68 registerProcessorParameter(
"UpperTruncationFraction",
69 "Upper truncation fraction, default: 0.3 (30%)",
73 registerProcessorParameter(
"isSmearing",
74 "Flag for dEdx Smearing",
78 registerProcessorParameter(
"smearingFactor",
79 "Smearing factor for dEdx smearing",
83 registerProcessorParameter(
"NumberofHitsCorrectionParameters",
84 "parameters for number of hits correction",
88 std::vector<float> apar = {0.635762, -0.0573237};
89 registerProcessorParameter(
"AngularCorrectionParameters",
90 "parameters for angular correction",
94 std::vector<float> errexp = {-0.34, -0.45};
95 registerProcessorParameter(
"dEdxErrorScalingExponents",
96 "scaling exponents of the dE/dx error for path length and number of hits, respectively",
100 registerProcessorParameter(
"dxStrategy",
101 "ID of the track length calculation: 1 - hit-to-hit distance; 2 - hit-to-hit path length of projected hits; 3 - path over hit row",
105 registerProcessorParameter(
"StrategyCompHist",
106 "If set, an AIDA root file will be generated with Bethe-Bloch histograms (dE/dx over momentum) for each dx strategy (default: false).",
110 registerProcessorParameter(
"StrategyCompHistWeight",
111 "If set, the Bethe-Bloch histograms will have a sqrt(nHits) weighting (default: false).",
115 registerProcessorParameter(
"StrategyCompHistFiles",
116 "File names of the generated dx strategy comparison histograms (if chosen). The respective strategy number and '.png' is added.",
118 std::string(
"dEdx_Histo_Strategy"));
124 streamlog_out(DEBUG) <<
" init called " << std::endl ;
130 dd4hep::Detector& lcdd = dd4hep::Detector::getInstance();
131 dd4hep::DetElement tpcDE = lcdd.detector(
"TPC") ;
132 const dd4hep::rec::FixedPadSizeTPCData* tpc = tpcDE.extension<dd4hep::rec::FixedPadSizeTPCData>() ;
137 lcdd.field().magneticField( { 0., 0., 0. } , bfieldV ) ;
138 _bField = bfieldV[2]/dd4hep::tesla ;
140 engine =
new std::default_random_engine();
142 streamlog_out(MESSAGE) <<
"TPC inner radius = " << _TPC_inner <<
" mm TPC outer radius = " <<
_TPC_outer <<
" mm"<< std::endl;
143 streamlog_out(MESSAGE) <<
"TPC pad height = " <<
_TPC_padHeight <<
" mm B field = " <<
_bField <<
" T" <<std::endl;
144 streamlog_out(DEBUG) <<
"dd4hep::mm = " <<
dd4hep::mm <<
" dd4hep::cm = " <<
dd4hep::cm << std::endl;
149 const int nBinsX=1000, nBinsY=300;
150 double minBinX=-1, maxBinX=2;
151 double minBinY= 0, maxBinY=1
e-6;
152 double histbinsX[nBinsX+1], histbinsY[nBinsY+1];
153 for (
int i=0; i<nBinsX+1; i++) histbinsX[i] = pow( 10, minBinX + (maxBinX-minBinX)*i/(
float)(nBinsX) );
154 for (
int i=0; i<nBinsY+1; i++) histbinsY[i] = minBinY + (maxBinY-minBinY)*i/(float)(nBinsY);
157 AIDAProcessor::tree(
this);
158 _BBHist_Strategy1 =
new TH2D(
"BBHist_Strategy1",
"Bethe-Bloch curve for dx strategy 1: hit-to-hit distance",nBinsX,histbinsX,nBinsY,histbinsY);
159 _BBHist_Strategy2 =
new TH2D(
"BBHist_Strategy2",
"Bethe-Bloch curve for dx strategy 2: hit-to-hit path length of projected hits",nBinsX,histbinsX,nBinsY,histbinsY);
160 _BBHist_Strategy3 =
new TH2D(
"BBHist_Strategy3",
"Bethe-Bloch curve for dx strategy 3: path over hit row",nBinsX,histbinsX,nBinsY,histbinsY);
169 int nTrkCand =
_LDCCol->getNumberOfElements();
171 for (
int iTRK=0;iTRK<nTrkCand;++iTRK) {
173 TrackImpl * trkCand = (TrackImpl*)
_LDCCol->getElementAt( iTRK );
174 TrackerHitVec trkHits = trkCand->getTrackerHits();
182 TrackerHitVec tpcHitVec;
183 for(
unsigned int sdet=0;sdet<trkHits.size(); sdet++){
184 if(trkHits[sdet]->getType() == 0){
186 float x=trkHits[sdet]->getPosition()[0];
187 float y=trkHits[sdet]->getPosition()[1];
189 else streamlog_out(DEBUG) <<
"hit not in TPC: " << x <<
" " << y <<
" " << trkHits[sdet]->getPosition()[2] <<
" " << sqrt(x*x+y*y) << std::endl;
200 trkCand->setdEdx(dedx);
201 trkCand->setdEdxError(unum);
213 TCanvas *can =
new TCanvas;
214 TImage *img = TImage::Create();
215 gStyle->SetPalette(kBird);
248 int tH=hitVec.size();
251 const float* refPoint = trk->getReferencePoint();
252 LCVector3D refPointV3D = LCVector3D(refPoint[0],refPoint[1],refPoint[2]);
253 SimpleHelix trkHelix = SimpleHelix(trk->getD0(),trk->getPhi(),trk->getOmega(),trk->getZ0(),trk->getTanLambda(),refPointV3D);
254 HelixClass trkHelixC;
255 trkHelixC.Initialize_Canonical(trk->getPhi(),trk->getD0(),trk->getZ0(),trk->getOmega(),trk->getTanLambda(),
_bField);
258 std::vector<double> dEdxVec1, dEdxVec2, dEdxVec3;
259 double dx=0, dy=0, dz=0, length=0, totlength=0;
260 double dxy=0, r=0, theta=0, l=0;
261 double path=0, totpath=0, cpath=0;
262 double over=0, totover=0, cover=0;
263 double hitX =0, hitY =0, hitZ =0;
264 double hit0X=0, hit0Y=0, hit0Z=0;
266 for(
int iH=0; iH<tH; iH++){
267 TrackerHit * hit = hitVec[iH];
268 hitX = hit ->getPosition()[0];
269 hitY = hit ->getPosition()[1];
270 hitZ = hit ->getPosition()[2];
276 TrackerHit * hit0 = hitVec[iH-1];
277 hit0X = hit0->getPosition()[0];
278 hit0Y = hit0->getPosition()[1];
279 hit0Z = hit0->getPosition()[2];
288 dxy=sqrt(dx*dx+dy*dy);
289 r=1.0/trk->getOmega();
290 theta=2.0*asin(0.5*dxy/r);
293 length=sqrt(l*l+dz*dz);
297 dEdxVec1.push_back(hit->getEDep()/length);
302 double path1 = trkHelix.getPathAt(LCVector3D(hitX ,hitY ,hitZ ));
303 double path2 = trkHelix.getPathAt(LCVector3D(hit0X,hit0Y,hit0Z));
304 path = fabs(path2-path1);
306 dEdxVec2.push_back(hit->getEDep()/path);
315 double hitRadius = sqrt(hitX*hitX + hitY*hitY);
321 trkRefP[0] = (trkHelixC.getReferencePoint())[0];
322 trkRefP[1] = (trkHelixC.getReferencePoint())[1];
323 trkRefP[2] = (trkHelixC.getReferencePoint())[2];
324 float cross1[6], cross2[6];
325 float time1 = trkHelixC.getPointOnCircle(cyl1_radius, trkRefP, cross1);
326 float time2 = trkHelixC.getPointOnCircle(cyl2_radius, trkRefP, cross2);
328 bool rejected =
false;
329 if (fabs(time1)<1
e+10 && fabs(time2)<1
e+10) {
330 if (sqrt(pow(cross1[0]-cross1[3],2) + pow(cross1[1]-cross1[4],2) + pow(cross1[2]-cross1[5],2)) < 2*
_TPC_padHeight) rejected =
true;
331 if (sqrt(pow(cross2[0]-cross2[3],2) + pow(cross2[1]-cross2[4],2) + pow(cross2[2]-cross2[5],2)) < 2*
_TPC_padHeight) rejected =
true;
333 else rejected =
true;
337 float* cross_1 = cross1;
338 double dist1 = sqrt(pow(cross1[0]-hitX,2) + pow(cross1[1]-hitY,2) + pow(cross1[2]-hitZ,2));
339 double dist2 = sqrt(pow(cross1[3]-hitX,2) + pow(cross1[4]-hitY,2) + pow(cross1[5]-hitZ,2));
340 if (dist2 < dist1) cross_1 = &cross1[3];
341 float* cross_2 = cross2;
342 dist1 = sqrt(pow(cross2[0]-hitX,2) + pow(cross2[1]-hitY,2) + pow(cross2[2]-hitZ,2));
343 dist2 = sqrt(pow(cross2[3]-hitX,2) + pow(cross2[4]-hitY,2) + pow(cross2[5]-hitZ,2));
344 if (dist2 < dist1) cross_2 = &cross2[3];
347 dxy = sqrt(pow(cross_1[0]-cross_2[0],2) + pow(cross_1[1]-cross_2[1],2));
348 r = 1./trk->getOmega();
349 l = r*2.*asin(0.5*dxy/r);
350 over= sqrt(l*l + pow(cross_1[2]-cross_2[2],2));
354 dEdxVec3.push_back(hit->getEDep()/over);
358 streamlog_out(DEBUG3) <<
"1: " << length <<
" 2: " << path <<
" 3: " << over <<
" EDep: " << hit->getEDep() << std::endl;
359 if (length/over>1.5 || over/length>1.5) streamlog_out(DEBUG2) <<
" " << hitX <<
" " << hitY <<
" " << hitZ <<
" " << sqrt(hitX*hitX + hitY*hitY) << std::endl;
361 streamlog_out(DEBUG4) <<
"1: " << totlength <<
" 2: " << totpath <<
" of " << cpath <<
" 3: " << totover <<
" of " << cover << std::endl;
365 double normdedx=0, totway=0;
366 double trkcos = sqrt(trk->getTanLambda()*trk->getTanLambda()/(1.0+trk->getTanLambda()*trk->getTanLambda()));
372 double dedx1=0, dedx2=0, dedx3=0;
373 int nTruncate1=0, nTruncate2=0, nTruncate3=0;
375 std::sort(dEdxVec1.begin(),dEdxVec1.end());
376 std::sort(dEdxVec2.begin(),dEdxVec2.end());
377 std::sort(dEdxVec3.begin(),dEdxVec3.end());
384 dedx1 = dedx1/(float)(nTruncate1);
385 dedx2 = dedx2/(float)(nTruncate2);
386 dedx3 = dedx3/(float)(nTruncate3);
387 streamlog_out(DEBUG4) <<
" check dedx: " << dedx1 <<
" " << dedx2 <<
" " << dedx3 << std::endl;
399 double lmom = sqrt(pow(trkHelixC.getMomentum()[0],2) + pow(trkHelixC.getMomentum()[1],2) + pow(trkHelixC.getMomentum()[2],2));
414 case 1: normdedx = normdedx1; nTruncate = nTruncate1; totway = totlength;
break;
415 case 2: normdedx = normdedx2; nTruncate = nTruncate2; totway = totpath;
break;
416 case 3: normdedx = normdedx3; nTruncate = nTruncate3; totway = totover;
break;
422 std::vector<double> dEdxVec;
425 case 1: dEdxVec = dEdxVec1; totway = totlength;
break;
426 case 2: dEdxVec = dEdxVec2; totway = totpath;
break;
427 case 3: dEdxVec = dEdxVec3; totway = totover;
break;
430 std::sort(dEdxVec.begin(),dEdxVec.end());
432 dedx = dedx/(float)(nTruncate);
438 std::pair<double,double> ret;
439 if(std::isnan(normdedx))
443 streamlog_out(DEBUG4) <<
"NAN!" << std::endl;
448 ret.second=normdedx*std::pow(0.001*totway,
_errexp[0])*std::pow(nTruncate,
_errexp[1]);
457 double f1 = 1 + std::exp(-nHit/
_ncorrpar);
virtual void processRunHeader(LCRunHeader *run)
virtual void check(LCEvent *evt)
std::string _LDCTrackCollection
float _energyLossErrorTPC
double getNormalization(double dedx, float hit, double trkcos)
std::string _StratCompHistFiles
bool _StratCompHistWeight
std::pair< double, double > CalculateEnergyLoss(TrackerHitVec &hitVec, Track *trk)
std::vector< float > _acorrpar
std::uniform_real_distribution dist
std::vector< float > _errexp
std::default_random_engine * engine
Compute_dEdxProcessor aCompute_dEdxProcessor
Compute dE/dx Processor This processor calculates the dE/dx for every track.
double getSmearing(double dEdx)
virtual void processEvent(LCEvent *evt)