JsonClusterTap.cxx
Go to the documentation of this file.
2 
5 #include "WireCellIface/IWire.h"
6 #include "WireCellIface/IBlob.h"
7 #include "WireCellIface/ISlice.h"
8 #include "WireCellIface/IFrame.h"
9 
10 
11 #include "WireCellUtil/Units.h"
12 #include "WireCellUtil/String.h"
14 
15 #include <fstream>
16 
19 
20 using namespace WireCell;
21 
22 
24  : m_filename("cluster-%03d.json")
25  , m_drift_speed(1.6*units::mm/units::us)
26  , log(Log::logger("io"))
27 {
28 }
29 
30 Img::JsonClusterTap::~JsonClusterTap()
31 {
32 }
33 
35 {
36  m_filename = get(cfg, "filename", m_filename);
37  m_drift_speed = get(cfg, "drift_speed", m_drift_speed);
38 }
39 
40 WireCell::Configuration Img::JsonClusterTap::default_configuration() const
41 {
43  // output json file. A "%d" type format code may be included to be resolved by a cluster identifier.
44  cfg["filename"] = m_filename;
45  // for conversion between time and "x" coordinate
46  cfg["drift_speed"] = m_drift_speed;
47  return cfg;
48 }
49 
50 
51 static
52 Json::Value size_stringer(const cluster_node_t& n)
53 {
54  return Json::nullValue;
55 }
56 
57 static
59 {
60  Json::Value ret;
61  for (int ind=0; ind<3; ++ind) {
62  ret[ind] = p[ind];
63  }
64  return ret;
65 }
66 
67 static
68 Json::Value channel_jsoner(const cluster_node_t& n)
69 {
70  IChannel::pointer ich = std::get<typename IChannel::pointer>(n.ptr);
71  Json::Value ret = Json::objectValue;
72  ret["ident"] = ich->ident();
73  ret["index"] = ich->index();
74  ret["wpid"] = ich->planeid().ident();
75  return ret;
76 }
77 
78 static
79 Json::Value wire_jsoner(const cluster_node_t& n)
80 {
81  IWire::pointer iwire = std::get<typename IWire::pointer>(n.ptr);
82  Json::Value ret = Json::objectValue;
83  ret["ident"] = iwire->ident();
84  ret["index"] = iwire->index();
85  ret["wpid"] = iwire->planeid().ident();
86  ret["chid"] = iwire->channel();
87  ret["seg"] = iwire->segment();
88  auto r = iwire->ray();
89  ret["tail"] = jpoint(r.first);
90  ret["head"] = jpoint(r.second);
91  return ret;
92 }
93 
94 
95 // this one needs extra info
96 struct blob_jsoner {
97 
98  double drift_speed;
99 
100  blob_jsoner(double ds) : drift_speed(ds) {}
101 
102  Json::Value operator()(const cluster_node_t& n) {
103  IBlob::pointer iblob = std::get<typename IBlob::pointer>(n.ptr);
104  IAnodeFace::pointer iface = iblob->face();
105  IWirePlane::vector iplanes = iface->planes();
106  IWire::pointer iwire = iplanes[2]->wires()[0];
107  const double xplane = iwire->center().x();
108 
109  // fixme: this is not a particularly portable way to go for all wire geometries.
110  const double xsign = iface->ident() == 0 ? 1.0 : -1.0;
111 
112  ISlice::pointer islice = iblob->slice();
113  // set X based on time with knowledge of local drift
114  // direction as given by the face.
115  double x0 = xplane + xsign * islice->start()*drift_speed;
116 
117  const auto& coords = iface->raygrid();
118 
119  Json::Value ret = Json::objectValue;
120  ret["span"] = islice->span()*drift_speed;
121  ret["ident"] = iblob->ident();
122  ret["value"] = iblob->value();
123  ret["error"] = iblob->uncertainty();
124  ret["faceid"] = iblob->face()->ident();
125  ret["sliceid"] = iblob->slice()->ident();
126  Json::Value jcorners = Json::arrayValue;
127  const auto& blob = iblob->shape();
128  for (const auto& c : blob.corners()) {
129  Json::Value j = jpoint(coords.ray_crossing(c.first, c.second));
130  j[0] = x0;
131  jcorners.append(j);
132  }
133  ret["corners"] = jcorners;
134 
135  //-- strip info is redunant with edges connected to wire vertices.
136  // Json::Value jstrips = Json::arrayValue;
137  // for (const auto& strip : blob.strips()) {
138  // int plane_ind = strip.layer - 2; // fixme
139  // if (plane_ind <0) { continue; }
140  // Json ::Value j = Json::objectValue;
141  // j["wpid"] = iplanes[plane_ind]->planeid().ident();
142  // j["planeind"] = plane_ind;
143  // j["wip1"] = strip.bounds.first;
144  // j["wip2"] = strip.bounds.second;
145  // Json::Value jwires = Json::arrayValue;
146  // const auto& wires = iplanes[plane_ind]->wires();
147  // for (auto wip = strip.bounds.first; wip < strip.bounds.second; ++wip) {
148  // jwires.append(wires[wip]->ident());
149  // }
150  // j["wids"] = jwires;
151  // jstrips.append(j);
152  // }
153  // ret["strips"] = jstrips;
154 
155  return ret;
156  }
157 };
158 
159 Json::Value slice_jsoner(const cluster_node_t& n)
160 {
161  ISlice::pointer islice = std::get<typename ISlice::pointer>(n.ptr);
162  Json::Value ret = Json::objectValue;
163 
164  ret["ident"] = islice->ident();
165  ret["frameid"] = islice->frame()->ident();
166  ret["start"] = islice->start();
167  ret["span"] = islice->span();
168  Json::Value jact = Json::objectValue;
169  for (const auto& it : islice->activity()) {
170  jact[String::format("%d", it.first->ident())] = it.second;
171  }
172  ret["activity"] = jact;
173  return ret;
174 }
175 
176 Json::Value measurement_jsoner(const cluster_node_t& n)
177 {
178  IChannel::shared_vector ichv = std::get<IChannel::shared_vector>(n.ptr);
179  Json::Value ret = Json::objectValue;
180  Json::Value j = Json::arrayValue;
181  for (auto ich : *ichv) {
182  j.append(ich->ident());
183  ret["wpid"] = ich->planeid().ident(); // last one wins, but they should all be the same
184  }
185  ret["chids"] = j;
186  return ret;
187 }
188 
189 
190 bool Img::JsonClusterTap::operator()(const input_pointer& in, output_pointer& out)
191 {
192  out = in;
193  if (!in) {
194  return true;
195  }
196 
197  std::vector< std::function< Json::Value(const cluster_node_t& ptr) > > jsoners{
200  wire_jsoner,
201  blob_jsoner(m_drift_speed),
202  slice_jsoner,
204  };
205  auto asjson = [&](const cluster_node_t& n) {
206  return jsoners[n.ptr.index()](n);
207  };
208 
209 
210 /*
211  * - vertices :: a list of graph vertices
212  * - edges :: a list of graph edges
213  *
214  * A vertex is represented as a JSON object with the following attributes
215  * - ident :: an indexable ID number for the node, and referred to in "edges"
216  * - type :: the letter "code" used in ICluster: one in "sbcwm"
217  * - data :: an object holding information about the corresponding vertex object
218  *
219  * An edge is a pair of vertex ident numbers.
220  *
221 */
222  const auto& gr = in->graph();
223 
224  Json::Value jvertices = Json::arrayValue;
225  for (auto vtx : boost::make_iterator_range(boost::vertices(gr))) {
226  const auto& vobj = gr[vtx];
227  if (!vobj.ptr.index()) {
228  // warn?
229  continue;
230  }
231  Json::Value jvtx = Json::objectValue;
232  jvtx["ident"] = (int)vtx;
233  jvtx["type"] = String::format("%c", vobj.code());
234  jvtx["data"] = asjson(vobj);
235 
236  jvertices.append(jvtx);
237  }
238 
239  Json::Value jedges = Json::arrayValue;
240  for (auto eit : boost::make_iterator_range(boost::edges(gr))) {
241  Json::Value jedge = Json::arrayValue;
242  jedge[0] = (int) boost::source(eit, gr);
243  jedge[1] = (int)boost::target(eit, gr);
244  jedges.append(jedge);
245  }
246 
247  Json::Value top = Json::objectValue;
248  top["vertices"] = jvertices;
249  top["edges"] = jedges;
250 
251  std::string fname = m_filename;
252  if (m_filename.find("%") != std::string::npos) {
253  fname = String::format(m_filename, in->ident());
254  log->debug("JsonClusterTap: {} -> {}", m_filename, fname);
255  }
256  std::ofstream fstr(fname);
257  if (!fstr) {
258  log->error("JsonClusterTap failed to open for writing: {}", fname);
259  return false;
260  }
261  log->info("JsonClusterTap writing: {}", fname);
262  fstr << top;
263 
264  return true;
265 }
266 
static Json::Value size_stringer(const cluster_node_t &n)
blob_jsoner(double ds)
std::string string
Definition: nybbler.cc:12
static Json::Value wire_jsoner(const cluster_node_t &n)
struct vector vector
WIRECELL_FACTORY(JsonClusterTap, WireCell::Img::JsonClusterTap, WireCell::IClusterFilter, WireCell::IConfigurable) using namespace WireCell
Json::Value operator()(const cluster_node_t &n)
cfg
Definition: dbjson.py:29
Cluster finding and building.
double drift_speed
std::shared_ptr< const ICluster > input_pointer
Definition: IFunctionNode.h:39
static Json::Value jpoint(const Point &p)
def configure(cfg)
Definition: cuda.py:34
GenericValue< UTF8<> > Value
GenericValue with UTF8 encoding.
Definition: document.h:2106
Json::Value measurement_jsoner(const cluster_node_t &n)
Json::Value slice_jsoner(const cluster_node_t &n)
std::shared_ptr< const ICluster > output_pointer
Definition: IFunctionNode.h:40
logptr_t logger(std::string name)
Definition: Logging.cxx:71
static const double mm
Definition: Units.h:73
void log(source_loc source, level::level_enum lvl, const char *fmt, const Args &...args)
Definition: spdlog.h:165
Definition: Main.h:22
p
Definition: test.py:223
static const double us
Definition: Units.h:101
Json::Value Configuration
Definition: Configuration.h:50
static Json::Value channel_jsoner(const cluster_node_t &n)
const GenericPointer< typename T::ValueType > & pointer
Definition: pointer.h:1124
std::size_t n
Definition: format.h:3399