10 #include "GaudiKernel/SystemOfUnits.h"
12 #define DEFINE_VECTOR(dType, varName, nEles) \
13 std::vector<dType> varName{}; \
14 varName.reserve(nEles);
18 bool sortTracks(std::tuple<int, double>&
a, std::tuple<int, double>&
b) {
19 if (std::get<0>(
a) != std::get<0>(
b)) {
20 return std::get<0>(
a) < std::get<0>(
b);
22 return std::get<1>(
a) < std::get<1>(
b);
32 declareInterface<IMMClusterBuilderTool>(
this);
37 return StatusCode::SUCCESS;
41 std::vector<MMPrepData>&& MMprds,
42 std::vector<std::unique_ptr<MMPrepData>>& clustersVect)
const {
50 MMprdsPerLayer.at(
layer).push_back(std::move(MMprd));
54 for (std::vector<MMPrepData>& prdInLay : MMprdsPerLayer) {
56 return m_idHelperSvc->mmIdHelper().channel(a.identify()) < m_idHelperSvc->mmIdHelper().channel(b.identify());
60 for (std::vector<MMPrepData>& MMprdsOfLayer : MMprdsPerLayer) {
61 std::vector<double> stripsLocalPosX;
62 stripsLocalPosX.reserve(MMprdsOfLayer.size());
67 stripsLocalPosX.push_back(
69 MMprd.localPosition().x());
72 double globalR = MMprd.globalPosition().perp();
73 double Tan =
globalR / MMprd.globalPosition().z();
77 << MMprd.driftDist() <<
" localPosX " <<
Amg::toString(MMprd.localPosition())
78 <<
" angleToIp " << angleToIp);
80 if (MMprdsOfLayer.size() < 2)
continue;
83 double meanX =
std::accumulate(stripsLocalPosX.begin(), stripsLocalPosX.end(), 0.0) / stripsLocalPosX.size();
85 std::for_each(stripsLocalPosX.begin(), stripsLocalPosX.end(), [meanX](
double&
d) { d -= meanX; });
89 std::vector<int>
flag = std::vector<int>(MMprdsOfLayer.size(), 0);
93 std::vector<int> idx_goodStrips;
98 if (idx_goodStrips.size() < 3 ||
sc.isFailure()) {
100 idx_goodStrips.clear();
101 for (
size_t i_hit = 0; i_hit < MMprdsOfLayer.size(); i_hit++) {
102 if (
flag.at(i_hit) == 0) idx_goodStrips.push_back(i_hit);
108 int nStripsCutByCrosstalk = 0;
109 while (!
applyCrossTalkCut(idx_goodStrips, MMprdsOfLayer,
flag, nStripsCutByCrosstalk).isFailure()) {}
110 ATH_MSG_DEBUG(
"After cutting CT idx_goddStrips " << idx_goodStrips <<
" flag " <<
flag);
112 std::vector<Identifier> stripsOfCluster;
113 std::vector<uint16_t> stripsOfClusterChannels;
114 std::vector<short int> stripsOfClusterTimes;
115 std::vector<int> stripsOfClusterCharges;
116 std::vector<float> stripsOfClusterDriftDists;
117 std::vector<
AmgVector(2)> stripsOfClusterDriftDistErrors;
118 std::vector<float> stripsOfClusterLocalPos;
119 stripsOfCluster.reserve(idx_goodStrips.size());
121 stripsOfClusterTimes.reserve(idx_goodStrips.size());
122 stripsOfClusterCharges.reserve(idx_goodStrips.size());
123 stripsOfClusterDriftDists.reserve(idx_goodStrips.size());
124 stripsOfClusterDriftDistErrors.reserve(idx_goodStrips.size());
125 stripsOfClusterLocalPos.reserve(idx_goodStrips.size());
127 ATH_MSG_DEBUG(
"Found good Strips: " << idx_goodStrips.size());
129 for (
int idx : idx_goodStrips) {
133 stripsOfCluster.push_back(MMprdsOfLayer.at(
idx).identify());
135 stripsOfClusterChannels.push_back(
m_idHelperSvc->mmIdHelper().channel(MMprdsOfLayer.at(
idx).identify()));
136 stripsOfClusterTimes.push_back(MMprdsOfLayer.at(
idx).time());
137 stripsOfClusterCharges.push_back(MMprdsOfLayer.at(
idx).charge());
139 stripsOfClusterDriftDists.push_back(MMprdsOfLayer.at(
idx).driftDist());
141 stripsOfClusterDriftDistErrors.emplace_back(
cov(0,0),
cov(1,1));
142 stripsOfClusterLocalPos.push_back(MMprdsOfLayer.at(
idx).localPosition().x());
145 double localClusterPosition = -9999;
146 double sigmaLocalClusterPosition = 0;
147 double finalFitAngle, finalFitChiSqProb;
149 sc =
finalFit(stripsOfCluster, stripsOfClusterLocalPos, stripsOfClusterDriftDists, stripsOfClusterDriftDistErrors,
150 localClusterPosition, sigmaLocalClusterPosition, finalFitAngle, finalFitChiSqProb);
154 if (
sc.isFailure())
break;
158 covN.coeffRef(0, 0) = sigmaLocalClusterPosition;
160 int idx = idx_goodStrips[0];
161 ATH_MSG_DEBUG(
"idx_goodStrips[0]: " <<
idx <<
" size: " << MMprdsOfLayer.size());
163 MMprdsOfLayer.at(
idx).localPosition().y());
166 float driftDist = 0.0;
168 std::unique_ptr<MMPrepData> prdN = std::make_unique<MMPrepData>(MMprdsOfLayer.at(
idx).identify(),
169 MMprdsOfLayer.at(
idx).collectionHash(),
170 std::move(localClusterPositionV),
171 std::move(stripsOfCluster),
173 MMprdsOfLayer.at(
idx).detectorElement(),
175 std::accumulate(stripsOfClusterCharges.begin(), stripsOfClusterCharges.end(), 0),
177 std::move(stripsOfClusterChannels),
178 std::move(stripsOfClusterTimes),
179 std::move(stripsOfClusterCharges));
183 ATH_MSG_DEBUG(
"Setting prd angle: " << finalFitAngle <<
" chi2 Prob: " << finalFitChiSqProb);
186 prdN->setDriftDist(std::move(stripsOfClusterDriftDists), std::move(stripsOfClusterDriftDistErrors));
188 prdN->setMicroTPC(finalFitAngle, finalFitChiSqProb);
189 ATH_MSG_DEBUG(
"Reading back prd angle: " << prdN->angle() <<
" chi2 Prob: " << prdN->chisqProb());
190 clustersVect.push_back(std::move(prdN));
192 int leftOverStrips = 0;
193 for (
auto f :
flag) {
194 if (
f == 0) leftOverStrips++;
196 if (leftOverStrips < 3)
break;
201 return StatusCode::SUCCESS;
205 std::vector<int>&
flag, std::vector<int>& idx_selected)
const {
206 ATH_MSG_DEBUG(
"beginning of runHoughTrafo() with: " << xpos.size() <<
" hits");
207 double maxX = *std::max_element(xpos.begin(), xpos.end());
208 double minX = *std::min_element(xpos.begin(), xpos.end());
209 std::unique_ptr<TH2D> h_hough =
nullptr;
212 if (
sc.isFailure())
return sc;
215 if (
sc.isFailure())
return sc;
217 std::vector<std::tuple<double, double>> houghPeaks;
219 if (
sc.isFailure())
return sc;
222 if (
sc.isFailure())
return sc;
223 return StatusCode::SUCCESS;
229 dmax = std::sqrt(
std::pow(dmax, 2) +
231 int nbinsd =
static_cast<int>(1.0 * dmax * 2 /
m_dResolution);
234 ATH_MSG_VERBOSE(
"Hough Using nBinsA " << nbinsa <<
" nBinsd " << nbinsd <<
" dmax " << dmax);
237 nbinsd, -dmax, dmax);
239 return StatusCode::SUCCESS;
243 std::vector<int>&
flag, std::unique_ptr<TH2D>& h_hough)
const {
244 for (
size_t i_hit = 0; i_hit < mmPrd.size(); i_hit++) {
245 if (
flag.at(i_hit) != 0)
continue;
246 for (
int i_alpha = 1; i_alpha < h_hough->GetNbinsX(); i_alpha++) {
247 double alpha = h_hough->GetXaxis()->GetBinCenter(i_alpha);
248 double d = xpos.at(i_hit) *
std::cos(alpha) - mmPrd.at(i_hit).driftDist() *
std::sin(alpha);
249 ATH_MSG_VERBOSE(
"Fill Hough alpha: " << alpha <<
" d " <<
d <<
" x " << xpos.at(i_hit) <<
" y " << mmPrd.at(i_hit).driftDist());
250 h_hough->Fill(alpha,
d);
253 return StatusCode::SUCCESS;
257 std::vector<std::tuple<double, double>>& maxPos)
const {
258 unsigned int cmax = h_hough->GetMaximum();
261 return StatusCode::FAILURE;
264 for (
int i_binX = 0; i_binX <= h_hough->GetNbinsX(); i_binX++) {
265 for (
int i_binY = 0; i_binY <= h_hough->GetNbinsY(); i_binY++) {
266 if (h_hough->GetBinContent(i_binX, i_binY) == cmax) {
269 <<
" BinY: " << i_binY <<
" over threshold: " << h_hough->GetBinContent(i_binX, i_binY));
270 maxPos.emplace_back(h_hough->GetXaxis()->GetBinCenter(i_binX), h_hough->GetYaxis()->GetBinCenter(i_binY));
274 return StatusCode::SUCCESS;
278 std::vector<int>&
flag, std::vector<std::tuple<double, double>>& tracks,
279 std::vector<int>& idxGoodStrips)
const {
280 std::vector<double>
chi2;
281 std::vector<std::vector<int>> allGoodStrips;
282 std::vector<int> ngoodStrips;
283 std::vector<std::tuple<int, double>> trackQuality;
284 for (
auto track : tracks) {
285 double houghAngle = std::get<0>(
track);
286 double houghD = std::get<1>(
track);
287 double slope, intercept;
291 if (
sc.isFailure()) {
return sc; }
292 std::vector<double> dist;
293 std::vector<int> indexUsedForDist, goodStrips;
294 for (
size_t i_hit = 0; i_hit < xpos.size(); i_hit++) {
295 if (
flag.at(i_hit) != 1) {
296 dist.push_back(mmPrd.at(i_hit).driftDist() - slope * xpos.at(i_hit) - intercept);
297 indexUsedForDist.push_back(i_hit);
303 for (
size_t i_hit : indexUsedForDist) {
304 double d = mmPrd.at(i_hit).driftDist() - slope * xpos.at(i_hit) - intercept;
307 dist.push_back(
d *
d / mmPrd.at(i_hit).localCovariance()(1, 1));
308 goodStrips.push_back(i_hit);
326 if (!goodStrips.empty()) {
327 allGoodStrips.push_back(goodStrips);
329 trackQuality.emplace_back(goodStrips.size(),
std::accumulate(dist.begin(), dist.end(), 0.0) / (dist.size() - 2));
332 if (
chi2.empty())
return StatusCode::FAILURE;
333 int trackIndex = std::min_element(trackQuality.begin(), trackQuality.end(),
sortTracks) - trackQuality.begin();
334 idxGoodStrips = allGoodStrips.at(trackIndex);
335 return StatusCode::SUCCESS;
339 double& interceptRMS)
const {
342 interceptRMS = std::fabs(dRMS);
343 ATH_MSG_VERBOSE(
"transformParameters alpha: " << alpha <<
" d: " <<
d <<
" dRMS: " << dRMS <<
" slope: " << slope
344 <<
" intercept: " << intercept);
345 return StatusCode::SUCCESS;
349 std::vector<int>&
flag,
int& nStripsCut)
const {
350 int N = idxSelected.size();
351 bool removedStrip =
false;
352 ATH_MSG_DEBUG(
"starting to remove cross talk strips " << idxSelected <<
" flag " <<
flag);
355 return StatusCode::FAILURE;
358 double ratioLastStrip = 1.0 * MMPrdsOfLayer.at(idxSelected.at(
N - 1)).charge() / MMPrdsOfLayer.at(idxSelected.at(
N - 2)).charge();
359 double ratioFirstStrip = 1.0 * MMPrdsOfLayer.at(idxSelected.at(0)).charge() / MMPrdsOfLayer.at(idxSelected.at(1)).charge();
360 ATH_MSG_DEBUG(
"ratioLastStrip " << ratioLastStrip <<
" ratioFirstStrip " << ratioFirstStrip);
362 flag.at(idxSelected.at(
N - 1)) = 2;
363 idxSelected.erase(idxSelected.begin() + (
N - 1));
366 ATH_MSG_DEBUG(
"cutting last strip nStripCuts: " << nStripsCut <<
" flag " <<
flag <<
" idxSelected " << idxSelected);
370 return StatusCode::FAILURE;
374 flag.at(idxSelected.at(0)) = 2;
375 idxSelected.erase(idxSelected.begin() + 0);
378 ATH_MSG_DEBUG(
"cutting first strip nStripCuts: " << nStripsCut <<
" flag " <<
flag <<
" idxSelected " << idxSelected);
382 return StatusCode::FAILURE;
384 ATH_MSG_DEBUG(
"return value " << (!removedStrip ?
"FAILURE" :
"SUCCESS"));
385 return (!removedStrip ? StatusCode::FAILURE : StatusCode::SUCCESS);
389 const std::vector<float>& driftDists,
const std::vector<
AmgVector(2)>& driftDistErrors,
390 double& x0,
double& sigmaX0,
double& fitAngle,
double& chiSqProb)
const {
391 std::unique_ptr<TGraphErrors> fitGraph = std::make_unique<TGraphErrors>();
392 std::unique_ptr<TF1> ffit = std::make_unique<TF1>(
"ffit",
"pol1");
396 double xmean =
std::accumulate(stripsPos.begin(), stripsPos.end(), 0.0) / stripsPos.size();
398 std::unique_ptr<TLinearFitter>
lf = std::make_unique<TLinearFitter>(1,
"1++x");
400 for (
size_t idx = 0;
idx < stripsPos.size();
idx++) {
401 double xpos = stripsPos.at(
idx) - xmean;
404 else if (
xmax < xpos)
406 lf->AddPoint(&xpos, driftDists.at(
idx));
407 fitGraph->SetPoint(fitGraph->GetN(), xpos, driftDists.at(
idx));
408 fitGraph->SetPointError(fitGraph->GetN() - 1, std::sqrt(driftDistErrors.at(
idx)[0]), std::sqrt(driftDistErrors.at(
idx)[1]));
413 ffit->SetParLimits(1, -11.5, -0.15);
415 ffit->SetParLimits(1, 0.15, 11.5);
417 ffit->SetParameters(
lf->GetParameter(0),
lf->GetParameter(1));
418 TFitResultPtr
s = fitGraph->Fit(
"ffit",
"SMQ",
"",
xmin - .5,
xmax + .5);
420 double cov = (
s->GetCovarianceMatrix())(0, 1);
422 double fitSlope = ffit->GetParameter(1);
423 double dHalfGap = 2.52;
424 double interceptCorr = dHalfGap - ffit->GetParameter(0);
425 x0 = interceptCorr / fitSlope;
427 (
std::pow(ffit->GetParError(0) / interceptCorr, 2) +
std::pow(ffit->GetParError(1) / fitSlope, 2) - 2. / (fitSlope * interceptCorr) *
cov) *
431 chiSqProb = ffit->GetProb();
442 ATH_MSG_DEBUG(
"Cluster position " << x0 <<
" +- " << sigmaX0);
450 if (
s != 0 &&
s != 4000) {
452 return StatusCode::FAILURE;
455 (ffit->GetParameter(1) <= -11.49 || ffit->GetParameter(1) >= -0.151))
456 return StatusCode::FAILURE;
458 (ffit->GetParameter(1) >= 11.49 || ffit->GetParameter(1) <= 0.151))
459 return StatusCode::FAILURE;
460 return StatusCode::SUCCESS;
464 const std::vector<NSWCalib::CalibratedStrip>& calibratedStrips,
469 std::vector<Identifier>
ids;
470 std::vector<float> stripsPos;
471 std::vector<float> driftDists;
472 std::vector<
AmgVector(2)> driftDistErrors;
475 ids.push_back(strip.identifier);
476 stripsPos.push_back(strip.locPos.x());
477 driftDists.push_back(strip.distDrift);
478 driftDistErrors.emplace_back(strip.resTransDistDrift, strip.resLongDistDrift);
481 double localClusterPosition = -9999;
482 double sigmaLocalClusterPosition = 0;
483 double finalFitAngle, finalFitChiSqProb;
485 StatusCode sc =
finalFit(
ids, stripsPos, driftDists, driftDistErrors, localClusterPosition, sigmaLocalClusterPosition, finalFitAngle,
487 if (
sc == StatusCode::FAILURE)
return RIO_Author::unKnownAuthor;
489 clusterLocalPosition[
Trk::locX] = localClusterPosition;
492 covN.coeffRef(0, 0) = sigmaLocalClusterPosition;
494 return RIO_Author::uTPCClusterBuilder;