|
| 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 |
| 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 sigoutform = std.extVar('signal_output_form'); // eg "sparse" or "dense" |
| 25 | +local raw_input_label = std.extVar('raw_input_label'); // eg "daq" |
| 26 | + |
| 27 | +local g = import 'pgraph.jsonnet'; |
| 28 | +local f = import 'pgrapher/experiment/sbnd/funcs.jsonnet'; |
| 29 | +local wc = import 'wirecell.jsonnet'; |
| 30 | +local tools_maker = import 'pgrapher/common/tools.jsonnet'; |
| 31 | + |
| 32 | +local data_params = import 'params.jsonnet'; |
| 33 | + |
| 34 | +local params = data_params { |
| 35 | + daq: super.daq { // <- super.daq overrides default values |
| 36 | + // Set the waveform sample length, eg, 6000, 15000, "auto" |
| 37 | + nticks: std.extVar('nticks'), |
| 38 | + }, |
| 39 | +}; |
| 40 | + |
| 41 | + |
| 42 | +local tools = tools_maker(params); |
| 43 | + |
| 44 | + |
| 45 | +local mega_anode = { |
| 46 | + type: 'MegaAnodePlane', |
| 47 | + name: 'meganodes', |
| 48 | + data: { |
| 49 | + anodes_tn: [wc.tn(anode) for anode in tools.anodes], |
| 50 | + }, |
| 51 | +}; |
| 52 | + |
| 53 | +local wcls_maker = import 'pgrapher/ui/wcls/nodes.jsonnet'; |
| 54 | +local wcls = wcls_maker(params, tools); |
| 55 | + |
| 56 | +// Collect the WC/LS input converters for use below. Make sure the |
| 57 | +// "name" argument matches what is used in the FHiCL that loads this |
| 58 | +// file. In particular if there is no ":" in the inputer then name |
| 59 | +// must be the emtpy string. |
| 60 | +local wcls_input = { |
| 61 | + adc_digits: g.pnode({ |
| 62 | + type: 'wclsRawFrameSource', |
| 63 | + name: '', |
| 64 | + data: { |
| 65 | + art_tag: raw_input_label, |
| 66 | + frame_tags: ['orig'], // this is a WCT designator |
| 67 | + // nticks: params.daq.nticks, |
| 68 | + }, |
| 69 | + }, nin=0, nout=1), |
| 70 | + |
| 71 | +}; |
| 72 | + |
| 73 | + |
| 74 | +// Collect all the wc/ls output converters for use below. Note the |
| 75 | +// "name" MUST match what is used in theh "outputers" parameter in the |
| 76 | +// FHiCL that loads this file. |
| 77 | + |
| 78 | +local wcls_output = { |
| 79 | + // The noise filtered "ADC" values. These are truncated for |
| 80 | + // art::Event but left as floats for the WCT SP. Note, the tag |
| 81 | + // "raw" is somewhat historical as the output is not equivalent to |
| 82 | + // "raw data". |
| 83 | + nf_digits: g.pnode({ |
| 84 | + type: 'wclsFrameSaver', |
| 85 | + name: 'nfsaver', |
| 86 | + data: { |
| 87 | + // anode: wc.tn(tools.anode), |
| 88 | + anode: wc.tn(mega_anode), |
| 89 | + digitize: true, // true means save as RawDigit, else recob::Wire |
| 90 | + frame_tags: ['raw'], |
| 91 | + // nticks: params.daq.nticks, |
| 92 | + chanmaskmaps: ['bad'], |
| 93 | + }, |
| 94 | + }, nin=1, nout=1, uses=[mega_anode]), |
| 95 | + |
| 96 | + |
| 97 | + // The output of signal processing. Note, there are two signal |
| 98 | + // sets each created with its own filter. The "gauss" one is best |
| 99 | + // for charge reconstruction, the "wiener" is best for S/N |
| 100 | + // separation. Both are used in downstream WC code. |
| 101 | + sp_signals: g.pnode({ |
| 102 | + type: 'wclsFrameSaver', |
| 103 | + name: 'spsaver', |
| 104 | + data: { |
| 105 | + anode: wc.tn(mega_anode), |
| 106 | + digitize: false, // true means save as RawDigit, else recob::Wire |
| 107 | + frame_tags: ['gauss', 'wiener'], |
| 108 | + |
| 109 | + // this may be needed to convert the decon charge [units:e-] to be consistent with the LArSoft default ?unit? e.g. decon charge * 0.005 --> "charge value" to GaussHitFinder |
| 110 | + frame_scale: [0.02, 0.02], |
| 111 | + nticks: params.daq.nticks, |
| 112 | + chanmaskmaps: [], |
| 113 | + }, |
| 114 | + }, nin=1, nout=1, uses=[mega_anode]), |
| 115 | +}; |
| 116 | + |
| 117 | +local perfect = import 'pgrapher/experiment/sbnd/chndb-perfect.jsonnet'; |
| 118 | +//local base = import 'pgrapher/experiment/sbnd/chndb-base_sbnd.jsonnet'; |
| 119 | + |
| 120 | +local chndb = [{ |
| 121 | + type: 'OmniChannelNoiseDB', |
| 122 | + name: 'ocndbperfect%d' % n, |
| 123 | + data: perfect(params, tools.anodes[n], tools.field, n){dft:wc.tn(tools.dft)}, |
| 124 | + // data: base(params, tools.anodes[n], tools.field, n){dft:wc.tn(tools.dft)}, |
| 125 | + uses: [tools.anodes[n], tools.field, tools.dft], |
| 126 | +} for n in std.range(0, std.length(tools.anodes) - 1)]; |
| 127 | + |
| 128 | +local chsel_pipes = [ |
| 129 | + g.pnode({ |
| 130 | + type: 'ChannelSelector', |
| 131 | + name: 'chsel%d' % n, |
| 132 | + data: { |
| 133 | + channels: std.range(5632 * n, 5632 * (n + 1) - 1), |
| 134 | + //tags: ['orig%d' % n], // traces tag |
| 135 | + }, |
| 136 | + }, nin=1, nout=1) |
| 137 | + for n in std.range(0, std.length(tools.anodes) - 1) |
| 138 | +]; |
| 139 | + |
| 140 | +local nf_maker = import 'pgrapher/experiment/sbnd/nf.jsonnet'; |
| 141 | +local nf_pipes = [nf_maker(params, tools.anodes[n], chndb[n], n, name='nf%d' % n) for n in std.range(0, std.length(tools.anodes) - 1)]; |
| 142 | + |
| 143 | +local sp_maker = import 'pgrapher/experiment/sbnd/sp.jsonnet'; |
| 144 | +local sp = sp_maker(params, tools, { sparse: sigoutform == 'sparse' }); |
| 145 | +local sp_pipes = [sp.make_sigproc(a) for a in tools.anodes]; |
| 146 | + |
| 147 | +local magoutput = 'sbnd-data-check.root'; |
| 148 | +local magnify = import 'pgrapher/experiment/sbnd/magnify-sinks.jsonnet'; |
| 149 | +local sinks = magnify(tools, magoutput); |
| 150 | + |
| 151 | +local nfsp_pipes = [ |
| 152 | + g.pipeline([ |
| 153 | + chsel_pipes[n], |
| 154 | + //sinks.orig_pipe[n], |
| 155 | + |
| 156 | + nf_pipes[n], |
| 157 | + //sinks.raw_pipe[n], |
| 158 | + |
| 159 | + sp_pipes[n], |
| 160 | + //sinks.decon_pipe[n], |
| 161 | + //sinks.threshold_pipe[n], |
| 162 | + // sinks.debug_pipe[n], // use_roi_debug_mode=true in sp.jsonnet |
| 163 | + ], |
| 164 | + 'nfsp_pipe_%d' % n) |
| 165 | + for n in std.range(0, std.length(tools.anodes) - 1) |
| 166 | +]; |
| 167 | + |
| 168 | +local fanpipe = f.fanpipe('FrameFanout', nfsp_pipes, 'FrameFanin', 'sn_mag_nf'); |
| 169 | + |
| 170 | +local retagger = g.pnode({ |
| 171 | + type: 'Retagger', |
| 172 | + data: { |
| 173 | + // Note: retagger keeps tag_rules an array to be like frame fanin/fanout. |
| 174 | + tag_rules: [{ |
| 175 | + // Retagger also handles "frame" and "trace" like fanin/fanout |
| 176 | + // merge separately all traces like gaussN to gauss. |
| 177 | + frame: { |
| 178 | + '.*': 'retagger', |
| 179 | + }, |
| 180 | + merge: { |
| 181 | + 'gauss\\d': 'gauss', |
| 182 | + 'wiener\\d': 'wiener', |
| 183 | + }, |
| 184 | + }], |
| 185 | + }, |
| 186 | +}, nin=1, nout=1); |
| 187 | + |
| 188 | +local sink = g.pnode({ type: 'DumpFrames' }, nin=1, nout=0); |
| 189 | + |
| 190 | + |
| 191 | +// local graph = g.pipeline([wcls_input.adc_digits, rootfile_creation_frames, fanpipe, retagger, wcls_output.sp_signals, sink]); |
| 192 | +local graph = g.pipeline([wcls_input.adc_digits, fanpipe, retagger, wcls_output.sp_signals, sink]); |
| 193 | + |
| 194 | +local app = { |
| 195 | + type: 'TbbFlow', |
| 196 | + data: { |
| 197 | + edges: g.edges(graph), |
| 198 | + }, |
| 199 | +}; |
| 200 | + |
| 201 | +// Finally, the configuration sequence |
| 202 | +g.uses(graph) + [app] |
0 commit comments