47 put(cfg,
"wire_schema",
"");
73 cfg[
"faces"][0] = Json::nullValue;
74 cfg[
"faces"][1] = Json::nullValue;
85 std::unordered_map<int, SimpleChannel*>
chid2sch;
89 const int chid = iwire->channel();
90 SimpleChannel* sc =
nullptr;
91 auto it = chid2sch.find(chid);
92 if (it == chid2sch.end()) {
93 sc =
new SimpleChannel(chid);
103 return chid2sch[chid];
111 m_ident = get<int>(
cfg,
"ident", 0);
114 if (!cfg[
"wires"].isNull()) {
115 l->warn(
"AnodePlane configuration is obsolete.");
116 l->warn(
"Use \"wire_store\" to name components instead of directly giving file names");
117 l->warn(
"This job will likely throw an exception next");
122 if (!cfg[
"fields"].isNull() or !cfg[
"field_response"].isNull()) {
123 l->warn(
"AnodePlane does not require any field response functions.");
126 auto jfaces = cfg[
"faces"];
127 if (jfaces.isNull() or jfaces.empty() or (jfaces[0].isNull() and jfaces[1].isNull())) {
128 l->critical(
"at least two faces need to be defined, got:\n{}", jfaces);
137 const string ws_name = get<string>(
cfg,
"wire_schema");
138 if (ws_name.empty()) {
139 l->critical(
"\"wire_schema\" parameter must specify an IWireSchema component");
142 auto iws = Factory::find_tn<IWireSchema>(ws_name);
150 std::vector<WireSchema::Face> ws_faces = ws_store.
faces(ws_anode);
151 const size_t nfaces = ws_faces.size();
155 m_faces.resize(nfaces);
157 for (
size_t iface=0; iface<nfaces; ++iface) {
158 const auto& ws_face = ws_faces[iface];
159 std::vector<WireSchema::Plane> ws_planes = ws_store.planes(ws_face);
160 const size_t nplanes = ws_planes.size();
163 bool sensitive_face =
true;
164 auto jface = jfaces[(
int)iface];
165 if (jface.isNull()) {
166 sensitive_face =
false;
167 l->debug(
"anode {} face {} is not sensitive", m_ident, iface);
169 const double response_x = jface[
"response"].asDouble();
170 const double anode_x =
get(jface,
"anode", response_x);
171 const double cathode_x = jface[
"cathode"].asDouble();
172 l->debug(
"AnodePlane: X planes: \"cathode\"@ {}m, \"response\"@{}m, \"anode\"@{}m",
177 for (
size_t iplane=0; iplane<nplanes; ++iplane) {
178 const auto& ws_plane = ws_planes[iplane];
181 if (wire_plane_id.
index() < 0) {
182 l->critical(
"Bad wire plane id: {}", wire_plane_id.
ident());
187 auto wire_pitch_dirs = ws_store.wire_pitch(ws_plane);
188 auto ecks_dir = wire_pitch_dirs.first.cross(wire_pitch_dirs.second);
190 std::vector<int> plane_chans = ws_store.channels(ws_plane);
191 m_channels.insert(m_channels.end(), plane_chans.begin(), plane_chans.end());
193 std::vector<WireSchema::Wire> ws_wires = ws_store.wires(ws_plane);
194 const size_t nwires = ws_wires.size();
198 for (
size_t iwire=0; iwire<
nwires; ++iwire) {
199 const auto& ws_wire = ws_wires[iwire];
200 const int chanid = plane_chans[iwire];
202 Ray ray(ws_wire.tail, ws_wire.head);
203 auto iwireptr = make_shared<SimpleWire>(
wire_plane_id, ws_wire.ident,
206 wires[iwire] = iwireptr;
207 m_c2wires[chanid].push_back(iwireptr);
208 m_c2wpid[chanid] = wire_plane_id.ident();
209 chwcollector(iwireptr);
212 const BoundingBox bb = ws_store.bounding_box(ws_plane);
214 const Vector plane_center = 0.5*(bb_ray.first + bb_ray.second);
216 const double pitchmin = wire_pitch_dirs.second.
dot(wires[0]->
center() - plane_center);
217 const double pitchmax = wire_pitch_dirs.second.dot(wires[nwires-1]->
center() - plane_center);
218 const Vector pimpos_origin(response_x, plane_center.
y(), plane_center.
z());
220 l->debug(
"AnodePlane: face:{}, plane:{}, origin:{} mm",
224 wire_pitch_dirs.first, wire_pitch_dirs.second,
225 pimpos_origin, nimpacts);
229 for (
auto w : wires) {
230 if (
w->segment() > 0) {
234 const int chanid =
w->channel();
238 m_ichannels[chanid] = ich;
239 plane_channels.push_back(ich);
243 planes[iplane] = make_shared<WirePlane>(ws_plane.ident,
pimpos, wires, plane_channels);
246 if (iplane == nplanes-1) {
247 const double mean_pitch = (pitchmax - pitchmin) / (nwires-1);
249 if (sensitive_face) {
250 auto v1 = bb_ray.first;
251 auto v2 = bb_ray.second;
255 Point p2(cathode_x, v2.y(),
std::max(v1.z(), v2.z()) + 0.5*mean_pitch);
259 l->debug(
"AnodePlane: face:{} with {} planes and sensvol: {}",
260 ws_face.ident, planes.size(), sensvol.
bounds());
262 m_faces[iface] = make_shared<AnodeFace>(ws_face.ident, planes, sensvol);
268 std::sort(m_channels.begin(), m_channels.end());
269 auto chend = std::unique(m_channels.begin(), m_channels.end());
270 m_channels.resize(
std::distance(m_channels.begin(), chend) );
277 for (
auto ptr : m_faces) {
278 if (
ptr->ident() == ident) {
290 auto got = m_c2wpid.find(channel);
291 if (got == m_c2wpid.end()) {
299 auto it = m_ichannels.find(chident);
300 if (it == m_ichannels.end()) {
313 auto it = m_c2wires.find(channel);
314 if (it == m_c2wires.end()) {
std::pair< Point, Point > Ray
A line segment running from a first (tail) to a second (head) point.
int ident() const
Unit ID as integer.
std::shared_ptr< const IChannel > pointer
void operator()(IWire::pointer iwire)
boost::error_info< struct tag_errmsg, std::string > errmsg
void put(Configuration &cfg, const std::string &dotpath, const T &val)
Put value in configuration at the dotted path.
SimpleChannel * operator()(int chid)
std::vector< pointer > vector
const WirePlaneLayer_t iplane2layer[3]
std::vector< pointer > vector
Vector of shared pointers.
std::shared_ptr< Interface > pointer
JAVACC_STRING_TYPE String
double distance(double x1, double y1, double z1, double x2, double y2, double z2)
static int max(int a, int b)
def wire_plane_id(plane, face, apa)
logptr_t logger(std::string name)
Thrown when a wrong value has been encountered.
WIRECELL_FACTORY(AnodePlane, WireCell::Gen::AnodePlane, WireCell::IAnodePlane, WireCell::IConfigurable) using namespace WireCell
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
T dot(const D3Vector &rhs) const
Return the dot product of this vector and the other.
Pimpos pimpos(nwires, min_wire_pitch, max_wire_pitch)
Json::Value Configuration
const GenericPointer< typename T::ValueType > & pointer
std::unordered_map< int, SimpleChannel * > chid2sch
std::string resolve(const std::string &filename)
const Ray & bounds() const
Return the ray representing the bounds.
int index() const
Layer as index number (0,1 or 2). -1 if unknown.
const int default_nimpacts