CMS 3D CMS Logo

MTDThresholdClusterizer.cc
Go to the documentation of this file.
1 // Our own includes
5 
8 
12 
14 
15 // STL
16 #include <stack>
17 #include <vector>
18 #include <iostream>
19 #include <atomic>
20 #include <cmath>
21 using namespace std;
22 
23 //----------------------------------------------------------------------------
25 //----------------------------------------------------------------------------
27  : // Get energy thresholds
28  theHitThreshold(conf.getParameter<double>("HitThreshold")),
29  theSeedThreshold(conf.getParameter<double>("SeedThreshold")),
30  theClusterThreshold(conf.getParameter<double>("ClusterThreshold")),
31  theTimeThreshold(conf.getParameter<double>("TimeThreshold")),
32  thePositionThreshold(conf.getParameter<double>("PositionThreshold")),
33  theNumOfRows(0),
34  theNumOfCols(0),
35  theCurrentId(0),
36  theBuffer(theNumOfRows, theNumOfCols),
37  bufferAlreadySet(false) {}
40 
41 // Configuration descriptions
43  desc.add<double>("HitThreshold", 0.);
44  desc.add<double>("SeedThreshold", 0.);
45  desc.add<double>("ClusterThreshold", 0.);
46  desc.add<double>("TimeThreshold", 10.);
47  desc.add<double>("PositionThreshold", -1.0);
48 }
49 
50 //----------------------------------------------------------------------------
53 //----------------------------------------------------------------------------
54 bool MTDThresholdClusterizer::setup(const MTDGeometry* geom, const MTDTopology* topo, const DetId& id) {
55  theCurrentId = id;
56  //using geopraphicalId here
57  const auto& thedet = geom->idToDet(id);
58  if (thedet == nullptr) {
59  throw cms::Exception("MTDThresholdClusterizer")
60  << "GeographicalID: " << std::hex << id.rawId() << " is invalid!" << std::dec << std::endl;
61  return false;
62  }
63  const ProxyMTDTopology& topoproxy = static_cast<const ProxyMTDTopology&>(thedet->topology());
64  const RectangularMTDTopology& topol = static_cast<const RectangularMTDTopology&>(topoproxy.specificTopology());
65 
66  // Get the new sizes.
67  unsigned int nrows = topol.nrows(); // rows in x
68  unsigned int ncols = topol.ncolumns(); // cols in y
69 
70  theNumOfRows = nrows; // Set new sizes
72 
73  LogDebug("MTDThresholdClusterizer") << "Buffer size [" << theNumOfRows + 1 << "," << theNumOfCols + 1 << "]";
74 
75  if (nrows > theBuffer.rows() || ncols > theBuffer.columns()) { // change only when a larger is needed
76  // Resize the buffer
77  theBuffer.setSize(nrows, ncols);
78  bufferAlreadySet = true;
79  }
80 
81  return true;
82 }
83 //----------------------------------------------------------------------------
89 //----------------------------------------------------------------------------
91  const MTDGeometry* geom,
92  const MTDTopology* topo,
96 
97  // Do not bother for empty detectors
98  if (begin == end) {
99  edm::LogInfo("MTDThresholdClusterizer") << "No hits to clusterize";
100  return;
101  }
102 
103  LogDebug("MTDThresholdClusterizer") << "Input collection " << input.size();
104  assert(output.empty());
105 
106  std::set<unsigned> geoIds;
107  std::multimap<unsigned, unsigned> geoIdToIdx;
108 
109  unsigned index = 0;
110  for (const auto& hit : input) {
111  MTDDetId mtdId = MTDDetId(hit.detid());
112  if (mtdId.subDetector() != MTDDetId::FastTime) {
113  throw cms::Exception("MTDThresholdClusterizer")
114  << "MTDDetId: " << std::hex << mtdId.rawId() << " is invalid!" << std::dec << std::endl;
115  }
116 
117  if (mtdId.mtdSubDetector() == MTDDetId::BTL) {
118  BTLDetId hitId(hit.detid());
119  //for BTL topology gives different layout id
120  DetId geoId = hitId.geographicalId(MTDTopologyMode::crysLayoutFromTopoMode(topo->getMTDTopologyMode()));
121  geoIdToIdx.emplace(geoId, index);
122  geoIds.emplace(geoId);
123  ++index;
124  } else if (mtdId.mtdSubDetector() == MTDDetId::ETL) {
125  ETLDetId hitId(hit.detid());
126  DetId geoId = hitId.geographicalId();
127  geoIdToIdx.emplace(geoId, index);
128  geoIds.emplace(geoId);
129  ++index;
130  } else {
131  throw cms::Exception("MTDThresholdClusterizer")
132  << "MTDDetId: " << std::hex << mtdId.rawId() << " is invalid!" << std::dec << std::endl;
133  }
134  }
135 
136  //cluster hits within geoIds (modules)
137  for (unsigned id : geoIds) {
138  // Set up the clusterization on this DetId.
139  if (!setup(geom, topo, DetId(id)))
140  return;
141 
142  auto range = geoIdToIdx.equal_range(id);
143  LogDebug("MTDThresholdClusterizer") << "Matching Ids for " << std::hex << id << std::dec << " ["
144  << range.first->second << "," << range.second->second << "]";
145 
146  // Copy MTDRecHits to the buffer array; select the seed hits
147  // on the way, and store them in theSeeds.
148  for (auto itr = range.first; itr != range.second; ++itr) {
149  const unsigned hitidx = itr->second;
150  copy_to_buffer(begin + hitidx, geom, topo);
151  }
152 
153  FTLClusterCollection::FastFiller clustersOnDet(output, id);
154 
155  for (unsigned int i = 0; i < theSeeds.size(); i++) {
156  if (theBuffer.energy(theSeeds[i]) > theSeedThreshold) { // Is this seed still valid?
157  // Make a cluster around this seed
158  const FTLCluster& cluster = make_cluster(theSeeds[i]);
159 
160  // Check if the cluster is above threshold
161  if (cluster.energy() > theClusterThreshold) {
162  LogDebug("MTDThresholdClusterizer")
163  << "putting in this cluster " << i << " #hits:" << cluster.size() << " E:" << cluster.energy()
164  << " T +/- DT:" << cluster.time() << " +/- " << cluster.timeError() << " X:" << cluster.x()
165  << " Y:" << cluster.y() << " xpos +/- err " << cluster.getClusterPosX() << " +/- "
166  << cluster.getClusterErrorX();
167  clustersOnDet.push_back(cluster);
168  }
169  }
170  }
171 
172  // Erase the seeds.
173  theSeeds.clear();
174  // Need to clean unused hits from the buffer array.
175  for (auto itr = range.first; itr != range.second; ++itr) {
176  const unsigned hitidx = itr->second;
177  clear_buffer(begin + hitidx);
178  }
179  }
180 }
181 
182 //----------------------------------------------------------------------------
188 //----------------------------------------------------------------------------
189 void MTDThresholdClusterizer::clear_buffer(RecHitIterator itr) { theBuffer.clear(itr->row(), itr->column()); }
190 
191 //----------------------------------------------------------------------------
193 //----------------------------------------------------------------------------
195  MTDDetId mtdId = MTDDetId(itr->detid());
196  int row = itr->row();
197  int col = itr->column();
199  float energy = itr->energy();
200  float time = itr->time();
201  float timeError = itr->timeError();
202  float position = itr->position();
203  float xpos = 0.f;
204  // position is the longitudinal offset that should be added into local x for bars in phi geometry
205  LocalPoint local_point(0, 0, 0);
206  LocalError local_error(0, 0, 0);
207  if (mtdId.mtdSubDetector() == MTDDetId::BTL) {
209  BTLDetId id = itr->id();
210  DetId geoId = id.geographicalId(MTDTopologyMode::crysLayoutFromTopoMode(topo->getMTDTopologyMode()));
211  const auto& det = geom->idToDet(geoId);
212  const ProxyMTDTopology& topoproxy = static_cast<const ProxyMTDTopology&>(det->topology());
213  const RectangularMTDTopology& topol = static_cast<const RectangularMTDTopology&>(topoproxy.specificTopology());
214 
215  LocalPoint lp_pixel(position, 0, 0);
216  local_point = topol.pixelToModuleLocalPoint(lp_pixel, row, col);
217  BTLRecHitsErrorEstimatorIM btlError(det, local_point);
218  local_error = btlError.localError();
219  xpos = local_point.x();
220  } else if (mtdId.mtdSubDetector() == MTDDetId::ETL) {
222  ETLDetId id = itr->id();
223  DetId geoId = id.geographicalId();
224  const auto& det = geom->idToDet(geoId);
225  const ProxyMTDTopology& topoproxy = static_cast<const ProxyMTDTopology&>(det->topology());
226  const RectangularMTDTopology& topol = static_cast<const RectangularMTDTopology&>(topoproxy.specificTopology());
227 
228  LocalPoint lp_pixel(0, 0, 0);
229  local_point = topol.pixelToModuleLocalPoint(lp_pixel, row, col);
230  }
231 
232  LogDebug("MTDThresholdClusterizer") << "DetId " << mtdId.rawId() << " subd " << mtdId.mtdSubDetector() << " row/col "
233  << row << " / " << col << " energy " << energy << " time " << time
234  << " time error " << timeError << " local_point " << local_point.x() << " "
235  << local_point.y() << " " << local_point.z() << " local error "
236  << std::sqrt(local_error.xx()) << " " << std::sqrt(local_error.yy()) << " xpos "
237  << xpos;
238  if (energy > theHitThreshold) {
239  theBuffer.set(row, col, subDet, energy, time, timeError, local_error, local_point, xpos);
240  if (energy > theSeedThreshold)
241  theSeeds.push_back(FTLCluster::FTLHitPos(row, col));
242  //sort seeds?
243  }
244 }
245 
246 //----------------------------------------------------------------------------
248 //----------------------------------------------------------------------------
250  //First we acquire the seeds for the clusters
251 
252  GeomDetEnumerators::Location seed_subdet = theBuffer.subDet(hit.row(), hit.col());
253  float seed_energy = theBuffer.energy(hit.row(), hit.col());
254  float seed_time = theBuffer.time(hit.row(), hit.col());
255  float seed_time_error = theBuffer.time_error(hit.row(), hit.col());
256  auto const seedPoint = theBuffer.local_point(hit.row(), hit.col());
257  double seed_error_xx = theBuffer.local_error(hit.row(), hit.col()).xx();
258  double seed_error_yy = theBuffer.local_error(hit.row(), hit.col()).yy();
259  double seed_xpos = theBuffer.xpos(hit.row(), hit.col());
261 
262  AccretionCluster acluster;
263  acluster.add(hit, seed_energy, seed_time, seed_time_error);
264 
265  // for BTL position along crystals add auxiliary vectors
266  std::array<float, AccretionCluster::MAXSIZE> pixel_x{{-99999.}};
267  std::array<float, AccretionCluster::MAXSIZE> pixel_errx2{{-99999.}};
268  if (seed_subdet == GeomDetEnumerators::barrel) {
269  pixel_x[acluster.top()] = seed_xpos;
270  pixel_errx2[acluster.top()] = seed_error_xx;
271  }
272 
273  bool stopClus = false;
274  //Here we search all hits adjacent to all hits in the cluster.
275  while (!acluster.empty() && !stopClus) {
276  //This is the standard algorithm to find and add a hit
277  auto curInd = acluster.top();
278  acluster.pop();
279  for (auto c = std::max(0, int(acluster.y[curInd] - 1));
280  c < std::min(int(acluster.y[curInd] + 2), int(theBuffer.columns())) && !stopClus;
281  ++c) {
282  for (auto r = std::max(0, int(acluster.x[curInd] - 1));
283  r < std::min(int(acluster.x[curInd] + 2), int(theBuffer.rows())) && !stopClus;
284  ++r) {
285  LogDebug("MTDThresholdClusterizer")
286  << "Clustering subdet " << seed_subdet << " around " << curInd << " X,Y = " << acluster.x[curInd] << ","
287  << acluster.y[curInd] << " r,c = " << r << "," << c << " energy,time = " << theBuffer.energy(r, c) << " "
288  << theBuffer.time(r, c);
289  if (theBuffer.energy(r, c) > theHitThreshold) {
290  if (std::abs(theBuffer.time(r, c) - seed_time) >
292  sqrt(theBuffer.time_error(r, c) * theBuffer.time_error(r, c) + seed_time_error * seed_time_error))
293  continue;
294  if ((seed_subdet == GeomDetEnumerators::barrel) && (theBuffer.subDet(r, c) == GeomDetEnumerators::barrel) &&
295  (thePositionThreshold > 0)) {
296  double hit_error_xx = theBuffer.local_error(r, c).xx();
297  double hit_error_yy = theBuffer.local_error(r, c).yy();
298  if (((theBuffer.local_point(r, c) - seedPoint).mag2()) >
300  (hit_error_xx + seed_error_xx + hit_error_yy + seed_error_yy))
301  continue;
302  }
303  FTLCluster::FTLHitPos newhit(r, c);
304  if (!acluster.add(newhit, theBuffer.energy(r, c), theBuffer.time(r, c), theBuffer.time_error(r, c))) {
305  stopClus = true;
306  break;
307  }
309  pixel_x[acluster.top()] = theBuffer.xpos(r, c);
310  pixel_errx2[acluster.top()] = theBuffer.local_error(r, c).xx();
311  }
312  theBuffer.clear(newhit);
313  }
314  }
315  }
316  } // while accretion
317 
318  FTLCluster cluster(theCurrentId,
319  acluster.isize,
320  acluster.energy.data(),
321  acluster.time.data(),
322  acluster.timeError.data(),
323  acluster.x.data(),
324  acluster.y.data(),
325  acluster.xmin,
326  acluster.ymin);
327 
328  // For BTL compute the optimal position along crystal and uncertainty on it in absolute length units
329 
330  if (seed_subdet == GeomDetEnumerators::barrel) {
331  float sumW(0.f), sumXW(0.f), sumXW2(0.f);
332  for (unsigned int index = 0; index < acluster.top(); index++) {
333  sumW += acluster.energy[index];
334  sumXW += acluster.energy[index] * pixel_x[index];
335  sumXW2 += acluster.energy[index] * acluster.energy[index] * pixel_errx2[index];
336  }
337  cluster.setClusterPosX(sumXW / sumW);
338  cluster.setClusterErrorX(std::sqrt(sumXW2) / sumW);
339  }
340 
341  return cluster;
342 }
void clusterize(const FTLRecHitCollection &input, const MTDGeometry *geom, const MTDTopology *topo, FTLClusterCollection &output) override
Cluster hits. This method operates on a matrix of hits and finds the largest contiguous cluster aroun...
int getMTDTopologyMode() const
Definition: MTDTopology.h:27
uint rows() const
void push_back(data_type const &d)
void set(uint row, uint col, GeomDetEnumerators::Location subDet, float energy, float time, float time_error, const LocalError &local_error, const LocalPoint &local_point, float xpos)
float energy(uint row, uint col) const
float x() const
Definition: FTLCluster.h:120
int size() const
Definition: FTLCluster.h:153
float time(uint row, uint col) const
LocalError local_error(uint row, uint col) const
static void fillPSetDescription(edm::ParameterSetDescription &desc)
T z() const
Definition: PV3DBase.h:61
uint columns() const
virtual const PixelTopology & specificTopology() const
FTLRecHitCollection::const_iterator RecHitIterator
std::vector< T >::const_iterator const_iterator
int mtdSubDetector() const
Definition: MTDDetId.h:56
const float theHitThreshold
Clustering-related quantities:
int theNumOfRows
Geometry-related information.
MTDThresholdClusterizer(edm::ParameterSet const &conf)
Constructor:
GeomDetEnumerators::Location subDet(uint row, uint col) const
Use subDet to identify whether the Hit is in BTL or ETL.
bool add(FTLCluster::FTLHitPos const &p, float const ienergy, float const itime, float const itimeError)
assert(be >=bs)
LocalPoint pixelToModuleLocalPoint(const LocalPoint &plp, int row, int col) const
Detector identifier base class for the MIP Timing Layer.
Definition: MTDDetId.h:21
static std::string const input
Definition: EdmProvDump.cc:50
float time_error(uint row, uint col) const
void copy_to_buffer(RecHitIterator itr, const MTDGeometry *geom, const MTDTopology *topo)
Copy FTLRecHit into the buffer, identify seeds.
float getClusterErrorX() const
Definition: FTLCluster.h:212
float yy() const
Definition: LocalError.h:24
T x() const
Definition: PV3DBase.h:59
T y() const
Definition: PV3DBase.h:60
float y() const
Definition: FTLCluster.h:125
bool setup(const MTDGeometry *geometry, const MTDTopology *topo, const DetId &id)
std::array< float, MAXSIZE > timeError
int ncolumns() const override
T sqrt(T t)
Definition: SSEVec.h:19
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
double f[11][100]
int nrows() const override
std::vector< FTLCluster::FTLHitPos > theSeeds
float getClusterPosX() const
Definition: FTLCluster.h:211
std::array< UShort, MAXSIZE > x
std::array< float, MAXSIZE > time
Log< level::Info, false > LogInfo
Definition: DetId.h:17
float xpos(uint row, uint col) const
constexpr uint32_t rawId() const
get the raw id
Definition: DetId.h:57
T mag2() const
The vector magnitude squared. Equivalent to vec.dot(vec)
float energy() const
Definition: FTLCluster.h:161
MTDArrayBuffer theBuffer
Data storage.
FTLCluster make_cluster(const FTLCluster::FTLHitPos &hit)
The actual clustering algorithm: group the neighboring hits around the seed.
Detector identifier class for the Endcap Timing Layer.
Definition: ETLDetId.h:15
SubDetector subDetector() const
Definition: MTDDetId.h:53
static int position[264][3]
Definition: ReadPGInfo.cc:289
Detector identifier class for the Barrel Timing Layer. The crystal count must start from 0...
Definition: BTLDetId.h:19
col
Definition: cuy.py:1009
void clear_buffer(RecHitIterator itr)
Clear the internal buffer array.
float timeError() const
Definition: FTLCluster.h:147
Definition: output.py:1
float time() const
Definition: FTLCluster.h:142
BTLDetId::CrysLayout crysLayoutFromTopoMode(const int &topoMode)
std::array< UShort, MAXSIZE > y
void clear(uint row, uint col)
LocalPoint local_point(uint row, uint col) const
std::array< float, MAXSIZE > energy
float xx() const
Definition: LocalError.h:22
void setSize(uint rows, uint cols)
#define LogDebug(id)