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']
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): print('\nAnalyzing TCN' + ex['TCN']) if len(ex['start']) == 0: print('Found no cycles with run numbers {0}!'.format(ex['runs'])) return canvas = ROOT.TCanvas('c', 'c') pdf = 'TCN{0}.pdf'.format(ex['TCN']) # subtract background from Li6 counts and normalize to monitor counts y, yerr = UCN.SubtractBackgroundAndNormalize(ex['li6counts'], ex['countduration'], 'li6', ex['monitorcounts2'], [math.sqrt(m) for m in ex['monitorcounts2']]) x = ex['storageduration'] xerr = [0. for _ in ex['storageduration']] # 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) canvas.SetLogy() #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 + '(') ex['tau'] = f.GetParams()[1] ex['tauerr'] = f.GetErrors()[1]*max(math.sqrt(f.Chi2()/f.Ndf()), 1.0) # do double exponential fit graph.SetTitle('TCN{0} (double exponential fit, with background subtracted, normalized to monitor detector, 0s excluded)'.format(ex['TCN'])) f = graph.Fit(UCN.DoubleExpo(), 'SQB', '', 1., 1000.) graph.Draw('AP') canvas.Print(pdf) print('{0} +/- {1}, {2} +/- {3} (double exponential fit, with background subtracted, normalized to monitor detector, 0s excluded)'.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])) # draw plot of temperature during each cycle UCN.PrintTemperatureVsCycle(ex, pdf) mtau = [] mtauerr = [] # fit single exponential to He3 count-rate histogram during storage period (pinhole method) for he3rate, m, s, c in zip(ex['he3rate'], ex['monitorduration'], ex['storageduration'], ex['countduration']): fitstart = m + 5 fitend = m + s # if not ex['pinhole']: # fitend = fitend + c if fitend > fitstart + 10 and he3rate.Integral(he3rate.FindBin(fitstart), he3rate.FindBin(fitend)) > 0: f = he3rate.Fit(UCN.SingleExpo(), 'SQB', '', fitstart, fitend) he3rate.SetTitle('TCN{0} (He3 rate)'.format(ex['TCN'])) he3rate.Draw() canvas.Print(pdf) # print fitted He3 rate to pdf mtau.append(f.GetParams()[1]) mtauerr.append(f.GetErrors()[1]*max(math.sqrt(f.Chi2()/f.Ndf()), 1.0)) # print average storage lifetime from He3 fits to pdf canvas = ROOT.TCanvas('c','c') if len(mtau) > 0: he3tau = ROOT.TGraphErrors(len(mtau), numpy.array(ex['cyclenumber']), numpy.array(mtau), numpy.array([0. for _ in mtau]), numpy.array(mtauerr)) fit = he3tau.Fit('pol0', 'SQ') ex['pinholetau'] = fit.Parameter(0) ex['pinholetauerr'] = fit.ParError(0)*max(math.sqrt(f.Chi2()/f.Ndf()), 1.0) he3tau.SetMarkerStyle(20) he3tau.GetXaxis().SetTitle('Cycle') he3tau.GetYaxis().SetTitle('Pinhole storage lifetime (s)') he3tau.SetTitle('') he3tau.Draw('AP') print('{0} +/- {1} (single exponential fit to rate in monitor detector during storage period)'.format(fit.Parameter(0), fit.ParError(0))) else: ex['pinholetau'] = 0. ex['pinholetauerr'] = 0. canvas.Print(pdf) # draw plot of Li6 background rate during each cycle ex['li6backgroundrate'], ex['li6backgroundrateerr'] = UCN.PrintBackgroundVsCycle(ex, pdf, 'li6') 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']] # subtract background from Li6 counts during irradiation and normalize to beam current, draw plot for each cycle ex['li6irradiationrate'], ex['li6irradiationrateerr'] = UCN.SubtractBackgroundAndNormalizeRate(ex['li6irradiation'], ex['irradiationduration'], 'li6', beam[0], beam[1]) UCN.PrintIrradiationBackgroundVsCycle(ex, pdf, 'li6') # report average monitor counts, range of beam current, range of He-II temperature monitoravg = numpy.average(ex['monitorcounts2'], None, [1./m for m in ex['monitorcounts2']], 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']))) # draw Li6 channel histogram ex['channels'].Draw() canvas.Print(pdf + ')')