test_omnicndb.cxx
Go to the documentation of this file.
2 #include "WireCellUtil/Persist.h"
4 #include "WireCellUtil/Testing.h"
8 
9 
10 #include "TCanvas.h"
11 #include "TGraph.h"
12 #include "TStyle.h"
13 #include "TH1F.h"
14 
15 #include <iostream>
16 #include <vector>
17 #include <string>
18 #include <algorithm>
19 #include <unordered_set>
20 
21 const std::string config_text = R"JSONNET(
22 // example OmniChannelNoiseDB configuration.
23 
24 local wc = import "wirecell.jsonnet";
25 
26 {
27  anode: "AnodePlane:0",
28  tick: 0.5*wc.us,
29  nsamples: 9600,
30 
31  // channel groups is a 2D list. Each element is one group of
32  // channels which should be considered together for coherent noise
33  // filtering.
34  groups: [std.range(g*48, (g+1)*48-1) for g in std.range(0,171)],
35 
36  // Default channel info which is used if not overriden by one of
37  // the channel_info objects (below) for a given channel.
38  default_info : {
39  nominal_baseline: 0.0, // adc count
40  gain_correction: 1.0, // unitless
41  response_offset: 79, // ticks?
42  pad_window_front: 20, // ticks?
43  pad_window_back: 10, // ticks?
44  min_rms_cut: 1.0, // units???
45  max_rms_cut: 5.0, // units???
46 
47  // parameter used to make "rcrc" spectrum
48  rcrc: 1.0*wc.millisecond,
49 
50  // parameters used to make "config" spectrum
51  reconfig : {},
52 
53  // list to make "noise" spectrum mask
54  freqmasks: [],
55 
56  // field response waveform to make "response" spectrum
57  response: {},
58 
59  },
60 
61  // overide defaults for specific channels. If an info is
62  // mentioned for a particular channel in multiple objects, last
63  // one wins.
64  channel_info: [
65 
66  {
67  channels: 4, // single channel
68  nominal_baseline: 400,
69  },
70  {
71  channels: [1,42,69], // explicit list
72  nominal_baseline: 2048.0, // adc count
73  reconfig : {
74  from: {gain: 7.8*wc.mV/wc.fC, shaping: 1.0*wc.us},
75  to: {gain: 14.0*wc.mV/wc.fC, shaping: 2.0*wc.us},
76  }
77  },
78  {
79  channels: { first: 1, last: 4 }, // inclusive range.
80  // could also use Jsonnet's std.range(first,last):
81  // channels: std.range(1,4),
82  nominal_baseline: 400.0,
83  },
84  {
85  channels: {first: 0, last: 2047,},
86  freqmasks: [ // masks in frequency domain.
87  { value: 1.0, lobin: 0, hibin: $.nsamples-1 },
88  { value: 0.0, lobin: 169, hibin: 173 },
89  { value: 0.0, lobin: 513, hibin: 516 },
90  ]
91  },
92  {
93  // All channels in a given anode wire plane. Note, if
94  // used, the anode plane must be added to top level
95  // configuration sequence. The "channels" can be
96  // specified by the other means.
97  channels: { wpid: wc.WirePlaneId(wc.Ulayer) },
98  response: {
99  // the average response to use that of the wpid.
100  wpid: wc.WirePlaneId(wc.Ulayer)
101  // or as a raw waveform:
102  // waveform: [time-domain samples assumed to be at tick sampling period]
103  // waveformid: <uniquenumber>
104  }
105  }
106  ],
107 
108 }
109 
110 )JSONNET";
111 
112 
113 
114 #include "anode_loader.h"
115 using namespace WireCell;
116 using namespace std;
117 
118 
119 typedef std::vector<WireCell::IChannelNoiseDatabase::filter_t> filter_bag_t;
120 
121 
122 void plot_spec(const filter_bag_t& specs, const std::string& name)
123 {
124  if (specs.empty()) {
125  cerr << "No specs for \"" << name << "\"\n";
126  return;
127  }
128  cerr << "plot spec \"" << name << "\" size=" << specs.size() << endl;
129 
130 
131  std::vector<TGraph*> graphs;
132  std::vector<float> tmp;
133  for (const auto& spec : specs) {
134  TGraph* graph = new TGraph();
135  graphs.push_back(graph);
136  for (size_t ind=0; ind< spec.size(); ++ind) {
137  double amp = std::abs(spec.at(ind));
138  graph->SetPoint(ind, ind, amp);
139  tmp.push_back(amp);
140  }
141  }
142  auto mme = std::minmax_element(tmp.begin(), tmp.end());
143  float ymin = *mme.first;
144  float ymax = *mme.second;
145 
146  const int ncolors=5;
147  int colors[ncolors] = {1,2,4,6,8};
148  for (size_t igraph = 0; igraph<graphs.size(); ++igraph) {
149  TGraph* graph = graphs[igraph];
150  graph->SetLineColor(colors[igraph%ncolors]);
151  graph->SetLineWidth(2);
152 
153  if (!igraph) {
154  auto frame = graph->GetHistogram();
155  frame->SetTitle(name.c_str());
156  frame->GetXaxis()->SetTitle("frequency bins");
157  frame->GetYaxis()->SetTitle("amplitude");
158  graph->Draw("AL");
159  frame->SetMinimum(ymin);
160  frame->SetMaximum(ymax);
161  cerr << name << " ymin=" << ymin << ", ymax=" << ymax << endl;
162  }
163  else {
164  graph->Draw("L");
165  }
166  }
167 }
168 
169 
170 int main(int argc, char* argv[])
171 {
172  /// User code should never do this.
173  auto anode_tns = anode_loader("uboone");
174  const std::string pcr_filename = "microboone-channel-responses-v1.json.bz2";
175 
176  {
178 
179  if (argc > 1) {
180  cerr << "testing with " << argv[1] << endl;
182  extvar["detector"] = "uboone";
183  cfg = Persist::load(argv[1], extvar);
184  if (cfg.isArray()) { // probably a full configuration
185  for (auto jone : cfg) {
186  string the_type = jone["type"].asString();
187  if (the_type == "wclsChannelNoiseDB" || the_type == "OmniChannelNoiseDB") {
188  //cerr << "Found my config\n" << jone << "\n";
189  cfg = jone["data"];
190  break;
191  }
192  }
193  }
194  }
195  else {
196  cerr << "testing with build in config text\n";
198  }
199  cfg["anode"] = anode_tns[0];
200 
201  auto icfg = Factory::lookup_tn<IConfigurable>("OmniChannelNoiseDB");
202  auto def = icfg->default_configuration();
203  cfg = update(def, cfg);
204  icfg->configure(cfg);
205  }
206 
207  auto anode = Factory::find_tn<IAnodePlane>(anode_tns[0]);
208  const int nchannels = anode->channels().size();
209 
210  auto idb = Factory::find_tn<IChannelNoiseDatabase>("OmniChannelNoiseDB");
211 
212  gStyle->SetOptStat(0);
213  TCanvas canvas("canvas","canvas",500,500);
214 
215  string pdfname = Form("%s.pdf",argv[0]);
216 
217  canvas.Print((pdfname+"[").c_str(),"pdf");
218  canvas.SetGridx(1);
219  canvas.SetGridy(1);
220  double tick = idb->sample_time();
221  cerr << "tick = " << tick/units::us << " us.\n";
222 
223  std::vector<std::string> scalar_names{
224  "nominal baseline", "gain correction", "response offset", "pad window front", "pad window back",
225  "min rms cut", "max rms cut", "rcrc sum", "config sum", "noise sum", "response sum"};
226 
227  const int nscalars = 11;
228  std::vector<TGraph*> scalars;
229  for (int ind=0; ind<11; ++ind) { scalars.push_back(new TGraph); }
230  for (int ch=0; ch<nchannels; ++ch) {
231  scalars[0]->SetPoint(ch, ch, idb->nominal_baseline(ch));
232  scalars[1]->SetPoint(ch, ch, idb->gain_correction(ch));
233  scalars[2]->SetPoint(ch, ch, idb->response_offset(ch));
234  scalars[3]->SetPoint(ch, ch, idb->pad_window_front(ch));
235  scalars[4]->SetPoint(ch, ch, idb->pad_window_back(ch));
236  scalars[5]->SetPoint(ch, ch, idb->min_rms_cut(ch));
237  scalars[6]->SetPoint(ch, ch, idb->max_rms_cut(ch));
238 
239  scalars[7]->SetPoint(ch, ch, std::abs(Waveform::sum(idb->rcrc(ch))));
240  scalars[8]->SetPoint(ch, ch, std::abs(Waveform::sum(idb->config(ch))));
241  scalars[9]->SetPoint(ch, ch, std::abs(Waveform::sum(idb->noise(ch))));
242  scalars[10]->SetPoint(ch, ch, std::abs(Waveform::sum(idb->response(ch))));
243 
244  }
245 
246  for (size_t ind=0; ind<nscalars; ++ind) {
247  TGraph* graph = scalars[ind];
248  graph->SetName(scalar_names[ind].c_str());
249  graph->SetLineColor(2);
250  graph->SetLineWidth(3);
251  graph->Draw("AL");
252 
253  auto frame = graph->GetHistogram();
254  frame->SetTitle(scalar_names[ind].c_str());
255  frame->GetXaxis()->SetTitle("channels");
256  canvas.Print(pdfname.c_str(), "pdf");
257  }
258 
259  canvas.Print((pdfname+"]").c_str(), "pdf");
260 
261 
262  return 0;
263 }
static QCString name
Definition: declinfo.cpp:673
void plot_spec(const filter_bag_t &specs, const std::string &name)
Configuration update(Configuration &a, Configuration &b)
Merge dictionary b into a, return a.
const std::string config_text
std::string string
Definition: nybbler.cc:12
def graph(desc, maker=maker)
Definition: apa.py:294
STL namespace.
std::map< std::string, std::string > externalvars_t
Definition: Persist.h:69
cfg
Definition: dbjson.py:29
std::vector< WireCell::IChannelNoiseDatabase::filter_t > filter_bag_t
const double tick
int main(int argc, char *argv[])
std::vector< std::string > anode_loader(std::string detector)
Definition: anode_loader.h:35
T abs(T value)
Json::Value load(const std::string &filename, const externalvars_t &extvar=externalvars_t(), const externalvars_t &extcode=externalvars_t())
Definition: Persist.cxx:121
string tmp
Definition: languages.py:63
Definition: Main.h:22
Json::Value loads(const std::string &text, const externalvars_t &extvar=externalvars_t(), const externalvars_t &extcode=externalvars_t())
Definition: Persist.cxx:152
Val sum(const Sequence< Val > &seq)
Return sum of all entries in sequence.
Definition: Waveform.h:178
Json::Value Configuration
Definition: Configuration.h:50
static const double us
Definition: Units.h:105
QTextStream & endl(QTextStream &s)