Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PHTpcCentralMembraneClusterizer.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file PHTpcCentralMembraneClusterizer.cc
2 
4 
6 #include <phool/getClass.h>
7 #include <phool/phool.h>
8 #include <TFile.h>
9 #include <TH1F.h>
10 #include <TH2F.h>
11 #include <string>
12 #include <TVector3.h>
13 #include <TCanvas.h>
14 #include <TGraph.h>
15 #include <cmath>
16 
19 
21 #include <trackbase/TrkrDefs.h>
22 #include <trackbase/TpcDefs.h>
23 #include <trackbase/TrkrCluster.h>
26 #include <trackbase/ActsGeometry.h>
27 #include <trackbase/TrkrCluster.h>
30 
31 
32 namespace
33 {
34 
35  // stream acts vector3
36  [[maybe_unused]] std::ostream& operator << (std::ostream& out, const TVector3& v )
37  {
38  out << "(" << v.x() << ", " << v.y() << ", " << v.z() << ")";
39  return out;
40  }
41 
42 }
43 
44 //____________________________________________________________________________..
46  SubsysReco(name)
47 {}
48 
49 //____________________________________________________________________________..
51 {
52  int ret = GetNodes(topNode);
53 
54  if( _histos )
55  {
56  m_histogramfile.reset( new TFile(m_histogramfilename.c_str(), "RECREATE"));
57  m_histogramfile->cd();
58  henergy = new TH1F("henergy", "cluster energy", 200, 0, 2000);
59  hxy = new TH2F("hxy","cluster x:y",800,-100,100,800,-80,80);
60  hz = new TH1F("hz","cluster z", 220, -2,2);
61 
62  hz_pos = new TH1F("hz_pos","cluster z>0", 400, 0,110);
63  hz_neg = new TH1F("hz_neg","cluster z<0", 400, -110,0);
64 
65  hClustE[0]= new TH1F("hRawClusterEnergy","Cluster Energy Before Merging;E[?]",200,0,2000);
66  hClustE[1] = new TH1F("hMatchedClusterEnergy","Pair Cluster Energy After Merging;E[?]",200,0,2000);
67  hClustE[2] = new TH1F("hSoloClusterEnergy","Lone Cluster Energy After Merging;E[?]",200,0,2000);
68 
69  hDist=new TH1F("hDist","3D distance to nearby clusters on same padrow;dist[cm]",100,-1,10);
70  hDistRow=new TH2F("hDistRow","phi distance to nearby clusters vs (lower)row;dist[rad];padrow",100,-0.001,0.01,60,-0.5,59.5);
71  hDist2=new TH1F("hDist2","phi distance to nearby clusters on same padrow;dist[rad]",100,-0.001,0.01);
72  hDistRowAdj=new TH2F("hDistRowAdj","phi distance to nearby clusters vs (lower)row;dist[rad];(lower) padrow",100,-0.001,0.01,60,-0.5,59.5);
73  hDist2Adj=new TH1F("hDist2Adj","phi distance to nearby clusters on adjacent padrow;dist[rad]",100,-0.001,0.01);
74  }
75 
76  hrPhi_reco_petalModulo_pos = new TH2F("hrPhi_reco_petalModulo_pos","Reco R vs #phi Z > 0;#phi;R (cm)",50,0.0,M_PI/9,400,20,78);
77  hrPhi_reco_petalModulo_neg = new TH2F("hrPhi_reco_petalModulo_neg","Reco R vs #phi;#phi Z < 0;R (cm)",50,0.0,M_PI/9,400,20,78);
78 
79  for(int i=0; i<48; i++){
80  hphi_reco_pos[i] = new TH1F(Form("hphi_reco_pos_layer%02d",7+i),Form("Reco #phi for Layer %02d Z > 0;#phi;counts",7+i),50,0.0,M_PI/9);
81  hphi_reco_neg[i] = new TH1F(Form("hphi_reco_neg_layer%02d",7+i),Form("Reco #phi for Layer %02d Z < 0;#phi;counts",7+i),50,0.0,M_PI/9);
82 
83  if(i<47){
84  hphi_reco_pair_pos[i] = new TH1F(Form("hphi_reco_pair_pos_layers%02d_%02d",7+i,8+i),Form("Reco #phi for Layers %02d and %02d Z > 0;#phi;counts",7+i,8+i),50,0.0,M_PI/9);
85  hphi_reco_pair_neg[i] = new TH1F(Form("hphi_reco_pair_neg_layers%02d_%02d",7+i,8+i),Form("Reco #phi for Layers %02d and %02d Z < 0;#phi;counts",7+i,8+i),50,0.0,M_PI/9);
86 
87  }
88  }
89 
90  return ret;
91 }
92 
93 //____________________________________________________________________________..
95 {
96 
97  //local coord conversion below
98  auto tgeometry = findNode::getClass<ActsGeometry>(topNode,"ActsGeometry");
99 
100  if(!tgeometry)
101  {
102  std::cout << PHWHERE << "No Acts geometry on node tree. Can't continue." << std::endl;
103  }
104 
105  if(Verbosity() > 0) std::cout << std::endl << "original size of cluster map: " << _cluster_map->size() << std::endl;
106 
107  std::vector<TVector3>pos; //position vector in cartesian
108  std::vector<int>layer; //cluster layer number
109  std::vector<unsigned int> side; // cluster side
110  std::vector<int>i_pair; //vector for pair matching
111  std::vector<float>energy;//vector for energy values of clusters
112  std::vector<bool>isAcrossGap;
113  int nTpcClust = 0;
114 
115  double mean_z_content_plus = 0.0;
116  double mean_z_content_minus = 0.0;
117 
118  //first loop over clusters to make mod phi histograms of each layer and each pair of layers
120  {
121  auto clusRange = _cluster_map->getClusters(hitsetkey);
122  for (auto clusiter = clusRange.first;
123  clusiter != clusRange.second; ++clusiter)
124  {
125 
126  const auto& [cluskey, cluster] = *clusiter;
127  auto glob = tgeometry->getGlobalPosition(cluskey, cluster);
128  TVector3 tmp_pos(glob(0),glob(1),glob(2));
129 
130  unsigned int layer = TrkrDefs::getLayer(cluskey);
131 
132  double phi = tmp_pos.Phi();
133 
134  double phiMod = phi;
135 
136  //make sure phiMod is between 0 and pi/9
137  while(phiMod < 0.0 || phiMod > M_PI/9){
138  if(phiMod < 0.0) phiMod += M_PI/9;
139  else if(phiMod > M_PI/9) phiMod -= M_PI/9;
140  }
141 
142  if(tmp_pos.Z() >= 0.0){
143 
144  hz_pos->Fill(tmp_pos.Z());
145 
146  //mean_z_content_plus += tmp_pos.Z();
147 
148  hrPhi_reco_petalModulo_pos->Fill(phiMod, tmp_pos.Perp());
149  hphi_reco_pos[layer-7]->Fill(phiMod);
150  //for layer pairs, if last layer can only go in layer 53-54 pair, if first layer can only go in layer 7-8 pair
151  if(layer < 54) hphi_reco_pair_pos[layer-7]->Fill(phiMod);
152  if(layer > 7) hphi_reco_pair_pos[layer-8]->Fill(phiMod);
153  }else{
154 
155  hz_neg->Fill(tmp_pos.Z());
156 
157  //mean_z_content_minus += tmp_pos.Z();
158 
159  hrPhi_reco_petalModulo_neg->Fill(phiMod, tmp_pos.Perp());
160  hphi_reco_neg[layer-7]->Fill(phiMod);
161  //for layer pairs, if last layer can only go in layer 53-54 pair, if first layer can only go in layer 7-8 pair
162  if(layer < 54) hphi_reco_pair_neg[layer-7]->Fill(phiMod);
163  if(layer > 7) hphi_reco_pair_neg[layer-8]->Fill(phiMod);
164  }
165 
166  }
167  }
168 
169  for(int i=1; i<hz_pos->GetNbinsX(); i++){
170  mean_z_content_plus += hz_pos->GetBinContent(i);
171  }
172  for(int i=1; i<hz_neg->GetNbinsX(); i++){
173  mean_z_content_minus += hz_neg->GetBinContent(i);
174  }
175 
176  mean_z_content_plus = mean_z_content_plus/hz_pos->GetNbinsX();
177  mean_z_content_minus = mean_z_content_minus/hz_neg->GetNbinsX();
178 
179 
180  //use peak in z distributions to identify if there is a CM Flash. Peak should be >20% of entries (needs to be tuned)
181  if(hz_pos->GetMaximum() < 5*mean_z_content_plus || hz_neg->GetMaximum() < 5*mean_z_content_minus) return Fun4AllReturnCodes::EVENT_OK;
182 
183  //loop over histos for each pair of layers, count number of bins above threshold
184  //for a given layer, layer pair with higher average value above threshold will be better match for meta-clustering
185  for(int i=0; i<47; i++){
186  for(int j=1; j<hphi_reco_pair_pos[i]->GetNbinsX(); j++){
187  if(hphi_reco_pair_pos[i]->GetBinContent(j) > (m_metaClusterThreshold + (mean_z_content_plus/18.0))){
188  nPairAbove_pos[i]++;
189  pairAboveContent_pos[i] += (hphi_reco_pair_pos[i]->GetBinContent(j)-(m_metaClusterThreshold + (mean_z_content_plus/18.0)));
190  }
191  if(hphi_reco_pair_neg[i]->GetBinContent(j) > (m_metaClusterThreshold + (mean_z_content_minus/18.0))){
192  nPairAbove_neg[i]++;
193  pairAboveContent_neg[i] += (hphi_reco_pair_neg[i]->GetBinContent(j)-(m_metaClusterThreshold + (mean_z_content_minus/18.0)));
194  }
195  }
196  }
197 
198 
199  //loop over clusters again
201  {
202  auto clusRange = _cluster_map->getClusters(hitsetkey);
203  for (auto clusiter = clusRange.first;
204  clusiter != clusRange.second; ++clusiter)
205  {
206 
208 
209  const auto& [cluskey, cluster] = *clusiter;
210  auto glob = tgeometry->getGlobalPosition(cluskey, cluster);
211  // std::cout << "PHTpcCentralMembraneClusterizer::process_event - key: " << cluskey << "z: " << glob.z() << std::endl;
212 
213  float x = glob(0);
214  float y = glob(1);
215  float z = glob(2);
216 
217  if(Verbosity() > 0)
218  {
219  unsigned int lyr = TrkrDefs::getLayer(cluskey);
220  unsigned short side = TpcDefs::getSide(cluskey);
221  std::cout << " z " << z << " side " << side << " layer " << lyr << " Adc " << cluster->getAdc() << " x " << x << " y " << y << std::endl;
222  }
223 
224  TVector3 tmp_pos(x,y,z);
225 
226  unsigned int lay = TrkrDefs::getLayer(cluskey);
227 
228  double phi = tmp_pos.Phi();
229  double phiMod = phi;
230 
231  while(phiMod < 0.0 || phiMod > M_PI/9){
232  if(phiMod < 0.0) phiMod += M_PI/9;
233  else if(phiMod > M_PI/9) phiMod -= M_PI/9;
234  }
235 
236  int phiBin = -1;
237 
238  bool aboveThreshold = true;
239 
240  //Find which phiMod bin cluster is in (with given layer) and if counts below threshold don't use
241  if(z >= 0){
242  phiBin = hphi_reco_pos[lay-7]->GetXaxis()->FindBin(phiMod);
243  if(hphi_reco_pos[lay-7]->GetBinContent(phiBin) < m_moduloThreshold) aboveThreshold = false;
244  }else{
245  phiBin = hphi_reco_neg[lay-7]->GetXaxis()->FindBin(phiMod);
246  if(hphi_reco_neg[lay-7]->GetBinContent(phiBin) < m_moduloThreshold) aboveThreshold = false;
247  }
248 
249  if( !aboveThreshold ) continue;
250 
251  if(cluster->getAdc() < _min_adc_value) continue;
252  if( std::abs(z) < _min_z_value) continue;
253 
254  //require that z be within 1cm of peak in z distributions (separate for each side)
255  if( (z>=0 && std::abs(z - hz_pos->GetBinCenter(hz_pos->GetMaximumBin())) > 1.0) || (z<0 && std::abs(z - hz_neg->GetBinCenter(hz_neg->GetMaximumBin())) > 1.0) ) continue;
256 
258 
259  i_pair.push_back(-1);
260  energy.push_back(cluster->getAdc());
261  nTpcClust++;
262  pos.push_back(TVector3(x,y,z));
263  layer.push_back((int)(TrkrDefs::getLayer(cluskey)));
264  side.push_back(TpcDefs::getSide(cluskey));
265  isAcrossGap.push_back(false);
266  if(Verbosity() > 0) std::cout << ":\t" << x << "\t" << y << "\t" << z <<std::endl;
267  }
268  }
269 
270  if(_histos)
271  {
272  // fill evaluation histograms
273  for (int i=0; i<nTpcClust; ++i)
274  for (int j=i+1; j<nTpcClust; j++)
275  {
276  // must match clusters that are on the same side
277  if( side[i] != side[j] ) continue;
278 
279  if(layer[i]==layer[j])
280  {
281  const TVector3 delta=pos[i]-pos[j];
282  const float dphi=std::abs(pos[i].DeltaPhi(pos[j]));
283  hDist->Fill(delta.Mag());
284  hDist2->Fill(dphi);
285  hDistRow->Fill(dphi,layer[i]);
286  }
287 
288  if (std::abs(layer[i]-layer[j])==1)
289  {
290  //match those centers to the known/expected stripe positions
291  const TVector3 delta=pos[i]-pos[j];
292  const float dphi=std::abs(pos[i].DeltaPhi(pos[j]));
293  hDist2Adj->Fill(dphi);
294  hDistRowAdj->Fill(dphi,layer[i]);
295  }
296  }
297  }
298 
299  //now for each cluster, find its nearest partner on an adjacent row
300 
301  /* TODO: check with Tony. Should be enough to loop for j=i+1 */
302 
303  const float maxphidist=0.003;//as read off the plots.
304  for (int i=0;i<nTpcClust;i++)
305  {
306 
307  int layerMatch = -1;
308 
309  int nRowsMatch = 2;
310  if(layer[i] >= 39) nRowsMatch = 4;
311  else if(layer[i] >= 23) nRowsMatch = 3;
312 
313  if( pos[i].Z() >= 0 ){
314  if(layer[i] == 7){
315  //if layer is 7, can only get one layer match
316  if(nPairAbove_pos[layer[i]-7] >= nRowsMatch) layerMatch = layer[i]+1;
317  }else if(layer[i] == 54){
318  //if layer is 8, can only get one layer match
319  if(nPairAbove_pos[layer[i]-8] >= nRowsMatch) layerMatch = layer[i]-1;
320  }else{
321  //if both pairs of rows have enough bins above threshold, match to pair with higher average
322  if(nPairAbove_pos[layer[i]-7] >= nRowsMatch && nPairAbove_pos[layer[i]-8] >= nRowsMatch){
323  if(pairAboveContent_pos[layer[i]-7]/nPairAbove_pos[layer[i]-7] > pairAboveContent_pos[layer[i]-8]/nPairAbove_pos[layer[i]-8]) layerMatch = layer[i]+1;
324  else layerMatch = layer[i]-1;
325  //otherwise just use the one that is above threshold
326  }else if(nPairAbove_pos[layer[i]-7] >= nRowsMatch) layerMatch = layer[i]+1;
327  else if(nPairAbove_pos[layer[i]-8] >= nRowsMatch) layerMatch = layer[i]-1;
328  }
329  }else{
330  if(layer[i] == 7){
331  if(nPairAbove_neg[layer[i]-7] >= nRowsMatch) layerMatch = layer[i]+1;
332  }else if(layer[i] == 54){
333  if(nPairAbove_neg[layer[i]-8] >= nRowsMatch) layerMatch = layer[i]-1;
334  }else{
335  if(nPairAbove_neg[layer[i]-7] >= nRowsMatch && nPairAbove_neg[layer[i]-8] >= nRowsMatch){
336  if(pairAboveContent_neg[layer[i]-7]/nPairAbove_neg[layer[i]-7] > pairAboveContent_neg[layer[i]-8]/nPairAbove_neg[layer[i]-8]) layerMatch = layer[i]+1;
337  else layerMatch = layer[i]-1;
338  }else if(nPairAbove_neg[layer[i]-7] >= nRowsMatch) layerMatch = layer[i]+1;
339  else if(nPairAbove_neg[layer[i]-8] >= nRowsMatch) layerMatch = layer[i]-1;
340  }
341  }
342 
343  //if the match is default and the layer is on the edge of a module, identify it as being across the gap
344  // if(layerMatch == -1 && (layer[i] == 22 || layer[i] == 23 || layer[i] == 38 || layer[i] == 39 || layer[i] == 7) ) isAcrossGap[i] = true;
345  if(layer[i] == 22 || layer[i] == 23 || layer[i] == 38 || layer[i] == 39 || layer[i] == 7) isAcrossGap[i] = true;
346 
347  float bestphidist=maxphidist;
348  for (int j=0;j<nTpcClust;j++)
349  {
350 
351  //radial match must be the correct layer identified above
352  if(layer[j] != layerMatch) continue;
353 
354  // redundant to the 'adjacent row' check: if (i==j) continue; //can't match yourself.
355  // must match to an adjacent row.
356  if (std::abs(layer[i]-layer[j])!=1) continue;
357 
358  //setting agross gap for ones where match was found
359  //if( (layer[i] == 22 && layer[j] == 23) || (layer[i] == 23 && layer[j] == 22) || (layer[i] == 38 && layer[j] == 39) || (layer[i] == 39 && layer[j] == 38) ) isAcrossGap[i] = true;
360 
361  // must match clusters that are on the same side
362  if( side[i] != side[j] ) continue;
363 
364  //must match clusters that are close to each other in Z
365  if(std::abs(pos[i].Z() - pos[j].Z()) > 0.5) continue;
366 
367  const float newphidist=std::abs(pos[i].DeltaPhi(pos[j]));
368  if (newphidist<bestphidist)
369  {
370  i_pair[i]=j;
371  bestphidist=newphidist;
372 
373  }
374  }
375  }
376 
377  // check to see if the cluster pairs each match each other
378  std::vector<bool>goodPair;
379  bool allGood=true;
380  int nGood=0;
381 
382  for (int i=0;i<nTpcClust;i++)
383  {
384  int myPair=i_pair[i];
385  int itsPair=myPair<0?-1:i_pair[myPair];
386  if (i!=itsPair )
387  {
388 
389  if( Verbosity() )
390  {
391  std::cout << "PHTpcCentralMembraneClusterizer::process_event -"
392  << " i: " << i
393  << " myPair: " << myPair
394  << " itsPair: " << itsPair
395  << std::endl;
396  }
397 
398  goodPair.push_back(false);
399  allGood=false;
400 
401  } else {
402  if (i<myPair) ++nGood;
403  goodPair.push_back(true);
404  }
405  }
406 
407  if(Verbosity())
408  {
409  if (allGood) std::cout << "PHTpcCentralMembraneClusterizer::process_event - all pairs are good" << std::endl;
410  else std::cout << "PHTpcCentralMembraneClusterizer::process_event - nGood: " << nGood << " out of " << nTpcClust/2 << std::endl;
411  }
412 
413  //build the weighted cluster centers
414  //==========================
415  std::vector<float>aveenergy;
416  std::vector<TVector3> avepos;
417  std::vector<unsigned int> nclusters;
418  std::vector<bool> isREdge;
419  std::vector<std::pair<int,int> > pairNums;
420 
421  // int nR2 = 0;
422  //int nR3 = 0;
423 
424  // double R2AveE = 0.0;
425  //double R3AveE = 0.0;
426 
427  std::pair<int,int> tmp_pair;
428 
429  for (int i=0;i<nTpcClust;++i)
430  {
431  if(_histos) hClustE[0]->Fill(energy[i]);
432 
433  if (goodPair[i])
434  {
435  if (i_pair[i]>i)
436  {
437  if(_histos) hClustE[1]->Fill(energy[i]+energy[i_pair[i]]);
438 
439  aveenergy.push_back(energy[i]+energy[i_pair[i]]);
440 
441  // if(
442 
443 
444  // The pads measure phi and z accurately
445  // They do not measure R! It is taken as the center of the padrow
446  // The x and y values are derived from phi and R. Not normally a problem, since tracks cross entire padrow
447  // CM flash clusters have limited radial extent, do not necessarily cross padrows completely - then their nominal R is wrong.
448  // So:
449  // Get phi from the energy weighted cluster phi values.
450  // Get R from the procedure below
451 
452  // Get phi and z centroid
453  double avePhi = (pos[i].Phi() * energy[i] + pos[i_pair[i]].Phi() * energy[i_pair[i]]) * (1./(energy[i]+energy[i_pair[i]]));
454  double aveZ = (pos[i].Z() * energy[i] + pos[i_pair[i]].Z() * energy[i_pair[i]]) * (1./(energy[i]+energy[i_pair[i]]));
455 
456  // Single padrow CM flash clusters, R position is not well defined because cluster is smaller than padrow
457  // 2-cluster case: Weighting by padrow center radius is not correct because distribution does not fill padrow (needs to be approximately linearly)
458  // Use ratio of component cluster energies to estimate number of sigmas at row boundary
459  float efrac = energy[i] / (energy[i] + energy[i_pair[i]]);
460 
461  PHG4TpcCylinderGeom *layergeom1 = _geom_container->GetLayerCellGeom(layer[i]);
462  double rad1 = layergeom1->get_radius();
463  PHG4TpcCylinderGeom *layergeom2 = _geom_container->GetLayerCellGeom(layer[i_pair[i]]);
464  double rad2 = layergeom2->get_radius();
465  //matching done correctly now, so distance between layers should be directly calculable
466  double layer_dr = std::abs(rad1 - rad2);
467 
468  double rad_lyr_boundary = rad1 + layer_dr / 2.0;
469 
470 
471  // We have to (temporarily) use distortion corrected cluster positions to determine which stripe this came from
472  Acts::Vector3 dist_pos(pos[i].X(), pos[i].Y(), pos[i].Z());
473  if( _dcc) dist_pos = _distortionCorrection.get_corrected_position( dist_pos, _dcc );
474  double dist_r = sqrt(dist_pos[0]*dist_pos[0] + dist_pos[1] * dist_pos[1]);
475  double cmclus_dr = _cmclus_dr_outer;
476 
477  if(dist_r < 41.0){
478  //if across boundary, use average
479  if(rad2 >= 41.0) cmclus_dr = 0.5*(_cmclus_dr_inner + _cmclus_dr_mid);
480  else cmclus_dr = _cmclus_dr_inner;
481  }else if(dist_r >= 41.0 && dist_r < 58.0){
482  //if across boundary, use average
483  if(rad2 >= 58.0) cmclus_dr = 0.5*(_cmclus_dr_mid + _cmclus_dr_outer);
484  else cmclus_dr = _cmclus_dr_mid;
485  }
486 
487  // Use radial width of stripe and efrac to determine where radius at center of distribution must be
488  double aveR = rad_lyr_boundary - efrac * cmclus_dr + cmclus_dr/2.0;
489 
490  if(Verbosity() > 0)
491  std::cout << " efrac " << efrac << " _cmclus_dr "<< cmclus_dr << " rad_lyr_boundary " << rad_lyr_boundary << " aveR " << aveR
492  << " layer i " << layer[i] << " R i " << rad1 << " layer i_pair " << layer[i_pair[i]] << " R i_pair " << rad2 << " layer_dr " << layer_dr << std::endl;
493 
494  TVector3 temppos(aveR*cos(avePhi), aveR*sin(avePhi), aveZ);
495  avepos.push_back(temppos);
496  nclusters.push_back(2);
497  if(isAcrossGap[i] && isAcrossGap[i_pair[i]]) isREdge.push_back(true);
498  else isREdge.push_back(false);
499 
500  tmp_pair.first = i;
501  tmp_pair.second = i_pair[i];
502  pairNums.push_back(tmp_pair);
503 
504 
505 
506  if(Verbosity() > 0)
507  std::cout << " layer i " << layer[i] << " energy " << energy[i] << " pos i " << pos[i].X() << " " << pos[i].Y() << " " << pos[i].Z()
508  << " layer i_pair " << layer[i_pair[i]] << " energy i_pair " << energy[i_pair[i]]
509  << " pos i_pair " << pos[i_pair[i]].X() << " " << pos[i_pair[i]].Y() << " " << pos[i_pair[i]].Z()
510  << " reco pos " << temppos.X() << " " << temppos.Y() << " " << temppos.Z()
511  << std::endl;
512  }
513  } else {
514 
515  if(_histos) hClustE[2]->Fill(energy[i]);
516  // These single cluster cases have good phi, but do not have a good radius centroid estimate - may want to skip them, record nclusters and identify if across gap
517  // if(layer[i] == 7) isAcrossGap[i] = true;
518 
519  aveenergy.push_back(energy[i]);
520  avepos.push_back(pos[i]);
521  nclusters.push_back(1);
522  isREdge.push_back(isAcrossGap[i]);
523  tmp_pair.first = i;
524  tmp_pair.second = -1;
525  pairNums.push_back(tmp_pair);
526 
527  }
528  }
529 
530  // Loop over the vectors and put the clusters on the node tree
531  //==============================================
532  if(Verbosity() > 1) std::cout << " vector size is " << avepos.size() << std::endl;
533 
534  for(unsigned int iv = 0; iv <avepos.size(); ++iv)
535  {
536  auto cmfc = new CMFlashClusterv3();
537 
538 
539  cmfc->setX(avepos[iv].X());
540  cmfc->setY(avepos[iv].Y());
541  cmfc->setZ(avepos[iv].Z());
542  cmfc->setAdc(aveenergy[iv]);
543  cmfc->setNclusters(nclusters[iv]);
544  cmfc->setIsRGap(isREdge[iv]);
545 
546  int pair1 = pairNums[iv].first;
547  int pair2 = pairNums[iv].second;
548 
549  cmfc->setX1(pos[pair1].X());
550  cmfc->setY1(pos[pair1].Y());
551  cmfc->setZ1(pos[pair1].Z());
552  cmfc->setLayer1(layer[pair1]);
553  cmfc->setAdc1(energy[pair1]);
554  if(pair2 != -1){
555  cmfc->setX2(pos[pair2].X());
556  cmfc->setY2(pos[pair2].Y());
557  cmfc->setZ2(pos[pair2].Z());
558  cmfc->setLayer2(layer[pair2]);
559  cmfc->setAdc2(energy[pair2]);
560  }else{
561  cmfc->setX2(0);
562  cmfc->setY2(0);
563  cmfc->setZ2(0);
564  cmfc->setLayer2(0);
565  cmfc->setAdc2(0);
566  }
567 
569 
570  ++m_cm_clusters;
571 
572  if( nclusters[iv]==1 ) ++m_cm_clusters_size1;
573  else if( nclusters[iv]==2 ) ++m_cm_clusters_size2;
574 
575  }
576 
577  // read back the clusters and make some histograms
578 
579  auto clusrange = _corrected_CMcluster_map->getClusters();
580  for (auto cmitr = clusrange.first;
581  cmitr !=clusrange.second;
582  ++cmitr)
583  {
584  auto cmkey = cmitr->first;
585  auto cmclus = cmitr->second;
586 
587  if(Verbosity() > 0)
588  std::cout << "found CM cluster " << cmkey << " with adc " << cmclus->getAdc()
589  << " x " << cmclus->getX() << " y " << cmclus->getY() << " z " << cmclus->getZ()
590  << " nclusters " << cmclus->getNclusters()
591  << std::endl;
592 
593  if(_histos)
594  {
595  henergy->Fill(cmclus->getAdc());
596  hxy->Fill(cmclus->getX(), cmclus->getY());
597  hz->Fill(cmclus->getZ());
598  }
599  }
600 
602 }
603 
604 //____________________________________________________________________________..
606 {
607 
608  if(_histos)
609  {
610  m_histogramfile->cd();
611 
612  henergy->Write();
613  hxy->Write();
614  hz->Write();
615 
616  hz_pos->Write();
617  hz_neg->Write();
618 
619  hClustE[0]->Write();
620  hClustE[1]->Write();
621  hClustE[2]->Write();
622  hDist->Write();
623  hDistRow->Write();
624  hDist2->Write();
625  hDistRowAdj->Write();
626  hDist2Adj->Write();
627 
628  for(int i=0; i<47; i++){
629  hphi_reco_pair_pos[i]->Write();
630  hphi_reco_pair_neg[i]->Write();
631  }
632 
633  m_histogramfile->Close();
634  }
635 
636  // print statistics
637  if( Verbosity() )
638  {
639  std::cout
640  << "PHTpcCentralMembraneClusterizer::End -"
641  << " cluster statistics total: " << m_total_clusters
642  << " accepted: " << m_accepted_clusters << " fraction: "
644  << std::endl;
645 
646  std::cout
647  << "PHTpcCentralMembraneClusterizer::End -"
648  << " cm clusters: " << m_cm_clusters
649  << std::endl;
650 
651  std::cout
652  << "PHTpcCentralMembraneClusterizer::End -"
653  << " cm clusters size 1: " << m_cm_clusters_size1
654  << std::endl;
655 
656  std::cout
657  << "PHTpcCentralMembraneClusterizer::End -"
658  << " cm clusters size 2: " << m_cm_clusters_size2
659  << std::endl;
660  }
662 }
663 
664 //____________________________________________________________________________..
666 {
667  //---------------------------------
668  // Get Objects off of the Node Tree
669  //---------------------------------
670 
671  _cluster_map = findNode::getClass<TrkrClusterContainer>(topNode, "TRKR_CLUSTER");
672  if (!_cluster_map)
673  {
674  std::cout << PHWHERE << " ERROR: Can't find node TRKR_CLUSTER" << std::endl;
676  }
677 
678  _geom_container = findNode::getClass<PHG4TpcCylinderGeomContainer>(topNode, "CYLINDERCELLGEOM_SVTX");
679  if (!_geom_container)
680  {
681  std::cout << PHWHERE << "ERROR: Can't find node CYLINDERCELLGEOM_SVTX" << std::endl;
683  }
684 
685  // tpc distortion correction
686  _dcc = findNode::getClass<TpcDistortionCorrectionContainer>(topNode,"TpcDistortionCorrectionContainer");
687  if( _dcc )
688  {
689  std::cout << "PHTpcCentralMembraneMatcher: found TPC distortion correction container" << std::endl;
690  }
691 
692  _corrected_CMcluster_map = findNode::getClass<CMFlashClusterContainer>(topNode, "CORRECTED_CM_CLUSTER");
694  {
695  std::cout << "Creating node CORRECTED_CM_CLUSTER" << std::endl;
696  PHNodeIterator iter(topNode);
697 
698  // Looking for the DST node
699  PHCompositeNode *dstNode = dynamic_cast<PHCompositeNode *>(iter.findFirst("PHCompositeNode", "DST"));
700  if (!dstNode)
701  {
702  std::cout << PHWHERE << "DST Node missing, doing nothing." << std::endl;
704  }
705  PHNodeIterator dstiter(dstNode);
706  PHCompositeNode *DetNode =
707  dynamic_cast<PHCompositeNode *>(dstiter.findFirst("PHCompositeNode", "TRKR"));
708  if (!DetNode)
709  {
710  DetNode = new PHCompositeNode("TRKR");
711  dstNode->addNode(DetNode);
712  }
713 
715  PHIODataNode<PHObject> *TrkrClusterContainerNode = new PHIODataNode<PHObject>(_corrected_CMcluster_map, "CORRECTED_CM_CLUSTER", "PHObject");
716  DetNode->addNode(TrkrClusterContainerNode);
717  }
718 
720 
721 }