def Transmission(ex): print('\nAnalyzing TCN{0}'.format(ex['TCN'])) if len(ex['start']) == 0: print('Found no cycles with run numbers {0}!'.format(ex['runs'])) return ex['li6backgroundrate'], ex['li6backgroundrateerr'] = UCN.BackgroundRate( ex['li6background'], ex['backgroundduration']) ex['li6irradiationrate'], ex['li6irradiationrateerr'] = UCN.SubtractBackgroundAndNormalizeRate(ex['li6irradiation'], ex['irradiationduration'], 'li6', \ [numpy.mean(cur) for cur in ex['beamcurrent']], [numpy.std(cur) for cur in ex['beamcurrent']]) print('Li6 background rate: {0} +/- {1} 1/s'.format( ex['li6backgroundrate'], ex['li6backgroundrateerr'])) # report average monitor counts monitoravg = numpy.average(ex['monitorcounts'], None, [1. / m for m in ex['monitorcounts']], True) print('Monitor counts: {0} +/- {1}'.format(monitoravg[0], 1. / math.sqrt(monitoravg[1]))) # report range of beam current print('Beam current from {0} to {1} uA'.format( min(min(c) for c in ex['beamcurrent']), max(max(c) for c in ex['beamcurrent']))) # report He-II temperature range print('Temperatures from {0} to {1} K'.format(min(ex['mintemperature']), max(ex['maxtemperature']))) canvas = ROOT.TCanvas('c', 'c') pdf = 'TCN{0}.pdf'.format(ex['TCN']) # plot ratio of background-corrected counts to monitor counts during counting y, yerr = UCN.SubtractBackgroundAndNormalize( ex['li6counts'], ex['countduration'], 'li6', ex['monitorcounts'], [math.sqrt(c) for c in ex['monitorcounts']]) graph = ROOT.TGraphErrors(len(y), numpy.array(ex['cyclenumber']), numpy.array(y), numpy.array([0. for _ in ex['cyclenumber']]), numpy.array(yerr)) graph.SetTitle('TCN{0}, normalized during counting'.format(ex['TCN'])) graph.GetXaxis().SetTitle('Cycle') graph.GetXaxis().SetLimits(0., max(ex['cyclenumber'])) graph.GetYaxis().SetTitle('UCN-count-to-monitor ratio') graph.SetMarkerStyle(20) transfit = ROOT.TF1('transfit', 'pol0', 0, 100) transfit.SetParName(0, '#bar{R}_{c}') f = graph.Fit(transfit, 'QS') graph.Draw('AP') canvas.Print(pdf + '(') ex['transmission'] = f.GetParams()[0] ex['transmissionerr'] = f.GetErrors()[0] * max(f.Chi2() / f.Ndf(), 1.) print('Li6-to-He3 ratio during counting: {0} +/- {1}'.format( ex['transmission'], ex['transmissionerr'])) if min(ex['monitorcounts2']) > 0: # plot ratio of background-corrected counts to monitor counts during irradiation y, yerr = UCN.SubtractBackgroundAndNormalize( ex['li6counts2'], ex['countduration2'], 'li6', ex['monitorcounts2'], [math.sqrt(c) for c in ex['monitorcounts2']]) graph = ROOT.TGraphErrors(len(y), numpy.array(ex['cyclenumber']), numpy.array(y), numpy.array([0. for _ in ex['cyclenumber']]), numpy.array(yerr)) graph.SetTitle('TCN{0}, normalized during irradiation'.format( ex['TCN'])) graph.GetXaxis().SetTitle('Cycle') graph.GetXaxis().SetLimits(0., max(ex['cyclenumber'])) graph.GetYaxis().SetTitle('UCN-count-to-monitor ratio') graph.SetMarkerStyle(20) transfit.SetParName(0, '#bar{R}_{i}') f = graph.Fit(transfit, 'QS') graph.Draw('AP') canvas.Print(pdf) ex['transmission2'] = f.GetParams()[0] ex['transmission2err'] = f.GetErrors()[0] * max(f.Chi2() / f.Ndf(), 1.) print('Li6-to-He3 ratio during irradiation: {0} +/- {1}\n'.format( ex['transmission2'], ex['transmission2err'])) UCN.PrintTemperatureVsCycle(ex, pdf) he3axis = ex['He3rate'][0].GetXaxis() he3rate = ROOT.TH1D('TCN{0}_He3'.format(ex['TCN']), ';Time (s); He3 rate (1/s)', he3axis.GetNbins(), he3axis.GetXmin(), he3axis.GetXmax()) he3rate.SetDirectory(0) for he3 in ex['He3rate']: he3rate.Add(he3) satfit = ROOT.TF1( 'satfit', '[0]*(erfc(sqrt([1]/x)-sqrt(x/[2]))-exp(4*sqrt([1]/[2]))*erfc(sqrt([1]/x)+sqrt(x/[2])))', 0, 60) for i, p in enumerate( zip([500., 12., 30.], [10000., 100., 100.], ['p_{0}', '#tau_{d}', '#tau'])): satfit.SetParameter(i, p[0]) satfit.SetParName(i, p[2]) fit = he3rate.Fit(satfit, 'MRSQ') he3rate.Draw() canvas.Print(pdf) li6fit = ROOT.TF1( 'li6fit', '(x<60 + [0]?0:[1])*(1 - exp(-(x - 60 - [0])/[2]))*(exp(-(x - 60 - [0])/[3]) + [4]*exp(-(x - 60 - [0])/[5]) +[6]*exp(-(x - 60 - [0])/[7])) + [8]', 60, 180) li6axis = ex['Li6rate'][0].GetXaxis() binwidth = li6axis.GetBinWidth(1) li6rate = ROOT.TH1D('TCN{0}_Li6'.format(ex['TCN']), ';Time (s); Li6 rate (1/{0}s)'.format(binwidth), li6axis.GetNbins(), li6axis.GetXmin(), li6axis.GetXmax()) li6rate.SetDirectory(0) for h in ex['Li6rate']: li6rate.Add(h) li6fit.SetNpx(li6rate.GetNbinsX()) li6fit.SetParameters(1.5, 1000., 0.2, 1.5, 1., 14., 0.1, 30.) for i, p in enumerate( zip([5, 1e5, 5., 10., 10, 30., 10., 100.], [ 't_{d}', 'p_{0}', '#tau_{rise}', '#tau_{1}', 'N_{2}', '#tau_{2}', 'N_{3}', '#tau_{3}' ])): li6fit.SetParLimits(i, 0., p[0]) li6fit.SetParName(i, p[1]) li6fit.FixParameter(8, UCN.DetectorBackground['li6'][0] * binwidth) li6fit.SetParError(8, UCN.DetectorBackground['li6'][1] * binwidth) li6rate.Fit(li6fit, 'MRSQL', '') # canvas.SetLogy() li6rate.Draw() canvas.Print(pdf) # canvas.SetLogy(0) li6background = ROOT.TH1D( 'Li6background', ';Time (s); Li6 background rate (1/{0}s)'.format(binwidth), li6axis.GetNbins(), li6axis.GetXmin(), li6axis.GetXmax()) li6background.SetDirectory(0) for b in range(li6background.GetNbinsX()): li6background.SetBinContent( b, UCN.DetectorBackground['li6'][0] * li6background.GetBinWidth(b)) li6background.SetBinError( b, UCN.DetectorBackground['li6'][1] * li6background.GetBinWidth(b)) li6background.Sumw2() li6norm = ROOT.TH1D( 'TCN{0}_Li6_norm'.format(ex['TCN']), ';Time (s);Li6 rate normalized during counting (1/{0}s)'.format( binwidth), int(li6axis.GetNbins() / 4.), li6axis.GetXmin(), li6axis.GetXmax()) li6norm.SetDirectory(0) for li6, m in zip(ex['Li6rate'], ex['monitorcounts']): li6copy = li6.Clone() li6copy.Add(li6background, -1.) li6copy.Rebin(4) normhist = ROOT.TH1D('normhist', ';Time (s);Normalization factor', int(li6axis.GetNbins() / 4.), li6axis.GetXmin(), li6axis.GetXmax()) for b in range(normhist.GetNbinsX()): normhist.SetBinContent(b, m) normhist.SetBinError(b, math.sqrt(m)) normhist.Sumw2() li6copy.Divide(normhist) li6copy.SetBit(ROOT.TH1.kIsAverage) li6norm.Add(li6copy) li6norm.SetBit(ROOT.TH1.kIsAverage) li6norm.Draw() canvas.Print(pdf) ex['Li6rate_normalized'] = li6norm li6norm2 = ROOT.TH1D( 'TCN{0}_Li6_norm'.format(ex['TCN']), ';Time (s);Li6 rate normalized during irradiation (1/{0}s)'.format( binwidth), int(li6axis.GetNbins() / 4.), li6axis.GetXmin(), li6axis.GetXmax()) li6norm2.SetDirectory(0) for li6, m in zip(ex['Li6rate'], ex['monitorcounts2']): li6copy = li6.Clone() li6copy.Add(li6background, -1.) li6copy.Rebin(4) normhist2 = ROOT.TH1D('normhist', ';Time (s);Normalization factor', int(li6axis.GetNbins() / 4.), li6axis.GetXmin(), li6axis.GetXmax()) for b in range(normhist2.GetNbinsX()): normhist2.SetBinContent(b, m) normhist2.SetBinError(b, math.sqrt(m)) normhist2.Sumw2() li6copy.Divide(normhist2) li6copy.SetBit(ROOT.TH1.kIsAverage) li6norm2.Add(li6copy) li6norm2.SetBit(ROOT.TH1.kIsAverage) li6norm2.Draw() canvas.Print(pdf) ex['Li6rate_normalized2'] = li6norm2 li6rate.SetStats(False) li6rate.GetYaxis().SetTitle('Ratio of cumulated rates') li6rate.Add(li6background, -len(ex['Li6rate'])) li6rate.Rebin(int(1. / binwidth)) li6rate.Divide(he3rate) li6rate.Draw('HIST') canvas.Print(pdf) rateratio = ROOT.TH1D('TCN{0}_ratio'.format(ex['TCN']), ';Time (s);Average rate ratio', int(he3axis.GetNbins() / 10.), he3axis.GetXmin(), he3axis.GetXmax()) rateratio.SetDirectory(0) for li6, he3 in zip(ex['Li6rate'], ex['He3rate']): li6.Add(li6background, -1) li6.Rebin(int(10. / binwidth)) he3.Rebin(10) li6.Divide(he3) # li6.Draw() # canvas.Print(pdf) li6.SetBit(ROOT.TH1.kIsAverage) rateratio.Add(li6) rateratio.SetBit(ROOT.TH1.kIsAverage) rateratio.Draw() canvas.Print(pdf) ex['channels'].Draw() canvas.Print(pdf) window = ROOT.TH1I('li6window', 'Li6 window;Time after valve opened (s);Frequency', 100, 0., 5.) for w in ex['li6window']: window.Fill(w[0]) window.Draw() canvas.Print(pdf + ')')
def StorageLifetime(ex): print('\nAnalyzing TCN' + ex['TCN']) if len(ex['start']) == 0: print('Found no cycles with run numbers {0}!'.format(ex['runs'])) return ex['li6backgroundrate'], ex['li6backgroundrateerr'] = UCN.BackgroundRate( ex['li6background'], ex['backgroundduration']) print('Li6 detector background rate: {0} +/- {1} 1/s'.format( ex['li6backgroundrate'], ex['li6backgroundrateerr'])) beam = [numpy.mean(cur) for cur in ex['beamcurrent'] ], [numpy.std(cur) for cur in ex['beamcurrent']] ex['li6irradiationrate'], ex[ 'li6irradiationrateerr'] = UCN.SubtractBackgroundAndNormalizeRate( ex['li6irradiation'], ex['irradiationduration'], 'li6', beam[0], beam[1]) # report average monitor counts, range of beam current, range of He-II temperature monitoravg = numpy.average(ex['monitorcounts'], None, [1. / m for m in ex['monitorcounts']], True) print 'Monitor counts: {0} +/- {1}'.format(monitoravg[0], 1. / math.sqrt(monitoravg[1])) print('Beam current from {0} to {1} uA'.format( min(min(c) for c in ex['beamcurrent']), max(max(c) for c in ex['beamcurrent']))) print 'Temperatures from {0} to {1} K'.format(min(ex['mintemperature']), max(ex['maxtemperature'])) x = ex['storageduration'] xerr = [0. for _ in ex['storageduration']] y, yerr = UCN.SubtractBackgroundAndNormalize( ex['li6counts'], ex['countduration'], 'li6', ex['monitorcounts'], [math.sqrt(m) for m in ex['monitorcounts']]) # plot normalized, background corrected counts vs storage time graph = ROOT.TGraphErrors(len(x), numpy.array(x), numpy.array(y), numpy.array(xerr), numpy.array(yerr)) graph.SetTitle( 'TCN{0} (single exponential fit, with background subtracted, normalized to monitor detector)' .format(ex['TCN'])) graph.GetXaxis().SetTitle('Storage time (s)') graph.GetYaxis().SetTitle('UCN-count-to-monitor ratio') # graph.SetMarkerStyle(20) # do single exponential fit f = graph.Fit(UCN.SingleExpo(), 'SQB', '', 0., 1000.) canvas = ROOT.TCanvas('c', 'c') canvas.SetLogy() graph.Draw('AP') pdf = 'TCN{0}.pdf'.format(ex['TCN']) canvas.Print(pdf + '(') ex['tau'] = f.GetParams()[1] ex['tauerr'] = f.GetErrors()[1] print( '{0} +/- {1} (single exponential fit, with background subtracted, normalized to monitor detector)' .format(ex['tau'], ex['tauerr'])) #do single exponential fit with data point at 0 excluded f = graph.Fit(UCN.SingleExpo(), 'SQB', '', 1., 1000.) graph.SetTitle( 'TCN{0} (single exponential fit, with background subtracted, normalized to monitor detector, 0s excluded)' .format(ex['TCN'])) graph.Draw('AP') canvas.Print(pdf) # do double exponential fit graph.SetTitle( 'TCN{0} (double exponential fit, with background subtracted, normalized to monitor detector)' .format(ex['TCN'])) f = graph.Fit(UCN.DoubleExpo(), 'SQB') graph.Draw('AP') canvas.Print(pdf) print( '{0} +/- {1}, {2} +/- {3} (double exponential fit, with background subtracted, normalized to monitor detector)' .format(f.GetParams()[1], f.GetErrors()[1], f.GetParams()[3], f.GetErrors()[3])) # plot uncorrected UCN counts y = [float(c) for c in ex['li6counts']] yerr = [math.sqrt(c) for c in ex['li6counts']] graph = ROOT.TGraphErrors(len(x), numpy.array(x), numpy.array(y), numpy.array(xerr), numpy.array(yerr)) graph.SetTitle( 'TCN{0} (single exponential fit + background, unnormalized)'.format( ex['TCN'])) graph.GetXaxis().SetTitle('Storage time (s)') graph.GetYaxis().SetTitle('UCN count') # do single exponential fit with background f = graph.Fit(UCN.SingleExpoWithBackground(), 'SQB') graph.Draw('AP') canvas.Print(pdf) print( '{0} +/- {1} (single exponential fit with {2} +/- {3} background, unnormalized)' .format(f.GetParams()[1], f.GetErrors()[1], f.GetParams()[2], f.GetErrors()[2])) mtau = [] mtauerr = [] for he3rate, m, s in zip(ex['he3rate'], ex['monitorduration'], ex['storageduration']): fitstart = m + 5 fitend = m + s if fitend > fitstart + 10 and he3rate.Integral( he3rate.FindBin(fitstart), he3rate.FindBin(fitend)) > 0: f = he3rate.Fit(UCN.SingleExpo(), 'SQB', '', fitstart, fitend) he3rate.Draw() canvas.Print(pdf) # print fitted He3 rate to pdf mtau.append(f.GetParams()[1]) mtauerr.append(f.GetErrors()[1]) # print average storage lifetime from He3 fits to pdf canvas = ROOT.TCanvas('c', 'c') if len(mtau) > 0: tauavg = numpy.average(mtau, None, [1. / dt**2 for dt in mtauerr], True) label = ROOT.TLatex(0.1, 0.6, 'Average lifetime from He3 data:') label.Draw() label2 = ROOT.TLatex( 0.1, 0.5, '#tau = {0} +/- {1} s'.format(tauavg[0], 1. / tauavg[1]**2)) label2.Draw() print( '{0} +/- {1} (single exponential fit to rate in monitor detector during storage period)' .format(tauavg[0], 1. / tauavg[1]**2)) canvas.Print(pdf + ')')
def StorageLifetime(ex, FitResult=None): print('\nAnalyzing TCN{0} in runs {1}'.format(ex['TCN'], ex['runs'])) if len(ex['start']) == 0: print('Found no cycles with run numbers {0}!'.format(ex['runs'])) return # report start time print(datetime.datetime.fromtimestamp(min(ex['start']))) # report range of beam current print('Beam current from {0:.3} to {1:.3} uA'.format( min(min(c) for c in ex['beamcurrent']), max(max(c) for c in ex['beamcurrent']))) # report range of temperature and vapor pressure print('Temperatures from {0:.3} to {1:.3} K'.format( min(ex['mintemperature']), max(ex['maxtemperature']))) print('Vapor pressure from {0:.3} to {1:.3} torr'.format( min(ex['minvaporpressure']), max(ex['maxvaporpressure']))) beam = [numpy.mean(cur) for cur in ex['beamcurrent'] ], [numpy.std(cur) for cur in ex['beamcurrent']] canvas = ROOT.TCanvas('c1', 'c1') canvas.SetLogy() for det in ['li6', 'he3']: ex[det + 'backgroundrate'], ex[det + 'backgroundrateerr'] = UCN.BackgroundRate( ex[det + 'background'], ex['backgroundduration']) ex[det + 'irradiationrate'], ex[ det + 'irradiationrateerr'] = UCN.SubtractBackgroundAndNormalizeRate( ex[det + 'irradiation'], ex['irradiationduration'], det, beam[0], beam[1]) print(det + ' detector background rate: {0:.4} +/- {1:.2} 1/s'.format( ex[det + 'backgroundrate'], ex[det + 'backgroundrateerr'])) x = numpy.array(ex['storageduration']) xerr = numpy.array([0. for _ in x]) # subtract background from UCN counts ex[det + 'counts_normalized'], ex[ det + 'counts_normalized_err'] = UCN.SubtractBackgroundAndNormalize( ex[det + 'counts'], ex['countduration'], det, beam[0], beam[1]) y = numpy.array(ex[det + 'counts_normalized']) yerr = numpy.array(ex[det + 'counts_normalized_err']) # plot normalized Li6 counts vs storage time graph = ROOT.TGraphErrors(len(x), x, y, xerr, yerr) graph.SetTitle( 'TCN{0} ({1} detector, single exponential fit, background subtracted, normalized to beam current)' .format(ex['TCN'], det)) graph.GetXaxis().SetTitle('Storage time (s)') graph.GetYaxis().SetTitle('UCN count (#muA^{-1})') # graph.SetMarkerStyle(20) # do single exponential fit f = graph.Fit(UCN.SingleExpo(), 'SQB') if sum(y) > 0 and f.Error(1) < 5.: ex[det + 'tau'] = f.Parameter(1) ex[det + 'tauerr'] = f.Error(1) * max(f.Chi2() / f.Ndf(), 1.) else: print( 'SKIPPING lifetime measurement from {0} detector in run(s) {1} because there were no counts detected or the error is larger than 5 s.' .format(det, ex['runs'])) ex[det + 'tau'] = 0. ex[det + 'tauerr'] = 0. print( '{0:.4} +/- {1:.2} ({2} detector, single exponential fit, background subtracted, normalized to beam current)' .format(ex[det + 'tau'], ex[det + 'tauerr'], det)) graph.Draw('AP') pdf = 'TCN{0}_{1}.pdf'.format(ex['TCN'], ex['runs'][0]) if det == 'li6': canvas.Print(pdf + '(') else: canvas.Print(pdf) if FitResult: r = DoCombinedFit([ex], pdf, FitResult) print('{0:.4} +/- {1:.2} (wall-storage lifetime from combined fit)'. format(ex['tau_wall'], ex['tau_wallerr'])) canvas.SetLogy(0) UCN.PrintTemperatureVsCycle(ex, pdf) ex['channels'].Draw() canvas.Print(pdf + ')') # return result from primary detector if max(ex['li6counts']) > max(ex['he3counts']): ex['tau'] = ex['li6tau'] ex['tauerr'] = ex['li6tauerr'] else: ex['tau'] = ex['he3tau'] ex['tauerr'] = ex['he3tauerr']