def main():
    ROOT.gROOT.SetBatch()

    # Create workspace to contain full analysis
    model = ROOT.RooWorkspace('model', True)

    # get toy histogram
    toy_data_dh = fh.getHistFromFile( file_name    = toy_data_file_name
                                    , hist_name    = 'toy__flavor_all__mbl_all__BMINUSL_MET'
                                    , roo_real_var = mbl_real_var
                                    , label        = 'toy'
                                    , model        = model
                                    )['dh']
    model.Print()
    print toy_data_dh

    # --------------------------------------------------------------------------
    bkg_pdf_basic = getFunctionalForm('basic', mbl_real_var, model)
    bkg_pdf_basic.fitTo(toy_data_dh)

    # --------------------------------------------------------------------------
    # draw background template to a canvas
    plot_basic_lin = fh.drawToCanvas( roo_object_list   = [ toy_data_dh, bkg_pdf_basic ]
                                    , roo_real_var      = mbl_real_var
                                    , line_colors       = [ROOT.kBlack, ROOT.kBlue]
                                    , label             = 'basic'
                                    , range_string_list = ['', '']
                                    , log               = False
                                    )
    plot_basic_log = fh.drawToCanvas( roo_object_list   = [ toy_data_dh, bkg_pdf_basic ]
                                    , roo_real_var      = mbl_real_var
                                    , line_colors       = [ROOT.kBlack, ROOT.kBlue]
                                    , label             = 'basic'
                                    , range_string_list = ['', '']
                                    , log               = True
                                    )

    # --------------------------------------------------------------------------
    out_file = ROOT.TFile('fit.root', 'RECREATE')
    out_file.cd()
    plot_basic_lin['canv'].Write('c_fit_basic__lin')
    plot_basic_log['canv'].Write('c_fit_basic__log')
    out_file.Close()

    # --------------------------------------------------------------------------
    model.writeToFile('fit_workspace.root', True)
def main():
    ROOT.gROOT.SetBatch()

    # Create workspace to contain full analysis
    model = ROOT.RooWorkspace('model', True)

    # get template histogram
    bkg_template_dict = fh.getHistFromFile( file_name = bkg_template_file_name
                                          , hist_name = 'template__flavor_all__mbl_all__BMINUSL_MET'
                                          , roo_real_var = mbl_real_var
                                          , label = 'bkg_template'
                                          , model = model
                                          )

    # get toy histogram
    toy_data_dh = fh.getHistFromFile( file_name = toy_data_file_name
                                    , hist_name = 'toy__flavor_all__mbl_all__BMINUSL_MET'
                                    , roo_real_var = mbl_real_var
                                    , label = 'toy'
                                    , model = model
                                    )['dh']

    # draw background template to a canvas
    template_draw_dict = fh.drawToCanvas( roo_object_list   = [bkg_template_dict['pdf']]
                                        , roo_real_var      = mbl_real_var
                                        , line_colors       = [ROOT.kBlack]
                                        , label             = 'mbl_templates'
                                        , range_string_list = ['full_range']
                                        , log               = True
                                        )

    # draw toy data to a canvas
    toy_draw_dict = fh.drawToCanvas( roo_object_list   = [toy_data_dh]
                                   , roo_real_var      = mbl_real_var
                                   , line_colors       = [ROOT.kBlack]
                                   , label             = 'mbl_toy'
                                   , range_string_list = ['full_range']
                                   , log               = True
                                   )

    # do basic fit -- no sliding window
    basic_fit_dict = fitAndDrawToCanvas( toy_data_dh
                                       , bkg_template_dict
                                       , mbl_real_var
                                       , 'basic_fit'
                                       , model
                                       )

    # do sliding fit window scan
    sliding_window_scan = performSlidingWindowScan( toy_data_dh
                                                  , bkg_template_dict
                                                  , mbl_real_var
                                                  , 'sliding_window'
                                                  , model
                                                  )

    # Print a bunch of info to screen
    print 'basic fit -- n_bkg: %s' % basic_fit_dict['n_bkg'].getVal()
    for sws in sorted(sliding_window_scan.iterkeys()):
        print sws
        print sliding_window_scan[sws]['n_bkg'].GetName()
        print 'fit window string: %s' % sliding_window_scan[sws]['fit_range_string']
        print 'norm: %s' % sliding_window_scan[sws]['n_bkg'].getVal()
        print 'error: %s' % sliding_window_scan[sws]['n_bkg'].getError()
        print 'chi2_sideband: %s' % sliding_window_scan[sws]['chi2_sideband']
        print 'ndof_sideband: %s' % sliding_window_scan[sws]['ndof_sideband']
        print 'chi2_over_ndof (sideband): %s' % sliding_window_scan[sws]['chi2_over_ndof_sideband']
        print 'chi2_search: %s' % sliding_window_scan[sws]['chi2_search']
        print 'ndof_search: %s' % sliding_window_scan[sws]['ndof_search']
        print 'chi2_over_ndof (search): %s' % sliding_window_scan[sws]['chi2_over_ndof_search']
        print ''

    # write canvas to file
    out_file = ROOT.TFile('fit.root', 'RECREATE')
    out_file.cd()
    template_draw_dict['canv'].Write()
    toy_draw_dict['canv'].Write()
    basic_fit_dict['canv_lin'].Write()
    basic_fit_dict['canv_log'].Write()
    for sws in sorted(sliding_window_scan.iterkeys()):
        sliding_window_scan[sws]['canv_lin'].Write()
        sliding_window_scan[sws]['canv_log'].Write()

    # --------------------------------------------------------------------------
    model.writeToFile('fit_workspace.root', True)
