FrameFanin.cxx
Go to the documentation of this file.
2 
6 
7 #include <iostream>
8 
11 
12 
13 using namespace WireCell;
14 
15 Gen::FrameFanin::FrameFanin(size_t multiplicity)
16  : m_multiplicity(multiplicity)
17 {
18 }
19 Gen::FrameFanin::~FrameFanin()
20 {
21 }
22 
23 WireCell::Configuration Gen::FrameFanin::default_configuration() const
24 {
26  cfg["multiplicity"] = (int)m_multiplicity;
27 
28  // A non-null entry in this array is taken as a string and used to
29  // tag traces which arrive on the corresponding input port when
30  // they are placed to the output frame. This creates a tagged
31  // subset of output traces corresponding to the entire set of
32  // traces in the input frame from the associated port.
33  cfg["tags"] = Json::arrayValue;
34 
35  // Tag rules are an array, one element per input port. Each
36  // element is an object keyed with "frame" or "trace". Each of
37  // their values are an object keyed by a regular expression
38  // (regex) and with values that are a single tag or an array of
39  // tags. See util/test_tagrules for examples.
40  cfg["tag_rules"] = Json::arrayValue;
41 
42  return cfg;
43 }
45 {
46  int m = get<int>(cfg, "multiplicity", (int)m_multiplicity);
47  if (m<=0) {
48  THROW(ValueError() << errmsg{"FrameFanin multiplicity must be positive"});
49  }
50  m_multiplicity = m;
51  m_tags.resize(m);
52 
53  // Tag entire input frame worth of traces in the output frame.
54  auto jtags = cfg["tags"];
55  for (int ind=0; ind<m; ++ind) {
56  m_tags[ind] = convert<std::string>(jtags[ind], "");
57  }
58 
59  // frame/trace tagging at the port level
60  m_ft.configure(cfg["tag_rules"]);
61 }
62 
63 
64 std::vector<std::string> Gen::FrameFanin::input_types()
65 {
66  const std::string tname = std::string(typeid(input_type).name());
67  std::vector<std::string> ret(m_multiplicity, tname);
68  return ret;
69 
70 }
71 
72 bool Gen::FrameFanin::operator()(const input_vector& invec, output_pointer& out)
73 {
74  out = nullptr;
75  size_t neos = 0;
76  for (const auto& fr : invec) {
77  if (!fr) {
78  ++neos;
79  }
80  }
81  if (neos == invec.size()) {
82  return true;
83  }
84  if (neos) {
85  std::cerr << "Gen::FrameFanin: " << neos << " input frames missing\n";
86  }
87 
88  if (invec.size() != m_multiplicity) {
89  std::cerr << "Gen::FrameFanin: got unexpected multiplicity, got:"
90  << invec.size() << " want:" << m_multiplicity << std::endl;
91  THROW(ValueError() << errmsg{"unexpected multiplicity"});
92  }
93 
94 
95  std::vector<IFrame::trace_list_t> by_port(m_multiplicity);
96 
97  // ...
98  std::vector< std::tuple<tagrules::tag_t, IFrame::trace_list_t, IFrame::trace_summary_t> > stash;
99 
100  tagrules::tagset_t fouttags;
101  ITrace::vector out_traces;
102  IFrame::pointer one = nullptr;
103  for (size_t iport=0; iport < m_multiplicity; ++iport) {
104  const size_t trace_offset = out_traces.size();
105 
106  const auto& fr = invec[iport];
107  if (!one) { one = fr; }
108  auto traces = fr->traces();
109 
110  { // collect output frame tags by tranforming each input frame
111  // tag based on user rules.
112  auto fintags = fr->frame_tags();
113  fintags.push_back("");
114  auto fo = m_ft.transform(iport, "frame", fintags);
115  fouttags.insert(fo.begin(), fo.end());
116  }
117 
118  // collect transformed trace tags, any trace summary and their
119  // offset trace indeices. annoying_factor *= 10;
120  for (auto inttag : fr->trace_tags()) {
121  tagrules::tagset_t touttags = m_ft.transform(iport, "trace", inttag);
122  if (touttags.empty()) {
123  // std::cerr << "FrameFanin: no port trace tag for " << inttag << "\n";
124  continue;
125  }
126  // std::cerr << "FrameFanin: port trace tags for " << inttag << ":\n";
127  // for (const auto& t : touttags) {
128  // std::cerr << "\t" << t << "\n";
129  // }
130 
131  const auto& summary = fr->trace_summary(inttag);
132  IFrame::trace_list_t outtrinds;
133  for (size_t trind : fr->tagged_traces(inttag)) {
134  outtrinds.push_back(trind + trace_offset);
135  }
136  for (auto ot : touttags) {
137  // need to stash them until after creating the output frame.
138  stash.push_back(std::make_tuple(ot, outtrinds, summary));
139  }
140  };
141 
142 
143  if (! m_tags[iport].empty() ) {
144  IFrame::trace_list_t tl(traces->size());
145  std::iota(tl.begin(), tl.end(), trace_offset);
146  by_port[iport] = tl;
147  }
148 
149  // Insert one intput frames traces.
150  out_traces.insert(out_traces.end(), traces->begin(), traces->end());
151  }
152 
153  auto sf = new SimpleFrame(one->ident(), one->time(), out_traces, one->tick());
154  for (size_t iport=0; iport < m_multiplicity; ++iport) {
155  if (m_tags[iport].size()) {
156  // std::cerr << "FrameFanin: tagging trace set: " << by_port[iport].size() << " traces from port "
157  // << iport << " with " << m_tags[iport] << std::endl;
158  sf->tag_traces(m_tags[iport], by_port[iport]);
159  }
160  }
161  for (auto ftag : fouttags) {
162  // std::cerr << "FrameFanin: tagging frame: " << ftag << std::endl;
163  sf->tag_frame(ftag);
164  }
165  for (auto ttt : stash) {
166  // std::cerr << "FrameFanin: tagging traces: "
167  // << get<0>(ttt) << std::endl;
168  sf->tag_traces(get<0>(ttt), get<1>(ttt), get<2>(ttt));
169  }
170 
171  out = IFrame::pointer(sf);
172  return true;
173 }
174 
175 
static QCString name
Definition: declinfo.cpp:673
static const double m
Definition: Units.h:79
std::shared_ptr< const IFrame > pointer
Definition: IData.h:19
std::vector< input_pointer > input_vector
Definition: IFaninNode.h:46
std::unordered_set< tag_t > tagset_t
Definition: TagRules.h:48
void tag_traces(const tag_t &tag, const IFrame::trace_list_t &indices, const IFrame::trace_summary_t &summary=IFrame::trace_summary_t(0))
Definition: SimpleFrame.cxx:76
std::string string
Definition: nybbler.cc:12
boost::error_info< struct tag_errmsg, std::string > errmsg
Definition: Exceptions.h:54
cfg
Definition: dbjson.py:29
std::vector< pointer > vector
Definition: IData.h:21
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:87
WIRECELL_FACTORY(FrameFanin, WireCell::Gen::FrameFanin, WireCell::IFrameFanin, WireCell::IConfigurable) using namespace WireCell
def configure(cfg)
Definition: cuda.py:34
#define THROW(e)
Definition: Exceptions.h:25
Thrown when a wrong value has been encountered.
Definition: Exceptions.h:37
Definition: Main.h:22
Json::Value Configuration
Definition: Configuration.h:50
std::shared_ptr< const IFrame > output_pointer
Definition: IFaninNode.h:45
def summary(store)
Definition: info.py:119
const GenericPointer< typename T::ValueType > & pointer
Definition: pointer.h:1124
std::vector< size_t > trace_list_t
Definition: IFrame.h:36
decltype(auto) constexpr empty(T &&obj)
ADL-aware version of std::empty.
Definition: StdUtils.h:92
QTextStream & endl(QTextStream &s)