3 Export wirecell.sigproc functionality to a main Click program. 9 from wirecell
import units
11 @click.group(
"sigproc")
15 Wire Cell Signal Processing Features 19 @cli.command(
"response-info")
20 @click.argument(
"json-file")
24 Show some info about a field response file (.json or .json.bz2). 26 import response.persist
as per
27 fr = per.load(json_file)
28 print (
"origin:%.2f cm, period:%.2f us, tstart:%.2f us, speed:%.2f mm/us, axis:(%.2f,%.2f,%.2f)" % \
29 (fr.origin/units.cm, fr.period/units.us, fr.tstart/units.us, fr.speed/(units.mm/units.us), fr.axis[0],fr.axis[1],fr.axis[2]))
31 print (
"\tplane:%d, location:%.4fmm, pitch:%.4fmm" % \
32 (pr.planeid, pr.location/units.mm, pr.pitch/units.mm))
34 @cli.command(
"convert-garfield")
35 @click.option(
"-o",
"--origin", default=
"10.0*cm",
36 help=
"Set drift origin (give units, eg '10*cm').")
37 @click.option(
"-s",
"--speed", default=
"1.114*mm/us",
38 help=
"Set nominal drift speed (give untis, eg '1.114*mm/us').")
39 @click.option(
"-n",
"--normalization", default=0.0,
40 help=
"Set normalization: 0:none, <0:electrons, >0:multiplicative scale. def=0")
41 @click.option(
"-z",
"--zero-wire-locs", default=[0.0,0.0,0.0], nargs=3, type=float,
42 help=
"Set location of zero wires. def: 0 0 0")
43 @click.argument(
"garfield-fileset")
44 @click.argument(
"wirecell-field-response-file")
47 garfield_fileset, wirecell_field_response_file):
49 Convert an archive of a Garfield fileset (zip, tar, tgz) into a 50 Wire Cell field response file (.json with optional .gz or .bz2 53 import garfield
as gar
54 import response
as res
55 import response.persist
as per
57 origin = eval(origin, units.__dict__)
58 speed = eval(speed, units.__dict__)
59 rflist = gar.load(garfield_fileset, normalization, zero_wire_locs)
60 fr = res.rf1dtoschema(rflist, origin, speed)
61 per.dump(wirecell_field_response_file, fr)
66 @cli.command(
"plot-garfield-exhaustive")
67 @click.option(
"-n",
"--normalization", default=0.0,
68 help=
"Set normalization: 0:none, <0:electrons, >0:multiplicative scale. def=0")
69 @click.option(
"-z",
"--zero-wire-locs", default=[0.0,0.0,0.0], nargs=3, type=float,
70 help=
"Set location of zero wires. def: 0 0 0")
71 @click.argument(
"garfield-fileset")
72 @click.argument(
"pdffile")
75 garfield_fileset, pdffile):
77 Plot all the Garfield current responses. 80 dat = gar.load(garfield_fileset, normalization, zero_wire_locs)
82 plots.garfield_exhaustive(dat, pdffile)
84 @cli.command(
"plot-garfield-track-response")
85 @click.option(
"-g",
"--gain", default=-14.0,
86 help=
"Set gain in mV/fC.")
87 @click.option(
"-s",
"--shaping", default=2.0,
88 help=
"Set shaping time in us.")
89 @click.option(
"-t",
"--tick", default=0.5,
90 help=
"Set tick time in us (0.1 is good for no shaping).")
91 @click.option(
"-p",
"--tick-padding", default=0,
92 help=
"Number of ticks of zero ADC to pre-pad the plots.")
93 @click.option(
"-e",
"--electrons", default=13300,
94 help=
"Set normalization in units of electron charge.")
95 @click.option(
"-a",
"--adc-gain", default=1.2,
96 help=
"Set ADC gain (unitless).")
97 @click.option(
"--adc-voltage", default=2.0,
98 help=
"Set ADC voltage range in Volt.")
99 @click.option(
"--adc-resolution", default=12,
100 help=
"Set ADC resolution in bits.")
101 @click.option(
"-n",
"--normalization", default=-1,
102 help=
"Set normalization: 0:none, <0:electrons, >0:multiplicative scale. def=-1")
103 @click.option(
"-z",
"--zero-wire-locs", default=[0.0, 0.0, 0.0], nargs=3, type=float,
104 help=
"Set location of zero wires. def: 0 0 0")
105 @click.option(
"--ymin", default=-40.0,
107 @click.option(
"--ymax", default=60.0,
109 @click.option(
"--regions", default=0, type=int,
110 help=
"Set how many wire regions to use, default to all")
111 @click.option(
"--dump-data", default=
"", type=str,
112 help=
"Dump the plotted data in format given by extension (.json, .txt or .npz/.npy)")
113 @click.argument(
"garfield-fileset")
114 @click.argument(
"pdffile")
117 adc_gain, adc_voltage, adc_resolution,
118 normalization, zero_wire_locs,
121 garfield_fileset, pdffile):
123 Plot Garfield response assuming a perpendicular track. 125 Note, defaults are chosen to reproduce the "ADC Waveform with 2D 126 MicroBooNE Wire Plane Model" plot for the MicroBooNE noise paper. 132 gain *= units.mV/units.fC
135 electrons *= units.eplus
138 adc_voltage *= units.volt
139 adc_resolution = 1<<adc_resolution
140 adc_per_voltage = adc_gain*adc_resolution/adc_voltage
142 dat = gar.load(garfield_fileset, normalization, zero_wire_locs)
145 print (
"Limiting to %d regions" % regions)
146 dat = [r
for r
in dat
if abs(r.region)
in range(regions)]
148 uvw = res.line(dat, electrons)
151 if "ub_" in garfield_fileset:
152 detector =
"MicroBooNE" 153 if "dune_" in garfield_fileset:
155 print (
'Using detector hints: "%s"' % detector)
157 nwires = len(set([
abs(r.region)
for r
in dat])) - 1
161 fig,data = plots.plot_digitized_line(uvw, gain, shaping,
162 adc_per_voltage = adc_per_voltage,
164 ymin=ymin, ymax=ymax, msg=msg,
165 tick_padding=tick_padding)
166 print (
"plotting to %s" % pdffile)
170 print (
"dumping data to %s" % dump_data)
172 if dump_data.endswith(
".npz"):
174 numpy.savez(dump_data, data);
175 if dump_data.endswith(
".npy"):
177 numpy.save(dump_data, data);
178 if dump_data.endswith(
".txt"):
179 with
open(dump_data,
"wt")
as fp:
181 line =
'\t'.join(map(str, line))
183 if dump_data.endswith(
".json"):
185 open(dump_data,
"wt").
write(json.dumps(data.tolist(), indent=4))
190 @cli.command(
"plot-response")
191 @click.argument(
"responsefile")
192 @click.argument(
"pdffile")
195 import response.persist
as per
196 import response.plots
as plots
198 fr = per.load(responsefile)
199 plots.plot_planes(fr, pdffile)
202 @cli.command(
"plot-electronics-response")
203 @click.option(
"-g",
"--gain", default=14.0,
204 help=
"Set gain in mV/fC.")
205 @click.option(
"-s",
"--shaping", default=2.0,
206 help=
"Set shaping time in us.")
207 @click.option(
"-t",
"--tick", default=0.5,
208 help=
"Set tick time in us (0.1 is good for no shaping).")
209 @click.argument(
"plotfile")
213 Plot the electronics response function. 215 gain *= units.mV/units.fC
219 fig = plots.one_electronics(gain, shaping, tick)
220 fig.savefig(plotfile)
223 @cli.command(
"convert-noise-spectra")
224 @click.option(
"-f",
"--format", default=
"microboonev1",
225 help=
"Format of input file")
226 @click.argument(
"inputfile")
227 @click.argument(
"outputfile")
231 Convert an file of noise spectra in some external format into WCT format. 234 if format ==
"microboonev1":
236 loader = load_noise_spectra_v1
240 click.echo(
'Unknown format: "%s"' % format)
243 spectra = loader(inputfile)
246 persist.dump(outputfile, spectra)
248 @cli.command(
"plot-noise-spectra")
249 @click.argument(
"spectrafile")
250 @click.argument(
"plotfile")
254 Plot contents of a WCT noise spectra file such as produced by 255 the convert-noise-spectra subcommand. 258 spectra = persist.load(spectrafile)
259 plots.plot_many(spectra, plotfile)
263 @cli.command(
"channel-responses")
264 @click.option(
"-t",
"--tscale", default=
"0.5*us", type=str,
265 help=
"Scale of time axis in the histogram.")
266 @click.option(
"-s",
"--scale", default=
"1e-9*0.5/1.13312", type=str,
267 help=
"Scale applied to the samples.")
268 @click.option(
"-n",
"--name", default=
"pResponseVsCh",
269 help=
"Data name (eg, the TH2D name if using 'hist' schema")
270 @click.argument(
"infile")
271 @click.argument(
"outfile")
274 '''Produce the per-channel calibrated response JSON file from a TH2D 275 of the given name in the input ROOT file provided by the analysis. 277 - tscale :: a number to multiply to the time axis of the histogram 278 in order to bring the result into the WCT system of units. It 279 may be expressed as a string of an algebraic expression which 280 includes symbols, eg "0.5*us". 282 - scale :: a number multiplied to all samples in the histogram in 283 order to make the sample value a unitless relative measure. It 284 may be expressed as a string of an algebraic expression which 285 includes symbols, eg "0.5*us". For uBoone's initial 286 20171006_responseWaveforms.root the appropriate scale is 287 1e-9*0.5/1.13312 = 4.41267e-10 292 from root_numpy
import hist2array
294 tscale = eval(tscale, units.__dict__)
295 scale = eval(scale, units.__dict__)
297 tf = ROOT.TFile.Open(
str(infile))
299 h = tf.Get(
str(name))
301 click.echo(
'Failed to get histogram "%s" from %s' % (name, infile))
304 arr,edges = hist2array(h, return_edges=
True)
308 t0,t1 = tscale*(tedges[0:2])
311 nchans, nticks = arr.shape
313 for ch
in range(nchans):
315 res = [
float(
"%.6g"%x)
for x
in arr[ch,:].tolist()]
319 dat = dict(tick=tick, t0=t0, channels=channels)
321 jtext = json.dumps(dat, indent=4)
322 if outfile.endswith(
".json.bz2"):
324 bz2.BZ2File(outfile,
'w').
write(jtext)
326 if outfile.endswith(
".json.gz"):
328 gzip.open(outfile,
'wb').
write(jtext)
338 if '__main__' == __name__:
def plot_electronics_response(ctx, gain, shaping, tick, plotfile)
def plot_noise_spectra(ctx, spectrafile, plotfile)
int open(const char *, int)
Opens a file descriptor.
def plot_garfield_track_response(ctx, gain, shaping, tick, tick_padding, electrons, adc_gain, adc_voltage, adc_resolution, normalization, zero_wire_locs, ymin, ymax, regions, dump_data, garfield_fileset, pdffile)
size_t write(int, const char *, size_t)
Writes count bytes from buf to the filedescriptor fd.
def channel_responses(ctx, tscale, scale, name, infile, outfile)
def convert_garfield(ctx, origin, speed, normalization, zero_wire_locs, garfield_fileset, wirecell_field_response_file)
def convert_noise_spectra(ctx, format, inputfile, outputfile)
def plot_response(ctx, responsefile, pdffile)
def response_info(ctx, json_file)
def plot_garfield_exhaustive(ctx, normalization, zero_wire_locs, garfield_fileset, pdffile)