7 @file TilePostProcessing.py
8 @brief Functions for post-processing of histograms from TileMonitoring for the Run III
11 import os, sys, signal, subprocess
12 from AthenaCommon.Utils.unixtools
import find_datafile
16 """ This function returns 1D histogram for Tile module """
20 ROOT.gROOT.SetBatch(
True)
22 from TileCalibBlobObjs.Classes
import TileCalibUtils
as Tile
24 gain = inputs[0][0][
'gain']
25 gainName = {
'hi' :
'high',
'lo' :
'low'}.
get(gain)
26 module = inputs[0][0][
'module']
27 run =
str(inputs[0][1][0].GetTitle()).
split(
' ')[1]
29 fullName = f
'{module}_{gain}_{name}'
30 fullTitle = f
'Run {run} {module} {gainName} gain: {title}'
31 histogram = ROOT.TH1F(fullName, fullTitle, Tile.MAX_CHAN, 0.0, Tile.MAX_CHAN)
37 labelSize=None, ymin=None, ymax=None, delta=0.1):
38 """ This function set up stype of Tile module monitoring histogram """
40 if ymin
and (histogram.GetMinimum() > ymin + delta * abs(ymin)):
41 histogram.SetMinimum(ymin)
42 if ymax
and (histogram.GetMaximum() < (1.0 - delta) * ymax):
43 histogram.SetMaximum(ymax)
45 histogram.SetMarkerStyle(markerStyle)
47 histogram.SetMarkerColor(markerColor)
49 histogram.SetMarkerSize(markerSize)
51 histogram.SetLabelSize(labelSize,
"X")
52 histogram.SetLabelSize(labelSize,
"Y")
56 """ This function produces 2D histogram with RMS from Profile2D per Tile partition """
58 assert len(inputs) == 1
60 inputProfile = inputs[0][1][0]
61 assert "TProfile2D" in str(inputProfile.ClassName())
62 inputProfile.SetErrorOption(
"s")
64 fullName =
'{}_{}'.
format(name, inputs[0][0][
'partition'])
65 if 'gain' in inputs[0][0]:
66 fullName +=
'_' + inputs[0][0][
'gain']
68 fullTitle =
str(inputProfile.GetTitle()).
split(
':')[0] +
': ' + title
70 nBinsX = inputProfile.GetNbinsX()
71 nBinsY = inputProfile.GetNbinsY()
73 outputHistogram = inputProfile.Clone()
74 outputHistogram.Reset()
75 outputHistogram.SetTitle(fullTitle)
76 outputHistogram.SetName(fullName)
77 for binX
in range(0, nBinsX + 1):
78 for binY
in range(0, nBinsY + 1):
79 rms = inputProfile.GetBinError(binX, binY)
81 outputHistogram.SetBinContent(binX, binY, rms)
82 outputHistogram.SetBinEntries(inputProfile.GetBin(binX, binY), 1)
84 return [outputHistogram]
88 """ This function produces 2D histograms with Tile raw channel noise per partition """
92 ROOT.gROOT.SetBatch(
True)
94 from TileMonitoring.TileMonitoringCfgHelper
import getLabels
95 from TileCalibBlobObjs.Classes
import TileCalibUtils
as Tile
97 def _getTilePartitionHistogram2D(name, title, partition, run):
98 fullName =
'TileRawChannelNoise_{}_{}'.
format(name, partition)
99 fullTitle =
'Run {} Partition {}: {}'.
format(run, partition, title)
100 histogram = ROOT.TH2F(fullName, fullTitle,
101 Tile.MAX_DRAWER, 0.5, Tile.MAX_DRAWER + 0.5,
102 Tile.MAX_CHAN, -0.5, Tile.MAX_CHAN - 0.5)
103 moduleLables =
getLabels((
'modules'), partition)
104 channelLables =
getLabels((
'channels'), partition)
105 for axis,labels
in ((histogram.GetXaxis(), moduleLables), (histogram.GetYaxis(), channelLables)):
106 for bin
in range(0, len(labels)):
107 axis.SetBinLabel(bin + 1, labels[bin])
111 partition = inputs[0][0][
'module'][:3]
112 run =
str(inputs[0][1][0].GetTitle()).
split(
' ')[1]
114 rmsHistogram = _getTilePartitionHistogram2D(
'RMS',
'RMS of gaussians', partition, run)
115 sigmaHistogram = _getTilePartitionHistogram2D(
'Sigma',
'Sigma of gaussians', partition, run)
116 chi2Histogram = _getTilePartitionHistogram2D(
'Chi2',
'Chi2 of gaussians', partition, run)
117 probabilityHistogram = _getTilePartitionHistogram2D(
'Prob',
'Probability of gaussians', partition, run)
118 rmsOverSigmaHistogram = _getTilePartitionHistogram2D(
'RmsOverSigma',
'RMS/Sigma of gaussians', partition, run)
120 fitfunction = ROOT.TF1(
"total",
"gaus(0)")
121 fitfunction.SetLineColor(2)
125 module =
int(input[0][
'module'][3:])
126 channel =
int(input[0][
'channel'])
130 nEntries = plot.GetEntries()
135 rmsHistogram.Fill(module, channel, rms)
137 fitfunction.SetParameters(0.1 * nEntries, 0., 0.7 * rms)
139 binWidth = plot.GetBinWidth(0)
140 lowLimit = binWidth * 0.5
141 highLimit =
max(rms * 1.05, binWidth * 2.0)
143 fitfunction.SetParLimits(0, 0., nEntries)
144 fitfunction.FixParameter(1, 0.)
145 fitfunction.SetParLimits(2, lowLimit, highLimit)
147 plot.Fit(fitfunction,
"BQ")
149 sigma = fitfunction.GetParameter(2)
150 chi2 = fitfunction.GetChisquare()
151 prob = fitfunction.GetProb()
153 sigmaHistogram.Fill(module, channel, sigma)
154 chi2Histogram.Fill(module, channel, chi2)
155 probabilityHistogram.Fill(module, channel, prob)
156 rmsOverSigmaHistogram.Fill(module, channel, rms/sigma)
158 return [rmsHistogram, sigmaHistogram, chi2Histogram, probabilityHistogram, rmsOverSigmaHistogram]
162 """ This function produces 1D summary histogram per Tile module with pedestals and LFN of all channels in the module """
169 inputHistogram = input[1][0]
170 channel =
int(input[0][
'channel'])
171 bin =
int(channel) + 1
173 rms = inputHistogram.GetRMS()
174 pedestal = inputHistogram.GetMean()
175 pedestalHistogram.SetBinContent(bin, pedestal)
176 pedestalHistogram.SetBinError(bin, rms)
178 lfnHistogram.SetBinContent(bin, rms)
180 return [pedestalHistogram, lfnHistogram]
184 """ This function produces 1D summary histogram per Tile module with HFN of all channels in the module """
190 inputHistogram = input[1][0]
191 channel =
int(input[0][
'channel'])
192 bin =
int(channel) + 1
194 hfn = inputHistogram.GetMean()
195 hfnHistogram.SetBinContent(bin, hfn)
197 return [hfnHistogram]
201 """ This function produces 1D summary histogram per Tile module with CRC errors of all DMU in the module """
205 ROOT.gROOT.SetBatch(
True)
207 module = inputs[0][0][
'module']
208 run =
str(inputs[0][1][0].GetTitle()).
split(
' ')[1]
210 crcName = f
'{module}_crc'
211 crcTitle = f
'Run {run} {module}: CRC errors'
212 crcHistogram = ROOT.TH1F(crcName, crcTitle, 16, 0.0, 16.0)
216 inputHistogram = input[1][0]
217 dmu =
int(input[0][
'dmu'])
220 underflow = inputHistogram.GetBinContent(0)
221 crcGlobal = inputHistogram.GetBinContent(1)
222 crcOk = inputHistogram.GetBinContent(2)
223 crcFE = inputHistogram.GetBinContent(3)
224 crcROD = inputHistogram.GetBinContent(4)
225 crcFE_ROD = inputHistogram.GetBinContent(5)
228 if (underflow + crcFE + crcROD + crcFE_ROD) > 0:
229 if (crcROD == 0)
and (crcFE_ROD == 0):
231 elif (crcFE == 0)
and (crcFE_ROD == 0):
247 crcHistogram.SetBinContent(bin, weight)
249 return [crcHistogram]
254 """ This function produces 1D summary histogram per Tile module with BCID errors of all DMU in the module """
258 ROOT.gROOT.SetBatch(
True)
260 gain = inputs[0][0][
'gain']
261 gainName = {
'hi' :
'high',
'lo' :
'low'}.
get(gain)
262 module = inputs[0][0][
'module']
263 run =
str(inputs[0][1][0].GetTitle()).
split(
' ')[1]
265 bcidName = f
'{module}_{gain}_bcid'
266 bcidTitle = f
'Run {run} {module} {gainName} gain: BCID errors'
267 bcidHistogram = ROOT.TH1F(bcidName, bcidTitle, 16, 0.0, 16.0)
271 inputHistogram = input[1][0]
272 dmu =
int(input[0][
'dmu'])
275 underflow = inputHistogram.GetBinContent(0)
276 bcidZero = inputHistogram.GetBinContent(1)
277 bcidOk = inputHistogram.GetBinContent(2)
278 bcidOther = inputHistogram.GetBinContent(3)
281 if (underflow + bcidOther) > 0:
294 bcidHistogram.SetBinContent(bin, weight)
296 return [bcidHistogram]
302 This function analyzes a histogram with samples from Tile channel and returns number of stuck bits
304 New function implemented by Tibor Zenis, which checks how many bit flips happen compared to the expected ones
305 It works for CIS and Laser because the adc range is not sufficiently excersized in the other run types.
309 nBins = inputHistogram.GetNbinsX()
310 nBits =
round(math.log2(nBins))
312 bitValue = [1 << bit
for bit
in range(0, nBits)]
313 nBitFlipsAtSignalRegion = [0
for bit
in range(0, nBits)]
314 nBitFlipsAtSignalEdges = [0
for bit
in range(0, nBits)]
316 nextBinContent = inputHistogram.GetBinContent(1)
317 previousBinIsNotEmpty = nextBinContent > 0
319 currentBinContent = 2
320 for currentBin
in range(1, nBins):
322 previousBinContent = currentBinContent
323 currentBinContent = nextBinContent
324 binIsNotEmpty = currentBinContent > 0
325 nextBinContent = inputHistogram.GetBinContent(currentBin + 2)
if currentBin < nBins - 1
else 0
328 expectedContent = 0.125 * (nextBinContent + previousBinContent - math.sqrt(nextBinContent) - math.sqrt(previousBinContent))
329 if binIsNotEmpty
and currentBinContent < expectedContent:
330 probability = 1. - currentBinContent / expectedContent
331 binIsNotEmpty =
False
333 if binIsNotEmpty
or previousBinIsNotEmpty:
334 for bit
in range(0, nBits):
335 if ((currentBin & bitValue[bit]) != ((currentBin - 1) & bitValue[bit])):
336 nBitFlipsAtSignalRegion[bit] += 1
340 if (binIsNotEmpty
and previousBinIsNotEmpty)
or not (binIsNotEmpty
or previousBinIsNotEmpty):
344 for bit
in range(0, nBits):
345 if ((currentBin & bitValue[bit]) != ((currentBin - 1) & bitValue[bit])):
346 if (currentBin & bitValue[bit]):
347 nBitFlipsAtSignalEdges[bit] += probability
if binIsNotEmpty
else -probability
349 nBitFlipsAtSignalEdges[bit] += -probability
if binIsNotEmpty
else probability
353 previousBinIsNotEmpty =
not previousBinIsNotEmpty
356 for bit
in range(0, nBits):
357 if (((nBitFlipsAtSignalRegion[bit] > 2)
and abs(nBitFlipsAtSignalEdges[bit]) == nBitFlipsAtSignalRegion[bit])
358 or (abs(nBitFlipsAtSignalEdges[bit]) > 7
and abs(nBitFlipsAtSignalEdges[bit]) * 3 > nBitFlipsAtSignalRegion[bit])):
366 """ This function analyzes a histogram with samples from Tile channel and returns number of stuck bits """
376 firstBin = inputHistogram.FindFirstBinAbove(0)
380 lastBin = inputHistogram.FindLastBinAbove(0)
388 nBins = inputHistogram.GetNbinsX()
390 if (firstBin == nBins / 2 + 1)
or (lastBin == nBins / 2
and inputHistogram.GetBinContent(lastBin) > 3):
396 nBits =
round(math.log2(nBins))
397 for stuckValue
in (0, 1):
398 for stuckBit
in range(0, nBits):
402 windowLength = (1 << stuckBit)
403 beginBin = (1 - stuckValue) * windowLength
405 while beginBin + 1 < lastBin:
406 endBin = beginBin + windowLength
408 if endBin > firstBin:
409 for bin
in range(beginBin, endBin):
411 if (firstBin < bin + 1)
and (bin + 1 < lastBin):
412 sumInBinsChecked += inputHistogram.GetBinContent(bin + 1)
415 beginBin = endBin + windowLength
417 if sumInBinsChecked == 0
and nBinsChecked > 0:
420 if (nStuckBits == 0):
427 """ Produce Tile 1D summary histograms per module with stuck bits and zeros for all channels in the module """
433 inputHistogram = input[1][0]
434 channel =
int(input[0][
'channel'])
435 bin =
int(channel) + 1
437 nZeros = inputHistogram.GetBinContent(1)
438 integral = inputHistogram.Integral(2, inputHistogram.GetNbinsX())
451 bitsHistogram.SetBinContent(bin, weight)
453 return [bitsHistogram]
457 """ Produce Tile 2D histograms per module with covariance and correlation of channels in the module. """
461 ROOT.gROOT.SetBatch(
True)
465 from TileCalibBlobObjs.Classes
import TileCalibUtils
as Tile
467 gain = inputs[0][0][
'gain']
468 gainName = {
'hi' :
'high',
'lo' :
'low'}.
get(gain)
469 module = inputs[0][0][
'module']
470 run =
str(inputs[0][1][0].GetTitle()).
split(
' ')[1]
472 covarianceName = f
'{module}_{gain}_covar'
473 covarianceTitle = f
'Run {run} {module} {gainName} gain: Covariance'
474 covarianceHistogram = ROOT.TH2F(covarianceName, covarianceTitle,
475 Tile.MAX_CHAN, 0.0, Tile.MAX_CHAN,
476 Tile.MAX_CHAN, 0.0, Tile.MAX_CHAN)
478 correlationName = f
'{module}_{gain}_corr'
479 correlationTitle = f
'Run {run} {module} {gainName} gain: Correlation'
480 correlationHistogram = ROOT.TH2F(correlationName, correlationTitle,
481 Tile.MAX_CHAN, 0.0, Tile.MAX_CHAN,
482 Tile.MAX_CHAN, 0.0, Tile.MAX_CHAN)
484 meanSampleHistogram = inputs[0][1][0]
485 meanSample12Histogram = inputs[0][1][1]
487 meanRMS = [0
for i
in range(0,48)]
488 covariance = [[0
for i
in range(0,48)]
for j
in range(0,48)]
490 for channel1
in range(0, Tile.MAX_CHAN):
491 meanSample1 = meanSampleHistogram.GetBinContent(channel1 + 1)
492 for channel2
in range(0, Tile.MAX_CHAN):
493 meanSample2 = meanSampleHistogram.GetBinContent(channel2 + 1)
494 meanSample12 = meanSample12Histogram.GetBinContent(channel1 + 1, channel2 + 1)
495 covariance12 = meanSample12 - meanSample1*meanSample2
496 covariance[channel1][channel2] = covariance12
498 covariance11 = covariance[channel1][channel1]
499 meanRMS[channel1] = 0
if covariance11 == 0
else covariance11 / math.sqrt(abs(covariance11))
501 for channel1
in range(0, Tile.MAX_CHAN):
502 for channel2
in range(0, Tile.MAX_CHAN):
503 meanRMS1 = meanRMS[channel1]
504 meanRMS2 = meanRMS[channel2]
505 if (meanRMS1 == 0)
or (meanRMS2 == 0):
508 correlation = covariance[channel1][channel2] / (meanRMS1 * meanRMS2)
509 correlationHistogram.SetBinContent(channel1 + 1, channel2 + 1, correlation)
510 covarianceHistogram.SetBinContent(channel1 + 1, channel2 + 1, covariance[channel1][channel2])
512 return [covarianceHistogram, correlationHistogram]
516 """ This function produces 2D summary histogram per Tile module with Chi2 vs amplitude of all channels in the module """
518 gain = inputs[0][0][
'gain']
519 gainName = {
'hi' :
'high',
'lo' :
'low'}.
get(gain)
520 module = inputs[0][0][
'module']
521 run =
str(inputs[0][1][0].GetTitle()).
split(
' ')[1]
523 chi2AmpName = f
'{module}_{gain}_summary_chi2_amp'
524 chi2AmpTitle = f
'Run {run} {module} {gainName} gain: Summary DSP #chi^{2} vs Amplitude'
525 inputHistogram = inputs[0][1][0]
526 chi2AmpHistogram = inputHistogram.Clone()
527 chi2AmpHistogram.Reset()
528 chi2AmpHistogram.SetTitle(chi2AmpTitle)
529 chi2AmpHistogram.SetName(chi2AmpName)
532 inputHistogram = input[1][0]
533 if inputHistogram.GetEntries() > 0:
534 chi2AmpHistogram.Add(inputHistogram)
538 return [chi2AmpHistogram]
541 """ This function produces 1D summary histogram per Tile module with amplitude, sigma, and RMS of all channels in the module """
546 ROOT.gROOT.SetBatch(
True)
548 gain = inputs[0][0][
'gain']
554 fitFunction = ROOT.TF1(
"g",
'gaus')
555 inputHistogram = inputs[0][1][0]
556 overlapHistogram = inputHistogram.GetBinWidth(1) == inputHistogram.GetBinWidth(100)
560 inputHistogram = input[1][0]
561 nEntries = inputHistogram.GetEntries()
563 channel =
int(input[0][
'channel'])
564 bin =
int(channel) + 1
566 rms = inputHistogram.GetRMS()
567 amplitude = inputHistogram.GetMean()
568 amplitudeHistogram.SetBinContent(bin, amplitude)
569 amplitudeHistogram.SetBinError(bin, rms / math.sqrt(nEntries))
571 rmsHistogram.SetBinContent(bin, rms)
572 rmsHistogram.SetBinError(bin, rms / math.sqrt(2.0 * nEntries))
576 inputHistogram.Scale(1,
'width')
577 inputHistogram.Fit(fitFunction,
'Q')
578 sigma = fitFunction.GetParameter(2)
579 sigmaError = fitFunction.GetParError(2)
580 sigmaHistogram.SetBinContent(bin, sigma)
581 sigmaHistogram.SetBinError(bin, sigmaError)
584 ymin={
'hi' : -0.05,
'lo' : -1.0}.
get(gain),
585 ymax={
'hi' : 0.05,
'lo' : 1.0}.
get(gain))
587 yMin =
min(0.0, rmsHistogram.GetMinimum(), sigmaHistogram.GetMinimum())
588 yMax =
max({
'hi' : 0.05,
'lo' : 1.0}.
get(gain), rmsHistogram.GetMaximum(), sigmaHistogram.GetMaximum())
593 return [amplitudeHistogram, sigmaHistogram, rmsHistogram]
597 """ This function fills 1D summary histogram per Tile module with mean value and RMS of all channels in the module """
601 inputHistogram = input[1][0]
602 nEntries = inputHistogram.GetEntries()
604 channel =
int(input[0][
'channel'])
605 bin =
int(channel) + 1
607 rms = inputHistogram.GetRMS()
608 mean = inputHistogram.GetMean()
609 histogram.SetBinContent(bin, mean)
610 histogram.SetBinError(bin, rms)
614 """ This function produces 1D summary histogram per Tile module adding all histograms per channel in the module """
616 gain = inputs[0][0][
'gain']
617 gainName = {
'hi' :
'high',
'lo' :
'low'}.
get(gain)
618 module = inputs[0][0][
'module']
619 run =
str(inputs[0][1][0].GetTitle()).
split(
' ')[1]
621 fullName = f
'{module}_{gain}_{name}'
622 fullTitle = f
'Run {run} {module} {gainName} gain: {title}'
623 inputHistogram = inputs[0][1][0]
624 sumHistogram = inputHistogram.Clone()
626 sumHistogram.SetTitle(fullTitle)
627 sumHistogram.SetName(fullName)
630 inputHistogram = input[1][0]
631 nEntries = inputHistogram.GetEntries()
633 sumHistogram.Add(inputHistogram)
639 """ This function produces 1D summary histogram per Tile module with time of all channels in the module """
645 return [timeHistogram]
649 """ This function produces 1D summary histogram per Tile module with time corrected of all channels in the module """
655 return [timeHistogram]
659 """ This function produces 1D summary histogram per Tile module with amplitude difference between offline and DSP of all channels in the module """
661 ampDiffHistogram =
getTileModuleHistogram(inputs,
'dspfit_ampdiff',
'(DSP-OFFLINE)/OFFLINE Amplitude and RMS')
665 sumAmpDiffHistogram =
getTileModuleSumHistogram(inputs,
'dspfit_amphbar',
'(DSP-OFFLINE)/OFFLINE Amplitude for all channels')
667 return [ampDiffHistogram, sumAmpDiffHistogram]
671 """ This function produces 1D summary histogram per Tile module with DSP amplitudes of all channels in the module """
676 return [amplitudeHistogram]
680 """ This function produces 1D summary histogram per Tile module with time difference between offline and DSP of all channels in the module """
688 return [timeDiffHistogram, sumTimeDiffHistogram]
693 This function converts Tile channel number to PMT number (hole/position in drawer)
695 Negative number means that PMT is not connected!
698 position = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
699 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
700 27, 26, 25, 30, 29, 28,-33,-32, 31, 36, 35, 34,
701 39, 38, 37, 42, 41, 40, 45,-44, 43, 48, 47, 46,
703 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
704 13, 14, 15, 16, 17, 18,-19,-20, 21, 22, 23, 24,
705 -27,-26,-25,-31,-32,-28, 33, 29, 30,-36,-35, 34,
706 44, 38, 37, 43, 42, 41,-45,-39,-40,-48,-47,-46 ]
708 if module.startswith(
'EB'):
710 pmt = position[channel]
714 if module
in [
'EBA15',
'EBC18']
and (channel < 4
or channel
in [18, 19]):
721 """ This function produces 1D summary histogram per Tile module with amplitude variance over mean of all channels in the module """
724 module = inputs[0][0][
'module']
739 inputHistogram = input[1][0]
740 nEntries = inputHistogram.GetEntries()
742 channel =
int(input[0][
'channel'])
743 bin =
int(channel) + 1
746 emptyPMTHistogram.SetBinContent(bin, 0.01)
747 emptyPMTHistogram.SetBinError(bin, 0.01)
749 mean = inputHistogram.GetMean()
750 rms = inputHistogram.GetRMS()
752 meanError = rms / math.sqrt(nEntries)
753 rmsError = rms / math.sqrt(2 * nEntries)
755 if mean > 10e-3
and rms > 0.:
756 varianceOverMean = rms * rms / mean - kapa * mean
757 varianceOverMeanError = (rms * rms / mean) * math.sqrt(4 * (rmsError / rms) * (rmsError / rms) +
758 (meanError / mean) * (meanError / mean))
760 varianceOverMean = -0.5
761 varianceOverMeanError = 0.001
764 evenPMTHistogram.SetBinContent(bin, varianceOverMean)
765 evenPMTHistogram.SetBinError(bin, varianceOverMeanError)
767 oddPMTHistogram.SetBinContent(bin, varianceOverMean)
768 oddPMTHistogram.SetBinError(bin, varianceOverMeanError)
771 maxY =
max(1.05 * oddPMTHistogram.GetMaximum(), 1.05 * evenPMTHistogram.GetMaximum(), 0.20)
772 minY =
min(oddPMTHistogram.GetMinimum() - 0.05 * abs(oddPMTHistogram.GetMinimum()),
773 evenPMTHistogram.GetMinimum() - 0.05 * abs(evenPMTHistogram.GetMinimum()), -0.10)
775 emptyPMTHistogram.GetYaxis().SetRangeUser(minY, maxY)
777 return [evenPMTHistogram, oddPMTHistogram, emptyPMTHistogram]
781 """ This function produces 1D summary histogram graph per Tile module with amplitude over charge ratio of all channels in the module """
785 ROOT.gROOT.SetBatch(
True)
787 from TileCalibBlobObjs.Classes
import TileCalibUtils
as Tile
789 capactior =
str(inputs[0][1][0].GetName()).
split(
'_').pop()
790 amplitudeOverQHistogram =
getTileModuleHistogram(inputs, f
'qratio_{capactior}', f
'Amplitude/Q Ratio for {capactior} pF')
792 gain = inputs[0][0][
'gain']
793 gainName = {
'hi' :
'high',
'lo' :
'low'}.
get(gain)
794 module = inputs[0][0][
'module']
795 run =
str(inputs[0][1][0].GetTitle()).
split(
' ')[1]
797 amplitudeOverQGraphName = f
'{module}_{gain}_tails_{capactior}'
798 amplitudeOverQGraphTitle = f
'Run {run} {module} {gainName} gain: Mean Amplitude/Q and up/down tails for {capactior} pF'
799 amplitudeOverQGraph = ROOT.TGraphAsymmErrors(Tile.MAX_CHAN)
800 amplitudeOverQGraph.SetName(amplitudeOverQGraphName)
801 amplitudeOverQGraph.SetTitle(amplitudeOverQGraphTitle)
806 lowIntegralLimit = 0.005
807 mediumIntegralLimit = 0.010
808 highIntegralLimit = 0.015
812 inputHistogram = input[1][0]
813 channel =
int(input[0][
'channel'])
814 nEntries = inputHistogram.GetEntries()
816 bin =
int(channel) + 1
818 mean = inputHistogram.GetMean()
819 amplitudeOverQHistogram.SetBinContent(bin, mean)
826 minBin = inputHistogram.FindFirstBinAbove(0)
827 maxBin = inputHistogram.FindLastBinAbove(0)
828 xMin = inputHistogram.GetBinCenter(minBin)
829 xMax = inputHistogram.GetBinCenter(maxBin)
830 if downLimit < mean < upLimit:
834 downLimitBin = inputHistogram.FindBin(downLimit)
837 integral = inputHistogram.Integral(0, downLimitBin)
838 ratio = integral / nEntries
839 if ratio > highIntegralLimit:
842 elif ratio > mediumIntegralLimit:
845 elif ratio > lowIntegralLimit:
854 upLimitBin = inputHistogram.FindBin(upLimit)
857 integral = inputHistogram.Integral(upLimitBin, (inputHistogram.GetNbinsX() + 1))
858 ratio = integral / nEntries
859 if ratio > highIntegralLimit:
862 elif ratio > mediumIntegralLimit:
865 elif ratio > lowIntegralLimit:
871 amplitudeOverQGraph.SetPoint(channel, channel + 0.5, mean)
872 amplitudeOverQGraph.SetPointError(channel, 0.0, 0.0,
max(0.0, mean - xMin),
max(0.0, xMax - mean))
874 amplitudeOverQGraph.SetPoint(channel, channel + 0.5, 0.0)
876 amplitudeOverQHistogram.SetStats(ROOT.kFALSE)
879 amplitudeOverQGraph.GetXaxis().SetRangeUser(0, 48)
883 return [amplitudeOverQHistogram, amplitudeOverQGraph]
887 """ This function produces 1D summary histogram per Tile module with amplitude over charge ratio of all channels in the module """
891 ROOT.gROOT.SetBatch(
True)
893 capactior =
str(inputs[0][1][0].GetName()).
split(
'_').pop()
894 timeSlopeHistogram =
getTileModuleHistogram(inputs, f
'tslope_{capactior}', f
'Time slope for {capactior} pF')
895 timeOffsetHistogram =
getTileModuleHistogram(inputs, f
'toffset_{capactior}', f
'Time offset for {capactior} pF')
897 fitFunction = ROOT.TF1(
"polfun",
"pol1", 0., 25.)
901 inputHistogram = input[1][0]
903 nEntries = inputHistogram.GetEntries()
905 profile = inputHistogram.ProfileX()
906 nBins = profile.GetNbinsX()
907 histogram = ROOT.TH1S(
"histogram",
"TMP Histogram", nBins, profile.GetBinLowEdge(1), profile.GetBinLowEdge(nBins + 1))
911 lastBinContent = -99.0
912 for xBin
in range(1, nBins + 1):
913 if profile.GetBinError(xBin) > 1e-7:
914 binContent = profile.GetBinContent(xBin)
916 if (timeShift < 1)
and (binContent - (lastBinContent + (xBin - lastBin))) < -10.0:
919 lastBinContent = binContent
920 histogram.SetBinContent(xBin, binContent + timeShift)
921 histogram.SetBinError(xBin, profile.GetBinError(xBin))
923 if histogram.GetEntries() > 1:
924 histogram.Fit(fitFunction,
"NQ")
926 channel =
int(input[0][
'channel'])
927 bin =
int(channel) + 1
930 timeOffset = fitFunction.GetParameter(0) - 25.0
931 timeOffsetError =
min(5.0, fitFunction.GetParError(0))
932 timeOffsetHistogram.SetBinContent(bin, timeOffset)
933 timeOffsetHistogram.SetBinError(bin, timeOffsetError)
935 timeSlope = fitFunction.GetParameter(1)
936 timeSlopeError =
min(5.0, fitFunction.GetParError(1))
937 timeSlopeHistogram.SetBinContent(bin, timeSlope)
938 timeSlopeHistogram.SetBinError(bin, timeSlopeError)
943 return [timeSlopeHistogram, timeOffsetHistogram]
946 if __name__==
'__main__':
949 parser= argparse.ArgumentParser()
951 parser.add_argument(
'--stateless', action=
"store_true", help=
'Run Online Tile Post Processing in partition')
952 parser.add_argument(
'--tmdb', action=
"store_true", help=
'Run Tile TMDB Post Processing')
953 parser.add_argument(
'--digi-noise', action=
"store_true", dest=
'digiNoise', help=
'Run Tile Digi Noise Post Processing')
954 parser.add_argument(
'--raw-chan-noise', action=
"store_true", dest=
'rawChanNoise', help=
'Run Tile Digi Noise Post Processing')
955 parser.add_argument(
'--interval', type=int, default=60, help=
'Interval (in seconds) to run Tile Monitoring Post Processing')
956 parser.add_argument(
'--noise-interval', type=int, default=300, dest=
'noiseInterval',
957 help=
'Interval (in seconds) to run Tile Noise Monitoring Post Processing')
959 args = parser.parse_args()
963 server =
'Histogramming'
964 partition = os.getenv(
"TDAQ_PARTITION",
"ATLAS")
969 print(
'Terminating postporcessing ...')
972 signal.signal(signal.SIGTERM, sigtermHandler)
976 inputPath = f
'{partition};{server};TileMIG:TileGatherer'
977 outputPath = f
'{partition};{server};TilePT-stateless-PP'
979 physConfigurations = []
981 physConfigurations += [os.path.join(dataPath,
'TileTMDBPostProc.yaml')]
983 physPostProcess = ([
'histgrinder', inputPath, outputPath,
984 '--inmodule',
'DQOnlinePostprocessing.atlas_oh.OHInputModule',
985 '--outmodule',
'DQOnlinePostprocessing.atlas_oh.OHOutputModule',
986 '--prefix',
'/',
'-c'] + physConfigurations)
988 subprocess.run(physPostProcess)
990 elif any([args.digiNoise, args.rawChanNoise]):
992 inputPath = f
'{partition};{server};TilePT-stateless-noise-01'
993 outputPath = f
'{partition};{server};TilePT-stateless-noise-PP'
995 noiseConfigurations = []
997 noiseConfigurations += [os.path.join(dataPath,
'TileDigiNoisePostProc.yaml')]
998 if args.rawChanNoise:
999 noiseConfigurations += [os.path.join(dataPath,
'TileRawChanNoisePostProc.yaml')]
1001 noisePostProcess = ([
'histgrinder', inputPath, outputPath,
1002 '--inmodule',
'DQOnlinePostprocessing.atlas_oh.OHInputModule',
1003 '--outmodule',
'DQOnlinePostprocessing.atlas_oh.OHOutputModule',
1004 '--prefix',
'/',
'-c'] + noiseConfigurations)
1006 subprocess.run(noisePostProcess)