All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
generate_simple_weighted_template.py
Go to the documentation of this file.
1 #! /usr/bin/env python
2 ######################################################################
3 #
4 # Name: generate_simple_weighted_template.py
5 #
6 # Purpose: Create templates
7 #
8 # Created: February-2020 Iker Loïc de Icaza Astiz (icaza@fnal.gov)
9 #
10 # Usage:
11 #
12 # generate_simple_weighted_template.py (--sbnd | --icarus) file
13 #
14 # Options:
15 #
16 # [-h|--help] - Print help message.
17 # (--sbnd or --icarus) to select for which experiment generate metrics
18 # Arguments:
19 #
20 # file ... - Input file.
21 #
22 ######################################################################
23 
24 import sys
25 import os
26 import string
27 import argparse
28 import numpy as np
29 from time import sleep
30 from array import array
31 
32 from ROOT import TStyle, TCanvas, TColor, TGraph, TGraphErrors
33 from ROOT import TH1D, TH2D, TProfile, TFile, TF1
34 from ROOT import gROOT
35 import ROOT
36 
37 try:
38  # import project_utilities
39  import larbatch_posix
40  import fhicl
41 except ImportError:
42  print("Failed to import 'larbatch_posix' or 'fhicl' modules")
43  print("Setup 'fhiclpy' first:\n\tsetup fhiclpy vV_VV_VV -q QQQ:QQQQ")
44  exit(1)
45 
46 
47 class dotDict(dict):
48  def __getattr__(self,val):
49  return self[val]
50 
51 
52 # Globally turn off root warnings.
53 # Don't let root see our command line options.
54 myargv = sys.argv
55 sys.argv = myargv[0:1]
56 if 'TERM' in os.environ:
57  del os.environ['TERM']
58 ROOT.gErrorIgnoreLevel = ROOT.kError
59 sys.argv = myargv
60 
61 detector = "experiment"
62 # # Print help
63 # def help():
64 
65 # filename = sys.argv[0]
66 # file = open(filename)
67 
68 # doprint = False
69 
70 # for line in file.readlines():
71 # if line[2:9] == 'stat.py':
72 # doprint = True
73 # elif line[0:6] == '######' and doprint:
74 # doprint = False
75 # if doprint:
76 # if len(line) > 2:
77 # print(line[2:], end=' ')
78 # else:
79 # print()
80 
81 
82 
83 def hypo_flashx_from_H2(flash_rr, rr_h2, flash_ratio, ratio_h2):
84  rr_hypoX, rr_hypoXWgt = x_estimate_and_rms(flash_rr, rr_h2);
85  ratio_hypoX, ratio_hypoXWgt = x_estimate_and_rms(flash_ratio, ratio_h2);
86 
87  sum_weights = rr_hypoXWgt + ratio_hypoXWgt
88  hypo_x = (rr_hypoX*rr_hypoXWgt + ratio_hypoX*ratio_hypoXWgt) / sum_weights
89  hypo_x_err = np.sqrt(sum_weights) / sum_weights
90  # return (hypo_x, hypo_x_err, rr_hypoX, ratio_hypoX)
91  return hypo_x
92 
93 
94 def x_estimate_and_rms(metric_value, metric_h2):
95  kMinEntriesInProjection = 100
96  fXBinWidth = 5.
97  bin = metric_h2.GetYaxis().FindBin(metric_value);
98  bins = metric_h2.GetNbinsY();
99  metric_hypoX = -1.;
100  metric_hypoXWgt = 0.;
101  bin_buff = 0;
102  while 0 < bin-bin_buff or bin+bin_buff <= bins :
103  low_bin = bin-bin_buff if 0 < bin-bin_buff else 0
104  high_bin = bin+bin_buff if bin+bin_buff <= bins else -1
105  metric_px = metric_h2.ProjectionX("metric_px", low_bin, high_bin);
106  if metric_px.GetEntries() > kMinEntriesInProjection :
107  metric_hypoX = metric_px.GetRandom();
108  metric_rmsX = metric_px.GetRMS();
109  if metric_rmsX < fXBinWidth: # something went wrong
110  print(f"metric_h2 projected on metric_value: {metric_value}, bin: {bin}, "
111  f"bin_buff: {bin_buff}; has {metric_px.GetEntries()} entries.")
112  print(f"metric_hypoX: {metric_hypoX}, metric_rmsX: {metric_rmsX}")
113  return (-1., 0.); # no estimate
114  metric_hypoXWgt = 1/(metric_rmsX*metric_rmsX);
115  return (metric_hypoX, metric_hypoXWgt);
116  bin_buff += 1;
117  return (-1., 0.); # no estimate
118 
119 
120 def y_bias(y_skew, hypo_x, y_bias_slope):
121  if detector == "sbnd":
122  return y_skew * hypo_x * hypo_x * y_bias_slope
123  elif detector == "icarus":
124  return y_skew * hypo_x * y_bias_slope
125 
126 
127 def z_bias(z_skew, hypo_x, z_bias_slope):
128  if detector == "sbnd":
129  return z_skew * hypo_x * z_bias_slope;
130  elif detector == "icarus":
131  return z_skew * hypo_x * z_bias_slope;
132 
133 
134 def generator(nuslice_tree, rootfile, pset):
135  drift_distance = pset.DriftDistance
136  x_bins = pset.XBins
137  xbin_width = drift_distance/x_bins
138  half_bin_width = xbin_width/2.
139  y_bias_slope = pset.YBiasSlope
140  z_bias_slope = pset.ZBiasSlope
141 
142  xvals = np.arange(half_bin_width, drift_distance, xbin_width)
143  xerrs = np.array([half_bin_width] * len(xvals))
144  dist_to_anode_bins = x_bins
145  dist_to_anode_low = 0.
146  dist_to_anode_up = drift_distance
147  if detector == "sbnd":
148  x_gl_low = -215
149  x_gl_up = 215
150  elif detector == "icarus":
151  if pset.Cryostat == 0:
152  x_gl_low = -380
153  x_gl_up = -50
154  if pset.Cryostat == 1:
155  x_gl_low = 380
156  x_gl_up = 50
157 
158  profile_bins = x_bins
159  profile_option = 's' # errors are the standard deviation
160 
161  dy_spreads = [None] * x_bins
162  dy_means = [None] * x_bins
163  dy_h2 = TH2D("dy_h2", "#Delta y",
164  dist_to_anode_bins, dist_to_anode_low, dist_to_anode_up,
165  pset.dy_bins, pset.dy_low, pset.dy_up)
166  dy_h2.GetXaxis().SetTitle("distance from anode (cm)")
167  dy_h2.GetYaxis().SetTitle("y_flash - y_TPC (cm)")
168  dy_prof = TProfile("dy_prof", "Profile of dy_spreads in #Delta y",
169  profile_bins, dist_to_anode_low, dist_to_anode_up,
170  pset.dy_low*2, pset.dy_up*2, profile_option)
171  dy_prof.GetXaxis().SetTitle("distance from anode (cm)")
172  dy_prof.GetYaxis().SetTitle("y_flash - y_TPC (cm)")
173  dy_h1 = TH1D("dy_h1", "",
174  profile_bins, dist_to_anode_low, dist_to_anode_up)
175  dy_h1.GetXaxis().SetTitle("distance from anode (cm)")
176  dy_h1.GetYaxis().SetTitle("y_flash - y_TPC (cm)")
177 
178  dz_spreads = [None] * x_bins
179  dz_means = [None] * x_bins
180  dz_h2 = TH2D("dz_h2", "#Delta z",
181  dist_to_anode_bins, dist_to_anode_low, dist_to_anode_up,
182  pset.dz_bins, pset.dz_low, pset.dz_up)
183  dz_h2.GetXaxis().SetTitle("distance from anode (cm)")
184  dz_h2.GetYaxis().SetTitle("z_flash - z_TPC (cm)")
185  dz_prof = TProfile("dz_prof", "Profile of dz_spreads in #Delta z",
186  profile_bins, dist_to_anode_low, dist_to_anode_up,
187  pset.dz_low*2.5, pset.dz_up*2.5, profile_option)
188  dz_prof.GetXaxis().SetTitle("distance from anode (cm)")
189  dz_prof.GetYaxis().SetTitle("z_flash - z_TPC (cm)")
190  dz_h1 = TH1D("dz_h1", "",
191  profile_bins, dist_to_anode_low, dist_to_anode_up)
192  dz_h1.GetXaxis().SetTitle("distance from anode (cm)")
193  dz_h1.GetYaxis().SetTitle("z_flash - z_TPC (cm)")
194 
195  rr_spreads = [None] * x_bins
196  rr_means = [None] * x_bins
197  rr_h2 = TH2D("rr_h2", "PE Spread",
198  dist_to_anode_bins, dist_to_anode_low, dist_to_anode_up,
199  pset.rr_bins, pset.rr_low, pset.rr_up)
200  rr_h2.GetXaxis().SetTitle("distance from anode (cm)")
201  rr_h2.GetYaxis().SetTitle("spread (cm)")
202  rr_prof = TProfile("rr_prof", "Profile of PE Spread",
203  profile_bins, dist_to_anode_low, dist_to_anode_up,
204  pset.rr_low, pset.rr_up, profile_option)
205  rr_prof.GetXaxis().SetTitle("distance from anode (cm)")
206  rr_prof.GetYaxis().SetTitle("spread (cm)")
207  rr_h1 = TH1D("rr_h1", "",
208  profile_bins, dist_to_anode_low, dist_to_anode_up)
209  rr_h1.GetXaxis().SetTitle("distance from anode (cm)")
210  rr_h1.GetYaxis().SetTitle("spread (cm)")
211 
212  ratio_spreads = [None] * x_bins
213  ratio_means = [None] * x_bins
214  ratio_h2 = TH2D("ratio_h2", "PE Ratio",
215  dist_to_anode_bins, dist_to_anode_low, dist_to_anode_up,
216  pset.ratio_bins, pset.ratio_low, pset.ratio_up)
217  ratio_h2.GetXaxis().SetTitle("distance from anode (cm)")
218  ratio_h2.GetYaxis().SetTitle("ratio")
219  ratio_prof = TProfile("ratio_prof", "Profile of PE Ratio",
220  profile_bins, dist_to_anode_low, dist_to_anode_up,
221  pset.ratio_low, pset.ratio_up, profile_option)
222  ratio_prof.GetXaxis().SetTitle("distance from anode (cm)")
223  ratio_prof.GetYaxis().SetTitle("ratio")
224  ratio_h1 = TH1D("ratio_h1", "",
225  profile_bins, dist_to_anode_low, dist_to_anode_up)
226  ratio_h1.GetXaxis().SetTitle("distance from anode (cm)")
227  ratio_h1.GetYaxis().SetTitle("ratio")
228 
229  unfolded_score_scatter = TH2D("unfolded_score_scatter", "Scatter plot of match scores",
230  2*dist_to_anode_bins, x_gl_low, x_gl_up,
231  pset.score_hist_bins, pset.score_hist_low, pset.score_hist_up*(3./5.))
232  unfolded_score_scatter.GetXaxis().SetTitle("X global (cm)")
233  unfolded_score_scatter.GetYaxis().SetTitle("match score (arbitrary)")
234  oldunfolded_score_scatter = TH2D("oldunfolded_score_scatter", "Scatter plot of match scores, old metrics",
235  2*dist_to_anode_bins, x_gl_low, x_gl_up,
236  pset.score_hist_bins, pset.score_hist_low, pset.score_hist_up*(3./5.))
237  oldunfolded_score_scatter.GetXaxis().SetTitle("X global (cm)")
238  oldunfolded_score_scatter.GetYaxis().SetTitle("match score (arbitrary)")
239  match_score_scatter = TH2D("match_score_scatter", "Scatter plot of match scores",
240  dist_to_anode_bins, dist_to_anode_low, dist_to_anode_up,
241  pset.score_hist_bins, pset.score_hist_low, pset.score_hist_up*(3./5.))
242  match_score_scatter.GetXaxis().SetTitle("distance from anode (cm)")
243  match_score_scatter.GetYaxis().SetTitle("match score (arbitrary)")
244  match_score_h1 = TH1D("match_score", "Match Score",
245  pset.score_hist_bins, pset.score_hist_low, pset.score_hist_up)
246  match_score_h1.GetXaxis().SetTitle("match score (arbitrary)")
247 
248  # fill rr_h2 and ratio_h2 first
249  for e in nuslice_tree:
250  if e.slices > e.true_nus: continue
251  qX = e.charge_x
252  rr_h2.Fill(qX, e.flash_rr)
253  rr_prof.Fill(qX, e.flash_rr)
254  ratio_h2.Fill(qX, e.flash_ratio)
255  ratio_prof.Fill(qX, e.flash_ratio)
256  # use rr_h2 and ratio_h2 to compute hypo_x
257  for e in nuslice_tree:
258  if e.slices > e.true_nus: continue
259  qX = e.charge_x
260  hypo_x = hypo_flashx_from_H2(e.flash_rr, rr_h2, e.flash_ratio, ratio_h2)
261  corr_flash_y = e.flash_yb - y_bias(e.y_skew, hypo_x, y_bias_slope)
262  corr_flash_z = e.flash_zb - z_bias(e.z_skew, hypo_x, z_bias_slope)
263 
264  dy_h2.Fill(qX, corr_flash_y - e.charge_y)
265  dy_prof.Fill(qX, corr_flash_y - e.charge_y)
266  dz_h2.Fill(qX, corr_flash_z - e.charge_z)
267  dz_prof.Fill(qX, corr_flash_z - e.charge_z)
268 
269 
270  # fill histograms for match score calculation from profile histograms
271  for ib in list(range(0, profile_bins)):
272  ibp = ib + 1
273  dy_h1.SetBinContent(ibp, dy_prof.GetBinContent(ibp))
274  dy_h1.SetBinError(ibp, dy_prof.GetBinError(ibp))
275  dy_means[int(ib)] = dy_prof.GetBinContent(ibp)
276  dy_spreads[int(ib)] = dy_prof.GetBinError(ibp)
277  dz_h1.SetBinContent(ibp, dz_prof.GetBinContent(ibp))
278  dz_h1.SetBinError(ibp, dz_prof.GetBinError(ibp))
279  dz_means[int(ib)] = dz_prof.GetBinContent(ibp)
280  dz_spreads[int(ib)] = dz_prof.GetBinError(ibp)
281  rr_h1.SetBinContent(ibp, rr_prof.GetBinContent(ibp))
282  rr_h1.SetBinError(ibp, rr_prof.GetBinError(ibp))
283  rr_means[int(ib)] = rr_prof.GetBinContent(ibp)
284  rr_spreads[int(ib)] = rr_prof.GetBinError(ibp)
285  ratio_h1.SetBinContent(ibp, ratio_prof.GetBinContent(ibp))
286  ratio_h1.SetBinError(ibp, ratio_prof.GetBinError(ibp))
287  ratio_means[int(ib)] = ratio_prof.GetBinContent(ibp)
288  ratio_spreads[int(ib)] = ratio_prof.GetBinError(ibp)
289 
290  for e in nuslice_tree:
291  if e.slices > e.true_nus: continue
292  qX = e.charge_x
293  qXGl = e.charge_x_gl
294  # calculate match score
295  isl = int(qX/xbin_width)
296  score = 0.
297  if dy_spreads[isl] <= 1.e-8:
298  print("Warning zero spread.\n",
299  f"qX: {qX}. isl: {isl}. dy_spreads[isl]: {dy_spreads[isl]} ")
300  dy_spreads[isl] = dy_spreads[isl+1]
301  if dz_spreads[isl] <= 1.e-8:
302  print("Warning zero spread.\n",
303  f"qX: {qX}. isl: {isl}. dz_spreads[isl]: {dz_spreads[isl]} ")
304  dz_spreads[isl] = dz_spreads[isl+1]
305  if rr_spreads[isl] <= 1.e-8:
306  print("Warning zero spread.\n",
307  f"qX: {qX}. isl: {isl}. rr_spreads[isl]: {rr_spreads[isl]} ")
308  rr_spreads[isl] = rr_spreads[isl+1]
309  if ratio_spreads[isl] <= 1.e-8:
310  print("Warning zero spread.\n",
311  f"qX: {qX}. isl: {isl}. ratio_spreads[isl]: {ratio_spreads[isl]} ")
312  ratio_spreads[isl] = ratio_spreads[isl+1]
313  # ratio_spreads[isl] = ratio_spreads[isl-1]
314  hypo_x = hypo_flashx_from_H2(e.flash_rr, rr_h2, e.flash_ratio, ratio_h2)
315  corr_flash_y = e.flash_yb - y_bias(e.y_skew, hypo_x, y_bias_slope)
316  corr_flash_z = e.flash_zb - z_bias(e.z_skew, hypo_x, z_bias_slope)
317 
318  score += abs(abs(corr_flash_y-e.charge_y) - dy_means[isl])/dy_spreads[isl]
319  score += abs(abs(corr_flash_z-e.charge_z) - dz_means[isl])/dz_spreads[isl]
320  score += abs(e.flash_rr-rr_means[isl])/rr_spreads[isl]
321  if (detector == "sbnd" and pset.UseUncoatedPMT) or \
322  (detector == "icarus" and pset.UseOppVolMetric) :
323  score += abs(e.flash_ratio-ratio_means[isl])/ratio_spreads[isl]
324 
325  oldunfolded_score_scatter.Fill(qXGl, e.score)
326  unfolded_score_scatter.Fill(qXGl, score)
327  match_score_scatter.Fill(qX, score)
328  match_score_h1.Fill(score)
329 
330  metrics_filename = 'fm_metrics_' + detector + '.root'
331  hfile = gROOT.FindObject(metrics_filename)
332  if hfile:
333  hfile.Close()
334  hfile = TFile(metrics_filename, 'RECREATE',
335  'Simple flash matching metrics for ' + detector.upper())
336 
337  dy_h2.Write()
338  dy_prof.Write()
339  dy_h1.Write()
340  dz_h2.Write()
341  dz_prof.Write()
342  dz_h1.Write()
343  rr_h2.Write()
344  rr_prof.Write()
345  rr_h1.Write()
346 
347  errors = [1, 0, -1]
348  fitname_suffix = ["_h", "_m", "_l"]
349  rr_fit_funcs = []
350  for e,suf in zip(errors, fitname_suffix):
351  yvals = [a + e*b for a, b in zip(rr_means, rr_spreads)]
352  graph = TGraph(x_bins,
353  array('f', xvals), array('f', yvals))
354  name = "rr_fit" + suf
355  print("Fitting: ", name)
356  f = TF1(name, pset.rr_TF1_fit)
357  graph.Fit(f)
358  f.Write()
359  rr_fit_funcs.append(f)
360  ratio_h2.Write()
361  ratio_prof.Write()
362  ratio_h1.Write()
363  ratio_fit_funcs = []
364  for e,suf in zip(errors, fitname_suffix):
365  yvals = [a + e*b for a, b in zip(ratio_means, ratio_spreads)]
366  graph = TGraph(x_bins,
367  array('f', xvals), array('f', yvals))
368  name = "ratio_fit" + suf
369  print("Fitting: ", name)
370  f = TF1(name, pset.ratio_TF1_fit)
371  graph.Fit(f)
372  f.Write()
373  ratio_fit_funcs.append(f)
374  match_score_scatter.Write()
375  oldunfolded_score_scatter.Write()
376  unfolded_score_scatter.Write()
377  match_score_h1.Write()
378  hfile.Close()
379 
380  canv = TCanvas("canv")
381 
382  dy_h2.Draw()
383  crosses = TGraphErrors(x_bins,
384  array('f', xvals), array('f', dy_means),
385  array('f', xerrs), array('f', dy_spreads))
386  crosses.SetLineColor(ROOT.kAzure+9)
387  crosses.SetLineWidth(3)
388  crosses.Draw("Psame")
389  canv.Print("dy.pdf")
390  canv.Update()
391 
392  dz_h2.Draw()
393  crosses = TGraphErrors(x_bins,
394  array('f', xvals), array('f', dz_means),
395  array('f', xerrs), array('f', dz_spreads))
396  crosses.SetLineColor(ROOT.kAzure+9)
397  crosses.SetLineWidth(3)
398  crosses.Draw("Psame")
399  canv.Print("dz.pdf")
400  canv.Update()
401 
402  rr_h2.Draw()
403  crosses = TGraphErrors(x_bins,
404  array('f', xvals), array('f', rr_means),
405  array('f', xerrs), array('f', rr_spreads))
406  crosses.SetLineColor(ROOT.kAzure+9)
407  crosses.SetLineWidth(3)
408  crosses.Draw("Psame")
409  for f in rr_fit_funcs:
410  f.SetLineColor(ROOT.kOrange+7)
411  f.DrawF1(0., drift_distance, "lsame")
412  canv.Print("rr.pdf")
413  canv.Update()
414 
415  ratio_h2.Draw()
416  crosses = TGraphErrors(x_bins,
417  array('f', xvals), array('f', ratio_means),
418  array('f', xerrs), array('f', ratio_spreads))
419  crosses.SetLineColor(ROOT.kAzure+9)
420  crosses.SetLineWidth(3)
421  crosses.Draw("Psame")
422  for f in ratio_fit_funcs:
423  f.SetLineColor(ROOT.kOrange+7)
424  f.DrawF1(0., drift_distance, "lsame")
425  canv.Print("ratio.pdf")
426  canv.Update()
427 
428  oldunfolded_score_scatter.Draw()
429  canv.Print("oldunfolded_score_scatter.pdf")
430  canv.Update()
431 
432  unfolded_score_scatter.Draw()
433  canv.Print("unfolded_score_scatter.pdf")
434  canv.Update()
435 
436  match_score_scatter.Draw()
437  canv.Print("match_score_scatter.pdf")
438  canv.Update()
439 
440  match_score_h1.Draw()
441  canv.Print("match_score.pdf")
442  canv.Update()
443  sleep(20)
444 
445 # Main program.
446 def main():
447 
448  # Parse arguments.
449  parser = argparse.ArgumentParser(prog='generate_simple_weighted_template.py')
450  parser.add_argument('file')
451  # parser.add_argument('--help', '-h',
452  # action='store_true',
453  # help='help flag' )
454  group = parser.add_mutually_exclusive_group(required=True)
455  group.add_argument('--sbnd', action='store_true', help='Generate metrics for SBND')
456  group.add_argument('--icarus', action='store_true', help='Generate metrics for ICARUS')
457  args = parser.parse_args()
458 
459  # if args.help:
460  # print("To run do:\n"/
461  # "generate_simple_weighted_template.py file.root\n"/
462  # "where file.root has a fmatch/nuslicetree")
463  # return(0)
464  if args.sbnd :
465  print("Generate metrics for SBND")
466  elif args.icarus :
467  print("Generate metrics for ICARUS")
468 
469  if not larbatch_posix.exists(args.file):
470  print('Input file %s does not exist.' % args.file)
471  return 1
472 
473  print('\nOpening %s' % args.file)
474  rootfile = TFile.Open(args.file)
475  if not rootfile.IsOpen() or rootfile.IsZombie():
476  print('Failed to open %s' % args.file)
477  return 1
478  global detector
479  if args.sbnd:
480  fcl_params = fhicl.make_pset('flashmatch_sbnd.fcl')
481  pset = dotDict(fcl_params['sbnd_simple_flashmatch'])
482  detector = "sbnd"
483  dir = rootfile.Get(args.file+":/fmatch")
484  nuslice_tree = dir.Get("nuslicetree") # , nuslice_tree)
485  # nuslice_tree.Print()
486  elif args.icarus:
487  fcl_params = fhicl.make_pset('flashmatch_simple_icarus.fcl')
488  # TODO: add option to use cryo 0 and cryo 1
489  pset = dotDict(fcl_params['icarus_simple_flashmatch_0'])
490  detector = "icarus"
491  dir = rootfile.Get(args.file+":/fmatchCryo0")
492  nuslice_tree = dir.Get("nuslicetree") # , nuslice_tree)
493  # nuslice_tree.Print()
494 
495  generator(nuslice_tree, rootfile, pset)
496 
497 
498 if __name__ == '__main__':
499  sys.exit(main())
do one_file $F done echo for F in find $TOP name CMakeLists txt print
T abs(T value)
auto zip(Iterables &&...iterables)
Range-for loop helper iterating across many collections at the same time.
Definition: zip.h:295
list
Definition: file_to_url.sh:28