The fiducial volume management system in the Wire-Cell Prototype is a sophisticated component handling detector volume definitions, dead regions, and volume-based event classification. The system integrates boundary definitions, coordinate transformations, and multiple checking mechanisms.
// Basic detector boundaries
double m_top; // Top distance
double m_bottom; // Bottom distance
double m_upstream; // Upstream boundary
double m_downstream; // Downstream boundary
double m_anode; // Anode position
double m_cathode; // Cathode position
// Space charge boundaries
double m_sc_bottom_1_x, m_sc_bottom_1_y; // Bottom space charge boundary point 1
double m_sc_bottom_2_x, m_sc_bottom_2_y; // Bottom space charge boundary point 2
double m_sc_top_1_x, m_sc_top_1_y; // Top space charge boundary point 1
double m_sc_top_2_x, m_sc_top_2_y; // Top space charge boundary point 2
double m_sc_upstream_1_x, m_sc_upstream_1_z; // Upstream space charge point 1
double m_sc_upstream_2_x, m_sc_upstream_2_z; // Upstream space charge point 2
double m_sc_downstream_1_x, m_sc_downstream_1_z; // Downstream space charge point 1
double m_sc_downstream_2_x, m_sc_downstream_2_z; // Downstream space charge point 2
// Boundary vectors for polygon checks
std::vector<double> boundary_xy_x, boundary_xy_y; // XY plane boundaries
std::vector<double> boundary_xz_x, boundary_xz_z; // XZ plane boundaries
std::vector<double> boundary_SCB_xy_x, boundary_SCB_xy_y; // Space charge XY boundaries
std::vector<double> boundary_SCB_xz_x, boundary_SCB_xz_z; // Space charge XZ boundaries
// Multi-segment boundary arrays
std::vector<std::vector<double>> boundary_xy_x_array, boundary_xy_y_array;
std::vector<std::vector<double>> boundary_xz_x_array, boundary_xz_z_array;
std::vector<std::vector<double>> boundary_SCB_xy_x_array, boundary_SCB_xy_y_array;
std::vector<std::vector<double>> boundary_SCB_xz_x_array, boundary_SCB_xz_z_array;
// Time to position conversion
double offset_t, slope_t; // (time_slice - offset_t) / slope_t = position_x
// Wire plane coordinate conversions
double offset_u, slope_u; // U-plane conversion
double offset_v, slope_v; // V-plane conversion
double offset_w, slope_w; // W-plane conversion
double angle_u, angle_v, angle_w; // Wire plane angles
int dead_region_ch_ext; // Dead region channel extension
bool inside_fiducial_volume(WCP::Point& p, double offset_x, std::vector<double>* tolerance_vec)
- Determines segment indices based on position:
int index_y = floor((p.y/units::cm+116)/24); // some of these are hard-coded numbers to match the input space charge boundary
int index_z = floor(p.z/units::m);
- Boundary checking with tolerances:
if(tolerance_vec==NULL) {
c1 = pnpoly(boundary_xy_x, boundary_xy_y, p.x-offset_x, p.y);
c2 = pnpoly(boundary_xz_x, boundary_xz_z, p.x-offset_x, p.z);
} else {
// Applies tolerances to boundaries
double tx = tolerance_vec->at(0);
double ty_bot = tolerance_vec->at(1);
double ty_top = tolerance_vec->at(2);
double tz = tolerance_vec->at(3);
// Adjusts boundaries and performs check
}
bool inside_dead_region(WCP::Point& p)
- Coordinate conversion:
int time_slice = p.x * slope_t + offset_t;
double pos_u = cos(angle_u) * p.z - sin(angle_u) * p.y;
double pos_v = cos(angle_v) * p.z - sin(angle_v) * p.y;
double pos_w = cos(angle_w) * p.z - sin(angle_w) * p.y;
- Channel mapping:
int ch_u = pos_u * slope_u + offset_u;
int ch_v = pos_v * slope_v + offset_v + 2400;
int ch_w = pos_w * slope_w + offset_w + 4800;
- Dead region checking:
void AddDeadRegion(WCP::SlimMergeGeomCell* mcell, std::vector<int>& time_slices)
{
// Time window extension
int start_time = time_slices.front() - dead_region_ch_ext;
int end_time = time_slices.back() + dead_region_ch_ext;
// Channel mapping
for (int i = start_ch; i <= end_ch; i++) {
if (ch_mcell_set_map.find(i) == ch_mcell_set_map.end()) {
std::set<SlimMergeGeomCell*> mcells_set;
mcells_set.insert(mcell);
ch_mcell_set_map[i] = mcells_set;
} else {
ch_mcell_set_map[i].insert(mcell);
}
}
}
bool check_dead_volume(WCP::Point& p, TVector3& dir, double step, double offset_x)
- Step-wise volume checking:
while(inside_fiducial_volume(temp_p,offset_x)) {
num_points++;
if (inside_dead_region(temp_p))
num_points_dead++;
if (num_points - num_points_dead >= 4)
return true;
temp_p.x += dir.X() * step;
temp_p.y += dir.Y() * step;
temp_p.z += dir.Z() * step;
}
bool check_fully_contained(WCP::FlashTPCBundle *bundle, double offset_x,
WCP::ToyCTPointCloud& ct_point_cloud,
std::map<WCP::PR3DCluster*, WCP::PR3DCluster*>& old_new_cluster_map,
unsigned int* fail_mode, int flag)
- Cluster validation
- Boundary intersection checks
- Dead region consideration
- Signal processing quality assessment
int pnpoly(std::vector<double>& vertx, std::vector<double>& verty,
double testx, double testy)
Implementation of point-in-polygon algorithm:
int c = 0;
for (i = 0, j = vertx.size()-1; i < vertx.size(); j = i++) {
if (((verty[i]>testy) != (verty[j]>testy)) &&
(testx < (vertx[j]-vertx[i]) * (testy-verty[i]) /
(verty[j]-verty[i]) + vertx[i]))
c = !c;
}
- Different boundary definitions for data and simulation
- Configurable tolerances and extensions
- Adjustable dead region parameters
- Detector coordinates (x, y, z)
- Wire plane coordinates (u, v, w)
- Time slice coordinates
- Cached boundary arrays for quick lookup
- Efficient point-in-polygon testing
- Early exit conditions in volume checks
- Use of STL containers for dynamic storage
- Efficient mapping structures for dead regions
- Optimized boundary representation
ToyFiducial fid(dead_region_ch_ext, offset_t, offset_u, offset_v, offset_w,
slope_t, slope_u, slope_v, slope_w, angle_u, angle_v, angle_w,
boundary_dis_cut, top, bottom, upstream, downstream, anode, cathode,
flag_data);
- Initialize with appropriate boundary parameters
- Consider detector conditions when setting tolerances
- Regularly update dead region maps
- Validate boundary definitions
- Boundary condition validation
- Coordinate range checking
- Dead region overlap handling