File indexing completed on 2025-12-16 09:20:22
0001 #include "LaserClusterizer.h"
0002
0003 #include "LaserEventInfo.h"
0004
0005 #include <trackbase/LaserCluster.h>
0006 #include <trackbase/LaserClusterContainer.h>
0007 #include <trackbase/LaserClusterContainerv1.h>
0008 #include <trackbase/LaserClusterv2.h>
0009 #include <trackbase/TpcDefs.h>
0010 #include <trackbase/TrkrDefs.h> // for hitkey, getLayer
0011 #include <trackbase/TrkrHit.h>
0012 #include <trackbase/TrkrHitSet.h>
0013 #include <trackbase/TrkrHitSetContainer.h>
0014
0015 #include <ffaobjects/EventHeader.h>
0016 #include <fun4all/Fun4AllReturnCodes.h>
0017 #include <fun4all/SubsysReco.h> // for SubsysReco
0018
0019 #include <g4detectors/PHG4TpcGeom.h>
0020 #include <g4detectors/PHG4TpcGeomContainer.h>
0021
0022 #include <phool/PHCompositeNode.h>
0023 #include <phool/PHIODataNode.h> // for PHIODataNode
0024 #include <phool/PHNode.h> // for PHNode
0025 #include <phool/PHNodeIterator.h>
0026 #include <phool/PHObject.h> // for PHObject
0027 #include <phool/PHTimer.h>
0028 #include <phool/getClass.h>
0029 #include <phool/phool.h> // for PHWHERE
0030
0031 #include <Acts/Definitions/Units.hpp>
0032 #include <Acts/Surfaces/Surface.hpp>
0033
0034 #include <TF1.h>
0035 #include <TFile.h>
0036 #include <TH3.h>
0037
0038
0039 #include <Fit/Fitter.h>
0040
0041
0042 #include <boost/geometry.hpp>
0043 #include <boost/geometry/geometries/box.hpp>
0044 #include <boost/geometry/geometries/point.hpp>
0045 #include <boost/geometry/index/rtree.hpp>
0046
0047 #include <array>
0048 #include <cmath> // for sqrt, cos, sin
0049 #include <iostream>
0050 #include <limits>
0051 #include <map> // for _Rb_tree_cons...
0052 #include <string>
0053 #include <utility> // for pair
0054 #include <vector>
0055 #include <set>
0056 #include <queue>
0057 #include <tuple>
0058
0059 #include <pthread.h>
0060
0061 namespace bg = boost::geometry;
0062 namespace bgi = boost::geometry::index;
0063
0064 using point = bg::model::point<float, 3, bg::cs::cartesian>;
0065 using box = bg::model::box<point>;
0066 using specHitKey = std::pair<TrkrDefs::hitkey, TrkrDefs::hitsetkey>;
0067 using adcKey = std::pair<unsigned int, specHitKey>;
0068 using pointKeyLaser = std::pair<point, specHitKey>;
0069 using hitData = std::pair<point, adcKey>;
0070
0071
0072 int layerMins[3] = {7,23,39};
0073 int layerMaxes[3] = {22, 38, 54};
0074
0075
0076
0077 namespace
0078 {
0079 struct thread_data
0080 {
0081 PHG4TpcGeomContainer *geom_container = nullptr;
0082 ActsGeometry *tGeometry = nullptr;
0083 std::vector<TrkrHitSet *> hitsets;
0084 std::vector<unsigned int> layers;
0085 bool side = false;
0086 unsigned int sector = 0;
0087 unsigned int module = 0;
0088 std::vector<LaserCluster *> cluster_vector;
0089 std::vector<TrkrDefs::cluskey> cluster_key_vector;
0090 double adc_threshold = 74.4;
0091 int peakTimeBin = 325;
0092 int layerMin = 1;
0093 int layerMax = 1;
0094 double tdriftmax = 0;
0095 int eventNum = 0;
0096 int Verbosity = 0;
0097 TH3D *hitHist = nullptr;
0098 bool doFitting = false;
0099 };
0100
0101 pthread_mutex_t mythreadlock;
0102
0103 const std::vector<point> neighborOffsets = {
0104 point(1, 0, 0), point(-1, 0, 0),
0105 point(0, 1, 0), point(0, -1, 0),
0106 point(0, 0, 1), point(0, 0, -1),
0107 point(0, 0, 2), point(0, 0, -2)
0108 };
0109
0110
0111 double layerFunction(double *x, double *par)
0112 {
0113 double A = par[0];
0114 double mu = par[1];
0115
0116
0117 double binCenter = round(x[0]);
0118 double overlapLow = std::max(binCenter - 0.5, mu - 0.5);
0119 double overlapHigh = std::min(binCenter + 0.5, mu + 0.5);
0120 double overlap = overlapHigh - overlapLow;
0121 if(overlap <= 0.0)
0122 {
0123 return 0.0;
0124 }
0125 return A*overlap;
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136 }
0137
0138 double phiFunction(double *x, double *par)
0139 {
0140 if(par[2] < 0.0)
0141 {
0142 return 0.0;
0143 }
0144 return par[0] * TMath::Gaus(x[0],par[1],par[2],false);
0145 }
0146
0147 double timeFunction(double *x, double *par)
0148 {
0149 if(par[2] < 0.0)
0150 {
0151 return 0.0;
0152 }
0153 double g = TMath::Gaus(x[0],par[1],par[2],true);
0154 double cdf = 1 + TMath::Erfc(par[3]*(x[0]-par[1])/(sqrt(2.0)*par[2]));
0155 return par[0]*g*cdf;
0156 }
0157
0158 void findConnectedRegions3(std::vector<hitData> &clusHits, std::pair<TrkrDefs::hitkey, TrkrDefs::hitsetkey> &maxKey)
0159 {
0160 std::vector<std::vector<hitData>> regions;
0161
0162 std::vector<hitData> unvisited;
0163 for(auto &clusHit : clusHits)
0164 {
0165 unvisited.push_back(clusHit);
0166 }
0167
0168 while(!unvisited.empty())
0169 {
0170 std::vector<hitData> region;
0171 std::queue<hitData> q;
0172
0173 unsigned int mIndex = 0;
0174 int i=0;
0175 for(auto hit : unvisited)
0176 {
0177 if(hit.second.second.first == maxKey.first && hit.second.second.second == maxKey.second)
0178 {
0179 mIndex = i;
0180 break;
0181 }
0182 i++;
0183 }
0184
0185 auto seed = unvisited[mIndex];
0186 unvisited.erase(unvisited.begin()+mIndex);
0187 q.push(seed);
0188 region.push_back(seed);
0189
0190 while(!q.empty())
0191 {
0192 float ix = q.front().first.get<0>();
0193 float iy = q.front().first.get<1>();
0194 float iz = q.front().first.get<2>();
0195 q.pop();
0196
0197 for (auto neigh : neighborOffsets)
0198 {
0199 float nx = ix + neigh.get<0>();
0200 float ny = iy + neigh.get<1>();
0201 float nz = iz + neigh.get<2>();
0202
0203 for(unsigned int v=0; v<unvisited.size(); v++)
0204 {
0205
0206 if(fabs(unvisited[v].first.get<0>() - nx) < 0.01 && fabs(unvisited[v].first.get<1>() - ny) < 0.01 && fabs(unvisited[v].first.get<2>() - nz) < 0.01)
0207 {
0208 auto newSeed = unvisited[v];
0209 unvisited.erase(unvisited.begin()+v);
0210 q.push(newSeed);
0211 region.push_back(newSeed);
0212 break;
0213 }
0214 }
0215 }
0216 }
0217 regions.push_back(region);
0218
0219 }
0220
0221 clusHits.clear();
0222 for(auto hit : regions[0])
0223 {
0224 clusHits.push_back(hit);
0225 }
0226
0227 }
0228
0229
0230 void remove_hits(std::vector<hitData> &clusHits, bgi::rtree<hitData, bgi::quadratic<16>> &rtree, std::multimap<unsigned int, pointKeyLaser> &adcMap)
0231 {
0232 for (auto &clusHit : clusHits)
0233 {
0234 auto spechitkey = clusHit.second.second;
0235
0236 rtree.remove(clusHit);
0237
0238 for (auto iterAdc = adcMap.begin(); iterAdc != adcMap.end();)
0239 {
0240 if(iterAdc->second.second == spechitkey)
0241 {
0242 iterAdc = adcMap.erase(iterAdc);
0243 break;
0244 }
0245 else
0246 {
0247 ++iterAdc;
0248 }
0249 }
0250 }
0251
0252 }
0253
0254 void calc_cluster_parameter(std::vector<hitData> &clusHits, thread_data &my_data, std::pair<TrkrDefs::hitkey, TrkrDefs::hitsetkey> maxADCKey)
0255 {
0256
0257
0258
0259 findConnectedRegions3(clusHits, maxADCKey);
0260
0261
0262 double rSum = 0.0;
0263 double phiSum = 0.0;
0264 double tSum = 0.0;
0265
0266 double layerSum = 0.0;
0267 double iphiSum = 0.0;
0268 double itSum = 0.0;
0269
0270 double adcSum = 0.0;
0271
0272 double maxAdc = 0.0;
0273 TrkrDefs::hitsetkey maxKey = 0;
0274
0275 unsigned int nHits = clusHits.size();
0276
0277 auto *clus = new LaserClusterv2;
0278
0279 int meanSide = 0;
0280
0281 std::vector<float> usedLayer;
0282 std::vector<float> usedIPhi;
0283 std::vector<float> usedIT;
0284
0285 double meanLayer = 0.0;
0286 double meanIPhi = 0.0;
0287 double meanIT = 0.0;
0288
0289 for (auto &clusHit : clusHits)
0290 {
0291 float coords[3] = {clusHit.first.get<0>(), clusHit.first.get<1>(), clusHit.first.get<2>()};
0292 std::pair<TrkrDefs::hitkey, TrkrDefs::hitsetkey> spechitkey = clusHit.second.second;
0293 unsigned int adc = clusHit.second.first;
0294
0295 int side = TpcDefs::getSide(spechitkey.second);
0296
0297 if (side)
0298 {
0299 meanSide++;
0300 }
0301 else
0302 {
0303 meanSide--;
0304 }
0305
0306 PHG4TpcGeom *layergeom = my_data.geom_container->GetLayerCellGeom((int) coords[0]);
0307
0308 double r = layergeom->get_radius();
0309 double phi = layergeom->get_phi(coords[1], side);
0310 double t = layergeom->get_zcenter(fabs(coords[2]));
0311
0312 double hitzdriftlength = t * my_data.tGeometry->get_drift_velocity();
0313 double hitZ = my_data.tdriftmax * my_data.tGeometry->get_drift_velocity() - hitzdriftlength;
0314
0315
0316 bool foundLayer = false;
0317 for (float i : usedLayer)
0318 {
0319 if (coords[0] == i)
0320 {
0321 foundLayer = true;
0322 break;
0323 }
0324 }
0325
0326 if (!foundLayer)
0327 {
0328 usedLayer.push_back(coords[0]);
0329 }
0330
0331 bool foundIPhi = false;
0332 for (float i : usedIPhi)
0333 {
0334 if (coords[1] == i)
0335 {
0336 foundIPhi = true;
0337 break;
0338 }
0339 }
0340
0341 if (!foundIPhi)
0342 {
0343 usedIPhi.push_back(coords[1]);
0344 }
0345
0346 bool foundIT = false;
0347 for (float i : usedIT)
0348 {
0349 if (coords[2] == i)
0350 {
0351 foundIT = true;
0352 break;
0353 }
0354 }
0355
0356 if (!foundIT)
0357 {
0358 usedIT.push_back(coords[2]);
0359 }
0360
0361 clus->addHit();
0362 clus->setHitLayer(clus->getNhits() - 1, coords[0]);
0363 clus->setHitIPhi(clus->getNhits() - 1, coords[1]);
0364 clus->setHitIT(clus->getNhits() - 1, coords[2]);
0365 clus->setHitX(clus->getNhits() - 1, r * cos(phi));
0366 clus->setHitY(clus->getNhits() - 1, r * sin(phi));
0367 clus->setHitZ(clus->getNhits() - 1, hitZ);
0368 clus->setHitAdc(clus->getNhits() - 1, (float) adc);
0369
0370 rSum += r * adc;
0371 phiSum += phi * adc;
0372 tSum += t * adc;
0373
0374 layerSum += coords[0] * adc;
0375 iphiSum += coords[1] * adc;
0376 itSum += coords[2] * adc;
0377
0378 meanLayer += coords[0];
0379 meanIPhi += coords[1];
0380 meanIT += coords[2];
0381
0382 adcSum += adc;
0383
0384 if (adc > maxAdc)
0385 {
0386 maxAdc = adc;
0387 maxKey = spechitkey.second;
0388 }
0389
0390 }
0391
0392 if (nHits == 0)
0393 {
0394 return;
0395 }
0396
0397
0398 double clusR = rSum / adcSum;
0399 double clusPhi = phiSum / adcSum;
0400 double clusT = tSum / adcSum;
0401 double zdriftlength = clusT * my_data.tGeometry->get_drift_velocity();
0402
0403 double clusX = clusR * cos(clusPhi);
0404 double clusY = clusR * sin(clusPhi);
0405 double clusZ = my_data.tdriftmax * my_data.tGeometry->get_drift_velocity() - zdriftlength;
0406 if (meanSide < 0)
0407 {
0408 clusZ = -clusZ;
0409 for (int i = 0; i < (int) clus->getNhits(); i++)
0410 {
0411 clus->setHitZ(i, -1 * clus->getHitZ(i));
0412 }
0413 }
0414
0415 std::sort(usedLayer.begin(), usedLayer.end());
0416 std::sort(usedIPhi.begin(), usedIPhi.end());
0417 std::sort(usedIT.begin(), usedIT.end());
0418
0419 meanLayer = meanLayer / nHits;
0420 meanIPhi = meanIPhi / nHits;
0421 meanIT = meanIT / nHits;
0422
0423 double sigmaLayer = 0.0;
0424 double sigmaIPhi = 0.0;
0425 double sigmaIT = 0.0;
0426
0427 double sigmaWeightedLayer = 0.0;
0428 double sigmaWeightedIPhi = 0.0;
0429 double sigmaWeightedIT = 0.0;
0430
0431 pthread_mutex_lock(&mythreadlock);
0432 my_data.hitHist = new TH3D(Form("hitHist_event%d_side%d_sector%d_module%d_cluster%d",my_data.eventNum,(int)my_data.side,(int)my_data.sector,(int)my_data.module,(int)my_data.cluster_vector.size()),";layer;iphi;it",usedLayer.size()+2,usedLayer[0]-1.5,*usedLayer.rbegin()+1.5,usedIPhi.size()+2,usedIPhi[0]-1.5,*usedIPhi.rbegin()+1.5,usedIT.size()+2,usedIT[0]-1.5,*usedIT.rbegin()+1.5);
0433
0434
0435
0436
0437 for (int i = 0; i < (int) clus->getNhits(); i++)
0438 {
0439
0440 my_data.hitHist->Fill(clus->getHitLayer(i), clus->getHitIPhi(i), clus->getHitIT(i), clus->getHitAdc(i));
0441
0442 sigmaLayer += pow(clus->getHitLayer(i) - meanLayer, 2);
0443 sigmaIPhi += pow(clus->getHitIPhi(i) - meanIPhi, 2);
0444 sigmaIT += pow(clus->getHitIT(i) - meanIT, 2);
0445
0446 sigmaWeightedLayer += clus->getHitAdc(i) * pow(clus->getHitLayer(i) - (layerSum / adcSum), 2);
0447 sigmaWeightedIPhi += clus->getHitAdc(i) * pow(clus->getHitIPhi(i) - (iphiSum / adcSum), 2);
0448 sigmaWeightedIT += clus->getHitAdc(i) * pow(clus->getHitIT(i) - (itSum / adcSum), 2);
0449 }
0450
0451 bool fitSuccess = false;
0452 ROOT::Fit::Fitter *fit3D = new ROOT::Fit::Fitter;
0453
0454 if(my_data.doFitting)
0455 {
0456
0457 double par_init[7] = {
0458 maxAdc,
0459 meanLayer,
0460 meanIPhi, 0.75,
0461 meanIT, 0.5, 1
0462 };
0463
0464 double satThreshold = 900.0;
0465 double sigma_ADC = 20.0;
0466
0467 auto nll = [&](const double* par)
0468 {
0469 double nll_val = 0.0;
0470
0471 int nx = my_data.hitHist->GetNbinsX();
0472 int ny = my_data.hitHist->GetNbinsY();
0473 int nz = my_data.hitHist->GetNbinsZ();
0474
0475 double parLayer[2] = {1.0,par[1]};
0476 double parPhi[4] = {1.0,par[2],par[3]};
0477 double parTime[4] = {1.0,par[4],par[5],par[6]};
0478
0479 double xyz[3];
0480
0481 for (int i = 1; i <= nx; ++i)
0482 {
0483 xyz[0] = my_data.hitHist->GetXaxis()->GetBinCenter(i);
0484 for (int j = 1; j <= ny; ++j)
0485 {
0486 xyz[1] = my_data.hitHist->GetYaxis()->GetBinCenter(j);
0487 for (int k = 1; k <= nz; ++k)
0488 {
0489 xyz[2] = my_data.hitHist->GetZaxis()->GetBinCenter(k);
0490 double observed = my_data.hitHist->GetBinContent(i, j, k);
0491
0492 double expected = par[0]*layerFunction(&xyz[0], parLayer)*phiFunction(&xyz[1], parPhi)*timeFunction(&xyz[2], parTime);
0493
0494 if(observed <= my_data.adc_threshold)
0495 {
0496 double arg = (expected - my_data.adc_threshold) / (sqrt(2.0) * sigma_ADC);
0497 double tail_prob = 0.5 * TMath::Erfc(arg);
0498 nll_val -= log(tail_prob + 1e-12);
0499 }
0500 else if(observed < satThreshold)
0501 {
0502 double resid = (observed - expected) / sigma_ADC;
0503 nll_val += 0.5 * (resid * resid + log(2 * TMath::Pi() * sigma_ADC * sigma_ADC));
0504 }
0505 else if(observed >= satThreshold)
0506 {
0507 double arg = (satThreshold - expected) / (sqrt(2.0) * sigma_ADC);
0508 double tail_prob = 0.5 * TMath::Erfc(arg);
0509 nll_val -= log(tail_prob + 1e-12);
0510 }
0511 }
0512 }
0513 }
0514 return nll_val;
0515 };
0516
0517 fit3D->SetFCN(7, nll, par_init);
0518
0519 fit3D->Config().ParSettings(0).SetName("amp");
0520 fit3D->Config().ParSettings(0).SetStepSize(10);
0521 fit3D->Config().ParSettings(0).SetLimits(0,5000);
0522 fit3D->Config().ParSettings(1).SetName("mu_layer");
0523 fit3D->Config().ParSettings(1).SetStepSize(0.1);
0524 fit3D->Config().ParSettings(1).SetLimits(usedLayer[0],*usedLayer.rbegin());
0525 fit3D->Config().ParSettings(2).SetName("mu_phi");
0526 fit3D->Config().ParSettings(2).SetStepSize(0.1);
0527 fit3D->Config().ParSettings(2).SetLimits(usedIPhi[0],*usedIPhi.rbegin());
0528 fit3D->Config().ParSettings(3).SetName("sig_phi");
0529 fit3D->Config().ParSettings(3).SetStepSize(0.1);
0530 fit3D->Config().ParSettings(3).SetLimits(0.01,2);
0531 fit3D->Config().ParSettings(4).SetName("mu_t");
0532 fit3D->Config().ParSettings(4).SetStepSize(0.1);
0533 fit3D->Config().ParSettings(4).SetLimits(usedIT[0],*usedIT.rbegin());
0534 fit3D->Config().ParSettings(5).SetName("sig_t");
0535 fit3D->Config().ParSettings(5).SetStepSize(0.1);
0536 fit3D->Config().ParSettings(5).SetLimits(0.01,10);
0537 fit3D->Config().ParSettings(6).SetName("lambda_t");
0538 fit3D->Config().ParSettings(6).SetStepSize(0.01);
0539 fit3D->Config().ParSettings(6).SetLimits(0,5);
0540
0541
0542 if(usedLayer.size() == 1)
0543 {
0544 fit3D->Config().ParSettings(1).Fix();
0545 }
0546
0547 fitSuccess = fit3D->FitFCN();
0548
0549
0550 if (my_data.Verbosity > 2)
0551 {
0552 std::cout << "fit success: " << fitSuccess << std::endl;
0553 }
0554 }
0555 pthread_mutex_unlock(&mythreadlock);
0556
0557
0558
0559 if(my_data.doFitting && fitSuccess)
0560 {
0561
0562 const ROOT::Fit::FitResult& result = fit3D->Result();
0563
0564
0565 PHG4TpcGeom *layergeomLow = my_data.geom_container->GetLayerCellGeom((int) floor(result.Parameter(1)));
0566 PHG4TpcGeom *layergeomHigh = my_data.geom_container->GetLayerCellGeom((int) ceil(result.Parameter(1)));
0567
0568 double RLow = layergeomLow->get_radius();
0569 double RHigh = layergeomHigh->get_radius();
0570
0571 double phiHigh_RLow = -999.0;
0572 if(ceil(result.Parameter(2)) < layergeomLow->get_phibins())
0573 {
0574 phiHigh_RLow = layergeomLow->get_phi(ceil(result.Parameter(2)), (meanSide < 0 ? 0 : 1));
0575 }
0576 double phiHigh_RHigh = -999.0;
0577 if(ceil(result.Parameter(2)) < layergeomHigh->get_phibins())
0578 {
0579 phiHigh_RHigh = layergeomHigh->get_phi(ceil(result.Parameter(2)), (meanSide < 0 ? 0 : 1));
0580 }
0581
0582 double phiLow_RLow = layergeomLow->get_phi(floor(result.Parameter(2)), (meanSide < 0 ? 0 : 1));
0583 double phiLow_RHigh = layergeomHigh->get_phi(floor(result.Parameter(2)), (meanSide < 0 ? 0 : 1));
0584
0585 double meanR = (result.Parameter(1) - floor(result.Parameter(1))) * (RHigh - RLow) + RLow;
0586
0587 double meanPhi_RLow = ((result.Parameter(2) - floor(result.Parameter(2)))) * (phiHigh_RLow - phiLow_RLow) + phiLow_RLow;
0588 double meanPhi_RHigh = ((result.Parameter(2) - floor(result.Parameter(2)))) * (phiHigh_RHigh - phiLow_RHigh) + phiLow_RHigh;
0589
0590 double meanPhi = 0.5*(meanPhi_RLow + meanPhi_RHigh);
0591 if(phiHigh_RLow == -999.0 && phiHigh_RHigh != -999.0)
0592 {
0593 meanPhi = meanPhi_RHigh;
0594 }
0595 else if(phiHigh_RLow != -999.0 && phiHigh_RHigh == -999.0)
0596 {
0597 meanPhi = meanPhi_RLow;
0598 }
0599
0600
0601 if(phiHigh_RLow == -999.0 && phiHigh_RHigh == -999.0)
0602 {
0603 clus->setAdc(adcSum);
0604 clus->setX(clusX);
0605 clus->setY(clusY);
0606 clus->setZ(clusZ);
0607 clus->setFitMode(false);
0608 clus->setLayer(layerSum / adcSum);
0609 clus->setIPhi(iphiSum / adcSum);
0610 clus->setIT(itSum / adcSum);
0611 clus->setNLayers(usedLayer.size());
0612 clus->setNIPhi(usedIPhi.size());
0613 clus->setNIT(usedIT.size());
0614 clus->setSDLayer(sqrt(sigmaLayer / nHits));
0615 clus->setSDIPhi(sqrt(sigmaIPhi / nHits));
0616 clus->setSDIT(sqrt(sigmaIT / nHits));
0617 clus->setSDWeightedLayer(sqrt(sigmaWeightedLayer / adcSum));
0618 clus->setSDWeightedIPhi(sqrt(sigmaWeightedIPhi / adcSum));
0619 clus->setSDWeightedIT(sqrt(sigmaWeightedIT / adcSum));
0620 }
0621 else
0622 {
0623 clus->setAdc(adcSum);
0624 clus->setX(meanR*cos(meanPhi));
0625 clus->setY(meanR*sin(meanPhi));
0626 clus->setZ(clusZ);
0627 clus->setFitMode(true);
0628 clus->setLayer(result.Parameter(1));
0629 clus->setIPhi(result.Parameter(2));
0630 clus->setIT(result.Parameter(4));
0631 clus->setNLayers(usedLayer.size());
0632 clus->setNIPhi(usedIPhi.size());
0633 clus->setNIT(usedIT.size());
0634 clus->setSDLayer(sqrt(sigmaLayer / nHits));
0635 clus->setSDIPhi(sqrt(sigmaIPhi / nHits));
0636 clus->setSDIT(sqrt(sigmaIT / nHits));
0637 clus->setSDWeightedLayer(sqrt(sigmaWeightedLayer / adcSum));
0638 clus->setSDWeightedIPhi(result.Parameter(3));
0639 clus->setSDWeightedIT(result.Parameter(5));
0640 }
0641 }
0642 else
0643 {
0644 clus->setAdc(adcSum);
0645 clus->setX(clusX);
0646 clus->setY(clusY);
0647 clus->setZ(clusZ);
0648 clus->setFitMode(false);
0649 clus->setLayer(layerSum / adcSum);
0650 clus->setIPhi(iphiSum / adcSum);
0651 clus->setIT(itSum / adcSum);
0652 clus->setNLayers(usedLayer.size());
0653 clus->setNIPhi(usedIPhi.size());
0654 clus->setNIT(usedIT.size());
0655 clus->setSDLayer(sqrt(sigmaLayer / nHits));
0656 clus->setSDIPhi(sqrt(sigmaIPhi / nHits));
0657 clus->setSDIT(sqrt(sigmaIT / nHits));
0658 clus->setSDWeightedLayer(sqrt(sigmaWeightedLayer / adcSum));
0659 clus->setSDWeightedIPhi(sqrt(sigmaWeightedIPhi / adcSum));
0660 clus->setSDWeightedIT(sqrt(sigmaWeightedIT / adcSum));
0661 }
0662
0663 const auto ckey = TrkrDefs::genClusKey(maxKey, my_data.cluster_vector.size());
0664 my_data.cluster_vector.push_back(clus);
0665 my_data.cluster_key_vector.push_back(ckey);
0666
0667 if(fit3D)
0668 {
0669 delete fit3D;
0670 }
0671
0672 if(my_data.hitHist)
0673 {
0674 delete my_data.hitHist;
0675 my_data.hitHist = nullptr;
0676 }
0677
0678
0679 }
0680
0681
0682 void ProcessModuleData(thread_data *my_data)
0683 {
0684
0685 if (my_data->Verbosity > 2)
0686 {
0687 pthread_mutex_lock(&mythreadlock);
0688 std::cout << "working on side: " << my_data->side << " sector: " << my_data->sector << " module: " << my_data->module << std::endl;
0689 pthread_mutex_unlock(&mythreadlock);
0690 }
0691
0692 bgi::rtree<hitData, bgi::quadratic<16>> rtree;
0693
0694 std::multimap<unsigned int, pointKeyLaser> adcMap;
0695
0696 if (my_data->hitsets.size() == 0)
0697 {
0698 return;
0699 }
0700 for(int i=0; i<(int)my_data->hitsets.size(); i++)
0701 {
0702 auto *hitset = my_data->hitsets[i];
0703 unsigned int layer = my_data->layers[i];
0704 bool side = my_data->side;
0705 unsigned int sector = my_data->sector;
0706
0707 TrkrDefs::hitsetkey hitsetKey = TpcDefs::genHitSetKey(layer, sector, (int)side);
0708
0709 TrkrHitSet::ConstRange hitrangei = hitset->getHits();
0710
0711 for (TrkrHitSet::ConstIterator hitr = hitrangei.first; hitr != hitrangei.second; ++hitr)
0712 {
0713 float_t fadc = hitr->second->getAdc();
0714 unsigned short adc = 0;
0715 if (fadc > my_data->adc_threshold)
0716 {
0717 adc = (unsigned short) fadc;
0718 }
0719 else
0720 {
0721 continue;
0722 }
0723
0724 int iphi = TpcDefs::getPad(hitr->first);
0725 int it = TpcDefs::getTBin(hitr->first);
0726
0727 if(fabs(it - my_data->peakTimeBin) > 5)
0728 {
0729 continue;
0730 }
0731
0732 point coords = point((int) layer, iphi, it);
0733
0734 std::vector<hitData> testduplicate;
0735 rtree.query(bgi::intersects(box(point(layer - 0.001, iphi - 0.001, it - 0.001),
0736 point(layer + 0.001, iphi + 0.001, it + 0.001))),
0737 std::back_inserter(testduplicate));
0738 if (!testduplicate.empty())
0739 {
0740 testduplicate.clear();
0741 continue;
0742 }
0743
0744 TrkrDefs::hitkey hitKey = TpcDefs::genHitKey(iphi, it);
0745
0746 auto spechitkey = std::make_pair(hitKey, hitsetKey);
0747 pointKeyLaser coordsKey = std::make_pair(coords, spechitkey);
0748 adcMap.insert(std::make_pair(adc, coordsKey));
0749 auto adckey = std::make_pair(adc, spechitkey);
0750 rtree.insert(std::make_pair(point(1.0*layer, 1.0*iphi, 1.0*it), adckey));
0751 }
0752 }
0753
0754
0755 while (adcMap.size() > 0)
0756 {
0757 auto iterKey = adcMap.rbegin();
0758 if(iterKey == adcMap.rend())
0759 {
0760 break;
0761 }
0762
0763
0764 auto coords = iterKey->second.first;
0765 int layer = coords.get<0>();
0766 int iphi = coords.get<1>();
0767 int it = coords.get<2>();
0768
0769 if (my_data->Verbosity > 2)
0770 {
0771 pthread_mutex_lock(&mythreadlock);
0772 std::cout << "working on cluster " << my_data->cluster_vector.size() << " side: " << my_data->side << " sector: " << my_data->sector << " module: " << (layer<23 ? 1 : (layer<39 ? 2 : 3) ) << std::endl;
0773 pthread_mutex_unlock(&mythreadlock);
0774
0775 }
0776
0777 std::vector<hitData> clusHits;
0778
0779 rtree.query(bgi::intersects(box(point(layer - my_data->layerMin, iphi - 6, it - 5), point(layer + my_data->layerMax, iphi + 6, it + 5))), std::back_inserter(clusHits));
0780
0781 calc_cluster_parameter(clusHits, *my_data, iterKey->second.second);
0782
0783 remove_hits(clusHits, rtree, adcMap);
0784
0785 }
0786 }
0787
0788 void *ProcessModule(void *threadarg)
0789 {
0790 auto my_data = static_cast<thread_data *>(threadarg);
0791 ProcessModuleData(my_data);
0792 pthread_exit(nullptr);
0793 }
0794 }
0795
0796 LaserClusterizer::LaserClusterizer(const std::string &name)
0797 : SubsysReco(name)
0798 {
0799 }
0800
0801 int LaserClusterizer::InitRun(PHCompositeNode *topNode)
0802 {
0803 TH1::AddDirectory(kFALSE);
0804
0805 PHNodeIterator iter(topNode);
0806
0807
0808 PHCompositeNode *dstNode = dynamic_cast<PHCompositeNode *>(iter.findFirst("PHCompositeNode", "DST"));
0809 if (!dstNode)
0810 {
0811 std::cout << PHWHERE << "DST Node missing, doing nothing." << std::endl;
0812 return Fun4AllReturnCodes::ABORTRUN;
0813 }
0814
0815
0816 std::string laserClusterNodeName = "LASER_CLUSTER";
0817 if (m_lamination)
0818 {
0819 laserClusterNodeName = "LAMINATION_CLUSTER";
0820 }
0821 auto laserclusters = findNode::getClass<LaserClusterContainer>(dstNode, laserClusterNodeName);
0822 if (!laserclusters)
0823 {
0824 PHNodeIterator dstiter(dstNode);
0825 PHCompositeNode *DetNode =
0826 dynamic_cast<PHCompositeNode *>(dstiter.findFirst("PHCompositeNode", "TRKR"));
0827 if (!DetNode)
0828 {
0829 DetNode = new PHCompositeNode("TRKR");
0830 dstNode->addNode(DetNode);
0831 }
0832
0833 laserclusters = new LaserClusterContainerv1;
0834 PHIODataNode<PHObject> *LaserClusterContainerNode =
0835 new PHIODataNode<PHObject>(laserclusters, laserClusterNodeName, "PHObject");
0836 DetNode->addNode(LaserClusterContainerNode);
0837 }
0838
0839 m_geom_container =
0840 findNode::getClass<PHG4TpcGeomContainer>(topNode, "TPCGEOMCONTAINER");
0841 if (!m_geom_container)
0842 {
0843 std::cout << PHWHERE << "ERROR: Can't find node TPCGEOMCONTAINER" << std::endl;
0844 return Fun4AllReturnCodes::ABORTRUN;
0845 }
0846
0847 AdcClockPeriod = m_geom_container->GetFirstLayerCellGeom()->get_zstep();
0848 m_tdriftmax = AdcClockPeriod * NZBinsSide;
0849
0850 return Fun4AllReturnCodes::EVENT_OK;
0851 }
0852
0853 int LaserClusterizer::process_event(PHCompositeNode *topNode)
0854 {
0855 eventHeader = findNode::getClass<EventHeader>(topNode, "EventHeader");
0856 if (!eventHeader)
0857 {
0858 std::cout << PHWHERE << " EventHeader Node missing, doing nothing." << std::endl;
0859 return Fun4AllReturnCodes::ABORTRUN;
0860 }
0861
0862 m_event = eventHeader->get_EvtSequence();
0863
0864 if (Verbosity() > 1)
0865 {
0866 std::cout << "LaserClusterizer::process_event working on event " << m_event << std::endl;
0867 }
0868
0869 m_laserEventInfo = findNode::getClass<LaserEventInfo>(topNode, "LaserEventInfo");
0870 if (!m_laserEventInfo)
0871 {
0872 std::cout << PHWHERE << "ERROR: Can't find node LaserEventInfo" << std::endl;
0873 return Fun4AllReturnCodes::ABORTRUN;
0874 }
0875
0876 if((eventHeader->get_RunNumber() > 66153 && !m_laserEventInfo->isGl1LaserEvent()) || (eventHeader->get_RunNumber() <= 66153 && !m_laserEventInfo->isLaserEvent()))
0877 {
0878 return Fun4AllReturnCodes::EVENT_OK;
0879 }
0880
0881 if (Verbosity() > 1)
0882 {
0883 std::cout << "LaserClusterizer::process_event laser event found" << std::endl;
0884 }
0885
0886 PHNodeIterator iter(topNode);
0887 PHCompositeNode *dstNode = static_cast<PHCompositeNode *>(iter.findFirst("PHCompositeNode", "DST"));
0888 if (!dstNode)
0889 {
0890 std::cout << PHWHERE << "DST Node missing, doing nothing." << std::endl;
0891 return Fun4AllReturnCodes::ABORTRUN;
0892 }
0893
0894 m_hits = findNode::getClass<TrkrHitSetContainer>(topNode, "TRKR_HITSET");
0895 if (!m_hits)
0896 {
0897 std::cout << PHWHERE << "ERROR: Can't find node TRKR_HITSET" << std::endl;
0898 return Fun4AllReturnCodes::ABORTRUN;
0899 }
0900
0901
0902 std::string laserClusterNodeName = "LASER_CLUSTER";
0903 if (m_lamination)
0904 {
0905 laserClusterNodeName = "LAMINATION_CLUSTER";
0906 }
0907 m_clusterlist = findNode::getClass<LaserClusterContainer>(topNode, laserClusterNodeName);
0908 if (!m_clusterlist)
0909 {
0910 std::cout << PHWHERE << " ERROR: Can't find " << laserClusterNodeName << "." << std::endl;
0911 return Fun4AllReturnCodes::ABORTRUN;
0912 }
0913
0914 m_tGeometry = findNode::getClass<ActsGeometry>(topNode,
0915 "ActsGeometry");
0916 if (!m_tGeometry)
0917 {
0918 std::cout << PHWHERE
0919 << "ActsGeometry not found on node tree. Exiting"
0920 << std::endl;
0921 return Fun4AllReturnCodes::ABORTRUN;
0922 }
0923
0924 TrkrHitSetContainer::ConstRange hitsetrange = m_hits->getHitSets(TrkrDefs::TrkrId::tpcId);;
0925
0926 struct thread_pair_t
0927 {
0928 pthread_t thread{};
0929 thread_data data;
0930 };
0931
0932 std::vector<thread_pair_t> threads;
0933 threads.reserve(72);
0934
0935 pthread_attr_t attr;
0936 pthread_attr_init(&attr);
0937 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
0938
0939 if (pthread_mutex_init(&mythreadlock, nullptr) != 0)
0940 {
0941 std::cout << std::endl << " mutex init failed" << std::endl;
0942 return 1;
0943 }
0944
0945 for (unsigned int sec=0; sec<12; sec++)
0946 {
0947 for (int s=0; s<2; s++)
0948 {
0949 for (unsigned int mod=0; mod<3; mod++)
0950 {
0951
0952 if(Verbosity() > 2)
0953 {
0954 std::cout << "making thread for side: " << s << " sector: " << sec << " module: " << mod << std::endl;
0955 }
0956
0957 thread_pair_t &thread_pair = threads.emplace_back();
0958
0959 std::vector<TrkrHitSet *> hitsets;
0960 std::vector<unsigned int> layers;
0961
0962 std::vector<LaserCluster *> cluster_vector;
0963 std::vector<TrkrDefs::cluskey> cluster_key_vector;
0964
0965 for (TrkrHitSetContainer::ConstIterator hitsetitr = hitsetrange.first;
0966 hitsetitr != hitsetrange.second;
0967 ++hitsetitr)
0968 {
0969 unsigned int layer = TrkrDefs::getLayer(hitsetitr->first);
0970 int side = TpcDefs::getSide(hitsetitr->first);
0971 unsigned int sector = TpcDefs::getSectorId(hitsetitr->first);
0972 if (sector != sec || side != s)
0973 {
0974 continue;
0975 }
0976 if ((mod==0 && (layer<7 || layer>22)) || (mod==1 && (layer<=22 || layer>38) ) || (mod==2 && (layer<=38 || layer>54)))
0977 {
0978 continue;
0979 }
0980
0981 TrkrHitSet *hitset = hitsetitr->second;
0982
0983 hitsets.push_back(hitset);
0984 layers.push_back(layer);
0985
0986 }
0987
0988 thread_pair.data.geom_container = m_geom_container;
0989 thread_pair.data.tGeometry = m_tGeometry;
0990 thread_pair.data.hitsets = hitsets;
0991 thread_pair.data.layers = layers;
0992 thread_pair.data.side = (bool)s;
0993 thread_pair.data.sector = sec;
0994 thread_pair.data.module = mod;
0995 thread_pair.data.cluster_vector = cluster_vector;
0996 thread_pair.data.cluster_key_vector = cluster_key_vector;
0997 thread_pair.data.adc_threshold = m_adc_threshold;
0998 thread_pair.data.peakTimeBin = m_laserEventInfo->getPeakSample(s);
0999 thread_pair.data.layerMin = 3;
1000 thread_pair.data.layerMax = 3;
1001 thread_pair.data.tdriftmax = m_tdriftmax;
1002 thread_pair.data.eventNum = m_event;
1003 thread_pair.data.Verbosity = Verbosity();
1004 thread_pair.data.hitHist = nullptr;
1005 thread_pair.data.doFitting = m_do_fitting;
1006
1007 int rc;
1008 rc = pthread_create(&thread_pair.thread, &attr, ProcessModule, (void *) &thread_pair.data);
1009
1010 if (rc)
1011 {
1012 std::cout << "Error:unable to create thread," << rc << std::endl;
1013 }
1014
1015 if (m_do_sequential)
1016 {
1017
1018 int rc2 = pthread_join(thread_pair.thread, nullptr);
1019 if (rc2)
1020 {
1021 std::cout << "Error:unable to join," << rc2 << std::endl;
1022 }
1023
1024
1025 const auto &data(thread_pair.data);
1026 for(int index = 0; index < (int) data.cluster_vector.size(); ++index)
1027 {
1028 auto cluster = data.cluster_vector[index];
1029 const auto ckey = data.cluster_key_vector[index];
1030
1031 m_clusterlist->addClusterSpecifyKey(ckey, cluster);
1032 }
1033 }
1034 }
1035 }
1036 }
1037
1038 pthread_attr_destroy(&attr);
1039
1040 if (!m_do_sequential)
1041 {
1042 for (const auto & thread_pair : threads)
1043 {
1044 int rc2 = pthread_join(thread_pair.thread, nullptr);
1045 if (rc2)
1046 {
1047 std::cout << "Error:unable to join," << rc2 << std::endl;
1048 }
1049
1050
1051
1052 for(int index = 0; index < (int) thread_pair.data.cluster_vector.size(); ++index)
1053 {
1054 auto cluster = thread_pair.data.cluster_vector[index];
1055 const auto ckey = thread_pair.data.cluster_key_vector[index];
1056
1057 m_clusterlist->addClusterSpecifyKey(ckey, cluster);
1058 }
1059 }
1060 }
1061
1062 threads.clear();
1063
1064 if (Verbosity() > 1)
1065 {
1066 std::cout << "LaserClusterizer::process_event " << m_clusterlist->size() << " clusters found" << std::endl;
1067 }
1068
1069 return Fun4AllReturnCodes::EVENT_OK;
1070
1071 }