def fit_real_data(label): ''' Fit dataset specified by the label: "data" (full 2011A+B), "2011A" or "2011B". ''' fit_result = pm.fitTo(data[label], roo.Range('fit'), roo.NumCPU(8), roo.Timer(), # roo.Verbose() roo.InitialHesse(True), roo.Minos(), roo.Save(), ) w.Import(fit_result, 'fitresult_' + label)
's_{fit}: %.3f #pm %.3f %%' % (phoScale.getVal(), phoScale.getError()), 's_{fit} - s_{shape}: %.4f #pm %.4f %%' % ( phoScale.getVal() - t2pdf.s0val, phoScale.getError() ), 'r_{shape}: %.3f %%' % t2pdf.r0val, 'r_{fit}: %.3f #pm %.3f %%' % (phoRes.getVal(), phoRes.getError()), 'r_{fit}/r_{shape}: %.4f #pm %.4f' % ( phoRes.getVal() / t2pdf.r0val, phoRes.getError() / t2pdf.r0val), ], position=(0.2, 0.75)).draw() canvases.update() t.setRange(*t1range) xtpdf.fitTo(xtdata, roo.NumCPU(8), roo.Verbose(True), roo.Timer(True), roo.SumW2Error(True), roo.Minos(ROOT.RooArgSet(phoRes))) ## Plot fXT(t|s,r) fitted to data ## canvases.next('tpdf').SetGrid() ## t.setRange(5, 10) ## t.SetTitle('log(m_{#mu#mu#gamma}^{2} - m_{#mu#mu}^{2})') ## tpdf.fitTo(tdata, roo.Range(5.5, 9.5)) ## plot = t.frame(roo.Range(6, 9)) ## tdata.plotOn(plot) ## tpdf.plotOn(plot) ## tpdf.paramOn(plot) ## plot.Draw() canvases.update() sw.Stop() print 'CPU time:', sw.CpuTime(), 's, real time:', sw.RealTime(), 's'
unitg = w.factory('Gaussian::unitg(pull[-5,5],zero[0],unit[1])') pull = w.var('pull') defaultd = ROOT.RooDataSet('defaultd', 'defaultd', ROOT.RooArgSet(pull)) bind = ROOT.RooDataSet('bind', 'bind', ROOT.RooArgSet(pull)) mediand = ROOT.RooDataSet('mediand', 'mediand', ROOT.RooArgSet(pull)) pdgd = ROOT.RooDataSet('pdgd', 'pdgd', ROOT.RooArgSet(pull)) ## Build the model # model = w.factory('Gaussian::gaus(x[-5,5],mean[0,-6,6],sigma[1,0.5,2])') model = w.factory('RooSechPdf::sech(x[-5,5],mean[0,-6,6],sigma[1,0.5,2])') x = w.factory('x') for itoy in range(ntoys): ## Use the model to generate a toy dataset data = model.generate(ROOT.RooArgSet(x), nentries, roofit.NumCPU(numCPU)) ## Fit the model to the generated data model.fitTo(data, roofit.NumCPU(numCPU), roofit.Verbose(False)) ## Get custom binning nevents = data.tree().Draw(x.GetName(), '', 'goff') bins = DataDrivenBinning(nevents, data.tree().GetV1(), minBinContent, maxBinContent) binning = bins.binning(ROOT.RooBinning()) ubinning = bins.uniformBinning(ROOT.RooUniformBinning()) ## Make sure that there are at least 1./epsilonPerBin curve points ## in each bin. The RooChi2Calculator fails if there is none perhaps ## due to a bug in RooCurve::average? Reason is not understood yet. epsilon = epsilonPerBin * ubinning.binWidth(0) / bins.length()
def process_monte_carlo(): ''' Get, fit and plot monte carlo. ''' global fitdata1 fitdata1 = fit_calibrator.get_smeared_data( sfit, rfit, 'fitdata1', 'fitdata1', True ) fitdata1.reduce(ROOT.RooArgSet(mmgMass, mmMass)) fitdata1.append(data['zj1']) fitdata1.SetName('fitdata1') data['fit1'] = fitdata1 if reduce_data == True: fitdata1 = fitdata1.reduce(roo.Range(reduced_entries, fitdata1.numEntries())) check_timer('3. get fit data (%d entries)' % fitdata1.numEntries()) nll = pm.createNLL(fitdata1, roo.Range('fit'), roo.NumCPU(8)) minuit = ROOT.RooMinuit(nll) minuit.setProfile() minuit.setVerbose() phoScale.setError(1) phoRes.setError(1) ## Initial HESSE status = minuit.hesse() fitres = minuit.save(name + '_fitres1_inithesse') w.Import(fitres, fitres.GetName()) check_timer('4. initial hesse (status: %d)' % status) ## Minimization minuit.setStrategy(2) status = minuit.migrad() fitres = minuit.save(name + '_fitres2_migrad') w.Import(fitres, fitres.GetName()) check_timer('5. migrad (status: %d)' % status) ## Parabolic errors status = minuit.hesse() fitres = minuit.save(name + '_fitres3_hesse') w.Import(fitres, fitres.GetName()) check_timer('6. hesse (status: %d)' % status) ## Minos errors status = minuit.minos() fitres = minuit.save(name + '_fitres4_minos') w.Import(fitres, fitres.GetName()) check_timer('7. minos (status: %d)' % status) #fres = pm.fitTo(fitdata1, roo.SumW2Error(True), #roo.Range('fit'), ## roo.Strategy(2), #roo.InitialHesse(True), #roo.Minos(), #roo.Verbose(True), #roo.NumCPU(8), roo.Save(), roo.Timer()) signal_model._phorhist.GetXaxis().SetRangeUser(75, 105) signal_model._phorhist.GetYaxis().SetRangeUser(0, 15) signal_model._phorhist.GetXaxis().SetTitle('%s (%s)' % (mmgMass.GetTitle(), mmgMass.getUnit())) signal_model._phorhist.GetYaxis().SetTitle('E^{#gamma} Resolution (%)') signal_model._phorhist.GetZaxis().SetTitle('Probability Density (1/GeV/%)') signal_model._phorhist.SetTitle(latex_title) signal_model._phorhist.GetXaxis().SetTitleOffset(1.5) signal_model._phorhist.GetYaxis().SetTitleOffset(1.5) signal_model._phorhist.GetZaxis().SetTitleOffset(1.5) signal_model._phorhist.SetStats(False) canvases.next(name + '_phorhist') signal_model._phorhist.Draw('surf1') global graph graph = signal_model.make_mctrue_graph() graph.GetXaxis().SetTitle('E^{#gamma} resolution (%)') graph.GetYaxis().SetTitle('m_{#mu^{+}#mu^{-}#gamma} effective #sigma (GeV)') graph.SetTitle(latex_title) canvases.next(name + '_mwidth_vs_phor').SetGrid() graph.Draw('ap') mmgMass.setBins(80) plot = mmgMass.frame(roo.Range('plot')) plot.SetTitle('Fall11 MC, ' + latex_title) fitdata1.plotOn(plot) pm.plotOn(plot, roo.Range('plot'), roo.NormRange('plot')) pm.plotOn(plot, roo.Range('plot'), roo.NormRange('plot'), roo.Components('*zj*'), roo.LineStyle(ROOT.kDashed)) canvases.next(name + '_fit').SetGrid() plot.Draw() ## Estimate the MC truth phos and phor: old_precision = set_default_integrator_precision(2e-9, 2e-9) calibrator0.s.setRange(-15, 15) calibrator0.r.setRange(0,25) calibrator0.phoEResPdf.fitTo(fitdata1, roo.Range(-50, 50), roo.Strategy(2)) set_default_integrator_precision(*old_precision) set_mc_truth(calibrator0.s, calibrator0.r) ## Store the result in the workspace: w.saveSnapshot('mc_fit', ROOT.RooArgSet(phoScale, phoRes, phoScaleTrue, phoResTrue)) ## Draw the results on the canvas: Latex([ 'E^{#gamma} Scale (%)', ' MC Truth: %.2f #pm %.2f' % (calibrator0.s.getVal(), calibrator0.s.getError()), ' MC Fit: %.2f #pm %.2f ^{+%.2f}_{%.2f}' % ( phoScale.getVal(), phoScale.getError(), phoScale.getErrorHi(), phoScale.getErrorLo() ), '', 'E^{#gamma} Resolution (%)', ' MC Truth: %.2f #pm %.2f' % (calibrator0.r.getVal(), calibrator0.r.getError()), ' MC Fit: %.2f #pm %.2f ^{+%.2f}_{%.2f}' % ( phoRes.getVal(), phoRes.getError(), phoRes.getErrorHi(), phoRes.getErrorLo() ), '', 'Signal Purity (%)', ' MC Truth: %.2f' % fsr_purity, ' MC Fit: %.2f #pm %.2f' % ( 100 * w.var('signal_f').getVal(), 100 * w.var('signal_f').getError() ) ], position=(0.2, 0.8) ).draw() check_timer('8. fast plots')
def __init__(self, name, title, mass, phos, phor, data, workspace, phostarget, phortargets, rho=1.5, mirror=ROOT.RooKeysPdf.NoMirror, mrangetrain=(40, 140), mrangenorm=(50, 130), mrangefit=(60, 120)): '''PhosphorModel4(str name, str title, RooRealVar mass, RooRealVar phos, RooRealVar phor, RooDataSet data, float phostarget, [float] phortargets, float rho=1.5, int mirror=ROOT.RooKeysPdf.NoMirror) name - PDF name title - PDF title mass - mumugamma invariant mass (GeV), observable phos - photon energy scale (%), parameter phor - photon energy resolution (%), paramter data - (mmMass, mmgMass, phoERes = 100*(phoEreco/phoEgen - 1), dataset on which the shapes of reference PDFs are trained. phostarget - target reference value of the photon energy scale at which the model is being trained phortargetss - a list of target photon energy resolution values for the moment morphing rho - passed to trained RooKeysPdfs mirror - passed to trained RooKeysPdfs ''' ## Attach args. self._name = name self._title = title self._mass = mass self._phos = phos self._phor = phor self._data = data self._phostarget = phostarget self._phortargets = phortargets[:] self._rho = rho self._mirror = mirror ## Attach other attributes. self._massrange = (mass.getMin(), mass.getMax()) self._sdata_list = [] self._phostrue_list = [] self._phortrue_list = [] self._dm_dphos_list = [] self._msubs_list = [] self._keys_pdfs = [] self._keys_modes = [] self._keys_effsigmas = [] self._keys_fitresults = [] self._pdfs = [] self._custs = [] # self._pdfrefs = [] self._mrefs = [] self._phormorphs = [] self._phorhists = [] self._workspace = workspace ## self._workspace = ROOT.RooWorkspace(name + '_workspace', ## title + ' workspace') w = self._workspace self.w = w ## Import important args in workspace. # w.Import(ROOT.RooArgSet(mass, phos, phor)) w.Import(mass) w.Import(phos) w.Import(phor) w.Import(self._data) w.factory('ConstVar::{name}_phostarget({value})'.format( name=name, value=self._phostarget)) ## Define the morphing parameter. This an identity with the ## photon resolution for now. mpar = self._mpar = w.factory( 'expr::{name}_mpar("{phor}", {{{phor}}})'.format( ## 'expr::{name}_mpar("2 + sqrt(0.5^2 + 0.05 * {phor}^2)", {{{phor}}})'.format( ## 'expr::{name}_mpar("2.325+sqrt(0.4571 + (0.1608*{phor})^2)", {{{phor}}})'.format( name=name, phor=phor.GetName())) ## Define the formula for dlog(m)/dphos. self._dm_dphos_func = w.factory(''' expr::dm_dphos_func("0.5 * (1 - mmMass^2 / mmgMass^2) * mmgMass", {mmMass, mmgMass}) ''') ## Get the calibrator. self._calibrator = MonteCarloCalibrator(self._data) ## Loop over target reference photon energy resolutions in phortargets. for index, phortarget in enumerate(self._phortargets): ## Store the target photon resolution value. w.factory('ConstVar::{name}_phortarget_{index}({value})'.format( name=name, index=index, value=phortarget)) ## Get the corresponding smeared RooDataSet sdata named ## {name}_sdata_{index} and attach it to self._sdata sdata = self._calibrator.get_smeared_data( self._phostarget, phortarget, name + '_sdata_%d' % index, title + ' sdata %d' % index, ## Get the true scale and resolution with errors. (This can be ## added to the calibrator and snapshots of ## self._calibrator.s and self._calibrator.r stored as ## {name}_sdata_{index}_sr in self._calibrator.w) dofit=True) self._sdata_list.append(sdata) w.Import(sdata) phostrue = ROOT.RooRealVar(self._calibrator.s, name + '_phostrue_%d' % index) phortrue = ROOT.RooRealVar(self._calibrator.r, name + '_phortrue_%d' % index) phostrue.setConstant(True) phortrue.setConstant(True) self._phostrue_list.append(phostrue) self._phortrue_list.append(phortrue) w.Import(phostrue) w.Import(phortrue) ## Calculate the dlogm/dphos {name}_dm_dphos_{index} ## for the smeared dataset. sdata.addColumn(self._dm_dphos_func) dm_dphos = w.factory(''' {name}_dm_dphos_{index}[{mean}, 0, 1] '''.format(name=name, index=index, mean=sdata.mean(sdata.get()['dm_dphos_func']))) dm_dphos.setConstant(True) self._dm_dphos_list.append(dm_dphos) ## Define the mass scaling {name}_msubs{i} introducing ## the dependence on phos. This needs self._calibrator.s and ## dm_dphos. ## msubs = w.factory( ## ''' ## LinearVar::{msubs}( ## {mass}, 1, ## expr::{offset}( ## "- 0.01 * {dm_dphos} * ({phos} - {phostrue})", ## {{ {dm_dphos}, {phos}, {phostrue} }} ## ) ## ) ## '''.format(msubs = name + '_msubs_%d' % index, ## offset = name + '_msubs_offset_%d' % index, ## mass = self._mass.GetName(), ## dm_dphos = dm_dphos.GetName(), ## phos = self._phos.GetName(), ## phostrue = phostrue.GetName()) ## ) ## LinearVar cannot be persisted. msubs = w.factory(''' expr::{msubs}( "{mass} - 0.01 * {dm_dphos} * ({phos} - {phostrue})", {{ {mass}, {dm_dphos}, {phos}, {phostrue} }} ) '''.format(msubs=name + '_msubs_%d' % index, mass=self._mass.GetName(), dm_dphos=dm_dphos.GetName(), phos=self._phos.GetName(), phostrue=phostrue.GetName())) self._msubs_list.append(msubs) ## Build the corresponding parametrized KEYS PDF {name}_kyes_{index} ## with {name}_keys_mode_{index} and ## {name}_keys_effsigma_{index}. keys_mode = w.factory( '{name}_keys_mode_{index}[91.2, 60, 120]'.format(name=name, index=index)) keys_effsigma = w.factory( '{name}_keys_effsigma_{index}[3, 0.1, 60]'.format(name=name, index=index)) mass.setRange(*mrangetrain) keys_pdf = ParametrizedKeysPdf(name + '_keys_pdf_%d' % index, name + '_keys_pdf_%d' % index, mass, keys_mode, keys_effsigma, sdata, rho=self._rho) self._keys_modes.append(keys_mode) self._keys_effsigmas.append(keys_effsigma) self._keys_pdfs.append(keys_pdf) ## Fit the KEYS PDF to the training data and save the result ## {name}_keys_fitresult_{index} and parameter snapshots ## {name}_keys_mctrue_{index}. mass.setRange(*mrangenorm) keys_fitresult = keys_pdf.fitTo(sdata, roo.Range(*mrangefit), roo.Strategy(2), roo.NumCPU(8), roo.Save(True)) self._keys_fitresults.append(keys_fitresult) w.Import(keys_fitresult, name + '_keys_fitresult_%d' % index) w.saveSnapshot( name + '_mctrue_%d' % index, ','.join([ phostrue.GetName(), phortrue.GetName(), keys_mode.GetName(), keys_effsigma.GetName() ])) ## Sample the fitted KEYS PDF to a histogram {name}_hist_{index}. mass.setRange(*mrangetrain) hist = keys_pdf.createHistogram(name + '_hist_%d' % index, mass, roo.Binning('cache')) ## Build a RooDataHist {name}_dhist{index} of the sampled histogram. dhist = ROOT.RooDataHist(name + '_dhist_%d' % index, name + '_dhist_%d' % index, ROOT.RooArgList(mass), hist) w.Import(dhist) ## Build a RooHistPdf {name}_pdf_{index} using the dhist and msubs. ## pdf = w.factory( pdf = w.factory('HistPdf::{name}({{{mass}}}, {dhist}, 1)'.format( name=name + '_pdf_%d' % index, msubs=msubs.GetName(), mass=mass.GetName(), dhist=dhist.GetName())) self._pdfs.append(pdf) mass.setRange(*self._massrange) ## Calculate morphing parameter reference values float mref[index]. phorval = phor.getVal() phor.setVal(phortrue.getVal()) self._mrefs.append(mpar.getVal()) phor.setVal(phorval) ## End of loop over target phortargets ## Make the reference and cache binnings in phor self._check_phor_ranges() partitions = self._partition_binning(self._phor, 'cache', 'reference') ## Loop over phor reference bins and define pairwise RooMomentMorphs. for ilo in range(len(self._mrefs) - 1): ihi = ilo + 1 mlo = self._mrefs[ilo] mhi = self._mrefs[ihi] pdflo = self._pdfs[ilo] pdfhi = self._pdfs[ihi] phormorph = w.factory(''' MomentMorph::{name}_phormorph_{ilo}to{ihi}( {mpar}, {{{mass}}}, {{{pdfs}}}, {{{mrefs}}} ) '''.format(name=name, ilo=ilo, ihi=ihi, mpar=mpar.GetName(), mass=mass.GetName(), pdfs='%s, %s' % (pdflo.GetName(), pdfhi.GetName()), mrefs='%f, %f' % (mlo, mhi))) self._phormorphs.append(phormorph) ## Sample the morph in a 2D histogram in mass and phor. phorhist = phormorph.createHistogram( name + '_phorhist_%dto%d' % (ilo, ihi), mass, roo.Binning('cache'), roo.YVar(phor, roo.Binning(partitions[ilo]))) self._phorhists.append(phorhist) ## End of loop over phor reference bins. self._stitch_phorhists() self._phor_dhist = phor_dhist = ROOT.RooDataHist( name + '_phor_dhist', name + '_phor_dhist', ROOT.RooArgList(mass, phor), self._phorhist) average_index = (len(self._msubs_list) + 1) / 2 msubs = self._msubs_list[average_index] ## self._model = model = ROOT.RooHistPdf( ## name + '_phor_histpdf', name + '_phor_histpdf', ## ROOT.RooArgList(msubs, phor), ROOT.RooArgList(mass, phor), phor_dhist, 2 ## ) ## self._model = model = ROOT.RooPhosphorPdf( ## name + '_phor_histpdf', name + '_phor_histpdf', mass, msubs, phor, phor_dhist, 2 ## ) ## ## Quick hack to make things work. ## self._customizer = customizer = ROOT.RooCustomizer(model, 'msub') ## customizer.replaceArg(mass, msubs) ## model = customizer.build() # ROOT.RooHistPdf.__init__(self, model) ROOT.RooPhosphorPdf.__init__(self, name, title, mass, msubs, phos, phor, phor_dhist, 2) self.SetName(name) self.SetTitle(title)