|
| 1 | +// This is a main entry point to configure a WC/LS job that applies |
| 2 | +// noise filtering and signal processing to existing RawDigits. The |
| 3 | +// FHiCL is expected to provide the following parameters as attributes |
| 4 | +// in the "params" structure. |
| 5 | +// |
| 6 | +// epoch: the hardware noise fix expoch: "before", "after", "dynamic" or "perfect" |
| 7 | +// reality: whether we are running on "data" or "sim"ulation. |
| 8 | +// raw_input_label: the art::Event inputTag for the input RawDigit |
| 9 | +// |
| 10 | +// see the .fcl of the same name for an example Version 2 |
| 11 | +// |
| 12 | +// Manual testing, eg: |
| 13 | +// |
| 14 | +// jsonnet -V reality=data -V epoch=dynamic -V raw_input_label=daq \\ |
| 15 | +// -V signal_output_form=sparse \\ |
| 16 | +// -J cfg cfg/pgrapher/experiment/uboone/wcls-nf-sp.jsonnet |
| 17 | +// |
| 18 | +// jsonnet -V reality=sim -V epoch=perfect -V raw_input_label=daq \\ |
| 19 | +// -V signal_output_form=sparse \\ |
| 20 | +// -J cfg cfg/pgrapher/experiment/uboone/wcls-nf-sp.jsonnet |
| 21 | + |
| 22 | + |
| 23 | +local epoch = std.extVar('epoch'); // eg "dynamic", "after", "before", "perfect" |
| 24 | +local reality = std.extVar('reality'); |
| 25 | +local sigoutform = std.extVar('signal_output_form'); // eg "sparse" or "dense" |
| 26 | + |
| 27 | +local wc = import 'wirecell.jsonnet'; |
| 28 | +local g = import 'pgraph.jsonnet'; |
| 29 | + |
| 30 | +local raw_input_label = std.extVar('raw_input_label'); // eg "daq" |
| 31 | +local volume_label = std.extVar('tpc_volume_label'); // eg "",0,1,2,3 |
| 32 | +local volume = if volume_label == '' then -1 else std.parseInt(volume_label); |
| 33 | + |
| 34 | +// local data_params = import 'params.jsonnet'; |
| 35 | +// local simu_params = import 'simparams.jsonnet'; |
| 36 | +// local params_init = if reality == 'data' then data_params else simu_params; |
| 37 | +local params_twofaced = import 'pgrapher/experiment/icarus/params_twofaced.jsonnet'; |
| 38 | + |
| 39 | +# Load the sim-params, overwrite the volume config for the two-faced version |
| 40 | +local base_params = import 'pgrapher/experiment/icarus/simparams.jsonnet'; |
| 41 | +local base = base_params + params_twofaced; |
| 42 | + |
| 43 | +// load the electronics response parameters |
| 44 | +local er_params = [ |
| 45 | + { |
| 46 | + gain: std.extVar('gain0')*wc.mV/wc.fC, |
| 47 | + shaping: std.extVar('shaping0')*wc.us, |
| 48 | + }, |
| 49 | + |
| 50 | + { |
| 51 | + gain: std.extVar('gain1')*wc.mV/wc.fC, |
| 52 | + shaping: std.extVar('shaping1')*wc.us, |
| 53 | + }, |
| 54 | + |
| 55 | + { |
| 56 | + gain: std.extVar('gain2')*wc.mV/wc.fC, |
| 57 | + shaping: std.extVar('shaping2')*wc.us, |
| 58 | + }, |
| 59 | +]; |
| 60 | + |
| 61 | + |
| 62 | +local params = base { |
| 63 | + files: super.files { |
| 64 | + fields: [ std.extVar('files_fields'), ], |
| 65 | + chresp: null, |
| 66 | + }, |
| 67 | + |
| 68 | + rc_resp: if std.extVar('file_rcresp') != "" then |
| 69 | + { |
| 70 | + // "icarus_fnal_rc_tail.json" |
| 71 | + filename: std.extVar('file_rcresp'), |
| 72 | + postgain: 1.0, |
| 73 | + start: 0.0, |
| 74 | + tick: 0.4*wc.us, |
| 75 | + nticks: params.daq.nticks,// 4255, |
| 76 | + type: "JsonElecResponse", |
| 77 | + } |
| 78 | + else super.rc_resp, |
| 79 | + |
| 80 | + elec: std.mapWithIndex(function (n, eparam) |
| 81 | + super.elec[n] + { |
| 82 | + gain: eparam.gain, |
| 83 | + shaping: eparam.shaping, |
| 84 | + }, er_params), |
| 85 | + |
| 86 | +}; |
| 87 | + |
| 88 | +// local tools_maker = import 'pgrapher/common/tools.jsonnet'; |
| 89 | +local tools_maker = import 'pgrapher/experiment/icarus/icarus_tools.jsonnet'; |
| 90 | +// local tools = tools_maker(params); |
| 91 | +local default_tools = tools_maker(params); |
| 92 | +local tools = std.mergePatch(default_tools, |
| 93 | + {dft: {type: "TorchDFT", data: {device: "gpu"}}}); |
| 94 | + |
| 95 | +local wcls_maker = import 'pgrapher/ui/wcls/nodes.jsonnet'; |
| 96 | +local wcls = wcls_maker(params, tools); |
| 97 | + |
| 98 | +local sp_maker = import 'pgrapher/experiment/icarus/sp.jsonnet'; |
| 99 | + |
| 100 | +//local chndbm = chndb_maker(params, tools); |
| 101 | +//local chndb = if epoch == "dynamic" then chndbm.wcls_multi(name="") else chndbm.wct(epoch); |
| 102 | + |
| 103 | + |
| 104 | +// Collect the WC/LS input converters for use below. Make sure the |
| 105 | +// "name" argument matches what is used in the FHiCL that loads this |
| 106 | +// file. In particular if there is no ":" in the inputer then name |
| 107 | +// must be the emtpy string. |
| 108 | +local wcls_input = { |
| 109 | + adc_digits: g.pnode({ |
| 110 | + type: 'wclsRawFrameSource', |
| 111 | + name: 'rfsrc%d' %volume, // to use multiple wirecell instances in a fhicl job |
| 112 | + data: { |
| 113 | + art_tag: raw_input_label, |
| 114 | + frame_tags: ['orig'], // this is a WCT designator |
| 115 | + tick: params.daq.tick, |
| 116 | + // nticks: params.daq.nticks, |
| 117 | + }, |
| 118 | + }, nin=0, nout=1), |
| 119 | + |
| 120 | +}; |
| 121 | + |
| 122 | +// Collect all the wc/ls output converters for use below. Note the |
| 123 | +// "name" MUST match what is used in theh "outputers" parameter in the |
| 124 | +// FHiCL that loads this file. |
| 125 | + |
| 126 | +local this_anode = tools.anodes[volume]; |
| 127 | + |
| 128 | +local wcls_output = { |
| 129 | + // The noise filtered "ADC" values. These are truncated for |
| 130 | + // art::Event but left as floats for the WCT SP. Note, the tag |
| 131 | + // "raw" is somewhat historical as the output is not equivalent to |
| 132 | + // "raw data". |
| 133 | + nf_digits: g.pnode({ |
| 134 | + type: 'wclsFrameSaver', |
| 135 | + name: 'nfsaver', |
| 136 | + data: { |
| 137 | + // anode: wc.tn(tools.anode), |
| 138 | + anode: wc.tn(this_anode), |
| 139 | + digitize: true, // true means save as RawDigit, else recob::Wire |
| 140 | + frame_tags: ['raw'], |
| 141 | + // nticks: params.daq.nticks, |
| 142 | + chanmaskmaps: ['bad'], |
| 143 | + plane_map: { |
| 144 | + "1": 3, // front induction: WireCell::kULayer -> geo::kH (1 -> 3) |
| 145 | + "2": 1, // middle induction: WireCell:kVLayer -> geo::kV (2 -> 1) |
| 146 | + "4": 0, // collection: WireCell::kWLayer -> geo::kU (4 -> 0) |
| 147 | + }, |
| 148 | + }, |
| 149 | + }, nin=1, nout=1, uses=[this_anode]), |
| 150 | + |
| 151 | + |
| 152 | + // The output of signal processing. Note, there are two signal |
| 153 | + // sets each created with its own filter. The "gauss" one is best |
| 154 | + // for charge reconstruction, the "wiener" is best for S/N |
| 155 | + // separation. Both are used in downstream WC code. |
| 156 | + sp_signals: g.pnode({ |
| 157 | + type: 'wclsFrameSaver', |
| 158 | + name: 'spsaver%d' %volume, // to use multiple wirecell instances in a fhicl job |
| 159 | + data: { |
| 160 | + // anode: wc.tn(tools.anode), |
| 161 | + anode: wc.tn(this_anode), |
| 162 | + digitize: false, // true means save as RawDigit, else recob::Wire |
| 163 | + // frame_tags: ['gauss', 'wiener', 'looseLf','shrinkROI','extendROI'], |
| 164 | + // frame_scale: [0.1, 0.1, 0.1], |
| 165 | + // frame_tags: ['gauss','wiener','looseLf','shrinkROI','extendROI','mp3ROI','mp2ROI', 'cleanupROI'], |
| 166 | + // frame_scale: [0.009,0.009,0.009,0.009,0.009,0.009,0.009,0.009], |
| 167 | + |
| 168 | + frame_tags: ['dnnsp'], |
| 169 | + frame_scale: [std.extVar('gain_ADC_per_e')], |
| 170 | + |
| 171 | + // nticks: params.daq.nticks, |
| 172 | + chanmaskmaps: ['bad'], |
| 173 | + nticks: -1, |
| 174 | + plane_map: { |
| 175 | + "1": 3, // front induction: WireCell::kULayer -> geo::kH (1 -> 3) |
| 176 | + "2": 1, // middle induction: WireCell:kVLayer -> geo::kV (2 -> 1) |
| 177 | + "4": 0, // collection: WireCell::kWLayer -> geo::kU (4 -> 0) |
| 178 | + }, |
| 179 | + }, |
| 180 | + }, nin=1, nout=1, uses=[this_anode]), |
| 181 | + |
| 182 | + h5io: g.pnode({ |
| 183 | + type: 'HDF5FrameTap', |
| 184 | + name: 'hio_sp%d' % volume, |
| 185 | + data: { |
| 186 | + anode: wc.tn(this_anode), |
| 187 | + trace_tags: ['gauss' |
| 188 | + , 'wiener' |
| 189 | + , 'tightLf' |
| 190 | + , 'looseLf' |
| 191 | + , 'decon' |
| 192 | + , 'cleanupROI' |
| 193 | + , 'breakROI1' |
| 194 | + , 'breakROI2' |
| 195 | + , 'shrinkROI' |
| 196 | + , 'extendROI' |
| 197 | + , 'mp3ROI' |
| 198 | + , 'mp2ROI' |
| 199 | + , 'dnnsp' |
| 200 | + ], |
| 201 | + filename: "wc-sp-%d.h5" % volume, |
| 202 | + chunk: [0, 0], // ncol, nrow |
| 203 | + gzip: 0, |
| 204 | + high_throughput: true, |
| 205 | + }, |
| 206 | + }, nin=1, nout=1, uses=[this_anode]), |
| 207 | + |
| 208 | +}; |
| 209 | + |
| 210 | +// local perfect = import 'chndb-perfect.jsonnet'; |
| 211 | +local base = import 'pgrapher/experiment/icarus/chndb-base.jsonnet'; |
| 212 | +local chndb = [{ |
| 213 | + type: 'OmniChannelNoiseDB', |
| 214 | + name: 'ocndbperfect%d' % n, |
| 215 | + // data: perfect(params, tools.anodes[n], tools.field, n), |
| 216 | + data: base(params, tools.anodes[n], tools.field, n){dft:wc.tn(tools.dft)}, |
| 217 | + uses: [tools.anodes[n], tools.field, tools.dft], // pnode extension |
| 218 | +} for n in std.range(0, std.length(tools.anodes) - 1)]; |
| 219 | + |
| 220 | +local nf_maker = import 'pgrapher/experiment/icarus/nf.jsonnet'; |
| 221 | +local nf_pipes = [nf_maker(tools.anodes[n], chndb[n], tools, name='nf%d' % n) for n in std.range(0, std.length(tools.anodes) - 1)]; |
| 222 | + |
| 223 | +local sp_override = { // assume all tages sets in base sp.jsonnet |
| 224 | + sparse: sigoutform == 'sparse', |
| 225 | + use_roi_refinement: true, |
| 226 | + use_roi_debug_mode: true, |
| 227 | + save_negtive_charge: true, |
| 228 | + wiener_tag: "", |
| 229 | + // gauss_tag: "", |
| 230 | + tight_lf_tag: "", |
| 231 | + // loose_lf_tag: "", |
| 232 | + break_roi_loop1_tag: "", |
| 233 | + break_roi_loop2_tag: "", |
| 234 | + shrink_roi_tag: "", |
| 235 | + extend_roi_tag: "", |
| 236 | + // decon_charge_tag: "", |
| 237 | + cleanup_roi_tag: "", |
| 238 | + // mp2_roi_tag: "", |
| 239 | + // mp3_roi_tag: "", |
| 240 | + use_multi_plane_protection: true, |
| 241 | + mp_tick_resolution: 8, |
| 242 | + process_planes: [0, 1, 2], |
| 243 | + isWrapped: true, |
| 244 | + nwires_separate_planes: [ |
| 245 | + [1056, 1056], [5600], [5600] |
| 246 | + ], |
| 247 | + troi_col_th_factor: std.parseJson(std.extVar('col_threshold_factor'))*1.0, // multiply by 1 to make into float |
| 248 | + troi_ind_th_factor: std.parseJson(std.extVar('ind_threshold_factor'))*1.0 |
| 249 | +}; |
| 250 | +local sp = sp_maker(params, tools, sp_override); |
| 251 | +local sp_pipes = [sp.make_sigproc(a) for a in tools.anodes]; |
| 252 | + |
| 253 | +local util = import 'pgrapher/experiment/icarus/funcs.jsonnet'; |
| 254 | +local chsel_pipes = [ |
| 255 | + g.pnode({ |
| 256 | + type: 'ChannelSelector', |
| 257 | + name: 'chsel%d' % n, |
| 258 | + data: { |
| 259 | + channels: util.anode_channels_twofaced(n), |
| 260 | + //tags: ['orig%d' % n], // traces tag |
| 261 | + }, |
| 262 | + }, nin=1, nout=1) |
| 263 | + for n in std.range(0, std.length(tools.anodes) - 1) |
| 264 | +]; |
| 265 | + |
| 266 | +local magoutput = 'icarus-data-check.root'; |
| 267 | +local magnify = import 'pgrapher/experiment/icarus/magnify-sinks.jsonnet'; |
| 268 | +local magnifyio = magnify(tools, magoutput); |
| 269 | + |
| 270 | +local dnnroi = import 'pgrapher/experiment/icarus/dnnroi.jsonnet'; |
| 271 | +local ts_u = { |
| 272 | + type: "TorchService", |
| 273 | + name: "dnnroi_u", |
| 274 | + data: { |
| 275 | + model: "NNs/plane0.ts", |
| 276 | + device: "gpu", |
| 277 | + concurrency: 1, |
| 278 | + }, |
| 279 | +}; |
| 280 | + |
| 281 | +local ts_v = { |
| 282 | + type: "TorchService", |
| 283 | + name: "dnnroi_v", |
| 284 | + data: { |
| 285 | + model: "NNs/plane1.ts", |
| 286 | + device: "gpu", |
| 287 | + concurrency: 1, |
| 288 | + }, |
| 289 | +}; |
| 290 | + |
| 291 | +local nfsp_pipes = [ |
| 292 | + g.pipeline([ |
| 293 | + chsel_pipes[n], |
| 294 | + // magnifyio.orig_pipe[n], |
| 295 | + |
| 296 | + nf_pipes[n], |
| 297 | + // magnifyio.raw_pipe[n], |
| 298 | + sp_pipes[n], |
| 299 | + dnnroi(tools.anodes[n], ts_u, ts_v), |
| 300 | + // magnifyio.decon_pipe[n], |
| 301 | + // magnifyio.threshold_pipe[n], |
| 302 | + // magnifyio.debug_pipe[n], // use_roi_debug_mode: true in sp.jsonnet |
| 303 | + ], |
| 304 | + 'nfsp_pipe_%d' % n) |
| 305 | + for n in [volume] |
| 306 | +]; |
| 307 | + |
| 308 | +local fanout_tag_rules = [ |
| 309 | + { |
| 310 | + frame: { |
| 311 | + '.*': 'orig%d' % tools.anodes[n].data.ident, |
| 312 | + }, |
| 313 | + trace: { |
| 314 | + // fake doing Nmult SP pipelines |
| 315 | + //orig: ['wiener', 'gauss'], |
| 316 | + //'.*': 'orig', |
| 317 | + }, |
| 318 | + } |
| 319 | + for n in [volume] |
| 320 | + ]; |
| 321 | + |
| 322 | +local fanin_tag_rules = [ |
| 323 | + { |
| 324 | + frame: { |
| 325 | + //['number%d' % n]: ['output%d' % n, 'output'], |
| 326 | + '.*': 'framefanin', |
| 327 | + }, |
| 328 | + trace: { |
| 329 | + ['extend_roi%d'%ind]:'extend_roi%d'%ind, |
| 330 | + ['shrink_roi%d'%ind]:'shrink_roi%d'%ind, |
| 331 | + // ['break_roi_2nd%d'%ind]:'break_roi_2nd%d'%ind, |
| 332 | + // ['break_roi_1st%d'%ind]:'break_roi_1st%d'%ind, |
| 333 | + ['cleanup_roi%d'%ind]:'cleanup_roi%d'%ind, |
| 334 | + ['mp2_roi%d'%ind]:'mp2_roi%d'%ind, |
| 335 | + ['mp3_roi%d'%ind]:'mp3_roi%d'%ind, |
| 336 | + ['gauss%d'%ind]:'gauss%d'%ind, |
| 337 | + 'dnnsp\\d':'dnnsp%d'%ind, |
| 338 | + ['wiener%d'%ind]:'wiener%d'%ind, |
| 339 | + // ['threshold%d'%ind]:'threshold%d'%ind, |
| 340 | + // ['tight_lf%d'%ind]:'tight_lf%d'%ind, |
| 341 | + ['loose_lf%d'%ind]:'loose_lf%d'%ind, |
| 342 | + // ['decon%d'%ind]:'decon%d'%ind, |
| 343 | + }, |
| 344 | + |
| 345 | + } |
| 346 | + for ind in [this_anode.data.ident] |
| 347 | + ]; |
| 348 | +local fanpipe = util.fanpipe('FrameFanout', nfsp_pipes, 'FrameFanin', 'nfsp%d' % volume, [], fanout_tag_rules, fanin_tag_rules); |
| 349 | + |
| 350 | +local retagger = g.pnode({ |
| 351 | + type: 'Retagger', |
| 352 | + data: { |
| 353 | + // Note: retagger keeps tag_rules an array to be like frame fanin/fanout. |
| 354 | + tag_rules: [{ |
| 355 | + // Retagger also handles "frame" and "trace" like fanin/fanout |
| 356 | + // merge separately all traces like gaussXYZ to gauss. |
| 357 | + frame: { |
| 358 | + '.*': 'retagger', |
| 359 | + }, |
| 360 | + merge: { |
| 361 | + 'dnnsp\\d': 'dnnsp', |
| 362 | + 'gauss\\d': 'gauss', |
| 363 | + 'wiener\\d': 'wiener', |
| 364 | + // 'tight_lf\\d': 'tightLf', |
| 365 | + 'loose_lf\\d': 'looseLf', |
| 366 | + // 'decon\\d': 'decon', |
| 367 | + 'cleanup_roi\\d': 'cleanupROI', |
| 368 | + // 'break_roi_1st\\d': 'breakROI1', |
| 369 | + // 'break_roi_2nd\\d': 'breakROI2', |
| 370 | + 'shrink_roi\\d': 'shrinkROI', |
| 371 | + 'extend_roi\\d': 'extendROI', |
| 372 | + 'mp3_roi\\d': 'mp3ROI', |
| 373 | + 'mp2_roi\\d': 'mp2ROI', |
| 374 | + }, |
| 375 | + }], |
| 376 | + }, |
| 377 | +}, nin=1, nout=1); |
| 378 | + |
| 379 | +local sink = g.pnode({ type: 'DumpFrames' }, nin=1, nout=0); |
| 380 | + |
| 381 | +// local graph = g.pipeline([wcls_input.adc_digits, chsel_pipes[volume], sp_pipes[volume], dnnroi(this_anode, ts_u, ts_v, output_scale=1), retagger, wcls_output.h5io, wcls_output.sp_signals, sink]); |
| 382 | +local graph = g.pipeline([wcls_input.adc_digits, fanpipe, retagger, wcls_output.sp_signals, sink]); |
| 383 | + |
| 384 | +local app = { |
| 385 | + type: 'Pgrapher', |
| 386 | + data: { |
| 387 | + edges: g.edges(graph), |
| 388 | + }, |
| 389 | +}; |
| 390 | + |
| 391 | +// Finally, the configuration sequence |
| 392 | +g.uses(graph) + [app] |
0 commit comments