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 + ')')
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']: 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(math.sqrt(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) for det in ['li6', 'he3']: ex[det + 'backgroundrate'], ex[ det + 'backgroundrateerr'] = UCN.PrintBackgroundVsCycle( ex, pdf, det) ex[det + 'irradiationrate'], ex[ det + 'irradiationrateerr'] = UCN.SubtractBackgroundAndNormalizeRate( ex[det + 'irradiation'], ex['irradiationduration'], det, beam[0], beam[1]) UCN.PrintIrradiationBackgroundVsCycle(ex, pdf, det) print(det + ' detector background rate: {0:.4} +/- {1:.2} 1/s'.format( ex[det + 'backgroundrate'], ex[det + 'backgroundrateerr'])) 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']