Skip to content

Commit a8996c0

Browse files
committed
add DepoFluxWriter jsonnet, and change all corresponding fcls to use DepoFluxWriter as default
- this is necessary for ML workflow, DepoFluxWriter has a configruable to allow saving orig_track_id from SimEnergyDeposits in SimChannel - DepoFluxWriter validated for SBND in larwirecell PR #41
1 parent ea78979 commit a8996c0

5 files changed

Lines changed: 355 additions & 7 deletions

File tree

sbndcode/Commissioning/fcls/detsim_comm_sbnd.fcl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
physics.producers.opdaq.ApplyTriggers: false
1414

1515
## need both of the below lines to save rawdigits!
16-
physics.producers.simtpc2d.wcls_main.outputers: [ "wclsDepoSetSimChannelSink:postdrift",
16+
physics.producers.simtpc2d.wcls_main.outputers: [ "wclsDepoFluxWriter:postdrift",
1717
"wclsFrameSaver:simdigits" , # adding this line asks wcls to save raw digits
1818
"wclsFrameSaver:spsaver"]
1919
physics.producers.simtpc2d.wcls_main.params.save_simdigits: "true" # needs to be a string!!
Lines changed: 345 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,345 @@
1+
// This is a main entry point for configuring a wire-cell CLI job to
2+
// simulate SBND. It is simplest signal-only simulation with
3+
// one set of nominal field response function.
4+
5+
local epoch = std.extVar('epoch'); // eg "dynamic", "after", "before", "perfect"
6+
local reality = std.extVar('reality');
7+
local sigoutform = std.extVar('signal_output_form'); // eg "sparse" or "dense"
8+
local savetid = std.extVar("save_track_id");
9+
10+
local g = import 'pgraph.jsonnet';
11+
local f = import 'pgrapher/common/funcs.jsonnet';
12+
local wc = import 'wirecell.jsonnet';
13+
local io = import 'pgrapher/common/fileio.jsonnet';
14+
local tools_maker = import 'pgrapher/common/tools.jsonnet';
15+
16+
local data_params = import 'params.jsonnet';
17+
local simu_params = import 'simparams.jsonnet';
18+
local params = if reality == 'data' then data_params else simu_params;
19+
20+
local base = import 'pgrapher/experiment/sbnd/simparams.jsonnet';
21+
local params = base {
22+
lar: super.lar { // <- super.lar overrides default values
23+
// Longitudinal diffusion constant
24+
DL: std.extVar('DL') * wc.cm2 / wc.s,
25+
// Transverse diffusion constant
26+
DT: std.extVar('DT') * wc.cm2 / wc.s,
27+
// Electron lifetime
28+
lifetime: std.extVar('lifetime') * wc.ms,
29+
// Electron drift speed, assumes a certain applied E-field
30+
drift_speed: std.extVar('driftSpeed') * wc.mm / wc.us,
31+
},
32+
};
33+
34+
local tools = tools_maker(params);
35+
local sim_maker = import 'pgrapher/experiment/sbnd/sim.jsonnet';
36+
local sim = sim_maker(params, tools);
37+
local nanodes = std.length(tools.anodes);
38+
local anode_iota = std.range(0, nanodes - 1);
39+
40+
local wcls_maker = import "pgrapher/ui/wcls/nodes.jsonnet";
41+
local wcls = wcls_maker(params, tools);
42+
43+
// added Ewerton 2023-03-14
44+
local wcls_input_sim = {
45+
depos: wcls.input.depos(name="", art_tag=std.extVar('inputTag')),
46+
deposet: g.pnode({
47+
type: 'wclsSimDepoSetSource',
48+
name: "",
49+
data: {
50+
model: "",
51+
scale: -1, //scale is -1 to correct a sign error in the SimDepoSource converter.
52+
art_tag: std.extVar('inputTag'), //name of upstream art producer of depos "label:instance:processName"
53+
id_is_track: if (savetid == 'true') then false else true,
54+
assn_art_tag: "",
55+
},
56+
}, nin=0, nout=1),
57+
};
58+
// Collect all the wc/ls output converters for use below. Note the
59+
// "name" MUST match what is used in theh "outputers" parameter in the
60+
// FHiCL that loads this file.
61+
local mega_anode = {
62+
type: 'MegaAnodePlane',
63+
name: 'meganodes',
64+
data: {
65+
anodes_tn: [wc.tn(anode) for anode in tools.anodes],
66+
},
67+
};
68+
local wcls_output_sim = {
69+
// ADC output from simulation
70+
// sim_digits: wcls.output.digits(name="simdigits", tags=["orig"]),
71+
sim_digits: g.pnode({
72+
type: 'wclsFrameSaver',
73+
name: 'simdigits',
74+
data: {
75+
anode: wc.tn(mega_anode),
76+
digitize: true, // true means save as RawDigit, else recob::Wire
77+
frame_tags: ['daq'],
78+
nticks: params.daq.nticks,
79+
pedestal_mean: 'native',
80+
},
81+
}, nin=1, nout=1, uses=[mega_anode]),
82+
// The noise filtered "ADC" values. These are truncated for
83+
// art::Event but left as floats for the WCT SP. Note, the tag
84+
// "raw" is somewhat historical as the output is not equivalent to
85+
// "raw data".
86+
nf_digits: wcls.output.digits(name="nfdigits", tags=["raw"]),
87+
// The output of signal processing. Note, there are two signal
88+
// sets each created with its own filter. The "gauss" one is best
89+
// for charge reconstruction, the "wiener" is best for S/N
90+
// separation. Both are used in downstream WC code.
91+
sp_signals: wcls.output.signals(name="spsignals", tags=["gauss", "wiener"]),
92+
// save "threshold" from normal decon for each channel noise
93+
// used in imaging
94+
sp_thresholds: wcls.output.thresholds(name="spthresholds", tags=["threshold"]),
95+
};
96+
97+
98+
local drifter = sim.drifter;
99+
100+
local setdrifter = g.pnode({
101+
type: 'DepoSetDrifter',
102+
data: {
103+
drifter: "Drifter"
104+
}
105+
}, nin=1, nout=1,
106+
uses=[drifter]);
107+
108+
// signal plus noise pipelines
109+
local sn_pipes = sim.splusn_pipelines;
110+
111+
local rng = tools.random;
112+
local wcls_depoflux_writer = g.pnode({
113+
type: 'wclsDepoFluxWriter',
114+
name: 'postdrift',
115+
data: {
116+
anodes: [wc.tn(anode) for anode in tools.anodes],
117+
field_response: wc.tn(tools.field),
118+
tick: 0.5 * wc.us,
119+
window_start: 0.0 * wc.ms,
120+
window_duration: self.tick * 3400,
121+
nsigma: 3.0,
122+
123+
reference_time: -1700 * wc.us,
124+
125+
energy: 1, # equivalent to use_energy = true
126+
simchan_label: 'simpleSC',
127+
sed_label: if (savetid == 'true') then 'ionandscint' else '',
128+
sparse: false,
129+
},
130+
}, nin=1, nout=1, uses=tools.anodes + [tools.field]);
131+
132+
local sp_maker = import 'pgrapher/experiment/sbnd/sp.jsonnet';
133+
local sp = sp_maker(params, tools, { sparse: sigoutform == 'sparse' });
134+
local sp_pipes = [sp.make_sigproc(a) for a in tools.anodes];
135+
136+
local magoutput = 'sbnd-data-check.root';
137+
local magnify = import 'pgrapher/experiment/sbnd/magnify-sinks.jsonnet';
138+
local sinks = magnify(tools, magoutput);
139+
140+
local perfect = import 'pgrapher/experiment/sbnd/chndb-perfect.jsonnet';
141+
142+
local chndb = [{
143+
type: 'OmniChannelNoiseDB',
144+
name: 'ocndbperfect%d' % n,
145+
data: perfect(params, tools.anodes[n], tools.field, n){dft:wc.tn(tools.dft)},
146+
// data: base(params, tools.anodes[n], tools.field, n){dft:wc.tn(tools.dft)},
147+
uses: [tools.anodes[n], tools.field, tools.dft],
148+
} for n in anode_iota];
149+
150+
local nf_maker = import 'pgrapher/experiment/sbnd/nf.jsonnet';
151+
local nf_pipes = [nf_maker(params, tools.anodes[n], chndb[n], n, name='nf%d' % n) for n in anode_iota];
152+
153+
local multipass1 = [
154+
g.pipeline([
155+
sn_pipes[n],
156+
],
157+
'multipass%d' % n)
158+
for n in anode_iota
159+
];
160+
161+
local multipass2 = [
162+
g.pipeline([
163+
sn_pipes[n],
164+
//sinks.orig_pipe[n],
165+
166+
// nf_pipes[n], // NEED to include this pipe for channelmaskmaps
167+
//sinks.raw_pipe[n],
168+
169+
sp_pipes[n],
170+
171+
//sinks.decon_pipe[n],
172+
//sinks.threshold_pipe[n],
173+
],
174+
'multipass%d' % n)
175+
for n in anode_iota
176+
];
177+
178+
179+
local f_sp = import 'pgrapher/experiment/sbnd/funcs.jsonnet';
180+
181+
local outtags = ['orig%d' % n for n in anode_iota];
182+
local bi_manifold1 = f.fanpipe('DepoSetFanout', multipass1, 'FrameFanin', 'sn_mag_nf', outtags);
183+
local bi_manifold2 = f_sp.fanpipe('DepoSetFanout', multipass2, 'FrameFanin', 'sn_mag_nf_mod2', outtags, "true");
184+
185+
local retagger_sim = g.pnode({
186+
type: 'Retagger',
187+
data: {
188+
// Note: retagger keeps tag_rules an array to be like frame fanin/fanout.
189+
tag_rules: [{
190+
// Retagger also handles "frame" and "trace" like fanin/fanout
191+
// merge separately all traces like gaussN to gauss.
192+
frame: {
193+
'.*': 'orig',
194+
},
195+
merge: {
196+
'orig\\d': 'daq',
197+
},
198+
}],
199+
},
200+
}, nin=1, nout=1);
201+
202+
local sink_sim = sim.frame_sink;
203+
204+
//===============================NF+SP============================================
205+
206+
// Collect all the wc/ls output converters for use below. Note the
207+
// "name" MUST match what is used in theh "outputers" parameter in the
208+
// FHiCL that loads this file.
209+
210+
local wcls_output_sp = {
211+
// The noise filtered "ADC" values. These are truncated for
212+
// art::Event but left as floats for the WCT SP. Note, the tag
213+
// "raw" is somewhat historical as the output is not equivalent to
214+
// "raw data".
215+
nf_digits: g.pnode({
216+
type: 'wclsFrameSaver',
217+
name: 'nfsaver',
218+
data: {
219+
anode: wc.tn(mega_anode),
220+
digitize: true, // true means save as RawDigit, else recob::Wire
221+
frame_tags: ['raw'],
222+
},
223+
}, nin=1, nout=1, uses=[mega_anode]),
224+
225+
226+
// The output of signal processing. Note, there are two signal
227+
// sets each created with its own filter. The "gauss" one is best
228+
// for charge reconstruction, the "wiener" is best for S/N
229+
// separation. Both are used in downstream WC code.
230+
sp_signals: g.pnode({
231+
type: 'wclsFrameSaver',
232+
name: 'spsaver',
233+
data: {
234+
anode: wc.tn(mega_anode),
235+
digitize: false, // true means save as RawDigit, else recob::Wire
236+
frame_tags: ['gauss', 'wiener'],
237+
238+
// this may be needed to convert the decon charge [units:e-] to be consistent with the LArSoft default
239+
// for SBND, this scale is about ~50. Frame scale needed when using LArSoft producers reading in recob::Wire.
240+
frame_scale: [0.02, 0.02],
241+
nticks: params.daq.nticks,
242+
chanmaskmaps: [],
243+
244+
// uncomment the below configs to save summaries and cmm
245+
// summary_tags: ['wiener'],
246+
// summary_operator: {threshold: 'set'},
247+
// summary_scale: [0.02], # summary scale should be the same as frame_scale
248+
// chanmaskmaps: ['bad'],
249+
},
250+
}, nin=1, nout=1, uses=[mega_anode]),
251+
252+
};
253+
254+
255+
local chsel_pipes = [
256+
g.pnode({
257+
type: 'ChannelSelector',
258+
name: 'chsel%d' % n,
259+
data: {
260+
channels: std.range(5632 * n, 5632 * (n + 1) - 1),
261+
},
262+
}, nin=1, nout=1)
263+
for n in anode_iota
264+
];
265+
266+
267+
local nfsp_pipes = [
268+
g.pipeline([
269+
chsel_pipes[n],
270+
//sinks.orig_pipe[n],
271+
272+
// nf_pipes[n], // NEED to include this pipe for channelmaskmaps
273+
//sinks.raw_pipe[n],
274+
275+
sp_pipes[n],
276+
//sinks.decon_pipe[n],
277+
//sinks.threshold_pipe[n],
278+
// sinks.debug_pipe[n], // use_roi_debug_mode=true in sp.jsonnet
279+
],
280+
'nfsp_pipe_%d' % n)
281+
for n in anode_iota
282+
];
283+
284+
//local fanpipe = f_sp.fanpipe('FrameFanout', nfsp_pipes, 'FrameFanin', 'sn_mag_nf'); // commented Ewerton 2023-05-24
285+
local fanpipe = f_sp.fanpipe('FrameFanout', nfsp_pipes, 'FrameFanin', 'sn_mag_nf_mod'); //added Ewerton 2023-05-24
286+
287+
local retagger_sp = g.pnode({
288+
type: 'Retagger',
289+
name: 'sp', //added Ewerton 2023-05-24
290+
data: {
291+
// Note: retagger keeps tag_rules an array to be like frame fanin/fanout.
292+
tag_rules: [{
293+
// Retagger also handles "frame" and "trace" like fanin/fanout
294+
// merge separately all traces like gaussN to gauss.
295+
frame: {
296+
'.*': 'retagger',
297+
},
298+
merge: {
299+
'gauss\\d': 'gauss',
300+
'wiener\\d': 'wiener',
301+
},
302+
}],
303+
},
304+
}, nin=1, nout=1);
305+
306+
local sink_sp = g.pnode({ type: 'DumpFrames' }, nin=1, nout=0);
307+
308+
local graph1 = g.pipeline([
309+
wcls_input_sim.deposet, //sim
310+
setdrifter, //sim
311+
wcls_depoflux_writer, //sim
312+
bi_manifold1, //sim
313+
retagger_sim, //sim
314+
wcls_output_sim.sim_digits, //sim
315+
fanpipe, //sp
316+
retagger_sp, //sp
317+
wcls_output_sp.sp_signals, //sp
318+
sink_sp //sp
319+
]);
320+
321+
322+
local graph2 = g.pipeline([
323+
wcls_input_sim.deposet, //sim
324+
setdrifter, //sim
325+
wcls_depoflux_writer, //sim
326+
bi_manifold2, //sim
327+
retagger_sp, //sp
328+
wcls_output_sp.sp_signals, //sp
329+
sink_sp //sp
330+
]);
331+
332+
local save_simdigits = std.extVar('save_simdigits');
333+
334+
local graph = if save_simdigits == "true" then graph1 else graph2;
335+
336+
local app = {
337+
type: 'TbbFlow',
338+
data: {
339+
edges: g.edges(graph),
340+
},
341+
};
342+
343+
// Finally, the configuration sequence
344+
g.uses(graph) + [app]
345+

sbndcode/WireCell/wcsimsp_sbnd.fcl

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,20 @@ sbnd_wcls_simsp: {
1818
inputers: ["wclsSimDepoSetSource:"]
1919

2020
outputers: [
21-
"wclsDepoSetSimChannelSink:postdrift",
21+
"wclsDepoFluxWriter:postdrift",
2222
# "wclsFrameSaver:simdigits" , # <- by default, do not save RawDigits. Uncomment this line to save RawDigits and set
2323
"wclsFrameSaver:spsaver"
2424
]
2525

2626
## This sets the "main" Jsonnet file which provides the
2727
## configuration for the Wire-Cell Toolkit components. It is
2828
## take as relative to entries in WIRECELL_PATH.
29-
configs: ["pgrapher/experiment/sbnd/wcls-sim-drift-simchannel-nf-sp.jsonnet"]
29+
configs: ["pgrapher/experiment/sbnd/wcls-sim-drift-depoflux-nf-sp.jsonnet"]
3030

3131

3232
## Set the "external variables" required by the Jsonnet.
3333
params : {
34-
## This locates the input raw::RawDigit collection in the art::Event
34+
## This locates the input SimEnergyDeposits in the art::Event
3535
inputTag: "ionandscint:"
3636

3737
## Set "data" vs. "sim". The epoch below probably should follow suit.
@@ -51,11 +51,14 @@ sbnd_wcls_simsp: {
5151

5252
## If save_simdigits="false", comment line with "wclsFrameSaver:simdigits" in outputers
5353
## If save_simdigits="true", uncomment line with "wclsFrameSaver:simdigits" in outputers
54-
save_simdigits: "false"
54+
## this is whether or not to save raw digits!!!
55+
save_simdigits: "false"
5556

5657
## Set the waveform sample length, eg, 6000, 15000, "auto"
5758
# nsample: 6000
5859

60+
save_track_id: "true"
61+
5962
}
6063

6164
structs: {

0 commit comments

Comments
 (0)