22 , m_tick(0.5*units::
us)
23 , m_start_time(0.0*units::
ns)
24 , m_readout_time(5.0*units::
ms)
30 Gen::MultiDuctor::~MultiDuctor()
46 cfg[
"anode"] = m_anode_tn;
47 cfg[
"chain"] = Json::arrayValue;
53 cfg[
"start_time"] = m_start_time;
56 cfg[
"readout_time"] = m_readout_time;
64 cfg[
"continuous"] = m_continuous;
67 cfg[
"first_frame_number"] = m_frame_count;
80 std::cerr <<
"Gen::MultiDuctor::Wirebounds: error: no depo given\n";
90 for (
auto jregion : jargs) {
94 for (
auto jrange: jregion) {
95 int iplane = jrange[
"plane"].asInt();
96 int imin = jrange[
"min"].asInt();
97 int imax = jrange[
"max"].asInt();
100 double pitch = pimpos[iplane]->distance(depo->pos(), 2);
101 int iwire = pimpos[iplane]->region_binning().bin(pitch);
102 inregion = inregion && (imin <= iwire && iwire <= imax);
120 if (!depo) {
return false;}
128 m_readout_time = get<double>(
cfg,
"readout_time", m_readout_time);
129 m_tick = get<double>(
cfg,
"tick", m_tick);
130 m_start_time = get<double>(
cfg,
"start_time", m_start_time);
131 m_frame_count = get<int>(
cfg,
"first_frame_number", m_frame_count);
132 m_continuous =
get(
cfg,
"continuous", m_continuous);
134 m_anode_tn =
get(
cfg,
"anode", m_anode_tn);
135 m_anode = Factory::find_tn<IAnodePlane>(m_anode_tn);
137 std::cerr <<
"Gen::MultiDuctor::configure: error: unknown anode: " << m_anode_tn <<
std::endl;
140 auto jchains = cfg[
"chains"];
141 if (jchains.isNull()) {
142 std::cerr <<
"Gen::MultiDuctor::configure: warning: configured with empty collection of chains\n";
147 if ( m_anode->faces().size() > 1 ) {
148 std::cerr <<
"Gen::MultDuctor:configure: warning: I currently only support a front-faced AnodePlane.\n";
151 std::vector<const Pimpos*>
pimpos;
152 for (
auto face : m_anode->faces()) {
153 if (face->planes().empty()) {
154 std::cerr <<
"Gen::MultDuctor: not given multi-plane AnodeFace for face "<<face->ident()<<
"\n";
157 for (
auto plane : face->planes()) {
158 pimpos.push_back(plane->pimpos());
162 if (pimpos.size() != 3) {
163 std::cerr <<
"Gen::MultiDuctor got unexpected number planes (" << pimpos.size() <<
") from anode\n";
167 for (
auto jchain : jchains) {
168 std::cerr <<
"Gen::MultiDuctor::configure chain:\n";
171 for (
auto jrule : jchain) {
172 auto rule = jrule[
"rule"].asString();
173 auto ductor_tn = jrule[
"ductor"].asString();
174 std::cerr <<
"\tMultiDuctor: " << ductor_tn <<
" rule: " << rule <<
std::endl;
175 auto ductor = Factory::find_tn<IDuctor>(ductor_tn);
179 auto jargs = jrule[
"args"];
180 if (rule ==
"wirebounds") {
183 if (rule ==
"bool") {
187 m_chains.push_back(dchain);
213 m_start_time = depo->time();
217 return depo->time() > m_start_time + m_readout_time;
223 auto traces = frame->traces();
224 if (!traces or traces->empty()) {
226 <<
" fid:" << frame->ident()
227 <<
" has no traces\n";
233 <<
" fid:" << frame->ident()
234 <<
" #ch:" << traces->size()
236 <<
" tbins:["<<
mm.first<<
","<<
mm.second<<
"]\n";
242 if (!start_processing(depo)) {
247 for (
auto& chain : m_chains) {
248 for (
auto& sd : chain) {
250 (*sd.ductor)(
nullptr, newframes);
261 if (!m_frame_buffer.size()) {
263 std::cerr <<
"MultiDuctor: returning empty frame with "<<m_frame_count
264 <<
" at " << m_start_time <<
"\n";
267 auto frame = std::make_shared<SimpleFrame>(m_frame_count, m_start_time, traces, m_tick);
268 outframes.push_back(frame);
270 m_start_time += m_readout_time;
281 const double target_time = m_start_time + m_readout_time;
283 for (
auto frame: m_frame_buffer) {
285 std::cerr <<
"Gen::MultiDuctor: skipping null frame in frame buffer\n";
288 if (!frame->traces()) {
289 std::cerr <<
"Gen::MultiDuctor: skipping empty frame in frame buffer\n";
294 const double tick = frame->tick();
295 if (
std::abs(tick - m_tick) > 0.0001) {
296 std::cerr <<
"MultiDuctor: configuration error: got different tick in frame from sub-ductor = " 310 to_extract.push_back(frame);
314 to_keep.push_back(frame);
321 to_extract.push_back(ff.first);
325 std::cerr <<
"Gen::MultiDuctor: error: early split is null\n";
329 to_keep.push_back(ff.second);
333 std::cerr <<
"Gen::MultiDuctor: error: late split is null\n";
337 m_frame_buffer = to_keep;
339 if (!to_extract.size()) {
342 std::cerr <<
"MultiDuctor: returning empty frame after sub frame sorting with " 343 << m_frame_count<<
" at " << m_start_time <<
"\n";
346 auto frame = std::make_shared<SimpleFrame>(m_frame_count, m_start_time, traces, m_tick);
347 outframes.push_back(frame);
348 m_start_time += m_readout_time;
364 for (
auto frame: to_extract) {
365 const double tref = frame->time();
366 const int extra_tbins = (tref-m_start_time)/m_tick;
367 for (
auto trace : (*frame->traces())) {
368 const int tbin =
trace->tbin() + extra_tbins;
369 const int chid =
trace->channel();
375 auto mtrace = std::make_shared<SimpleTrace>(chid, tbin,
trace->charge());
376 traces.push_back(mtrace);
379 auto frame = std::make_shared<SimpleFrame>(m_frame_count, m_start_time, traces, m_tick);
380 dump_frame(frame,
"Gen::MultiDuctor: output frame");
382 outframes.push_back(frame);
383 m_start_time += m_readout_time;
389 for (
auto frame : newframes) {
390 if (!frame) {
continue; }
391 auto traces = frame->traces();
392 if (!traces) {
continue; }
393 if (traces->empty()) {
continue; }
396 m_frame_buffer.push_back(frame);
405 maybe_extract(depo, outframes);
406 outframes.push_back(
nullptr);
407 if (!m_frame_buffer.empty()) {
408 std::cerr <<
"Gen::MultiDuctor: purging " << m_frame_buffer.size() <<
" frames at EOS\n";
409 for (
auto frame : m_frame_buffer) {
412 m_frame_buffer.clear();
419 bool all_okay =
true;
421 for (
auto& chain : m_chains) {
423 for (
auto& sd : chain) {
425 if (!sd.check(depo)) {
434 bool ok = (*sd.ductor)(depo, newframes);
436 all_okay = all_okay && ok;
443 std::cerr <<
"Gen::MultiDuctor: warning: no appropriate Ductor for depo at: " 447 maybe_extract(depo, outframes);
448 if (outframes.size()) {
449 std::cerr <<
"Gen::MultiDuctor: returning " << outframes.size() <<
" frames\n";
std::shared_ptr< const IFrame > pointer
Wirebounds(const std::vector< const Pimpos * > &p, Json::Value jargs)
void msg(const char *fmt,...)
ReturnBool(Json::Value jargs)
WIRECELL_FACTORY(MultiDuctor, WireCell::Gen::MultiDuctor, WireCell::IDuctor, WireCell::IConfigurable) using namespace WireCell
boost::error_info< struct tag_errmsg, std::string > errmsg
std::vector< const Pimpos * > pimpos
void dump_frame(WireCell::IFrame::pointer frame)
std::vector< pointer > vector
bool operator()(IDepo::pointer depo)
std::vector< SubDuctor > ductorchain_t
Q_EXPORT QTSManip setprecision(int p)
std::deque< output_pointer > output_queue
GenericValue< UTF8<> > Value
GenericValue with UTF8 encoding.
Thrown when a wrong value has been encountered.
bool operator()(IDepo::pointer depo)
Json::Value Configuration
std::shared_ptr< const IDepo > input_pointer
void split(std::string const &s, char c, OutIter dest)
const GenericPointer< typename T::ValueType > & pointer
Thrown when a wrong key or has been encountered.
QTextStream & endl(QTextStream &s)