5static double distance(
const std::pair<double, double>& p1,
6 const std::pair<double, double>& p2) {
7 return sqrt((p1.first - p2.first) * (p1.first - p2.first) +
8 (p1.second - p2.second) * (p1.second - p2.second));
11[[maybe_unused]]
static double distance(
12 const std::tuple<double, double, double>& p1,
13 const std::tuple<double, double, double>& p2) {
14 return sqrt((std::get<0>(p1) - std::get<0>(p2)) *
15 (std::get<0>(p1) - std::get<0>(p2)) +
16 (std::get<1>(p1) - std::get<1>(p2)) *
17 (std::get<1>(p1) - std::get<1>(p2)) +
18 (std::get<2>(p1) - std::get<2>(p2)) *
19 (std::get<2>(p1) - std::get<2>(p2)));
25static void rotate(
double& p,
double& q) {
34static void unrotate(
double& p,
double& q) {
55 EXCEPTION_RAISE(
"BadConf",
56 "Cannot shift both odd sensitive layers and odd bilayers");
63 ldmx_log(debug) <<
"Building module map with gap " << std::setprecision(2)
65 <<
", min/max radii of cell " <<
cell_r_min_ <<
" / "
75 ldmx_log(trace) <<
"Geometry fully constructed";
91 EXCEPTION_RAISE(
"BadConf",
"z = " + std::to_string(z) +
92 " mm is not within any"
93 " of the configured layers.");
96 return getID(x, y, layer_id, fallible);
100 bool fallible)
const {
113 double probe_x{p - module_xy.first}, probe_y{q - module_xy.second};
128 "Coordinates relative to layer (p,q) = (%.2f, %.2f) mm "
129 "derived from world coordinates (%.2f, %.2f) mm with layer = %d "
130 "are not inside any module.",
131 p, q, x, y, layer_id)
136 return getID(x, y, layer_id, module_id);
140 bool fallible)
const {
161 "Relative cell coordinates (%.2f, %.2f) mm "
162 "derived from world coordinates (%.2f, %.2f) mm with layer = %d "
163 "and module = %d are outside module hexagon",
164 p, q, x, y, layer_id, module_id)
169 return EcalID(layer_id, module_id, cell_id);
190 ldmx_log(debug) <<
"Shifting odd layers by (x,y) = (" <<
layer_shift_x_
193 ldmx_log(debug) <<
"Shifting odd bilayers by (x,y) = (" <<
layer_shift_x_
208 ldmx_log(trace) <<
" Layer " << i_layer <<
" has center at (" << x
209 <<
", " << y <<
", " << z <<
") mm";
216 static const double C_PI = 3.14159265358979323846;
227 for (
unsigned id = 1;
id < 7;
id++) {
237 ldmx_log(trace) <<
" Module " <<
id <<
" is centered at (x,y) = " <<
"("
238 << x <<
", " << y <<
") mm";
265 double gridMinP = 0., gridMinQ = 0.;
266 int numPCells = 0, numQCells = 0;
279 if (numQCells % 2 == 0)
289 gridMap.Honeycomb(gridMinP, gridMinQ,
cell_r_max_, numPCells, numQCells);
291 ldmx_log(trace) << std::setprecision(2)
292 <<
"Building buildCellMap with cell rmin: " <<
cell_r_min_
293 <<
" cell rmax: " <<
cell_r_max_ <<
" (gridMinP,gridMinQ) = ("
294 << gridMinP <<
"," << gridMinQ <<
")"
295 <<
" (numPCells,numQCells) = (" << numPCells <<
","
299 TListIter next(gridMap.GetBins());
300 TH2PolyBin* polyBin = 0;
304 while ((polyBin = (TH2PolyBin*)next())) {
308 poly = (TGraph*)polyBin->GetPolygon();
312 int numVerticesInside = 0;
313 double vertex_p[6], vertex_q[6];
315 ldmx_log(trace) <<
" Cell vertices";
316 for (
unsigned i = 0; i < 6; i++) {
317 poly->GetPoint(i, vertex_p[i], vertex_q[i]);
318 ldmx_log(trace) <<
" vtx # " << i;
319 ldmx_log(trace) <<
" vtx p,q " << vertex_p[i] <<
" " << vertex_q[i];
323 if (isinside[i]) numVerticesInside++;
326 if (numVerticesInside > 1) {
329 double actual_p[8], actual_q[8];
331 if (numVerticesInside < 6) {
335 ldmx_log(trace) <<
" Polygon " << cell_id
336 <<
" has vertices poking out of module hexagon.";
339 for (
int i = 0; i < 6; i++) {
340 int up = i == 5 ? 0 : i + 1;
341 int dn = i == 0 ? 5 : i - 1;
342 if (isinside[i] and (not isinside[up] or not isinside[dn])) {
349 double edge_origin_p, edge_origin_q;
350 double edge_dest_p, edge_dest_q;
371 if (vertex_q[i] < 0) {
377 double edge_slope_p = edge_dest_p - edge_origin_p;
378 double edge_slope_q = edge_dest_q - edge_origin_q;
382 <<
" is inside and adjacent to a vertex outside the module.";
383 ldmx_log(trace) <<
"Working on edge with slope (" << edge_slope_p
384 <<
"," << edge_slope_q <<
")" <<
" and origin ("
385 << edge_origin_p <<
"," << edge_origin_q <<
")";
389 double projection_factor =
390 ((vertex_p[i] - edge_origin_p) * edge_slope_p +
391 (vertex_q[i] - edge_origin_q) * edge_slope_q) /
392 (edge_slope_p * edge_slope_p + edge_slope_q * edge_slope_q);
394 double proj_p = edge_origin_p + projection_factor * edge_slope_p;
395 double proj_q = edge_origin_q + projection_factor * edge_slope_q;
397 if (not isinside[up]) {
399 actual_p[num_vertices] = vertex_p[i];
400 actual_q[num_vertices] = vertex_q[i];
401 actual_p[num_vertices + 1] = proj_p;
402 actual_q[num_vertices + 1] = proj_q;
405 actual_p[num_vertices] = proj_p;
406 actual_q[num_vertices] = proj_q;
407 actual_p[num_vertices + 1] = vertex_p[i];
408 actual_q[num_vertices + 1] = vertex_q[i];
412 ldmx_log(trace) <<
"New Vertex " << i <<
" : (" << vertex_p[i]
413 <<
"," << vertex_q[i] <<
")";
416 actual_p[num_vertices] = vertex_p[i];
417 actual_q[num_vertices] = vertex_q[i];
424 for (
int i = 0; i < 6; i++) {
425 actual_p[i] = vertex_p[i];
426 actual_q[i] = vertex_q[i];
439 double p = (polyBin->GetXMax() + polyBin->GetXMin()) / 2.;
440 double q = (polyBin->GetYMax() + polyBin->GetYMin()) / 2.;
442 ldmx_log(trace) <<
" Copying poly with ID " << polyBin->GetBinNumber()
443 <<
" and (p,q) (" << std::setprecision(2) << p <<
"," << q
454 ldmx_log(trace) <<
"Building cellModule position map";
458 double cell_x{cell_pq.first}, cell_y{cell_pq.second};
465 auto cell_rel_to_layer =
466 std::make_pair(module_xy.first + cell_x, module_xy.second + cell_y);
480 std::make_tuple(rel_to_layer.first + std::get<0>(layer_xyz),
481 rel_to_layer.second + std::get<1>(layer_xyz),
482 std::get<2>(layer_xyz));
505 ldmx_log(trace) <<
"Building Nearest and Next-Nearest Neighbor maps";
512 double dist = distance(probe_xyz, center_xyz);
514 nn_map_[center_id].push_back(probe_id);
516 nnn_map_[center_id].push_back(probe_id);
529 double x = fabs(cellLocation.first);
530 double y = fabs(cellLocation.second);
531 double r = sqrt(x * x + y * y);
532 double theta = (r > 1E-3) ? fabs(std::atan(y / x)) : 0;
537 sqrt(3.) *
module_r_max_ / (std::sin(theta) + sqrt(3.) * std::cos(theta));
542 ldmx_log(trace) << std::fixed << std::setprecision(2)
543 <<
"Checking if normXY=(" << normX <<
"," << normY
545 normX = fabs(normX), normY = fabs(normY);
546 double xvec = -1, yvec = -1. / sqrt(3);
547 double xref = 0.5, yref = sqrt(3) / 2.;
548 if ((normX > 1.) || (normY > yref)) {
549 ldmx_log(trace) <<
"They are outside quadrant.";
552 double dotProd = (xvec * (normX - xref) + yvec * (normY - yref));
553 ldmx_log(trace) << std::fixed << std::setprecision(2)
554 <<
"They are inside quadrant. Dot product (>0 is inside): "
556 return (dotProd > 0.);
Class that translates raw positions of ECal module hits into cells in a hexagonal readout.
Class encapsulating parameters for configuring a processor.
const T & get(const std::string &name) const
Retrieve the parameter of the given name.
Translation between real-space positions and cell IDs within the ECal.
std::map< EcalID, std::tuple< double, double, double > > cell_global_pos_
Position of cell centers relative to world geometry.
std::map< EcalID, std::vector< EcalID > > nnn_map_
Map of cell ID to neighbors of neighbor cells.
EcalID getID(double x, double y, double z, bool fallible=false) const
Get a cell's ID number from its position.
std::tuple< double, double, double > getPosition(EcalID id) const
Get a cell's position from its ID number.
void buildCellModuleMap()
Constructs the positions of all the cells in a layer relative to the ecal center.
double layer_shift_y_
shift of layers in the y-direction [mm]
double distanceToEdge(EcalID id) const
Distance to module edge, and whether cell is on edge of module.
std::pair< double, double > getPositionInModule(int cell_id) const
Get a cell's position within a module.
std::map< int, std::pair< double, double > > module_pos_xy_
Postion of module centers relative to the center of the layer in world coordinates.
void buildCellMap()
Constructs the flat-bottomed hexagonal grid (cellID) of corner-down hexagonal cells.
bool layer_shift_odd_
shift odd layers
double module_r_max_
Center-to-Corner Radius of module hexagon [mm].
double cell_r_min_
Center-to-Flat Radius of cell hexagon [mm].
std::map< int, std::tuple< double, double, double > > layer_pos_xy_
Position of layer centers in world coordinates (uses layer ID as key)
double n_cell_r_height_
Number of cell center-to-corner radii (one side of the cell) from the bottom to the top of the module...
std::map< int, std::pair< double, double > > cell_pos_in_module_
Position of cell centers relative to center of module in p,q space.
double layer_shift_x_
shift of layers in the x-direction [mm]
void buildModuleMap()
Constructs the positions of the seven modules (moduleID) relative to the ecal center.
std::map< EcalID, std::pair< double, double > > cell_pos_in_layer_
Position of cell centers relative to center of layer in world coordinates.
std::map< EcalID, std::vector< EcalID > > nn_map_
Map of cell ID to neighboring cells.
std::vector< double > layer_z_positions_
The layer Z postions are with respect to the front of the ECal [mm].
bool isInside(double normX, double normY) const
Determines if point (x,y), already normed to max hexagon radius, lies within a hexagon.
double si_thickness_
Thickness of the Si sensitive layer [mm].
bool layer_shift_odd_bilayer_
shift odd bi layers
void buildLayerMap()
Constructs the positions of the layers in world coordinates.
EcalGeometry(const framework::config::Parameters &ps)
Class constructor, for use only by the provider.
double cell_r_max_
Center-to-Corner Radius of cell hexagon [mm].
double ecal_front_z_
Front of ECal relative to world geometry [mm].
double gap_
Gap between module flat sides [mm].
double module_r_min_
Center-to-Flat Radius of module hexagon [mm].
TH2Poly cell_id_in_module_
Honeycomb Binning from ROOT.
void buildNeighborMaps()
Construts NNMap and NNNMap.
bool corners_side_up_
indicator of geometry orientation if true, flower shape's corners side (ie: side with two modules) is...
Extension of DetectorID providing access to ECal layers and cell numbers in a hex grid.
All classes in the ldmx-sw project use this namespace.