def fitAndDrawToCanvas( data_dh
                      , bkg_template
                      , roo_real_var
                      , label
                      , model
                      , fit_ranges = []
                      ):
    # perform fit to data
    fit_dict = performFit( data_dh
                         , bkg_template
                         , roo_real_var
                         , label
                         , model
                         , fit_ranges
                         )

    print 'fit and draw to canvas -- linear'
    print fit_dict['fit_range_string']
    draw_dict_lin = fh.drawToCanvas( [data_dh, fit_dict['pdf'], fit_dict['pdf']]
                                   , roo_real_var
                                   , line_colors = [ROOT.kBlack, ROOT.kRed, ROOT.kGreen]
                                   , label = label
                                   , range_string_list = ['full_range', fit_dict['fit_range_string'], fit_dict['search_range_string']]
                                   , log = False
                                   )

    print 'fit and draw to canvas -- log'
    print fit_dict['fit_range_string']
    draw_dict_log = fh.drawToCanvas( [data_dh, fit_dict['pdf'], fit_dict['pdf']]
                                   , roo_real_var
                                   , line_colors = [ROOT.kBlack, ROOT.kRed, ROOT.kGreen]
                                   , label = label
                                   , range_string_list = ['full_range', fit_dict['fit_range_string'], fit_dict['search_range_string']]
                                   , log = True
                                   )

    norm = fit_dict['n_bkg'].getVal()
    err = fit_dict['n_bkg'].getError()

    # get chi2 for sideband and search regions
    chi2_sideband = fit_dict['pdf'].createChi2( data_dh
                                              , ROOT.RooFit.DataError(ROOT.RooAbsData.Poisson)
                                              , ROOT.RooFit.Range(fit_dict['fit_range_string'])
                                              )
    chi2_search = fit_dict['pdf'].createChi2( data_dh
                                            , ROOT.RooFit.DataError(ROOT.RooAbsData.Poisson)
                                            , ROOT.RooFit.Range(fit_dict['search_range_string'])
                                            )

    # get ndfo for sideband and search regions
    ndof_sideband = fh.getNumBinsInRegion( fit_dict['fit_range_string']
                                         , fit_dict['local_roo_real_var']
                                         , bkg_template['hist']
                                         )
    ndof_search = fh.getNumBinsInRegion( fit_dict['search_range_string']
                                       , fit_dict['local_roo_real_var']
                                       , bkg_template['hist']
                                       )

    # calculate chi2/ndof for sideband and search regions
    chi2_over_ndof_sideband = chi2_sideband.getVal()/ndof_sideband
    chi2_over_ndof_search = chi2_search.getVal()/ndof_search

    # make labels for canvas
    search_region_string = ''
    if len(fit_ranges) == 0: search_region_string = 'N/A'
    # TODO make this more robust
    elif len(fit_ranges) == 2:
        search_region_string = '%d < m_{bl} < %d' % (fit_ranges[0]['max'], fit_ranges[1]['min'])

    label_info          = ROOT.TLatex(0.50, 0.85, 'Search region: %s' % (search_region_string))
    label_norm          = ROOT.TLatex(0.50, 0.80, 'Background: %0.1f #pm %0.1f' % (norm, err))
    label_chi2_sideband = ROOT.TLatex(0.50, 0.75, '#chi^{2}/ndof (sideband): %0.2f' % chi2_over_ndof_sideband)
    label_chi2_search   = ROOT.TLatex(0.50, 0.70, '#chi^{2}/ndof (search): %0.2f'   % chi2_over_ndof_search)

    label_info.SetTextSize(0.04)
    label_norm.SetTextSize(0.04)
    label_chi2_sideband.SetTextSize(0.04)
    label_chi2_search.SetTextSize(0.04)

    label_info.SetNDC()
    label_norm.SetNDC()
    label_chi2_sideband.SetNDC()
    label_chi2_search.SetNDC()

    draw_dict_lin['canv'].cd()
    label_info.Draw()
    label_norm.Draw()
    label_chi2_sideband.Draw()
    label_chi2_search.Draw()

    draw_dict_log['canv'].cd()
    label_info.Draw()
    label_norm.Draw()
    label_chi2_sideband.Draw()
    label_chi2_search.Draw()

    # save things to dictionary and return them so root doesn't lose them
    fit_dict['frame_lin'] = draw_dict_lin['frame']
    fit_dict['frame_log'] = draw_dict_log['frame']
    fit_dict['canv_lin'] = draw_dict_lin['canv']
    fit_dict['canv_log'] = draw_dict_log['canv']
    fit_dict['label_info'] = label_info
    fit_dict['label_norm'] = label_norm
    fit_dict['label_chi2_sideband'] = label_chi2_sideband
    fit_dict['label_chi2_search'] = label_chi2_search
    fit_dict['chi2_sideband'] = chi2_sideband.getVal()
    fit_dict['chi2_search'] = chi2_search.getVal()
    fit_dict['ndof_sideband'] = ndof_sideband
    fit_dict['ndof_search'] = ndof_search
    fit_dict['chi2_over_ndof_sideband'] = chi2_over_ndof_sideband
    fit_dict['chi2_over_ndof_search'] = chi2_over_ndof_search
    return fit_dict