6 import matplotlib.pyplot
as plt
10 Plot fine response functions 13 regions = sorted(set([x.region
for x
in rflist_fine]))
14 nregions = len(regions)
15 impacts = sorted(set([x.impact
for x
in rflist_fine]))
17 fig, axes = plt.subplots(nregions, 3, sharex=
True)
19 byplane = response.group_by(rflist_fine,
'plane')
21 for iplane, plane_rfs
in enumerate(byplane):
22 print (
'plane %d, %d regions' % (iplane, len(plane_rfs)))
23 byregion = response.group_by(plane_rfs,
'region')
25 byregion = [lst
for lst
in byregion
if lst[0].region
in regions]
27 for iregion, region_rfs
in enumerate(byregion):
28 region_rfs.sort(key=
lambda x: x.impact)
31 ax = axes[iregion][iplane]
32 ax.set_title(
'region %d' % (first.region,))
37 times = numpy.linspace(*rf.domainls)/units.us
38 ax.plot(times, rf.response)
44 Plot average field responses and with electronics shaping. 46 byplane = response.group_by(rflist_avg,
'plane')
47 nfields = len(byplane[0])
48 main_field = [rf
for rf
in byplane[2]
if rf.region == 0][0]
49 main_field_sum = numpy.max(numpy.abs(main_field.response))
50 main_shaped = main_field.shaped(gain_mVfC, shaping, nbins)
51 main_shaped_sum = numpy.max(numpy.abs(main_shaped.response))
52 rat = main_shaped_sum / main_field_sum
55 fig, axes = plt.subplots(nfields, 3, sharex=
True)
57 for iplane, plane_frs
in enumerate(byplane):
58 plane_frs.sort(key=
lambda x: x.region)
61 ax = axes[ifr][iplane]
62 ax.set_title(
'plane %s, region %d' % (fr.plane, fr.region,))
64 sh = fr.shaped(gain_mVfC, shaping, nbins)
65 ax.plot(fr.times/units.us, fr.response*rat)
66 ax.plot(sh.times/units.us, sh.response)
73 Plot one electronics response function 77 times = numpy.linspace(0, tmax, nticks)
78 res = response.electronics(times, gain, shaping)
79 fig, axes = plt.subplots(1, 1)
82 y = res/(units.mV/units.fC)
85 axes.set_title(
'Electronics response for gain=%.1f mV/fC, peaking=%.1f us' % \
86 (gain/(units.mV/units.fC), shaping/units.us))
87 axes.set_xlabel(
'Sample time [$\mu$s]')
88 axes.set_ylabel(
'Response')
95 Plot electronics response functions 97 fig, axes = plt.subplots(4,1, sharex=
True)
99 want_gains = [1.0, 4.7, 7.8, 14.0, 25.0]
101 engs = numpy.vectorize(response.electronics_no_gain_scale)
102 def engs_maximum(gain, shaping=2.0*units.us):
103 resp = engs(numpy.linspace(0,10*units.us, 100), gain, shaping)
104 return numpy.max(resp)
105 engs_maximum = numpy.vectorize(engs_maximum)
107 gainpar = numpy.linspace(0,300,6000)
108 for ishaping, shaping
in enumerate([0.5, 1.0, 2.0, 3.0]):
109 gain = engs_maximum(gainpar, shaping*units.us)
110 slope, inter = numpy.polyfit(gainpar, gain, 1)
112 for wg
in want_gains:
113 amin = numpy.argmin(numpy.abs(gain-wg))
114 hits.append((gainpar[amin], gain[amin]))
115 hits = numpy.asarray(hits).T
118 ax.set_title(
"shaping %.1f" % shaping)
119 ax.plot(gainpar, gain)
120 ax.scatter(hits[0], hits[1], alpha=0.5)
123 ax.text(p,g,
"%.2f"%p, verticalalignment=
'top', horizontalalignment=
'center')
124 ax.text(p,g,
"%.2f"%g, verticalalignment=
'bottom', horizontalalignment=
'center')
125 ax.text(250,10,
"%f slope" % slope, verticalalignment=
'top', horizontalalignment=
'center')
126 ax.text(250,10,
"%f mV/fC/par" % (1.0/slope,), verticalalignment=
'bottom', horizontalalignment=
'center')
132 fig, axes = plt.subplots(3, 2, sharex=
True, sharey=
True)
136 im1 = ax.imshow(numpy.absolute(frs), aspect=
'auto')
137 ax.set_title(
'%s response amp' % uvw[ind])
140 im2 = ax.imshow(numpy.angle(frs), aspect=
'auto')
141 ax.set_title(
'%s response phase' % uvw[ind])
143 fig.colorbar(im1, ax=axes[:,0].tolist())
144 fig.colorbar(im2, ax=axes[:,1].tolist())
150 Make a "contact sheet" of different responses on wires nearest a 151 path. Wire 0 is the wire most nearest. Each thumbnail shows 152 responses as a function of wire and time and thumbnails are 153 organized in rows of the same impact position and columns of the 156 Note, for the upper-most and lower-most impacts each neighboring wires there are impacts which start at 161 times, regions = numpy.meshgrid(
162 numpy.linspace(pibs.tmin, pibs.tmax, pibs.ntbins),
163 numpy.linspace(pibs.region_keys[0], pibs.region_keys[-1], len(pibs.region_keys)))
167 xylim = (60, 90, -10, 10)
169 impact_keys = list(pibs.impact_keys)
170 impact_keys.reverse()
172 fig, axes = plt.subplots(len(impact_keys), 3, sharex=
True, sharey=
True)
173 plt.subplots_adjust(left=0.05, right=0.95,
174 bottom=0.02, top=0.98,
175 wspace=0.2, hspace=0.2)
177 minres = [numpy.min(pibs.response(p, 0.0, 0))
for p
in 'uvw']
178 maxres = [numpy.max(pibs.response(p, 0.0, 0))
for p
in 'uvw']
181 for iplane, plane
in enumerate(pibs.plane_keys):
184 for iimpact, impact
in enumerate(impact_keys):
186 block = pibs.region_block(plane, impact)
187 ax = axes[iimpact,iplane]
188 plane_axes.append(ax)
189 im = ax.pcolormesh(times, regions, block)
192 ax.set_title(
'%s-plane, impact %0.1f' % (plane, impact))
193 if impact == impact_keys[-1]:
194 ax.set_xlabel(
'time [us]')
195 ax.set_ylabel(
'wire')
198 fig.colorbar(im, ax=[ax])
203 Make a plot for each plane of the response on its central wire due 204 to paths a all impacts running through the wire regions. 206 Note, the two impacts at the boundary between two wire regions are 207 explicitly shown. Each can be considered epsilon over the line of 211 region_keys = list(pibs.region_keys)
212 nregions = len(region_keys)
213 print (
'%d regions: %s' % (nregions, region_keys))
215 impact_keys = list(pibs.impact_keys)
216 nimpacts = len(impact_keys)
217 print (
'%d impacts: %s' % (nimpacts, impact_keys))
219 print (
"t=(%f,%f)" % (pibs.tmin, pibs.tmax))
220 times, regions = numpy.meshgrid(
221 numpy.linspace(pibs.tmin, pibs.tmax, pibs.ntbins),
222 numpy.linspace(impact_keys[0]+region_keys[0],
223 impact_keys[-1]+region_keys[-1],
226 xylim = (times.min(), times.max(), regions.min(), regions.max())
227 print (
'limits: ', xylim)
229 fig, axes = plt.subplots(3, 1, sharex=
True, sharey=
True)
231 for iplane, plane
in enumerate(pibs.plane_keys):
233 block = numpy.zeros((nregions*nimpacts, pibs.ntbins))
234 print (
'%s-plane shapes: times=%s regions=%s block=%s ' % (plane, times.shape, regions.shape, block.shape))
236 for iregion, region
in enumerate(region_keys):
237 for iimpact, impact
in enumerate(impact_keys):
238 row = nimpacts * iregion + iimpact
239 block[row] = pibs.response(plane,impact,-region)
242 im = ax.pcolormesh(times, regions, block)
245 ax.set_title(
'%s-plane' % plane)
246 ax.set_xlabel(
'time [us]')
247 ax.set_ylabel(
'impact position [pitch]')
248 fig.colorbar(im, ax=[ax])
258 Plot response functions as 1D graphs. 260 one = rflist_averages[0]
261 byplane = response.group_by(rflist_averages,
'plane')
263 nwires = map(len, byplane)
264 print (
"%d planes, nwires: %s" % (len(nwires),
str(nwires)))
267 region0s = response.by_region(rflist_averages)
268 shaped0s = [r.shaped()
for r
in region0s]
270 central_sum_field = sum(region0s[2].response)
271 central_sum_shape = sum(shaped0s[2].response)
274 fig, axes = plt.subplots(nwires, 2, sharex=
True)
276 for wire_region
in range(nwires):
277 axf = axes[wire_region][0]
278 axf.set_title(
'Wire region %d (field)' % wire_region)
279 axs = axes[wire_region][1]
280 axs.set_title(
'Wire region %d (shaped)' % wire_region)
282 for iplane
in range(3):
283 field_rf = byplane[iplane][wire_region]
284 shape_rf = field_rf.shaped()
286 field = field_rf.response
287 shape = shape_rf.response
288 field /= central_sum_field
289 shape /= central_sum_shape
291 ftime = 1.0e6*numpy.linspace(*field_rf.domainls)
292 stime = 1.0e6*numpy.linspace(*shape_rf.domainls)
294 axf.plot(ftime, field)
295 axs.plot(stime, shape)
299 Plot averages as 2D colz type plot 304 nwires = avgtriple[0].shape[0]
307 mintime = time[mintbin]
308 maxtime = time[maxtbin-1]
309 ntime = maxtbin-mintbin
310 deltatime = (maxtime-mintime)/ntime
312 x,y = numpy.meshgrid(numpy.linspace(mintime, maxtime, ntime),
313 numpy.linspace(minwires, maxwires, nwires))
322 for iplane
in range(3):
323 avg = avgtriple[iplane]
324 main = avg[:,mintbin:maxtbin]
325 edge = avg[:,maxtbin:]
326 ped = numpy.sum(edge) / (edge.shape[0] * edge.shape[1])
327 toplot.append(main - ped)
329 maxpix =
max(
abs(numpy.min(avgtriple)), numpy.max(avgtriple))
330 clim = (-maxpix/2.0, maxpix/2.0)
335 for iplane
in range(3):
336 ax = fig.add_subplot(3,1,iplane+1)
338 im = plt.imshow(toplot[iplane], cmap=cmap, clim=clim,
339 extent=[mintime, maxtime, minwires, maxwires], aspect=
'auto')
341 im = plt.pcolormesh(x,y, toplot[iplane], cmap=cmap, vmin=clim[0], vmax=clim[1])
345 fig.subplots_adjust(right=0.8)
346 cbar_ax = fig.add_axes([0.85, 0.15, 0.05, 0.7])
347 fig.colorbar(ims[0], ax=axes[0], cmap=cmap, cax=cbar_ax)
352 gain=14.0*units.mV/units.fC,
353 shaping=2.0*units.us,
355 adc_per_voltage = 1.2*4096/(2.0*units.volt),
356 detector =
"MicroBooNE",
357 ymin=
None, ymax=
None, msg=
"",
360 Make plot of shaped and digitized response functions. 362 >>> dat = garfield.load("/home/bviren/projects/wire-cell/garfield-data/ub_10.tar.gz") 363 >>> uvw = response.line.responses(dat) 364 >>> plots.plot_digitized_line(uvw) 366 See also wirecell.sigproc.paper.noise. 368 See also `wirecell-sigproc plot-garfield-track-response` command line. 371 time_offset = 50*units.us
374 dt_hi =
int(round(w.times[1] - w.times[0]))
377 n_lo =
int(round(dt_hi/tick * n_hi))
379 colors = [
'red',
'blue',
'black']
380 legends = [
'U-wire',
'V-wire',
'Y-wire']
382 fig, axes = plt.subplots(1, 1, dpi=144)
388 print (rf.plane, legends[ind], numpy.sum(rf.response)*dt_hi/units.eplus,
" electrons")
391 sig = rf.shaped(gain, shaping)
395 samp = sig.resample(n_lo)
396 x = (samp.times-time_offset)/units.us
402 print (
'Shaped:', ind, sum(samp.response))
404 adcf = numpy.floor(samp.response * adc_per_voltage)
405 y = numpy.array(adcf, dtype=int)
408 y = samp.response/units.mV
410 nonzero = [q
for q
in samp.response
if q>0]
412 dt = len(nonzero)*tick
414 print (
"qtot=%e C, itot=%e uA, dt=%d us, nele=%f" % \
415 (qtot/units.coulomb,itot/units.microampere,dt/units.us,qtot/units.eplus))
417 y = samp.response/units.nanoampere
419 print (
"padding waveforms by %d ticks" % tick_padding)
420 y = numpy.hstack((numpy.zeros((tick_padding,), dtype=int), y[:-tick_padding]))
422 ymins.append(numpy.min(y))
423 ymaxs.append(numpy.max(y))
425 if lstype ==
"steps":
426 print(x.shape, y.shape)
427 axes.step(x, y, color=colors[ind], label=legends[ind])
429 axes.plot(x, y, ls=lstype, color=colors[ind], label=legends[ind])
434 axes.legend(loc=
"upper left")
435 xmmymm = list(axes.axis())
446 axes.set_xlabel(
'Sample time [$\mu$s]')
448 axes.set_title(
'ADC Waveform with 2D %s Wire Plane Model' % detector)
449 axes.set_ylabel(
'ADC (baseline subtracted)')
451 xmmymm[3] =
max(ymaxs)
452 xmmymm[2] =
min(ymins)
454 axes.set_title(
'Voltage Waveform')
455 axes.set_ylabel(
'Voltage Sample (baseline subtracted) [mV]')
457 axes.set_title(
'Induced Current')
458 axes.set_xlabel(
'Time [$\mu$s]')
459 axes.set_ylabel(
'Instantaneous current (nanoamp)')
468 if "microboone" in detector.lower():
470 " Garfield 2D calculation\n(perpendicular line source)")
472 axes.text(textx,-20, msg)
474 if "dune" in detector.lower():
475 if tick_padding == 0:
479 " Garfield 2D calculation\n(perpendicular line source)")
482 return fig, numpy.vstack(data).T
488 Make detailed plots of all the Garfield current responses. 490 from matplotlib.backends.backend_pdf
import PdfPages
494 byplane = [rf
for rf
in rflist
if rf.plane == letter]
499 impacts.add(rf.impact)
501 with PdfPages(pdffile)
as pdf:
503 for impact
in sorted(impacts):
505 fig, axes = plt.subplots(nrows=3, ncols=1)
507 for letter, byplane, ax
in zip(
"uvw", uvw, axes):
508 byimpact = [rf
for rf
in byplane
if rf.impact == impact]
510 ax.set_title(
"%s impact %.1f" % (letter.upper(), impact))
511 ax.set_xlabel(
"time [$\mu$s]")
512 ax.set_ylabel(
"current [pAmp]")
515 ax.plot(rf.times/units.us, rf.response/units.picoampere,
516 label=
"wire:%d" % (rf.region))
517 xmmymm = list(ax.axis())
def response_averages_colz(avgtriple, time)
def average_shaping(rflist_avg, gain_mVfC=14, shaping=2.0 *units.us, nbins=5000)
def garfield_exhaustive(rflist, pdffile)
auto enumerate(Iterables &&...iterables)
Range-for loop helper tracking the number of iteration.
def fine_response(rflist_fine, regions=None, shaped=False)
def plot_digitized_line(uvw_rfs, gain=14.0 *units.mV/units.fC, shaping=2.0 *units.us, tick=0.5 *units.us, adc_per_voltage=1.2 *4096/(2.0 *units.volt), detector="MicroBooNE", ymin=None, ymax=None, msg="", tick_padding=0)
def field_response_spectra(frses)
def plane_impact_blocks(pibs)
def one_electronics(gain, shaping, tick=0.1 *units.us)
static int max(int a, int b)
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
auto zip(Iterables &&...iterables)
Range-for loop helper iterating across many collections at the same time.
def plane_impact_blocks_full(pibs)
def response_by_wire_region(rflist_averages)