8#include "Framework/Exception/Exception.h"
14static double distance(
const std::pair<double, double>& p1,
15 const std::pair<double, double>& p2) {
16 return sqrt((p1.first - p2.first) * (p1.first - p2.first) +
17 (p1.second - p2.second) * (p1.second - p2.second));
20[[maybe_unused]]
static double distance(
21 const std::tuple<double, double, double>& p1,
22 const std::tuple<double, double, double>& p2) {
23 return sqrt((std::get<0>(p1) - std::get<0>(p2)) *
24 (std::get<0>(p1) - std::get<0>(p2)) +
25 (std::get<1>(p1) - std::get<1>(p2)) *
26 (std::get<1>(p1) - std::get<1>(p2)) +
27 (std::get<2>(p1) - std::get<2>(p2)) *
28 (std::get<2>(p1) - std::get<2>(p2)));
34static void rotate(
double& p,
double& q) {
43static void unrotate(
double& p,
double& q) {
64 EXCEPTION_RAISE(
"BadConf",
65 "Cannot shift both odd sensitive layers and odd bilayers");
72 ldmx_log(debug) <<
"Building module map with gap " << std::setprecision(2)
74 <<
", min/max radii of cell " <<
cell_r_min_ <<
" / "
84 ldmx_log(trace) <<
"Geometry fully constructed";
100 EXCEPTION_RAISE(
"BadConf",
"z = " + std::to_string(z) +
101 " mm is not within any"
102 " of the configured layers.");
105 return getID(x, y, layer_id, fallible);
109 bool fallible)
const {
122 double probe_x{p - module_xy.first}, probe_y{q - module_xy.second};
137 "Coordinates relative to layer (p,q) = (%.2f, %.2f) mm "
138 "derived from world coordinates (%.2f, %.2f) mm with layer = %d "
139 "are not inside any module.",
140 p, q, x, y, layer_id)
145 return getID(x, y, layer_id, module_id);
149 bool fallible)
const {
170 "Relative cell coordinates (%.2f, %.2f) mm "
171 "derived from world coordinates (%.2f, %.2f) mm with layer = %d "
172 "and module = %d are outside module hexagon",
173 p, q, x, y, layer_id, module_id)
178 return EcalID(layer_id, module_id, cell_id);
199 ldmx_log(debug) <<
"Shifting odd layers by (x,y) = (" <<
layer_shift_x_
202 ldmx_log(debug) <<
"Shifting odd bilayers by (x,y) = (" <<
layer_shift_x_
217 ldmx_log(trace) <<
" Layer " << i_layer <<
" has center at (" << x
218 <<
", " << y <<
", " << z <<
") mm";
225 static const double c_pi = 3.14159265358979323846;
236 for (
unsigned id = 1;
id < 7;
id++) {
246 ldmx_log(trace) <<
" Module " <<
id <<
" is centered at (x,y) = " <<
"("
247 << x <<
", " << y <<
") mm";
274 double grid_min_p = 0., grid_min_q = 0.;
275 int num_p_cells = 0, num_q_cells = 0;
289 if (num_q_cells % 2 == 0)
299 grid_map.Honeycomb(grid_min_p, grid_min_q,
cell_r_max_, num_p_cells,
302 ldmx_log(trace) << std::setprecision(2)
303 <<
"Building buildCellMap with cell rmin: " <<
cell_r_min_
304 <<
" cell rmax: " <<
cell_r_max_ <<
" (gridMinP,gridMinQ) = ("
305 << grid_min_p <<
"," << grid_min_q <<
")"
306 <<
" (numPCells,numQCells) = (" << num_p_cells <<
","
307 << num_q_cells <<
")";
310 TListIter next(grid_map.GetBins());
311 TH2PolyBin* poly_bin = 0;
315 while ((poly_bin = (TH2PolyBin*)next())) {
319 poly = (TGraph*)poly_bin->GetPolygon();
323 int num_vertices_inside = 0;
324 double vertex_p[6], vertex_q[6];
326 ldmx_log(trace) <<
" Cell vertices";
327 for (
unsigned i = 0; i < 6; i++) {
328 poly->GetPoint(i, vertex_p[i], vertex_q[i]);
329 ldmx_log(trace) <<
" vtx # " << i;
330 ldmx_log(trace) <<
" vtx p,q " << vertex_p[i] <<
" " << vertex_q[i];
334 if (isinside[i]) num_vertices_inside++;
337 if (num_vertices_inside > 1) {
340 double actual_p[8], actual_q[8];
342 if (num_vertices_inside < 6) {
346 ldmx_log(trace) <<
" Polygon " << cell_id
347 <<
" has vertices poking out of module hexagon.";
350 for (
int i = 0; i < 6; i++) {
351 int up = i == 5 ? 0 : i + 1;
352 int dn = i == 0 ? 5 : i - 1;
353 if (isinside[i] and (not isinside[up] or not isinside[dn])) {
360 double edge_origin_p, edge_origin_q;
361 double edge_dest_p, edge_dest_q;
382 if (vertex_q[i] < 0) {
388 double edge_slope_p = edge_dest_p - edge_origin_p;
389 double edge_slope_q = edge_dest_q - edge_origin_q;
393 <<
" is inside and adjacent to a vertex outside the module.";
394 ldmx_log(trace) <<
"Working on edge with slope (" << edge_slope_p
395 <<
"," << edge_slope_q <<
")" <<
" and origin ("
396 << edge_origin_p <<
"," << edge_origin_q <<
")";
400 double projection_factor =
401 ((vertex_p[i] - edge_origin_p) * edge_slope_p +
402 (vertex_q[i] - edge_origin_q) * edge_slope_q) /
403 (edge_slope_p * edge_slope_p + edge_slope_q * edge_slope_q);
405 double proj_p = edge_origin_p + projection_factor * edge_slope_p;
406 double proj_q = edge_origin_q + projection_factor * edge_slope_q;
408 if (not isinside[up]) {
410 actual_p[num_vertices] = vertex_p[i];
411 actual_q[num_vertices] = vertex_q[i];
412 actual_p[num_vertices + 1] = proj_p;
413 actual_q[num_vertices + 1] = proj_q;
416 actual_p[num_vertices] = proj_p;
417 actual_q[num_vertices] = proj_q;
418 actual_p[num_vertices + 1] = vertex_p[i];
419 actual_q[num_vertices + 1] = vertex_q[i];
423 ldmx_log(trace) <<
"New Vertex " << i <<
" : (" << vertex_p[i]
424 <<
"," << vertex_q[i] <<
")";
427 actual_p[num_vertices] = vertex_p[i];
428 actual_q[num_vertices] = vertex_q[i];
435 for (
int i = 0; i < 6; i++) {
436 actual_p[i] = vertex_p[i];
437 actual_q[i] = vertex_q[i];
450 double p = (poly_bin->GetXMax() + poly_bin->GetXMin()) / 2.;
451 double q = (poly_bin->GetYMax() + poly_bin->GetYMin()) / 2.;
453 ldmx_log(trace) <<
" Copying poly with ID " << poly_bin->GetBinNumber()
454 <<
" and (p,q) (" << std::setprecision(2) << p <<
"," << q
465 ldmx_log(trace) <<
"Building cellModule position map";
469 double cell_x{cell_pq.first}, cell_y{cell_pq.second};
476 auto cell_rel_to_layer =
477 std::make_pair(module_xy.first + cell_x, module_xy.second + cell_y);
491 std::make_tuple(rel_to_layer.first + std::get<0>(layer_xyz),
492 rel_to_layer.second + std::get<1>(layer_xyz),
493 std::get<2>(layer_xyz));
516 ldmx_log(trace) <<
"Building Nearest and Next-Nearest Neighbor maps";
523 double dist = distance(probe_xyz, center_xyz);
525 nn_map_[center_id].push_back(probe_id);
527 nnn_map_[center_id].push_back(probe_id);
540 double x = fabs(cell_location.first);
541 double y = fabs(cell_location.second);
542 double r = sqrt(x * x + y * y);
543 double theta = (r > 1E-3) ? fabs(std::atan(y / x)) : 0;
548 sqrt(3.) *
module_r_max_ / (std::sin(theta) + sqrt(3.) * std::cos(theta));
553 ldmx_log(trace) << std::fixed << std::setprecision(2)
554 <<
"Checking if normXY=(" << normX <<
"," << normY
556 normX = fabs(normX), normY = fabs(normY);
557 double xvec = -1, yvec = -1. / sqrt(3);
558 double xref = 0.5, yref = sqrt(3) / 2.;
559 if ((normX > 1.) || (normY > yref)) {
560 ldmx_log(trace) <<
"They are outside quadrant.";
563 double dot_prod = (xvec * (normX - xref) + yvec * (normY - yref));
564 ldmx_log(trace) << std::fixed << std::setprecision(2)
565 <<
"They are inside quadrant. Dot product (>0 is inside): "
567 return (dot_prod > 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.