diff --git a/tifUtil/JMTROOTTools.py b/tifUtil/JMTROOTTools.py
new file mode 100644
index 0000000..7c42679
--- /dev/null
+++ b/tifUtil/JMTROOTTools.py
@@ -0,0 +1,308 @@
+import sys, os, tempfile
+from array import array
+
+if os.environ.has_key('JMT_ROOTTOOLS_NOBATCHMODE'):
+ import ROOT
+else:
+ sys.argv.append('-b') # Start ROOT in batch mode;
+ import ROOT; ROOT.TCanvas # make sure libGui gets initialized while '-b' is specified;
+ sys.argv.remove('-b') # and don't mess up sys.argv.
+
+# don't import this until after the above since it does a from ROOT import *
+import moduleSummaryPlottingTools as FNAL
+
+class plot_saver:
+ i = 0
+
+ def __init__(self, plot_dir=None, html=True, log=True, root=True, pdf=False, pdf_log=False, C=False, C_log=False, size=(820,630), per_page=-1, canvas_margins=None):
+ self.c = ROOT.TCanvas('c%i' % plot_saver.i, '', *size)
+ if canvas_margins is not None:
+ if type(canvas_margins) == int or type(canvas_margins) == float:
+ top, bottom, left, right = tuple(canvas_margins for x in xrange(4))
+ else:
+ top, bottom, left, right = canvas_margins
+ self.c.SetTopMargin(top)
+ self.c.SetBottomMargin(bottom)
+ self.c.SetLeftMargin(left)
+ self.c.SetRightMargin(right)
+ plot_saver.i += 1
+ self.saved = []
+ self.html = html
+ self.set_plot_dir(plot_dir)
+ self.log = log
+ self.root = root
+ self.pdf = pdf
+ self.pdf_log = pdf_log
+ self.C = C
+ self.C_log = C_log
+ self.per_page = per_page
+
+ def __del__(self):
+ self.write_index()
+
+ def update_canvas(self):
+ self.c.Update()
+
+ def anchor_name(self, fn):
+ return os.path.splitext(os.path.basename(fn))[0].replace('.', '_').replace('/', '_')
+
+ def write_index(self):
+ if not self.saved or not self.html:
+ return
+ html = open(os.path.join(self.plot_dir, 'index.html'), 'wt')
+ if self.per_page > 0:
+ nsaved = len(self.saved)
+ ndxs = range(0, nsaved, self.per_page)
+ npages = len(ndxs)
+ for page, ndx in enumerate(ndxs):
+ self.write_index_page(self.saved[ndx:ndx+self.per_page], page, npages)
+ else:
+ self.write_index_page(self.saved, 0, 1)
+
+ def write_index_page(self, saved, page, num_pages):
+ def html_fn(page):
+ if page == 0:
+ return 'index.html'
+ else:
+ return 'index_%i.html' % page
+ return
+ html = open(os.path.join(self.plot_dir, html_fn(page)), 'wt')
+ html.write('
\n')
+ def write_pages_line():
+ html.write('pages: ')
+ for i in xrange(num_pages):
+ if i == page:
+ html.write('%i ' % i)
+ else:
+ html.write('%i ' % (html_fn(i), i))
+ html.write('\n')
+ if num_pages > 1:
+ write_pages_line()
+ html.write('.. (parent directory)\n')
+ for i, save in enumerate(saved):
+ if type(save) == str:
+ # this is just a directory link
+ html.write('%10i%32s%s\n' % (save, i, 'change directory: ', save))
+ continue
+
+ fn, log, root, pdf, pdf_log, C, C_log = save
+
+ bn = os.path.basename(fn)
+ html.write('%10i ' % (self.anchor_name(fn), i))
+ if log:
+ html.write(' log' % os.path.basename(log))
+ else:
+ html.write(' ')
+ if root:
+ html.write(' root' % os.path.basename(root))
+ else:
+ html.write(' ')
+ if pdf:
+ html.write(' pdf' % os.path.basename(pdf))
+ else:
+ html.write(' ')
+ if pdf_log:
+ html.write(' pdf_log' % os.path.basename(pdf_log))
+ else:
+ html.write(' ')
+ if C:
+ html.write(' C' % os.path.basename(C))
+ else:
+ html.write(' ')
+ if C_log:
+ html.write(' C_log' % os.path.basename(C_log))
+ else:
+ html.write(' ')
+ html.write(' %s' % (bn, bn))
+ html.write('\n')
+ html.write('
')
+ for i, save in enumerate(saved):
+ if type(save) == str:
+ continue # skip dir entries
+ fn, log, root, pdf, pdf_log, C, C_log = save
+ bn = os.path.basename(fn)
+ rootlink = ', root' % os.path.basename(root) if root else ''
+ html.write('
\n' % (self.anchor_name(fn), self.anchor_name(fn), bn.replace('.png', ''), rootlink))
+ if log:
+ html.write('

\n' % (bn, os.path.basename(log)))
+ else:
+ html.write('
\n' % bn)
+ if num_pages > 1:
+ write_pages_line()
+ html.write('\n')
+
+ def set_plot_dir(self, plot_dir):
+ self.write_index()
+ self.saved = []
+ if plot_dir is not None and '~' in plot_dir:
+ plot_dir = os.path.expanduser(plot_dir)
+ self.plot_dir = plot_dir
+ if plot_dir is not None:
+ os.system('mkdir -p %s' % self.plot_dir)
+
+ def save_dir(self, n):
+ if self.plot_dir is None:
+ raise ValueError('save_dir called before plot_dir set!')
+ self.saved.append(n)
+
+ def save(self, n, log=None, root=None, pdf=None, pdf_log=None, C=None, C_log=None, logz=None, other_c=None):
+ can = self.c if other_c is None else other_c
+
+ if logz:
+ logfcn = can.SetLogz
+ else:
+ logfcn = can.SetLogy
+
+ log = self.log if log is None else log
+ root = self.root if root is None else root
+ pdf = self.pdf if pdf is None else pdf
+ pdf_log = self.pdf_log if pdf_log is None else pdf_log
+ C = self.C if C is None else C
+ C_log = self.C_log if C_log is None else C_log
+
+ if self.plot_dir is None:
+ raise ValueError('save called before plot_dir set!')
+ can.SetLogy(0)
+ fn = os.path.join(self.plot_dir, n + '.png')
+ can.SaveAs(fn)
+ if root:
+ root = os.path.join(self.plot_dir, n + '.root')
+ can.SaveAs(root)
+ if log:
+ logfcn(1)
+ log = os.path.join(self.plot_dir, n + '_log.png')
+ can.SaveAs(log)
+ logfcn(0)
+ if pdf:
+ pdf = os.path.join(self.plot_dir, n + '.pdf')
+ can.SaveAs(pdf)
+ if pdf_log:
+ logfcn(1)
+ pdf_log = os.path.join(self.plot_dir, n + '_log.pdf')
+ can.SaveAs(pdf_log)
+ logfcn(0)
+ if C:
+ C = os.path.join(self.plot_dir, n + '.C')
+ can.SaveAs(C_fn)
+ if C_log:
+ logfcn(1)
+ C_log = os.path.join(self.plot_dir, n + '_log.C')
+ can.SaveAs(C_log)
+ logfcn(0)
+ self.saved.append((fn, log, root, pdf, pdf_log, C, C_log))
+
+def set_style(light=False, date_pages=False):
+ ROOT.gStyle.SetPadTickX(1)
+ ROOT.gStyle.SetPadTickY(1)
+ ROOT.gErrorIgnoreLevel = 1001 # Suppress TCanvas::SaveAs messages.
+ if not light:
+ ROOT.gROOT.SetStyle('Plain')
+ ROOT.gStyle.SetFillColor(0)
+ if date_pages:
+ ROOT.gStyle.SetOptDate()
+ ROOT.gStyle.SetOptStat(1222222)
+ ROOT.gStyle.SetOptFit(2222)
+ ROOT.gStyle.SetPadTickX(1)
+ ROOT.gStyle.SetPadTickY(1)
+ ROOT.gStyle.SetMarkerSize(.1)
+ ROOT.gStyle.SetMarkerStyle(8)
+ ROOT.gStyle.SetGridStyle(3)
+ ROOT.gStyle.SetStatW(0.25)
+ ROOT.gStyle.SetStatFormat('6.4g')
+ ROOT.gStyle.SetPalette(1)
+ ROOT.gStyle.SetTitleFont(42, 'XYZ')
+ ROOT.gStyle.SetLabelFont(42, 'XYZ')
+ ROOT.gStyle.SetStatFont(42)
+ ROOT.gStyle.SetLegendFont(42)
+
+def differentiate_stat_box(hist, movement=1, new_color=None, new_size=None, color_from_hist=True, offset=None):
+ """Move hist's stat box and change its line/text color. If
+ movement is just an int, that number specifies how many units to
+ move the box downward. If it is a 2-tuple of ints (m,n), the stat
+ box will be moved to the left m units and down n units. A unit is
+ the width or height of the stat box.
+ Call TCanvas::Update first (and use TH1::Draw('sames') if
+ appropriate) or else the stat box will not exist."""
+
+ s = hist.FindObject('stats')
+
+ if color_from_hist:
+ new_color = hist.GetLineColor()
+
+ if new_color is not None:
+ s.SetTextColor(new_color)
+ s.SetLineColor(new_color)
+
+ if type(movement) == int:
+ movement = (0,movement)
+ m,n = movement
+
+ x1,x2 = s.GetX1NDC(), s.GetX2NDC()
+ y1,y2 = s.GetY1NDC(), s.GetY2NDC()
+
+ if new_size is not None:
+ x1 = x2 - new_size[0]
+ y1 = y2 - new_size[1]
+
+ if offset is None:
+ ox, oy = 0, 0
+ else:
+ ox, oy = offset
+
+ s.SetX1NDC(x1 - (x2-x1)*m + ox)
+ s.SetX2NDC(x2 - (x2-x1)*m + ox)
+ s.SetY1NDC(y1 - (y2-y1)*n + oy)
+ s.SetY2NDC(y2 - (y2-y1)*n + oy)
+
+def flat_to_module(label, module_name, lists, xform=None):
+ ''' Take a list of 16 lists, each of which has 4160 values, one
+ per pixel in row major format, and make TH2Fs suitable for shoving
+ into the fnal_pixel_plot function below.
+
+ label is an extra tag for the histograms so they can be unique
+
+ xform is an optional transformation function of the form
+ xform(label, module_name, rocnum, col, row, val) -> new_val.
+
+ Values can be None if skipping desired.
+ '''
+
+ assert len(lists) == 16
+ hs = []
+ for iroc,l in enumerate(lists):
+ roc = module_name + '_ROC' + str(iroc)
+ h = ROOT.TH2F('h_%s_%s' % (label, roc), label + ' : ' + roc, 52, 0, 52, 80, 0, 80)
+ h.SetStats(0)
+ hs.append(h)
+ for i,val in enumerate(l):
+ col = i / 80
+ row = i % 80
+ if xform is not None:
+ val = xform(label, module_name, iroc, col, row, val)
+ if val is not None:
+ h.SetBinContent(col+1, row+1, float(val))
+ return hs
+
+def fnal_pixel_plot(hs, module_name, title, z_range=None, existing_c=None):
+ h = FNAL.makeMergedPlot(hs, 'pos')
+ if z_range == 'auto':
+ z_range = FNAL.findZRange(hs)
+ if z_range is not None:
+ FNAL.setZRange(h, z_range)
+
+ fc = FNAL.setupSummaryCanvas(h, moduleName=module_name)
+ if existing_c is not None:
+ existing_c.cd()
+ existing_c.Clear()
+ fc.DrawClonePad()
+
+ pt = ROOT.TPaveText(-100,405,1395,432)
+ pt.AddText(title)
+ pt.SetTextAlign(12)
+ pt.SetTextFont(42)
+ pt.SetFillColor(0)
+ pt.SetBorderSize(0)
+ pt.SetFillStyle(0)
+ pt.Draw()
+
+ return h, fc, pt
diff --git a/tifUtil/JMTTools.py b/tifUtil/JMTTools.py
new file mode 100644
index 0000000..f430628
--- /dev/null
+++ b/tifUtil/JMTTools.py
@@ -0,0 +1,499 @@
+import sys, os, cPickle
+from array import array
+from glob import glob
+from collections import defaultdict
+from pprint import pprint
+from itertools import izip
+
+BUILD_HOME = os.environ['BUILD_HOME']
+POS_OUTPUT_DIRS = os.environ['POS_OUTPUT_DIRS']
+PIXELCONFIGURATIONBASE = os.environ['PIXELCONFIGURATIONBASE']
+
+def mkdir_p(d):
+ try:
+ os.mkdir(d)
+ except OSError:
+ pass
+
+def countem(l):
+ d = defaultdict(int)
+ for x in l:
+ d[x] += 1
+ return dict(d)
+
+def config_fn(x):
+ return os.path.join(PIXELCONFIGURATIONBASE, x)
+
+def config_key_fn(x, t=None):
+ if os.path.isfile(x):
+ return x
+ cfg_fn = config_fn(x)
+ if os.path.isfile(cfg_fn):
+ return cfg_fn
+
+def new_config_key(x, min_key=0):
+ new_key = min_key
+ d = None
+ while 1:
+ d = config_fn(os.path.join(x, str(new_key)))
+ if os.path.isdir(d):
+ new_key += 1
+ else:
+ break
+ return new_key, d
+
+def run_from_argv():
+ run = None
+ for x in sys.argv:
+ try:
+ run = int(x)
+ break
+ except ValueError:
+ pass
+ if run is None:
+ cwd = os.getcwd()
+ cwd = os.path.basename(cwd)
+ if cwd.startswith('Run_'):
+ run = int(cwd.split('Run_')[1])
+ else:
+ raise ValueError('no number in argv and cannot grok %s' % os.getcwd())
+ return run
+
+def run_dir(run):
+ run_thousand = run / 1000 * 1000
+ return os.path.join(POS_OUTPUT_DIRS, 'Run_%i' % run_thousand, 'Run_%i' % run)
+
+def run_dir_from_argv():
+ return run_dir(run_from_argv())
+
+def run_fn(run, fn):
+ return os.path.join(run_dir(run), fn)
+
+def run_fn_from_argv(fn):
+ return os.path.join(run_dir_from_argv(), fn)
+
+class calib_dat:
+ def __init__(self, run_or_fn):
+ if type(run_or_fn) == int:
+ run = run_or_fn
+ fn = os.path.join(run_dir(run), 'calib.dat')
+ else:
+ run = None
+ fn = run_or_fn
+
+ if not os.path.isfile(fn):
+ raise IOError('no file found at %s' % fn)
+
+ tokens = open(fn).read().strip().split()
+ assert tokens[0] == 'Mode:'
+ self.mode = tokens[1]
+
+ self.parameters = {}
+ if 'Parameters:' in tokens:
+ partoks = tokens[tokens.index('Parameters:') + 1 : tokens.index('Rows:')]
+ assert len(partoks) % 2 == 0
+ self.parameters = dict((partoks[i],partoks[i+1]) for i in xrange(0, len(partoks), 2))
+
+ def group(seq, sep, conv=None):
+ g = []
+ sep_isseq = type(sep) in (tuple,list)
+ for el in seq:
+ if (not sep_isseq and el == sep) or (sep_isseq and el in sep):
+ yield g
+ g = []
+ else:
+ g.append(el if conv is None else conv(el))
+ yield g
+
+ def intable(x):
+ try:
+ int(x)
+ except ValueError:
+ return False
+ return True
+
+ rind = tokens.index('Rows:')
+ cind = tokens.index('Cols:')
+ for ind, token in enumerate(tokens[cind+1:]):
+ if token != '|' and not intable(token):
+ cindlast = cind + ind
+ break
+ self.row_groups = list(group(tokens[rind+1:cind], '|', int))
+ self.col_groups = list(group(tokens[cind+1:cindlast+1], '|', int))
+
+ self.pixels = [(r,c) for rg in self.row_groups for r in rg for cg in self.col_groups for c in cg]
+
+ nind = tokens.index('Repeat:')
+ self.ntrigs = int(tokens[nind + 1])
+
+ self.vcalhigh = True
+ if 'VcalLow' in tokens:
+ self.vcalhigh = False
+
+ def lfind(l, i):
+ try:
+ return l.index(i)
+ except ValueError:
+ return 9999999
+
+ self.scans = []
+ sind = min(lfind(tokens, 'Scan:'), lfind(tokens, 'ScanValues:'))
+ if sind != 9999999:
+ self.scans = list(group(tokens[sind+1:nind], ('Scan:', 'ScanValues:')))
+
+ self.rocs = tokens[tokens.index('ToCalibrate:')+1:]
+
+class detconfig_dat:
+ def __init__(self, run_or_fn):
+ if type(run_or_fn) == int:
+ run = run_or_fn
+ fn = os.path.join(run_dir(run), 'detectconfig.dat')
+ else:
+ run = None
+ fn = run_or_fn
+
+ if not os.path.isfile(fn):
+ raise IOError('no file found at %s' % fn)
+
+ lines = [x.strip() for x in open(fn).read().split('\n') if x.strip()]
+ assert lines[0] == 'Rocs:'
+
+ self.rocs = {
+ 'all': [],
+ 'noqual': [],
+ 'qual': [],
+ }
+
+ for line in lines[1:]:
+ line = line.split()
+ self.rocs['all'].append(line[0])
+ if len(line) > 1:
+ self.rocs['qual'].append((line[0], tuple(line[1:])))
+ else:
+ self.rocs['noqual'].append(line[0])
+
+class TrimResult:
+ def __init__(self, s):
+ s = s.split()
+ assert len(s) == 9
+ dummy, self.roc, r, c, noise, thresh, istat, chi2, prob = s
+ self.row = int(r)
+ self.col = int(c)
+ self.noise = float(noise)
+ self.thresh = float(thresh)
+ self.istat = int(istat)
+ self.chi2 = float(chi2)
+ self.prob = float(prob)
+
+def dec(dcol, pxl):
+ dcol = dcol & 0x1f
+ pxl = pxl & 0xff
+ col = dcol*2 + pxl%2
+ row = 80 - pxl/2
+ return col, row
+
+class configurations_txt:
+ def __init__(self):
+ fn = os.path.join(PIXELCONFIGURATIONBASE, 'configurations.txt')
+ self.d = d = {}
+ e = None
+ key = None
+ for line in open(fn):
+ line = line.strip()
+ if line:
+ if line.startswith('key'):
+ if e:
+ d[key] = e
+ e = {}
+ key = int(line.split()[-1])
+ else:
+ line = line.split()
+ assert len(line) == 2
+ e[line[0]] = line[1]
+ if e:
+ d[key] = e
+
+ def __getitem__(self, key):
+ return self.d[key]
+
+ def compare(self, k0, k1):
+ #d0 = set(self.d[k0].items())
+ #d1 = set(self.d[k1].items())
+ #in_k0_not_k1 = d0 - d1
+ #in_k1_not_k0 = d1 - d0
+ #if in_k0_not_k1: print 'in', k0, 'not', k1, in_k0_not_k1
+ #if in_k1_not_k0: print 'in', k1, 'not', k0, in_k1_not_k0
+ #return not in_k0_not_k1 and not in_k1_not_k0
+
+ d0 = self.d[k0]
+ d1 = self.d[k1]
+ if d0 == d1:
+ return True
+ sk0 = set(d0.keys())
+ sk1 = set(d1.keys())
+ print '%-15s%15s%15s' % ('diffs:', k0, k1)
+ for sk in sorted(sk0 | sk1):
+ v0 = d0.get(sk, '')
+ v1 = d1.get(sk, '')
+ if v0 != v1:
+ print '%15s%15s%15s' % (sk, v0, v1)
+ return False
+
+def aliases_txt():
+ cd, vd = [], []
+
+ fn = os.path.join(PIXELCONFIGURATIONBASE, 'aliases.txt')
+ lines = open(fn).readlines()
+ assert lines[0].strip() == 'ConfigurationAliases'
+ lines.pop(0)
+
+ d = cd
+ for line in lines:
+ line = line.strip()
+ if line == 'VersionAliases':
+ d = vd
+ continue
+ line = line.split()
+ assert line[-1] == ';'
+ d.append((line[0], int(line[1]), ' '.join(line[2:-1])))
+
+ return cd, vd
+
+class dac_dat:
+ DACS = ['Vdd', 'Vana', 'Vsh', 'Vcomp', 'VwllPr', 'VwllSh', 'VHldDel', 'Vtrim', 'VcThr', 'VIbias_bus', 'PHOffset', 'Vcomp_ADC', 'PHScale', 'VIColOr', 'Vcal', 'CalDel', 'TempRange', 'WBC', 'ChipContReg', 'Readback']
+
+ def __init__(self, fn):
+ self.fn = fn
+ self.basefn = os.path.basename(fn)
+ self.dacs_by_roc = {}
+ this_roc = None
+ these_dacs = {}
+ def add():
+ global these_dacs, this_roc
+ for line in open(fn):
+ if line.startswith('ROC:'):
+ if these_dacs:
+ assert this_roc is not None
+ assert set(these_dacs.keys()) == set(self.DACS)
+ self.dacs_by_roc[this_roc] = these_dacs
+ this_roc = line.split()[-1]
+ assert '_ROC' in this_roc
+ these_dacs = {}
+ else:
+ dacname, dacval = line.split()
+ assert dacname.endswith(':')
+ dacname = dacname.replace(':', '')
+ dacval = int(dacval)
+ these_dacs[dacname] = dacval
+ assert this_roc is not None
+ assert set(these_dacs.keys()) == set(self.DACS)
+ self.dacs_by_roc[this_roc] = these_dacs
+ assert len(self.dacs_by_roc) == 16
+
+ def write(self, f):
+ if type(f) == str:
+ fn = f
+ f = open(fn, 'wt')
+ elif type(f) == int:
+ fn = os.path.join(PIXELCONFIGURATIONBASE, 'dac/' + str(f) + '/' + self.basefn)
+ f = open(fn, 'wt')
+ elif not hasattr(f, 'write'):
+ raise TypeError("can't handle f %r" % f)
+
+ rocs = self.dacs_by_roc.keys()
+ rocs.sort(key=lambda x: int(x.split('_ROC')[1]))
+ for roc in rocs:
+ f.write('ROC: %s\n' % roc)
+ dacs = self.dacs_by_roc[roc]
+ for dac in self.DACS:
+ f.write((dac + ':').ljust(15))
+ f.write('%i\n' % dacs[dac])
+
+class portcardmap_dat:
+ def __init__(self, fn):
+ self.fn = fn
+ if os.path.isdir(fn):
+ fn = os.path.join(fn, 'portcardmap.dat')
+ f = open(fn)
+ self.l = []
+ self.m = defaultdict(list)
+ self.p = {}
+ for line in f:
+ line = line.strip()
+ if not line or line.startswith('#'):
+ continue
+ line = line.split()
+ if len(line) == 3:
+ pc, module, ch = line
+ else:
+ pc, module, aorb, ch = line
+ ch = int(ch)
+ self.l.append((pc, module, ch))
+ self.m[pc].append((module, ch))
+ self.p[module] = (pc, ch)
+ self.l.sort(key=lambda x: (x[0], x[2]))
+
+class mask_dat:
+ def __init__(self, fn):
+ self.m = {}
+ self.fn = fn
+ if os.path.isdir(fn):
+ fn = os.path.join(fn, 'portcardmap.dat')
+ f = open(fn)
+ lines = [l.strip() for l in f.readlines() if l.strip()]
+ assert len(lines) == 16*(52 + 1)
+ self.module = None
+ for roc in xrange(16):
+ rocline = lines[0]
+ masklines = lines[1:53]
+ lines = lines[53:]
+
+ assert rocline.startswith('ROC:')
+ roc = rocline.split()[-1]
+ module, roc = roc.split('_ROC')
+ roc = int(roc)
+ if self.module is not None:
+ assert module == self.module
+ else:
+ self.module = module
+ self.m[roc] = [None]*52
+
+ for col, maskline in enumerate(masklines):
+ assert maskline.startswith('col%02i:' % col)
+ maskbits = maskline.split()[-1]
+ assert len(maskbits) == 80
+ self.m[roc][col] = list(maskbits)
+
+ def set(self, val, roc, **args):
+ assert str(val) in '10'
+
+ a = set(args.keys())
+ if a == set(('col', 'row')):
+ col, row = args['col'], args['row']
+ elif a == set(('dc', 'pxl')):
+ col, row = dec(args['dc'], args['pxl'])
+ else:
+ raise ValueError('args have to be col&row or dc&pxl')
+
+ assert 0 <= col <= 51 and 0 <= row <= 79
+ self.m[roc][col][row] = str(val)
+
+ def write(self, fn):
+ f = open(fn, 'wt')
+ for roc in xrange(16):
+ f.write('ROC: ' + self.module + '_ROC' + str(roc) + '\n')
+ for col in xrange(52):
+ f.write('col%02i: ' % col + ''.join(self.m[roc][col]) + '\n')
+ f.close()
+
+class translation_dat:
+ class entry:
+ def __init__(self, line):
+ line = line.split()
+ assert len(line) == 11
+ self.roc_name = line[0]
+ self.module, self.roc = self.roc_name.split('_ROC')
+ assert int(self.roc) % 8 == int(line[-1])
+ self.roc = int(self.roc)
+ self.aorb = line[1]
+ self.fec, self.mfec, self.mfecch, self.hubid, self.port, self.rocid, self.fedid, self.fedch = [int(x) for x in line[2:-1]]
+
+ def __init__(self, fn):
+ self.l = []
+ for line in open(fn):
+ line = line.strip()
+ if line.startswith('#') or not line:
+ continue
+ self.l.append(translation_dat.entry(line))
+
+ def module_name_from_fed_ch(self, fedid, fedch):
+ for x in self.l:
+ if x.fedid == fedid and x.fedch == fedch:
+ return x.module
+
+class trim_dat:
+ class entry:
+ def __init__(self, sg, th, istat, chi2, prob):
+ self.sg = sg
+ self.th = th
+ self.istat = istat
+ self.chi2 = chi2
+ self.prob = prob
+
+ def __init__(self, fn):
+ self.ls = defaultdict(lambda: [0]*4160)
+ self.seens = defaultdict(set)
+ for iline, line in enumerate(open(fn)):
+ line = line.strip()
+ if not line:
+ continue
+
+ line = line.split()
+ assert len(line) == 9
+ #assert line[0] == '[PixelSCurveHistoManager::fit()]RocName='
+ sanity = line[1].startswith('FPix_') or line[1].startswith('Pilt_')
+ assert sanity
+ roc = line[1]
+ seen = self.seens[roc]
+ l = self.ls[roc]
+ r, c = int(line[2]), int(line[3])
+ assert 0 <= c <= 51
+ assert 0 <= r <= 79
+ assert (c,r) not in seen
+ seen.add((c,r))
+ sg, th = float(line[4]), float(line[5])
+ #assert 0 <= th
+ assert 0 <= sg
+ istat, chi2, prob = float(line[6]), float(line[7]), float(line[8])
+ assert istat in [0,1,2,3]
+ assert 0 <= chi2
+ assert 0 <= prob
+ l[c*80 + r] = trim_dat.entry(sg, th, istat, chi2, prob)
+
+ def update(self, other):
+ for roc, l in other.ls.iteritems():
+ for i, x in enumerate(l):
+ if x != 0:
+ self.ls[roc][i] = x
+
+ def write(self, fn):
+ f = open(fn, 'wt')
+ for roc in sorted(self.ls.keys()):
+ for i in xrange(4160):
+ col = i / 80
+ row = i % 80
+ e = self.ls[roc][i]
+ if e != 0:
+ f.write('X %(roc)s %(row)s %(col)s ' % locals())
+ f.write('%.6f %.6f %i %.2f %.2f\n' % (e.sg, e.th, e.istat, e.chi2, e.prob))
+
+def merge_trim_dats(fns, new_fn=None):
+ # assemble a trim_dat from the fns, letting later fns override
+ # results for earlier fns
+ print fns[0]
+ td_merge = trim_dat(fns[0])
+ for fn in fns[1:]:
+ print fn
+ td_merge.update(trim_dat(fn))
+ if new_fn:
+ td_merge.write(new_fn)
+
+ return td_merge
+
+if __name__ == '__main__' and len(sys.argv) > 1:
+ mode = sys.argv[1]
+
+ if mode == 'merge_trim_dats':
+ if len(sys.argv) < 4:
+ print 'usage: python JMTTools.py %s txt_fn out_fn' % mode
+ else:
+ txt_fn = sys.argv[2]
+ out_fn = sys.argv[3]
+
+ fns = [line.strip() for line in open(txt_fn) if line.strip()]
+ td = merge_trim_dats(fns, out_fn)
+
+ elif mode == 'configs':
+ c = configurations_txt()
+ cd, vd = aliases_txt()
+ print 'configurations.txt in c and aliases.txt in cd, vd'
diff --git a/tifUtil/dumpAll_caldel.py b/tifUtil/dumpAll_caldel.py
new file mode 100644
index 0000000..fe448ac
--- /dev/null
+++ b/tifUtil/dumpAll_caldel.py
@@ -0,0 +1,72 @@
+import sys, os
+from pprint import pprint
+from JMTTools import *
+from JMTROOTTools import *
+set_style()
+
+run = run_from_argv()
+run_dir = run_dir(run)
+in_fn = os.path.join(run_dir, 'CalDel_1.root')
+if not os.path.isfile(in_fn):
+ raise IOError('no root file %s' % in_fn)
+out_dir = os.path.join(run_dir, 'dump_caldel')
+os.system('mkdir -p %s' % out_dir)
+
+f = ROOT.TFile(in_fn)
+
+dirs = ['FPix/FPix_%(hc)s/FPix_%(hc)s_D%(dsk)i/FPix_%(hc)s_D%(dsk)i_BLD%(bld)i/FPix_%(hc)s_D%(dsk)i_BLD%(bld)i_PNL%(pnl)i/FPix_%(hc)s_D%(dsk)i_BLD%(bld)i_PNL%(pnl)i_RNG%(rng)i' % locals() for hc in ['BmI', 'BmO', 'BpI', 'BpO'] for dsk in range(1,4) for bld in range(1,18) for pnl in range(1,3) for rng in range(1,3)]
+
+c = ROOT.TCanvas('c', '', 1300, 1000)
+c.Divide(4,4)
+c.cd(0)
+pdf_fn = os.path.join(out_dir, 'all.pdf')
+c.Print(pdf_fn + '[')
+
+for d in dirs:
+ if not f.Get(d):
+ continue
+ for ikey, key in enumerate(f.Get(d).GetListOfKeys()):
+ obj = key.ReadObj()
+ name = obj.GetName().replace('_c', '')
+ rest, roc = name.split('ROC')
+ iroc = int(roc)
+ if int(roc) < 10:
+ name = rest + 'ROC0' + roc
+ c.cd(iroc+1)
+ canvas = obj.GetListOfPrimitives()[0]
+ canvas.Draw('colz')
+ if len(obj.GetListOfPrimitives()) > 1:
+ for line in obj.GetListOfPrimitives()[1:]:
+ line.Draw()
+ c.cd(0)
+ c.SaveAs(os.path.join(out_dir, d.split('/')[-1]) + '.png')
+ c.Print(pdf_fn)
+c.Print(pdf_fn + ']')
+
+if 'html' in sys.argv:
+ pngs = [f for f in os.listdir(out_dir) if os.path.isfile(os.path.join(out_dir,f)) and f.endswith('png')]
+ pngs.sort()
+
+ html_fn = os.path.join(out_dir, 'index.html')
+ html = open(html_fn, 'wt')
+ html.write('\n')
+
+ for item in pngs:
+ html.write('
%s
\n' %item)
+ html.write('
\n' %item)
+
+ html.write('\n')
+ html.close()
+ os.system('firefox %s' %html_fn)
+else:
+ os.system('evince %s' %pdf_fn)
+
+
+if 'scp' in sys.argv:
+ remote_dir = 'public_html/qwer/dump_caldel/%i' % run
+ cmd = 'ssh jmt46@lnx201.lns.cornell.edu "mkdir -p %s"' % remote_dir
+ print cmd
+ os.system(cmd)
+ cmd = 'scp -r %s/* jmt46@lnx201.lns.cornell.edu:%s' % (out_dir, remote_dir)
+ print cmd
+ os.system(cmd)
diff --git a/tifUtil/dumpAll_delay25.py b/tifUtil/dumpAll_delay25.py
new file mode 100644
index 0000000..21ee231
--- /dev/null
+++ b/tifUtil/dumpAll_delay25.py
@@ -0,0 +1,47 @@
+import sys, os
+from pprint import pprint
+from JMTTools import *
+from JMTROOTTools import *
+set_style()
+
+run = run_from_argv()
+run_dir = run_dir(run)
+in_fn = os.path.join(run_dir, 'delay25_1.root')
+if not os.path.isfile(in_fn):
+ raise IOError('no root file %s' % in_fn)
+out_dir = os.path.join(run_dir, 'dump_delay25')
+os.system('mkdir -p %s' % out_dir)
+
+f = ROOT.TFile(in_fn)
+
+dirs = ['FPix/FPix_%(hc)s/FPix_%(hc)s_D%(dsk)i' % locals() for hc in ['BmI', 'BmO', 'BpI', 'BpO'] for dsk in range(1,4)]
+
+c = ROOT.TCanvas('c', '', 1300, 1000)
+c.Divide(3,2)
+c.cd(0)
+pdf_fn = os.path.join(out_dir, 'all.pdf')
+c.Print(pdf_fn + '[')
+
+for d in dirs:
+ if not f.Get(d):
+ continue
+ for ikey, key in enumerate(f.Get(d).GetListOfKeys()):
+ obj = key.ReadObj()#.GetListOfPrimitives()[0]
+ name = obj.GetName().replace(';1', '')
+ pc = name.split(' ')[5]
+ md = name.split(' ')[8]
+ num = 0
+ if 'command' in md:
+ num = int(md.split('command')[-1])
+ c.cd(num+1)
+ canvas = obj.GetListOfPrimitives()[0]
+ canvas.Draw()
+ if len(obj.GetListOfPrimitives()) > 1:
+ for x in obj.GetListOfPrimitives()[1:]:
+ x.Draw()
+ if num == 5:
+ c.cd(0)
+ c.Print(pdf_fn)
+c.Print(pdf_fn + ']')
+
+os.system('evince %s' %pdf_fn)
diff --git a/tifUtil/dumpAll_pixelalive.py b/tifUtil/dumpAll_pixelalive.py
new file mode 100644
index 0000000..37f621d
--- /dev/null
+++ b/tifUtil/dumpAll_pixelalive.py
@@ -0,0 +1,103 @@
+import sys, os
+from pprint import pprint
+from JMTTools import *
+from JMTROOTTools import *
+set_style()
+
+dynrng = 'nodynrng' not in sys.argv
+
+run = run_from_argv()
+run_dir = run_dir(run)
+in_fn = glob(os.path.join(run_dir, 'PixelAlive_Fed_*_Run_%i.root' % run))
+if not in_fn:
+ raise RuntimeError('need to make the root file: /nfshome0/pixelpilot/build/TriDAS/pixel/jmt/pxalive.sh %i' % run)
+if len(in_fn) > 1:
+ raise RuntimeError('too many root files')
+in_fn = in_fn[0]
+out_dir = os.path.join(run_dir, 'dump_pixelalive')
+os.system('mkdir -p %s' % out_dir)
+
+f = ROOT.TFile(in_fn)
+
+dirs = ['FPix/FPix_%(hc)s/FPix_%(hc)s_D%(dsk)i/FPix_%(hc)s_D%(dsk)i_BLD%(bld)i/FPix_%(hc)s_D%(dsk)i_BLD%(bld)i_PNL%(pnl)i/FPix_%(hc)s_D%(dsk)i_BLD%(bld)i_PNL%(pnl)i_RNG%(rng)i' % locals() for hc in ['BmI', 'BmO', 'BpI', 'BpO'] for dsk in range(1,4) for bld in range(1,18) for pnl in range(1,3) for rng in range(1,3)]
+
+by_ntrigs = []
+first = True
+
+c = ROOT.TCanvas('c', '', 1300, 1000)
+c.Divide(4,4)
+c.cd(0)
+pdf_fn = os.path.join(out_dir, 'all.pdf')
+c.Print(pdf_fn + '[')
+
+num_dead = defaultdict(int)
+eff_thresh = 100.
+
+for d in dirs:
+ if not f.Get(d):
+ continue
+ for ikey, key in enumerate(f.Get(d).GetListOfKeys()):
+ obj = key.ReadObj()
+ name = obj.GetName().replace(' (inv)', '')
+ rest, roc = name.split('ROC')
+ iroc = int(roc)
+ if int(roc) < 10:
+ name = rest + 'ROC0' + roc
+ mineff, maxeff = 100., 0.
+ ntrigs = int(obj.Integral())
+ by_ntrigs.append((ntrigs, name))
+ for x in xrange(1, obj.GetNbinsX()+1):
+ for y in xrange(1, obj.GetNbinsY()+1):
+ eff = obj.GetBinContent(x,y)
+ mineff = min(eff, mineff)
+ maxeff = max(eff, maxeff)
+ if obj.GetBinContent(x,y) < eff_thresh:
+ num_dead[name] += 1
+ c.cd(iroc+1)
+ if dynrng:
+ if maxeff - mineff < 1:
+ maxeff += 1
+ obj.SetMinimum(mineff)
+ obj.SetMaximum(maxeff)
+ obj.Draw('colz')
+ c.cd(0)
+ c.SaveAs(os.path.join(out_dir, d.split('/')[-1]) + '.png')
+ c.Print(pdf_fn)
+c.Print(pdf_fn + ']')
+
+by_ntrigs.sort(key=lambda x: x[1])
+by_ntrigs.sort(key=lambda x: x[0], reverse=True)
+pprint(by_ntrigs)
+
+if 'html' in sys.argv:
+ pngs = [f for f in os.listdir(out_dir) if os.path.isfile(os.path.join(out_dir,f)) and f.endswith('png')]
+ pngs.sort()
+
+ html_fn = os.path.join(out_dir, 'index.html')
+ html = open(html_fn, 'wt')
+ html.write('\n')
+
+ for item in pngs:
+ html.write('
%s
\n' %item)
+ html.write('
\n' %item)
+
+ html.write('\n')
+ html.close()
+ os.system('firefox %s' %html_fn)
+else:
+ os.system('evince %s' %pdf_fn)
+
+print '# dead pixels (eff lower than %f):' % eff_thresh
+for roc in sorted(num_dead.keys()):
+ if num_dead[roc]:
+ print '%s %10i' % (roc.ljust(35), num_dead[roc])
+
+
+if 'scp' in sys.argv:
+ remote_dir = 'public_html/qwer/dump_pixelalive/%i' % run
+ cmd = 'ssh jmt46@lnx201.lns.cornell.edu "mkdir -p %s"' % remote_dir
+ print cmd
+ os.system(cmd)
+ cmd = 'scp -r %s/* jmt46@lnx201.lns.cornell.edu:%s' % (out_dir, remote_dir)
+ print cmd
+ os.system(cmd)
diff --git a/tifUtil/dumpAll_pohbias.py b/tifUtil/dumpAll_pohbias.py
new file mode 100644
index 0000000..0e50dcf
--- /dev/null
+++ b/tifUtil/dumpAll_pohbias.py
@@ -0,0 +1,55 @@
+import sys, os
+from pprint import pprint
+from JMTTools import *
+from JMTROOTTools import *
+set_style()
+
+run = run_from_argv()
+run_dir = run_dir(run)
+in_fn = os.path.join(run_dir, 'POHBias.root')
+if not os.path.isfile(in_fn):
+ raise RuntimeError('no file at %s' % in_fn)
+out_dir = os.path.join(run_dir, 'dump_pohbias')
+os.system('mkdir -p %s' % out_dir)
+
+f = ROOT.TFile(in_fn)
+
+gains = range(4)
+feds = range(1294, 1305)
+fibre = range(25)
+
+dirs = ['gain%(gn)i/FED%(fd)i' % locals() for gn in gains for fd in feds]
+
+c = ROOT.TCanvas('c', '', 1800, 1750)
+c.Divide(4,6)
+c.cd(0)
+pdf_fn = os.path.join(out_dir, 'all.pdf')
+c.Print(pdf_fn + '[')
+
+for d in dirs:
+ if not f.Get(d):
+ continue
+ for ikey, key in enumerate(f.Get(d).GetListOfKeys()):
+ canvas = key.ReadObj()
+ name = canvas.GetName().replace(';1','')
+ obj = canvas.FindObject(name)
+ rest,fiber = name.split('fiber')
+ ifiber = int(fiber)
+ c.cd(ifiber)
+ obj.Draw('')
+ for x in canvas.GetListOfPrimitives():
+ if x.GetName() == 'TLine':
+ x.SetLineWidth(2)
+ x.Draw()
+ if key == f.Get(d).GetListOfKeys()[-1]:
+ c.Print(pdf_fn)
+ c.Close()
+ c = ROOT.TCanvas('c', '', 1800, 1750)
+ c.Divide(4,6)
+ c.cd(0)
+ #c.SaveAs(os.path.join(out_dir, d.split('/')[-1]) +'.pdf')
+c.cd(0)
+c.Print(pdf_fn + ']')
+
+os.system('evince %s' %pdf_fn)
+
diff --git a/tifUtil/dumpAll_tbmdelaywscores.py b/tifUtil/dumpAll_tbmdelaywscores.py
new file mode 100644
index 0000000..b03e899
--- /dev/null
+++ b/tifUtil/dumpAll_tbmdelaywscores.py
@@ -0,0 +1,35 @@
+import sys, os
+from pprint import pprint
+from JMTTools import *
+from JMTROOTTools import *
+set_style()
+
+run = run_from_argv()
+run_dir = run_dir(run)
+in_fn = os.path.join(run_dir, 'TBMDelay.root')
+if not os.path.isfile(in_fn):
+ raise RuntimeError('no file at %s' % in_fn)
+out_dir = os.path.join(run_dir, 'dump_tbmdelaywscores')
+os.system('mkdir -p %s' % out_dir)
+
+f = ROOT.TFile(in_fn)
+
+# JMT need ROOT os.walk...
+all_graphs = defaultdict(dict)
+
+c = ROOT.TCanvas('c', '', 1300, 1000)
+c.Divide(3,3)
+c.cd(0)
+pdf_fn = os.path.join(out_dir, 'all.pdf')
+c.Print(pdf_fn + '[')
+
+for ikey, key in enumerate(f.GetListOfKeys()):
+ obj = key.ReadObj()
+ c.cd(ikey % 9 + 1)
+ obj.Draw()
+ c.Update()
+ if ikey % 9 == 8:
+ c.cd(0)
+ c.Print(pdf_fn)
+c.cd(0)
+c.Print(pdf_fn + ']')
diff --git a/tifUtil/dumpAll_vcthrcaldel.py b/tifUtil/dumpAll_vcthrcaldel.py
new file mode 100644
index 0000000..26ce32b
--- /dev/null
+++ b/tifUtil/dumpAll_vcthrcaldel.py
@@ -0,0 +1,84 @@
+import sys, os
+from pprint import pprint
+from JMTTools import *
+from JMTROOTTools import *
+set_style()
+
+run = run_from_argv()
+run_dir = run_dir(run)
+in_fn = os.path.join(run_dir, 'VcThrCalDel_1.root')
+if not os.path.isfile(in_fn):
+ raise RuntimeError('no file at %s' % in_fn)
+out_dir = os.path.join(run_dir, 'dump_vcthrcaldel')
+os.system('mkdir -p %s' % out_dir)
+
+f = ROOT.TFile(in_fn)
+
+dirs = ['FPix/FPix_%(hc)s/FPix_%(hc)s_D%(dsk)i/FPix_%(hc)s_D%(dsk)i_BLD%(bld)i/FPix_%(hc)s_D%(dsk)i_BLD%(bld)i_PNL%(pnl)i/FPix_%(hc)s_D%(dsk)i_BLD%(bld)i_PNL%(pnl)i_RNG%(rng)i' % locals() for hc in ['BmI', 'BmO', 'BpI', 'BpO'] for dsk in range(1,4) for bld in range(1,18) for pnl in range(1,3) for rng in range(1,3)]
+
+by_ntrigs = []
+first = True
+
+c = ROOT.TCanvas('c', '', 1300, 1000)
+c.Divide(4,4)
+c.cd(0)
+pdf_fn = os.path.join(out_dir, 'all.pdf')
+c.Print(pdf_fn + '[')
+
+for d in dirs:
+ if not f.Get(d):
+ continue
+ for ikey, key in enumerate(f.Get(d).GetListOfKeys()):
+ canvas = key.ReadObj()
+ name = canvas.GetName().replace(' (inv)', '').replace('_Canvas', '')
+ obj = canvas.FindObject(name)
+ #lines = [x for x in canvas.GetListOfPrimitives() if x.Class().GetName() == "TLine"]
+ rest, roc = name.split('ROC')
+ iroc = int(roc)
+ if int(roc) < 10:
+ name = rest + 'ROC0' + roc
+ ntrigs = int(obj.Integral())
+ by_ntrigs.append((ntrigs, name))
+ c.cd(iroc+1)
+ obj.Draw('colz')
+ if 1:
+ for x in canvas.GetListOfPrimitives():
+ if x.GetName() == 'TLine':
+ x.SetLineWidth(1)
+ x.Draw()
+ c.cd(0)
+ c.SaveAs(os.path.join(out_dir, d.split('/')[-1]) + '.png')
+ #c.SaveAs(os.path.join(out_dir, d.split('/')[-1]) + '.root')
+ c.Print(pdf_fn)
+c.Print(pdf_fn + ']')
+
+by_ntrigs.sort(key=lambda x: x[1])
+by_ntrigs.sort(key=lambda x: x[0], reverse=True)
+pprint(by_ntrigs)
+
+if 'html' in sys.argv:
+ pngs = [f for f in os.listdir(out_dir) if os.path.isfile(os.path.join(out_dir,f)) and f.endswith('png')]
+ pngs.sort()
+
+ html_fn = os.path.join(out_dir, 'index.html')
+ html = open(html_fn, 'wt')
+ html.write('\n')
+
+ for item in pngs:
+ html.write('
%s
\n' %item)
+ html.write('
\n' %item)
+
+ html.write('\n')
+ html.close()
+ os.system('firefox %s' %html_fn)
+else:
+ os.system('evince %s' %pdf_fn)
+
+if 'scp' in sys.argv:
+ remote_dir = 'public_html/qwer/dump_vcthrcaldel/%i' % run
+ cmd = 'ssh jmt46@lnx201.lns.cornell.edu "mkdir -p %s"' % remote_dir
+ print cmd
+ os.system(cmd)
+ cmd = 'scp -r %s/* jmt46@lnx201.lns.cornell.edu:%s' % (out_dir, remote_dir)
+ print cmd
+ os.system(cmd)
diff --git a/tifUtil/moduleSummaryPlottingTools.py b/tifUtil/moduleSummaryPlottingTools.py
new file mode 100755
index 0000000..c83b410
--- /dev/null
+++ b/tifUtil/moduleSummaryPlottingTools.py
@@ -0,0 +1,972 @@
+from ROOT import *
+from array import array
+import collections
+import re
+import os
+
+# true dimensions of a sensor in 10^-4 m (active area + periphery)
+PERIPHERY = 12. # 1.2 mm
+ZOOM = 5 # integer value to upscale canvas size
+ROC_SIZE = ZOOM * 81. # 8.1 mm
+SENSOR_WIDTH = 8 * ROC_SIZE
+SENSOR_HEIGHT = 2 * ROC_SIZE
+PLOT_UNIT = 50. # fill plots in 50 um width bins
+X_UNIT = int(150./PLOT_UNIT)
+Y_UNIT = int(100./PLOT_UNIT)
+# ROCs have 52 columns (x) and 80 rows (y)
+N_COLS = 52
+N_ROWS = 80
+# ROC plots are 162 wide by 162 high in 50 um units
+ROC_PLOT_SIZE = X_UNIT * 50 + 2 * (2 * X_UNIT) # 50 normal cols + 2 wide ones
+MODULE_X_PLOT_SIZE = 8 * ROC_PLOT_SIZE
+MODULE_Y_PLOT_SIZE = 2 * ROC_PLOT_SIZE
+
+###############################################################################
+
+# BEGIN MODULE SUMMARY PLOTTING UTILITIES
+
+###############################################################################
+
+
+###############################################################################
+
+# function to process the 16 histograms and flip bin contents of the top half
+# input a set of histograms and return a flipped version of the top ones
+def flipTopRow(plots):
+
+ for roc in range(8):
+ histo = plots[roc].Clone()
+ histo.SetDirectory(0)
+ histo.Reset()
+ nBinsX = histo.GetNbinsX()
+ nBinsY = histo.GetNbinsY()
+ for x in range(1, nBinsX+1):
+ for y in range(1, nBinsY+1):
+ content = plots[roc].GetBinContent(x,y)
+ error = plots[roc].GetBinError(x,y)
+ if plots[roc].ClassName() == "TProfile2D":
+ histo.Fill(nBinsX-x, nBinsY-y, content)
+ else:
+ histo.SetBinContent(nBinsX-x+1, nBinsY-y+1, content)
+ histo.SetBinError(nBinsX-x+1, nBinsY-y+1, error)
+
+ plots[roc] = histo
+
+###############################################################################
+
+# function to rotate a module summary plot by 180 degrees
+def flipSummaryPlot(plot):
+
+ histo = plot.Clone()
+ histo.SetDirectory(0)
+ histo.Reset()
+ nBinsX = histo.GetNbinsX()
+ nBinsY = histo.GetNbinsY()
+ for x in range(1,nBinsX+1):
+ for y in range(1, nBinsY+1):
+ content = plot.GetBinContent(x,y)
+ error = plot.GetBinError(x,y)
+ histo.SetBinContent(nBinsX-x+1, nBinsY-y+1, content)
+ histo.SetBinError(nBinsX-x+1, nBinsY-y+1, error)
+
+ return histo
+
+###############################################################################
+
+# function to rotate a module summary plot clockwise by 90 degrees
+def rotateSummaryPlot(plot):
+ name = plot.GetName()
+ title = plot.GetTitle()
+ nBinsX = plot.GetNbinsX()
+ nBinsY = plot.GetNbinsY()
+ binEdgesX = []
+ binEdgesY = []
+ for bin in range(nBinsX+1):
+ binEdgesX.append(int(plot.GetXaxis().GetBinLowEdge(bin+1)))
+ for bin in range(nBinsY+1):
+ binEdgesY.append(int(plot.GetYaxis().GetBinLowEdge(bin+1)))
+ histo = plot.Clone()
+ histo.SetDirectory(0)
+ histo.Reset()
+ histo.SetBins(len(binEdgesY)-1,
+ array('d',binEdgesY),
+ len(binEdgesX)-1,
+ array('d',binEdgesX))
+ for x in range(1,nBinsX+1):
+ for y in range(1, nBinsY+1):
+ content = plot.GetBinContent(x,y)
+ error = plot.GetBinError(x,y)
+ histo.SetBinContent(y, nBinsX-x+1, content)
+ histo.SetBinError(y, nBinsX-x+1, content)
+
+ return histo
+
+
+###############################################################################
+
+# Input 16 plots (one per ROC) and return one merged plot with variable bins
+# fill in units of 50um to account for larger edge pixels
+def makeMergedPlot(plots, mode = 'pxar'):
+
+ flipTopRow(plots)
+
+ # x bins are units of 150um (except for bigger edge pixels)
+ rocBinEdgesX = [0]
+ for x in range(0,X_UNIT*(N_COLS-1),X_UNIT):
+ rocBinEdgesX.append(x+2*X_UNIT) # first bin is twice as wide
+
+ # y bins are units of 100um (except for bigger edge pixels)
+ rocBinEdgesY = [0]
+ for y in range(0,Y_UNIT*(N_ROWS-1),Y_UNIT):
+ rocBinEdgesY.append(y+Y_UNIT)
+
+ # we want to create a plot that's 8x2 ROCs
+
+ moduleBinEdgesX = []
+ for roc in range(8): # 0 - 7
+ for edge in rocBinEdgesX:
+ moduleBinEdgesX.append(edge + ROC_PLOT_SIZE*roc)
+ moduleBinEdgesX.append(8 * ROC_PLOT_SIZE) # add final bin by hand
+
+ moduleBinEdgesY = []
+ # add bottom row of rocs
+ for edge in rocBinEdgesY:
+ moduleBinEdgesY.append(edge)
+ # add top row of rocs
+ moduleBinEdgesY.append(ROC_PLOT_SIZE) # add last bin by hand
+ for edge in reversed(rocBinEdgesY):
+ moduleBinEdgesY.append(2 * ROC_PLOT_SIZE - edge)
+
+ # create clone of plot with new bin sizes
+ if mode == 'pxar':
+ plotName = plots[0].GetName().rstrip("0")
+ else:
+ histogram = plots[0].GetName()
+ chipIndex = histogram.rfind("_ROC")+4
+ afterChipIndex = histogram[chipIndex:].find("_")
+ plotName = histogram[:chipIndex-4]+histogram[chipIndex+afterChipIndex:].rstrip("0")
+ summaryPlot = TH2D(plotName,
+ "",
+ len(moduleBinEdgesX)-1,
+ array('d',moduleBinEdgesX),
+ len(moduleBinEdgesY)-1,
+ array('d',moduleBinEdgesY))
+ summaryPlot.SetStats(False)
+ summaryPlot.SetDirectory(0)
+
+ # fill new histogram with contents of original plots
+ # put ROC 0 at the top right, because reason
+
+ # fill bottom row first
+ for roc in range(8,16):
+ plot = plots[roc]
+
+ for x in range(1,plot.GetNbinsX()+1):
+ for y in range(1,plot.GetNbinsY()+1):
+ content = plot.GetBinContent(x,y)
+ error = plot.GetBinError(x,y)
+ summaryPlot.SetBinContent(x+N_COLS*(roc-8),y,content)
+ summaryPlot.SetBinError(x+N_COLS*(roc-8),y,error)
+
+ # fill top row second
+ for roc in range(7,-1,-1): # loop backwards so 0 is last
+ plot = plots[roc]
+
+ for x in range(1,plot.GetNbinsX()+1):
+ for y in range(1,plot.GetNbinsY()+1):
+ content = plot.GetBinContent(x,y)
+ error = plot.GetBinError(x,y)
+ summaryPlot.SetBinContent(x+N_COLS*(7-roc),y+N_ROWS,content)
+ summaryPlot.SetBinError(x+N_COLS*(7-roc),y+N_ROWS,error)
+
+ return summaryPlot
+
+###############################################################################
+
+# gets the global min and max
+# for each ROC, finds mean & RMS
+# sets global range according to global min and max
+# ignores any points outside a nSigma window around the ROC mean
+# returns zmin and zmax
+def findZRange(plots):
+ zMax = -999
+ zMin = 999
+ nSigma = 3
+ globalMin = 0.00002
+
+ for roc in range(len(plots)):
+ plot = plots[roc].Clone()
+
+ # don't consider empty plots from dead ROCs
+ if not plot.GetMaximum() and not plot.GetMinimum():
+# print "found empty plot:", plot.GetName()
+ continue
+
+ # treat special cases first - don't alter range
+ if "PixelAlive" in plot.GetName() or \
+ "MaskTest" in plot.GetName() or \
+ "AddressDecodingTest" in plot.GetName():
+ # avoid empty ROCs screwing up the range
+ if plot.GetMinimum() != plot.GetMaximum():
+ return(plot.GetMinimum(),plot.GetMaximum())
+ continue
+
+ if "rescaledThr" in plot.GetName():
+ rocMin = plot.GetMinimum() - 0.00001
+ else:
+ rocMin = max(plot.GetMinimum(), globalMin) - 0.00001
+ rocMax = plot.GetMaximum() + 0.00001
+ # create 1D distribution to get mean, RMS
+ oneDPlot = TH1F("1d","1d",10000,rocMin,rocMax)
+ for x in range(1,plot.GetNbinsX()+1):
+ for y in range(1,plot.GetNbinsY()+1):
+ content = plot.GetBinContent(x,y)
+ # ignore empty bins
+ if content == 0:
+ continue
+ # remove things close to -2 (failed s-curve thr)
+ if abs(content + 2) < 0.01:
+ continue
+ oneDPlot.Fill(content)
+
+ mean = oneDPlot.GetMean()
+ sigma = oneDPlot.GetRMS()
+ plotMin = mean - nSigma*sigma
+ plotMax = mean + nSigma*sigma
+ oneDPlot.Delete()
+
+ NBINS = 10000
+ # create zoomed 1D distribution to find normally distributed dataset
+ oneDPlotZoomed = TH1F("1d","1d",NBINS,plotMin,plotMax)
+ for x in range(1,plot.GetNbinsX()+1):
+ for y in range(1,plot.GetNbinsY()+1):
+ content = plot.GetBinContent(x,y)
+ if content < plotMin or content > plotMax or content < rocMin:
+ continue
+ # ignore empty bins
+ if content == 0:
+ continue
+ # remove things close to -2 (failed s-curve thr)
+ if abs(content + 2) < 0.01:
+ continue
+ oneDPlotZoomed.Fill(content)
+
+ mean = oneDPlotZoomed.GetMean()
+ sigma = oneDPlotZoomed.GetRMS()
+ oneDPlotZoomed.Delete()
+ plotMin = mean - nSigma*sigma
+ plotMax = mean + nSigma*sigma
+
+
+ binWidth = (plotMax - plotMin)/float(NBINS)
+ # create groomed 1D distribution to find min/max filled bins
+ oneDPlotGroomed = TH1F("1d","1d",NBINS,plotMin,plotMax)
+ for x in range(1,plot.GetNbinsX()+1):
+ for y in range(1,plot.GetNbinsY()+1):
+ content = plot.GetBinContent(x,y)
+ if content < plotMin and content > plotMax or content < rocMin:
+ continue
+ # ignore empty bins
+ if content == 0:
+ continue
+ # remove things close to -2 (failed s-curve thr)
+ if abs(content + 2) < 0.01:
+ continue
+ oneDPlotGroomed.Fill(content)
+
+ # get position of first and last bins with non-zero entries
+ rocMin = oneDPlotGroomed.GetBinLowEdge(oneDPlotGroomed.FindFirstBinAbove()) + binWidth
+ rocMax = oneDPlotGroomed.GetBinLowEdge(oneDPlotGroomed.FindLastBinAbove())
+
+ oneDPlotGroomed.Delete()
+
+ if rocMax > zMax:
+ zMax = rocMax
+ if rocMin < zMin:
+ zMin = rocMin
+
+ # round to nearest integer before returning
+ return (floor(zMin), ceil(zMax))
+
+###############################################################################
+
+# pass this function a plot and a list with two elements - [zMin,zMax]
+def setZRange(plot, range):
+
+ plot.SetMinimum(range[0])
+ plot.SetMaximum(range[1])
+
+###############################################################################
+
+# input a summary merged plot and draw it on a canvas
+# add axis ticks and labels
+# return canvas
+def setupSummaryCanvas(summaryPlot, moduleName = None):
+
+ pathToHistogram = summaryPlot.GetName()
+ splitPath = pathToHistogram.split("/")
+ plotName = splitPath[-1].split("_Summary")[0]
+ if len(splitPath) > 1:
+ dirName = splitPath[0]
+ else:
+ dirName = None
+
+ summaryPlot.SetName(plotName)
+ canvas = TCanvas(plotName,"")
+
+
+ # use numbers that are factors of ROC_SIZE to avoid rounding errors
+ # dirName will be empty in the MoReWeb case
+ if dirName is not None:
+ topMargin = ROC_SIZE
+ else:
+ topMargin = 2 * ROC_SIZE/3.
+ bottomMargin = 2 * ROC_SIZE/3.
+ leftMargin = 2 * ROC_SIZE/3.
+ rightMargin = 2 * ROC_SIZE
+
+ canvas.SetBorderMode(0)
+ canvas.SetBorderSize(0)
+ canvasWidth = int(SENSOR_WIDTH + leftMargin + rightMargin)
+ canvasHeight = int(SENSOR_HEIGHT + topMargin + bottomMargin)
+ canvas.SetCanvasSize(canvasWidth, canvasHeight)
+ canvas.SetFixedAspectRatio()
+ SetOwnership(canvas, False) # avoid going out of scope at return statement
+
+ gPad.SetBorderMode(0)
+ gPad.SetBorderSize(0)
+ gPad.SetLeftMargin(leftMargin/canvasWidth)
+ gPad.SetRightMargin(rightMargin/canvasWidth)
+ gPad.SetTopMargin(topMargin/canvasHeight)
+ gPad.SetBottomMargin(bottomMargin/canvasHeight)
+
+ summaryPlot.Draw("colz a") # in color (without axes)
+ SetOwnership(summaryPlot, False) # avoid going out of scope at return statement
+
+ canvas.Update()
+ palette = summaryPlot.GetListOfFunctions().FindObject("palette")
+ palette.SetX1NDC((canvasWidth-2*rightMargin/3.)/canvasWidth)
+ palette.SetX2NDC((canvasWidth-rightMargin/2.)/canvasWidth)
+ palette.SetY1NDC(0.05)
+ palette.SetY2NDC(0.95)
+ palette.SetLabelSize(0.06)
+ palette.SetLabelFont(42)
+
+ # START ADDING AXES
+
+ tickLength = 7
+ textBoxWidth = 20
+ axisLabels = []
+
+ # x-axis ticks
+ x_start = 0
+
+ # 8 ROCS
+ for roc in range(8):
+ # 5 ticks per ROC - at 0,10,20,30,40
+ xoffset = 0
+ for i in range(5):
+ if i is 1:
+ xoffset += 10 * X_UNIT + X_UNIT # account for wider edge pixel
+ elif i > 1:
+ xoffset += 10 * X_UNIT
+ x1 = x_start+xoffset
+ x2 = (MODULE_X_PLOT_SIZE-x_start)-xoffset
+
+ text1 = TPaveText(x1-textBoxWidth/2.,
+ -1*(tickLength + textBoxWidth + 5),
+ x1+textBoxWidth/2.,
+ -1*(tickLength + 5),
+ "NB")
+ text1.AddText(str(10*i))
+ axisLabels.append(text1)
+
+ text2 = TPaveText(x2-textBoxWidth/2.,
+ MODULE_Y_PLOT_SIZE + tickLength + textBoxWidth + 5,
+ x2+textBoxWidth/2.,
+ MODULE_Y_PLOT_SIZE + tickLength + 5,
+ "NB")
+ text2.AddText(str(10*i))
+ axisLabels.append(text2)
+
+ line1 = TLine()
+ line2 = TLine()
+ rocBoundaryLine = TLine()
+ rocBoundaryLine.SetLineStyle(2)
+ if i is 0:
+ line1.DrawLine(x1,
+ tickLength/5.,
+ x1,
+ -2*tickLength)
+ line2.DrawLine(x2,
+ MODULE_Y_PLOT_SIZE - tickLength/5.,
+ x2,
+ MODULE_Y_PLOT_SIZE + 2*tickLength)
+ if roc is not 0: # no vertical line at left module edge
+ rocBoundaryLine.DrawLine(x1,
+ 0,
+ x1,
+ MODULE_Y_PLOT_SIZE)
+ else:
+ line1.DrawLine(x1,
+ tickLength/5.,
+ x1,
+ -1*tickLength)
+ line2.DrawLine(x2,
+ MODULE_Y_PLOT_SIZE - tickLength/5.,
+ x2,
+ MODULE_Y_PLOT_SIZE + 1*tickLength)
+
+ # move to next ROC
+ x_start += ROC_PLOT_SIZE
+
+ rocBoundaryLine = TLine()
+ rocBoundaryLine.SetLineStyle(2)
+ rocBoundaryLine.DrawLine(0,
+ MODULE_Y_PLOT_SIZE/2.,
+ MODULE_X_PLOT_SIZE,
+ MODULE_Y_PLOT_SIZE/2.)
+
+ # y-axis ticks
+ # this should be easier since 80 is divisible by 10
+ y_offset = 0
+ for tick in range(17):
+
+ text1 = TPaveText(-1*(tickLength + textBoxWidth + 5),
+ y_offset - textBoxWidth/2.,
+ -1*(tickLength + 5),
+ y_offset + textBoxWidth/2.,
+ "NB")
+ text2 = TPaveText(MODULE_X_PLOT_SIZE + tickLength + 5,
+ y_offset - textBoxWidth/2.,
+ MODULE_X_PLOT_SIZE + tickLength + textBoxWidth + 5,
+ y_offset + textBoxWidth/2.,
+ "NB")
+
+ if tick < 8:
+ text1.AddText(str(10*tick))
+ text2.AddText(str(10*tick))
+ else:
+ text1.AddText(str(160-10*tick))
+ text2.AddText(str(160-10*tick))
+
+ axisLabels.append(text1)
+ axisLabels.append(text2)
+
+ line1 = TLine()
+ line2 = TLine()
+ if tick % 8 is 0:
+ line1.DrawLine(0,
+ y_offset,
+ -2 * tickLength,
+ y_offset)
+ line2.DrawLine(MODULE_X_PLOT_SIZE,
+ y_offset,
+ 2 * tickLength + MODULE_X_PLOT_SIZE,
+ y_offset)
+ else:
+ line1.DrawLine(0,
+ y_offset,
+ -1 * tickLength,
+ y_offset)
+ line2.DrawLine(MODULE_X_PLOT_SIZE,
+ y_offset,
+ 1 * tickLength + MODULE_X_PLOT_SIZE,
+ y_offset)
+ if tick is 7 or tick is 8:
+ y_offset += 10 * Y_UNIT + Y_UNIT # account for larger edge pixels
+ else:
+ y_offset += 10 * Y_UNIT
+
+
+ # roc labels for bottom row
+ for roc in range(8):
+ rocLabel = TPaveText(ROC_PLOT_SIZE/2. + ROC_PLOT_SIZE*roc - textBoxWidth*2,
+ -(4*textBoxWidth),
+ ROC_PLOT_SIZE/2. + ROC_PLOT_SIZE*roc + textBoxWidth*2,
+ -(2*textBoxWidth),
+ "NB")
+ rocLabel.AddText("C"+str(roc+8))
+ axisLabels.append(rocLabel)
+
+ # roc labels for top row
+ for roc in range(8):
+ rocLabel = TPaveText(ROC_PLOT_SIZE/2. + ROC_PLOT_SIZE*roc - textBoxWidth*2,
+ (4*textBoxWidth) + MODULE_Y_PLOT_SIZE,
+ ROC_PLOT_SIZE/2. + ROC_PLOT_SIZE*roc + textBoxWidth*2,
+ (2*textBoxWidth) + MODULE_Y_PLOT_SIZE,
+ "NB")
+ rocLabel.AddText("C"+str(7 -roc))
+ axisLabels.append(rocLabel)
+
+ for label in axisLabels:
+
+ label.SetFillColor(0)
+ label.SetTextAlign(22)
+ label.SetTextFont(42)
+ label.SetBorderSize(0)
+ label.Draw()
+ SetOwnership(label,False) # avoid going out of scope at return statement
+
+ title = TPaveText(leftMargin/canvasWidth,
+ (SENSOR_HEIGHT + bottomMargin + 0.6*topMargin)/canvasHeight,
+ (SENSOR_WIDTH + leftMargin)/canvasWidth,
+ (SENSOR_HEIGHT + bottomMargin + 0.95*topMargin)/canvasHeight,
+ "NDC NB")
+ # this is true except for MoReWeb, when we don't want to draw a title
+ if dirName is not None:
+ title.AddText(dirName + ": " + plotName)
+ title.SetFillColor(0)
+ title.SetTextAlign(22)
+ title.SetTextFont(42)
+ title.SetBorderSize(0)
+ title.Draw()
+ SetOwnership(title,False) # avoid going out of scope at return statement
+
+ if dirName is not None and moduleName is not None:
+ moduleLabel = TPaveText(leftMargin/canvasWidth,
+ (SENSOR_HEIGHT + bottomMargin + 0.6*topMargin)/canvasHeight,
+ (3 * leftMargin)/canvasWidth,
+ (SENSOR_HEIGHT + bottomMargin + 0.95*topMargin)/canvasHeight,
+ "NDC NB")
+ moduleLabel.AddText(moduleName)
+ moduleLabel.SetFillColor(0)
+ moduleLabel.SetTextAlign(22)
+ moduleLabel.SetTextFont(42)
+ moduleLabel.SetBorderSize(0)
+ moduleLabel.Draw()
+ SetOwnership(moduleLabel,False) # avoid going out of scope at return statement
+
+ return canvas
+
+###############################################################################
+
+def saveCanvasToNewFile(canvas,outputFileName):
+
+ outputFile = TFile(outputFileName, "RECREATE")
+ outputFile.cd()
+ canvas.Write()
+ outputFile.Close()
+
+###############################################################################
+
+def produce1DDistributions(inputFileName, pathToHistogram, version=0):
+
+ inputFile = TFile(inputFileName)
+ plots = []
+
+ # get plots
+ for roc in range(16):
+ plotPath = pathToHistogram + "_C" + str(roc) + "_V" + str(version)
+ if not inputFile.Get(plotPath):
+ print "missing plot:", plotPath
+ continue
+ else:
+ twoDplot = inputFile.Get(plotPath).Clone()
+
+ oneDplotName = "dist_"+twoDplot.GetName()
+ # we'll assume we're plotting an 8-bit DAC value,
+ # expect for a couple of explicit exceptions
+ if "_sig_" in oneDplotName:
+ oneDplot = TH1F(oneDplotName,oneDplotName,100,0,10)
+ elif "_TrimMap_" in oneDplotName:
+ oneDplot = TH1F(oneDplotName,oneDplotName,16,0,16)
+ else:
+ oneDplot = TH1F(oneDplotName,oneDplotName,256,0,256)
+ oneDplot.SetDirectory(0)
+ for x in range(1,twoDplot.GetNbinsX()+1):
+ for y in range(1,twoDplot.GetNbinsY()+1):
+ content = twoDplot.GetBinContent(x,y)
+ oneDplot.Fill(content)
+ plots.append(oneDplot)
+ return plots
+
+###############################################################################
+
+# recursively build list of directories in the input file
+def getListOfDirectories(inputFile, list = [], directory = ''):
+
+ inputFile.cd(directory)
+ list.append(directory)
+ for dirKey in gDirectory.GetListOfKeys():
+ if (dirKey.GetClassName() != "TDirectoryFile"):
+ continue
+ dir = dirKey.GetName()
+ newDirectory = directory + "/" + dir
+ getListOfDirectories(inputFile, list, newDirectory)
+
+# build list of 1D histograms in the input file
+def getListOf1DHistograms(inputFile, directoryList):
+
+ histogramList = []
+
+ for dir in directoryList:
+ inputFile.cd(dir)
+ for plotKey in gDirectory.GetListOfKeys():
+ if re.match ('TH1', plotKey.GetClassName()): # found a 1-D histogram
+ plotName = plotKey.GetName()
+ # only consider distributions made from 2D plots
+ if not plotName.startswith("dist_"):
+ continue
+ # ignore summary plots from previous processings
+ if "Summary" in plotName:
+ continue
+ pathToHistogram = dir+"/"+plotName
+ plot = inputFile.Get(pathToHistogram)
+ histogramList.append(pathToHistogram)
+
+ return histogramList
+
+# build list of 2D histograms in the input file
+def getListOf2DHistograms(inputFile, directoryList):
+
+ histogramList = []
+
+ for dir in directoryList:
+ inputFile.cd(dir)
+ for plotKey in gDirectory.GetListOfKeys():
+ if re.match ('TH2', plotKey.GetClassName()) or \
+ re.match ('TProfile2', plotKey.GetClassName()): # found a 2-D plot
+ plotName = plotKey.GetName()
+ pathToHistogram = dir+"/"+plotName
+ plot = inputFile.Get(pathToHistogram)
+ # only consider ROC summary plots
+ if plot.GetNbinsX() != 52 or plot.GetNbinsY() != 80:
+ continue
+ histogramList.append(pathToHistogram)
+
+ return histogramList
+
+# look through an input file (presumably a pxar output file)
+# find all roc summary plots and return a list of them
+def produce2DHistogramDictionary(inputFileName, mode = 'pxar'):
+
+ directoryList = []
+
+ inputFile = TFile(inputFileName)
+
+ getListOfDirectories(inputFile, directoryList)
+ histogramList = getListOf2DHistograms(inputFile, directoryList)
+
+ inputFile.Close()
+
+ # dictionary of histogram names, each entry containing the versions present
+ histogramDictionary = collections.OrderedDict()
+ for histogram in histogramList:
+ if mode == 'pxar':
+ version = histogram[-1:]
+ chipIndex = histogram.rfind("_C")
+ histoName = histogram[:chipIndex]
+ else:
+ version = '0'
+ chipIndex = histogram.rfind("_ROC")+4
+ afterChipIndex = histogram[chipIndex:].find("_")
+ histoName = histogram[:chipIndex]+histogram[chipIndex+afterChipIndex:]
+ # if it's not already in the list, add it
+ if not histoName in histogramDictionary:
+ histogramDictionary[histoName] = []
+ histogramDictionary[histoName].append(version)
+ # if it's there but this is a new version, add this version
+ else:
+ if not version in histogramDictionary[histoName]:
+ histogramDictionary[histoName].append(version)
+ return histogramDictionary
+
+###############################################################################
+
+# look through an input file (presumably a pxar output file)
+# find all roc summary 1D distributions and return a list of them
+def produce1DHistogramDictionary(inputFileName, mode = 'pxar'):
+
+ directoryList = []
+
+ inputFile = TFile(inputFileName)
+
+ getListOfDirectories(inputFile, directoryList)
+ histogramList = getListOf1DHistograms(inputFile, directoryList)
+
+ inputFile.Close()
+
+ # dictionary of histogram names, each entry containing the versions present
+ histogramDictionary = collections.OrderedDict()
+ for histogram in histogramList:
+
+ if mode == 'pxar':
+ version = histogram[-1:]
+ chipIndex = histogram.rfind("_C")
+ else:
+ version = '0'
+ chipIndex = histogram.rfind("_ROC")
+ histoName = histogram[:chipIndex]
+ # if it's not already in the list, add it
+ if not histoName in histogramDictionary:
+ histogramDictionary[histoName] = []
+ histogramDictionary[histoName].append(version)
+ # if it's there but this is a new version, add this version
+ else:
+ if not version in histogramDictionary[histoName]:
+ histogramDictionary[histoName].append(version)
+ return histogramDictionary
+
+
+###############################################################################
+
+def add2DSummaryPlots(inputFileName, histogramDictionary, mode = 'pxar', savePlots = False):
+
+ if savePlots:
+ outputDir = inputFileName.split(".root")[0] + "_2DModuleSummaryPlots"
+ if not os.path.isdir(outputDir):
+ os.mkdir(outputDir)
+
+ for histoName, versions in histogramDictionary.items():
+ for version in versions:
+ summaryPlot = produce2DSummaryPlot(inputFileName,histoName,version,mode)
+ if summaryPlot is None:
+ continue
+ directory = histoName.rsplit("/", 1)[0]
+ inputFile = TFile(inputFileName, "UPDATE")
+ inputFile.cd(directory)
+ gDirectory.Delete(summaryPlot.GetName()+";*") # remove duplicates
+ print "adding 2D summary plot: "+directory+"/"+summaryPlot.GetName()
+ summaryPlot.Write()
+ if savePlots:
+ outputFileName = directory + "_" + summaryPlot.GetName() + ".png"
+ summaryPlot.SaveAs(outputDir + "/" + outputFileName)
+ inputFile.Close()
+
+###############################################################################
+
+def add1DSummaryPlots(inputFileName, histogramDictionary, mode = 'pxar'):
+
+ for histoName, versions in histogramDictionary.items():
+ for version in versions:
+ summaryPlot = produce1DSummaryPlot(inputFileName,histoName,version,mode)
+ if summaryPlot is None:
+ continue
+ directory = histoName.rsplit("/", 1)[0]
+ inputFile = TFile(inputFileName, "UPDATE")
+ inputFile.cd(directory)
+ gDirectory.Delete(summaryPlot.GetName()+";*") # remove duplicates
+ print "adding 1D summary plot: "+directory+"/"+summaryPlot.GetName()
+ summaryPlot.Write()
+ inputFile.Close()
+
+###############################################################################
+
+def add1DDistributions(inputFileName, histogramDictionary):
+
+ for histoName, versions in histogramDictionary.items():
+ for version in versions:
+ distributions = produce1DDistributions(inputFileName,histoName,version)
+ directory = histoName.rsplit("/", 1)[0]
+ inputFile = TFile(inputFileName, "UPDATE")
+ inputFile.cd(directory)
+ for distribution in distributions:
+ # if the plot's already there, don't mess with it
+ existingPlot = gDirectory.Get(distribution.GetName())
+ if existingPlot:
+ continue
+ print "adding 1D distribution: "+directory+"/"+distribution.GetName()
+ distribution.Write()
+ inputFile.Close()
+
+###############################################################################
+
+# pass in the input file and location of relevant histogram
+# return the canvas with the finished summary plot
+def produce2DSummaryPlot(inputFileName, pathToHistogram, version=0, mode='pxar', zRange=(), moduleName = None):
+
+ plots = produce2DPlotList(inputFileName, pathToHistogram, version, mode)
+ if plots is None:
+ return None
+ summaryPlot = makeMergedPlot(plots, mode)
+ if not zRange: zRange = findZRange(plots)
+ setZRange(summaryPlot,zRange)
+ summaryCanvas = setupSummaryCanvas(summaryPlot, moduleName=moduleName)
+
+ return summaryCanvas
+
+###############################################################################
+
+# pass in the input file and location of relevant histogram
+# return the list of 16 ROC plots
+def produce2DPlotList(inputFileName, pathToHistogram, version=0, mode='pxar'):
+
+ inputFile = TFile(inputFileName)
+ plots = []
+ foundPlot = False
+
+ # get plots
+ for roc in range(16):
+ if mode == 'pxar':
+ plotPath = pathToHistogram + "_C" + str(roc) + "_V" + str(version)
+ else:
+ chipIndex = pathToHistogram.rfind("_ROC")+4
+ plotPath = pathToHistogram[:chipIndex]+str(roc)+pathToHistogram[chipIndex:]
+ if not inputFile.Get(plotPath):
+ print "missing plot:", plotPath
+ plot = TH2D("","",52,0,52,80,0,80) # insert empty plot
+ else:
+ foundPlot = True
+ plot = inputFile.Get(plotPath).Clone()
+ plotName = pathToHistogram.lstrip("/")
+ if mode == 'pxar':
+ plot.SetName(plotName + "_V" + str(version) + "_Summary" + str(roc))
+ else:
+ plot.SetName(plotName + "_Summary" + str(roc))
+ plot.SetDirectory(0)
+ plots.append(plot)
+ if not foundPlot:
+ print "no valid plots found, skipping"
+ return None
+
+ return plots
+
+###############################################################################
+
+# takes a set of 16 ROC plots
+# replaces the contents of each bin with 1 (true) or 0 (false) depending on
+# whether it falls within the provided range (inclusive)
+def makeBinaryPlots(plots, min=0, max=1):
+
+ # decide whether to include a range or veto a range
+ vetoRange = False
+ if max < min:
+ vetoRange = True
+
+ for roc in range(16):
+
+ histo = plots[roc].Clone()
+ histo.SetDirectory(0)
+ histo.Reset()
+ nBinsX = histo.GetNbinsX()
+ nBinsY = histo.GetNbinsY()
+ for x in range(1, nBinsX+1):
+ for y in range(1, nBinsY+1):
+ content = plots[roc].GetBinContent(x,y)
+ if plots[roc].GetEntries() == 0:
+ histo.SetBinContent(x, y, 0)
+ elif not vetoRange and (content >= min and content <= max):
+ histo.SetBinContent(x, y, 1)
+ elif vetoRange and (content >= min or content <= max):
+ histo.SetBinContent(x, y, 1)
+ else:
+ histo.SetBinContent(x, y, 0)
+
+ plots[roc] = histo
+
+
+###############################################################################
+
+# takes a set of 16 ROC plots
+# returns the sum of them all
+def makeSumPlot(plots):
+
+ histo = plots[0].Clone()
+ for roc in range(1,16):
+ histo.Add(plots[roc])
+
+ return histo
+
+###############################################################################
+
+# pass in the input file and location of relevant histogram
+# return the list of 16 ROC plots
+def produce1DPlotList(inputFileName, pathToHistogram, version=0, mode='pxar'):
+
+ inputFile = TFile(inputFileName)
+ plots = []
+ foundPlot = False
+
+ # get plots
+ for roc in range(16):
+ if mode == 'pxar':
+ plotPath = pathToHistogram + "_C" + str(roc) + "_V" + str(version)
+ else:
+ plotPath = pathToHistogram + "_ROC" + str(roc)
+ if not inputFile.Get(plotPath):
+ print "missing plot:", plotPath
+ plot = TH1D("","",256,0,256) # insert empty plot
+ else:
+ foundPlot = True
+ plot = inputFile.Get(plotPath).Clone()
+ plot.SetDirectory(0)
+ plots.append(plot)
+ if not foundPlot:
+ print "no valid plots found, skipping"
+ return None
+
+ return plots
+
+###############################################################################
+
+# pass in the input file and location of relevant histogram
+# return merged 1D summary plot
+def produce1DSummaryPlot(inputFileName, pathToHistogram, version=0, mode='pxar'):
+
+ plots = produce1DPlotList(inputFileName, pathToHistogram, version, mode)
+ if plots is None:
+ return None
+
+ summaryPlot = plots[0].Clone()
+ summaryPlot.SetDirectory(0)
+ if mode == 'pxar':
+ chipIndex = summaryPlot.GetName().rfind("_C")
+ else:
+ chipIndex = summaryPlot.GetName().rfind("_ROC")
+ newName = summaryPlot.GetName()[:chipIndex]
+ if mode == 'pxar':
+ summaryPlot.SetName(newName + "_V" + str(version) + "_Summary")
+ else:
+ summaryPlot.SetName(newName + "_Summary")
+ oldTitle = summaryPlot.GetTitle()
+ if "(C" in oldTitle:
+ chipIndex = oldTitle.rfind("(C")
+ versionIndex = oldTitle.rfind("(V")
+ else:
+ chipIndex = oldTitle.rfind("_C")
+ versionIndex = oldTitle.rfind("_V")
+ newTitle1 = oldTitle[:chipIndex]
+ newTitle2 = oldTitle[versionIndex:]
+ summaryPlot.SetTitle(newTitle1 + newTitle2)
+ for roc in range(1,16):
+ summaryPlot.Add(plots[roc])
+
+# functions = []
+# for function in summaryPlot.GetListOfFunctions():
+# functions.append(function)
+# for function in functions:
+# if function.InheritsFrom('TArrow'):
+# print function
+# function.Delete()
+# print "deleted"
+
+ return summaryPlot
+
+###############################################################################
+
+# temporary altered version of produceSummaryPlot for use in lessWeb.py
+def produceLessWebSummaryPlot(inputFile, pathToHistogram, outputDir, zRange=(), isBB3=False, version=0, moduleName = None):
+
+ summaryCanvas=produce2DSummaryPlot(inputFile.GetName(), pathToHistogram, zRange=zRange, moduleName=moduleName)
+
+ if summaryCanvas is None:
+ return
+
+ if isBB3 and zRange:
+ colors = array("i",[51+i for i in range(40)] + [kRed])
+ gStyle.SetPalette(len(colors), colors);
+ zMin=zRange[0]
+ zMax=zRange[1]
+ step=float(zMax-zMin)/(len(colors)-1)
+ levels = array('d',[zMin + i*step for i in range(len(colors)-1)]+[4.9999999])
+
+ summaryPlot=summaryCanvas.GetPrimitive(pathToHistogram.split("/")[-1]+'_V0')
+ summaryPlot.SetContour(len(levels),levels)
+
+ outputFileName = pathToHistogram.replace("/","_")
+ summaryCanvas.SaveAs(outputDir + "/" + outputFileName + ".png")
+
+ if isBB3 and zRange:
+ colors = array("i",[51+i for i in range(50)])
+ gStyle.SetPalette(len(colors), colors);