test_average_response.cxx
Go to the documentation of this file.
1 #include "MultiPdf.h" // local helper shared by a few tests
2 
4 #include "WireCellUtil/ExecMon.h"
5 
6 #include "TH2F.h"
7 #include "TFile.h"
8 #include "TGraph.h"
9 #include "TFrame.h"
10 
11 #include <iostream>
12 #include <string>
13 #include <algorithm>
14 
15 
16 using namespace WireCell;
17 using namespace WireCell::Test;
18 using namespace std;
19 
20 
21 void plot_plane_2d(MultiPdf& mpdf, const Response::Schema::FieldResponse& fr, int planeind, bool isavg)
22 {
23  const char* uvw = "UVW";
24 
25  const Response::Schema::PlaneResponse& pr = fr.planes[planeind];
26  const Response::Schema::PathResponse& par0 = pr.paths[0];
27  const int ntbins = par0.current.size();
28  const double tstart = fr.tstart;
29  const double period = fr.period;
30  const double pitch = pr.pitch;
31 
32  const char* type = "Fine";
33  if (isavg) {
34  type = "Average";
35  }
36 
37  int minregion = 999, maxregion = -999;
38  std::vector<double> impacts;
39  for (auto path : pr.paths) {
40  const int region = round((path.pitchpos-0.001)/pitch);
41  const double impact = path.pitchpos - region*pitch;
42  //cerr << "region=" << region << " impact=" << impact <<" pitchpos=" << path.pitchpos << endl;
43  minregion = std::min(minregion, region);
44  maxregion = std::max(maxregion, region);
45  if (region == 0) {
46  impacts.push_back(impact);
47  }
48  }
49  sort(impacts.begin(), impacts.end());
50  double dimpact = impacts[1] - impacts[0];
51  double maximpact = impacts[impacts.size()-1];
52  if (isavg) {
53  maximpact = dimpact = 0.0;
54  }
55 
56  int npitchbins = pr.paths.size();
57  double minpitch = -npitchbins/2;
58  double maxpitch = +npitchbins/2;
59  if (!isavg) {
60  maxpitch = maxregion * pitch + maximpact;
61  minpitch = minregion * pitch - maximpact;
62  npitchbins = (maxpitch-minpitch) / dimpact;
63  }
64  /*
65  cerr << isavg
66  << " tstart=" << tstart
67  << " period=" << period
68  << " ntbins=" << ntbins
69  << endl
70  << " npaths=" << npitchbins
71  << " dimpact=" << dimpact
72  << " maxregion=" << maxregion
73  << " minregion=" << minregion
74  << " maximpact=" << maximpact
75  << " maxpitch=" << maxpitch
76  << " minpitch=" << minpitch
77  << " npitchbins=" << npitchbins
78  << " impacts:" << impacts[0] << " -> " << impacts[impacts.size()-1]
79  << endl;
80  */
81 
82  TH2F h("h", Form("%s %c-plane", type, uvw[pr.planeid]),
83  ntbins, tstart, tstart + ntbins*period,
84  npitchbins, minpitch, maxpitch);
85  h.SetXTitle("time [us]");
86  h.SetYTitle("wire region");
87  h.SetStats(false);
88  //h.GetXaxis()->SetRangeUser(0, 100);
89  for (auto path : pr.paths) {
90  const Waveform::realseq_t& response = path.current;
91  for (int ind=0; ind<ntbins; ++ind) {
92  double value = response[ind];
93  const double t = tstart + period*ind;
94  if (isavg) {
95  h.Fill(t, path.pitchpos/pitch, value);
96  }
97  else {
98  h.Fill(t, path.pitchpos+0.5*dimpact, value);
99  }
100  }
101  }
102 
103  h.Draw("colz");
104  mpdf();
105 }
106 
107 
108 void plot_all_impact(MultiPdf& mpdf, const Response::Schema::FieldResponse& fr, bool isavg)
109 {
110  // plot Nregion X Nimpact
111 
112  const Response::Schema::PlaneResponse& p0r = fr.planes[0];
113  const Response::Schema::PathResponse& p0p0r = p0r.paths[0];
114  const int ntbins = p0p0r.current.size();
115  const double tstart = fr.tstart;
116  const double period = fr.period;
117  const double pitch = p0r.pitch;
118 
119  // figure out what impacts and regions there are
120  std::vector<double> impacts;
121  std::vector<int> regions;
122  for (auto path : p0r.paths) {
123  const int region = round((path.pitchpos-0.001)/pitch);
124  const double impact = path.pitchpos - region*pitch;
125  if (region == 0) {
126  impacts.push_back(impact);
127  }
128  if (std::abs(impact) < 0.001) {
129  regions.push_back(region);
130  }
131  }
132  sort(impacts.begin(), impacts.end());
133  sort(regions.begin(), regions.end());
134 
135  int plane_colors[] = {2,4,1};
136 
137 
138  int nimpacts = impacts.size();
139  int nregions = regions.size();
140  std::vector<TH1F*> hists[3];
141  for (int iplane=0; iplane<3; ++iplane) {
142  hists[iplane].resize(nimpacts*nregions);
143  for (int imp=0; imp<nimpacts; ++imp) {
144  for (int reg=0; reg<nregions; ++reg) {
145  int wire = reg - nregions/2;
146 
147  char sign=' '; // be a bit anal
148  if (wire>0) { sign='+'; }
149  if (wire<0) { sign='-'; }
150 
152  if (isavg) {
153  title = Form("Avg Response wire:%c%d", sign, std::abs(wire));
154  }
155  else {
156  title = Form("Fine Response wire:%c%d (impact=%.1f)", sign, std::abs(wire), impacts[imp]);
157  }
158 
159  TH1F* h = new TH1F(Form("h_%d_%d_%d", iplane, imp, reg),
160  title.c_str(),
161  ntbins, tstart, tstart + period*ntbins);
162  h->SetLineColor(plane_colors[iplane]);
163  hists[iplane][imp*nregions + reg] = h;
164  }
165  }
166  }
167 
168  for (auto plane : fr.planes) {
169  int iplane = plane.planeid;
170  for (auto path : plane.paths) {
171  const Waveform::realseq_t& response = path.current;
172  const int region = round((path.pitchpos-0.001)/pitch);
173  const double impact = path.pitchpos - region*pitch;
174 
175  int imp=-1, reg=-1; // I hate C++
176  for (size_t ind=0; ind<impacts.size(); ++ind) {
177  if (std::abs(impact-impacts[ind]) < 0.001) {
178  imp = ind;
179  break;
180  }
181  }
182  for (size_t ind=0; ind<regions.size(); ++ind) {
183  if (std::abs(region-regions[ind]) < 0.001) {
184  reg = ind;
185  break;
186  }
187  }
188  //cerr << "plane="<<iplane<<" imp="<<imp<<" impact="<<impact<<" reg="<<reg<<" region="<<region<<endl;
189  TH1F* hist = hists[iplane][imp*nregions + reg];
190  for (int ind=0; ind<ntbins; ++ind) {
191  double value = response[ind];
192  hist->SetBinContent(ind+1, value);
193  }
194  }
195  }
196 
197 
198  for (int reg=0; reg<nregions; ++reg) {
199  mpdf.canvas.Divide(1,nimpacts);
200  for (int imp=0; imp<nimpacts; ++imp) {
201  mpdf.canvas.cd(imp+1);
202  double minval = 999, maxval=-999;
203  for (int iplane=0; iplane<3; ++iplane) {
204  TH1F* hist = hists[iplane][imp*nregions + reg];
205  minval = min(minval, hist->GetMinimum());
206  maxval = max(maxval, hist->GetMaximum());
207  }
208  //cerr << "imp="<<imp<<" reg="<<reg<<endl;
209  double extraval = 0.01*(maxval-minval);
210  for (int iplane=0; iplane<3; ++iplane) {
211  TH1F* hist = hists[iplane][imp*nregions + reg];
212  hist->SetMinimum(minval-extraval);
213  hist->SetMaximum(maxval+extraval);
214  if (iplane) { // I hate root
215  hist->Draw("same");
216  }
217  else {
218  hist->Draw();
219  }
220  }
221  }
222  mpdf();
223  }
224 
225  for (int imp=0; imp<nimpacts; ++imp) {
226  for (int reg=0; reg<nregions; ++reg) {
227  for (int iplane=0; iplane<3; ++iplane) {
228  TH1F* hist = hists[iplane][imp*nregions + reg];
229  delete hist;
230  hists[iplane][imp*nregions + reg] = nullptr;
231  }
232  }
233  }
234 }
235 
236 const std::vector<double> all_gains{4.7, 7.8, 14.0, 25.0};
237 const std::vector<double> all_shapings{0.5*units::us, 1.0*units::us, 2.0*units::us, 3.0*units::us};
238 
239 typedef std::pair<int,int> GainShape;
240 typedef std::map<GainShape, Waveform::realseq_t> CerfMap;
241 
242 CerfMap make_cerf(double tmin=0, double tmax=100*units::us, int ntbins=1000);
243 CerfMap make_cerf(double tmin, double tmax, int ntbins)
244 {
245  const Waveform::Domain dom(tmin,tmax);
246  CerfMap ret;
247  for (int igain=0; igain<4;++igain) {
248  for (int ishap=0; ishap<4;++ishap) {
249  auto ele = Response::ColdElec(all_gains[igain], all_shapings[ishap]);
250  auto rf = ele.generate(dom, ntbins);
251  ret[GainShape(igain,ishap)] = rf;
252  }
253  }
254  return ret;
255 }
256 
257 void plot_cerf(MultiPdf& mpdf, CerfMap& cerf, double tmin=0, double tmax=100*units::us, int ntbins=1000);
258 void plot_cerf(MultiPdf& mpdf, CerfMap& cerf, double tmin, double tmax, int ntbins)
259 {
260  const double deltat = (tmax-tmin)/ntbins;
261 
262  auto frame = mpdf.canvas.DrawFrame(0,0,10,25);
263  mpdf.canvas.SetGridx();
264  mpdf.canvas.SetGridy();
265  frame->SetTitle("Electronics Responses");
266  frame->SetXTitle("time [us]");
267  frame->SetYTitle("gain [mV/fC]");
268 
269  int colors[] = {1,2,4,6};
270 
271  std::vector<TGraph*> garbage_collection;
272  for (int igain=0; igain<4;++igain) {
273  for (int ishap=0; ishap<4;++ishap) {
274  auto rf = cerf[GainShape(igain,ishap)];
275  TGraph* g = new TGraph(ntbins);
276  for (int ind=0; ind<ntbins; ++ind) {
277  g->SetPoint(ind, (tmin + ind*deltat)/units::us, rf[ind]);
278  }
279  g->Draw("L");
280  g->SetLineColor(colors[ishap]);
281  garbage_collection.push_back(g);
282  }
283  }
284  mpdf();
285  for (auto g : garbage_collection) {
286  delete g;
287  }
288 }
289 
290 int main(int argc, const char* argv[])
291 {
292 
293  if (argc < 2) {
294  cerr << "This test requires an Wire Cell Field Response input file." << endl;
295  return 0;
296  }
297 
298  WireCell::ExecMon em("test_persist_responses");
299  auto fr = Response::Schema::load(argv[1]);
300  em("loaded");
301 
302  auto fravg = Response::wire_region_average(fr);
303  em("averaged");
304 
305  auto all_cerf = make_cerf();
306 
307  {
308 
309  MultiPdf mpdf(argv[0]);
310  mpdf.canvas.SetRightMargin(.15);
311 
312  plot_cerf(mpdf, all_cerf);
313 
314  for (int ind=0; ind<3; ++ind) {
315  em("plot_plane");
316  plot_plane_2d(mpdf, fr, ind, false);
317  }
318  plot_all_impact(mpdf, fr, false);
319  em("done with fine responses");
320 
321  for (int ind=0; ind<3; ++ind) {
322  em("plot_plane avg");
323  plot_plane_2d(mpdf, fravg, ind, true);
324  }
325  plot_all_impact(mpdf, fravg, true);
326  em("done with avg responses");
327 
328  }
329 
330  cerr << em.summary() << endl;
331  return 0;
332 }
double pitch
The pitch distance between neighboring wires.
Definition: Response.h:65
double tstart
Time at which drift paths begin.
Definition: Response.h:89
CerfMap make_cerf(double tmin=0, double tmax=100 *units::us, int ntbins=1000)
Sequence< real_t > realseq_t
Definition: Waveform.h:31
std::pair< int, int > GainShape
std::string string
Definition: nybbler.cc:12
const std::vector< double > all_shapings
Schema::FieldResponse wire_region_average(const Schema::FieldResponse &fr)
Definition: Response.cxx:99
STL namespace.
double period
The sampling period of the response function.
Definition: Response.h:92
static const double g
Definition: Units.h:145
A functional object caching gain and shape.
Definition: Response.h:165
void plot_plane_2d(MultiPdf &mpdf, const Response::Schema::FieldResponse &fr, int planeind, bool isavg)
T abs(T value)
std::pair< double, double > Domain
Definition: Waveform.h:75
void plot_all_impact(MultiPdf &mpdf, const Response::Schema::FieldResponse &fr, bool isavg)
void plot_cerf(MultiPdf &mpdf, CerfMap &cerf, double tmin=0, double tmax=100 *units::us, int ntbins=1000)
std::vector< PlaneResponse > planes
List of PlaneResponse objects.
Definition: Response.h:78
std::map< GainShape, Waveform::realseq_t > CerfMap
static int max(int a, int b)
FieldResponse load(const char *filename)
Definition: Response.cxx:39
Definition: Main.h:22
WireCell::Waveform::realseq_t current
An array holding the induced current for the path on the wire-of-interest.
Definition: Response.h:33
int sign(double val)
Definition: UtilFunc.cxx:104
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
Definition: statistics.h:55
int main(int argc, const char *argv[])
const GenericPointer< typename T::ValueType > T2 value
Definition: pointer.h:1225
tstart
Definition: dbjson.py:36
static const double us
Definition: Units.h:105
std::vector< PathResponse > paths
List of PathResponse objects.
Definition: Response.h:54
const std::vector< double > all_gains
cet::registry_via_id< success_t, val > reg
Hold info about multiple plane responses in the detector.
Definition: Response.h:75
int planeid
A numerical identifier for the plane.
Definition: Response.h:57
std::string summary() const
Return summary up to now.
Definition: ExecMon.cxx:21
QTextStream & endl(QTextStream &s)
h
training ###############################
Definition: train_cnn.py:186