Angular analysis of B+->K*+(K+pi0)mumu
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

343 lines
15 KiB

  1. from ROOT import gROOT, gDirectory, gStyle, TChain, TTree, TAxis, TH1D, TLegend, TCanvas, TPad, TLine
  2. #TODO check what needs to be loaded where
  3. import subprocess
  4. import time
  5. import numpy as np
  6. import re #for splitting with multiple deliminers
  7. from array import array
  8. import numexpr
  9. from Utils import *
  10. from Plots import *
  11. from LHCbStyle import *
  12. from Globals import *
  13. '''
  14. Tool for comparing two variables from two datasets.
  15. Yes, writting it in Python3 would be smarter,
  16. but default is Python2 on all servers so far
  17. '''
  18. Min = 0.0
  19. Max = 0.0
  20. #TODO stripping comparisons
  21. def compareUltimate( variable1 = "Abs(K_star_plus_PT-K_plus_PT)/10", variable2 = "Sqrt(B_plus_PT)",
  22. year1 = 2011, year2 = 2012, cut1 = "", cut2 = "",
  23. magnet1 = "both", MC1 = False, TM1 = False, ReferenceChannel1 = False, PHSP1 = False, Preselected1 = True, BDTed1 = False,
  24. magnet2 = "both", MC2 = True, TM2 = False, ReferenceChannel2 = False, PHSP2 = False, Preselected2 = True, BDTed2 = False,
  25. sWeighted1 = True, bWeighted1 = False, b2Dweighted1 = False, weightBranch1 = firstMCweight(),
  26. sWeighted2 = False, bWeighted2 = False, b2Dweighted2 = True, weightBranch2 = firstMCweight(),
  27. bPrint = False, KshortDecaysInVelo1 = False, KshortDecaysInVelo2 = False, verbose = True):
  28. #TODO: add run option
  29. #if((plotLog1 and plotLogOneMinus1) or (plotLog2 and plotLogOneMinus2)):
  30. # raise Exception("Only Log( var ) or Log( 1 - var ) option possible, but both flags were set!")
  31. #No need to set it in here, will be taken care of by definning variable
  32. #The only requiremnt here that for cuts, no operations are allowed for now (no sqrt(x) < 0.5 or so)
  33. gROOT.SetBatch(1)
  34. #Set LHCb style for plots
  35. LHCbStyle()
  36. #TODO add check for valid particles
  37. #Force TM for weighted MC
  38. if (b2Dweighted1 or bWeighted1): TM1 = True
  39. if (b2Dweighted2 or bWeighted2): TM2 = True
  40. if (MC1): year1 = checkMCyear(year1,ReferenceChannel1, PHSP1)
  41. if (MC2): year2 = checkMCyear(year2,ReferenceChannel2, PHSP2)
  42. if (magnet1 == "down"):
  43. cut1 = ("Polarity=65535") if (cut1=="") else (cut1 + "&&Polarity=65535") #Somehow, it overflows to 2^16-1
  44. if (magnet1 == "up"):
  45. cut1 = ("Polarity=1") if (cut1=="") else (cut1 + "&&Polarity=1")
  46. if (magnet2 == "down"):
  47. cut2 = ("Polarity=65535") if (cut2=="") else (cut2 + "&&Polarity=65535")#Somehow, it overflows to 2^16-1
  48. if (magnet2 == "up"):
  49. cut2 = ("Polarity=1") if (cut2=="") else (cut2 + "&&Polarity=1")
  50. if (TM1):
  51. cut1 = ("TMedBKGCAT=1") if (cut1=="") else (cut1 + "&& TMedBKGCAT=1")
  52. if (TM2):
  53. cut2 = ("TMedBKGCAT=1") if (cut2=="") else (cut2 + "&& TMedBKGCAT=1")
  54. #raise an exception if MC and data is selected
  55. if ( (not MC1 and (TM1 or ReferenceChannel1 or PHSP1)) or (not MC2 and (TM2 or ReferenceChannel1 or PHSP1)) ) :
  56. raise Exception('Data cannot be TruthMatched nor RefChan nor PHSP! Check your options!')
  57. #Set DTF if required
  58. if (UseDTF()):
  59. variable1 = replace_variables_to_DTF(variable1)
  60. variable2 = replace_variables_to_DTF(variable2)
  61. if (verbose):
  62. print "[DEBUG]\t\tUsing variables ", variable1, variable2
  63. #Get Run
  64. Run1 = 1 if (year1 < 2013) else 2
  65. Run2 = 1 if (year2 < 2013) else 2
  66. #Set up a dictionary with dataset information
  67. optionsDictionary1 = getOptionsDictionary(year1, Run1, magnet1, MC1, TM1, ReferenceChannel1, PHSP1, Preselected1,
  68. BDTed1, sWeighted1, bWeighted1, b2Dweighted1, weightBranch1,KshortDecaysInVelo1, False)
  69. optionsDictionary2 = getOptionsDictionary(year2, Run2, magnet2, MC2, TM2, ReferenceChannel2, PHSP2, Preselected2,
  70. BDTed2, sWeighted2, bWeighted2, b2Dweighted2, weightBranch2,KshortDecaysInVelo2, False)
  71. #Check for year+sample
  72. if (not checkYearSample(optionsDictionary1)[0]):
  73. print checkYearSample(optionsDictionary1)[1]
  74. return 0
  75. if (not checkYearSample(optionsDictionary2)[0]):
  76. print checkYearSample(optionsDictionary2)[1]
  77. return 0
  78. #In case of the need of build, uncomment
  79. #import os
  80. #os.system("g++ getPathForPython.cc `root-config --libs --cflags` -o getPathForPython")
  81. #Read the trees
  82. tree1 = TChain(treeName(MC1,TM1,Preselected1))
  83. tree2 = TChain(treeName(MC2,TM2,Preselected2))
  84. addToTChain(tree1, optionsDictionary1, verbose)
  85. addToTChain(tree2, optionsDictionary2, verbose)
  86. #Load the branches into basic histograms
  87. histName1 = histName(variable1,optionsDictionary1)+"1"
  88. histName2 = histName(variable2,optionsDictionary2)+"2"
  89. drawVar1 = addTMathTags(variable1)
  90. drawVar2 = addTMathTags(variable2)
  91. if verbose:
  92. print "[DEBUG]\t\tVariable names are: ", histName1, histName2
  93. print "[DEBUG]\t\tDrawing variables: ", drawVar1 , drawVar2
  94. #Create default histograms directly from the tree
  95. tree1.Draw("%s >> %s" % (drawVar1,histName1) )
  96. hist1Drawn = gDirectory.Get(histName1)
  97. if verbose: print "[DEBUG]\t\tDrawing into ", hist1Drawn.GetName()
  98. tree2.Draw("%s >> %s" % (drawVar2,histName2) )
  99. hist2Drawn = gDirectory.Get(histName2)
  100. if verbose: print "[DEBUG]\t\tDrawing into ", hist2Drawn.GetName()
  101. #Check if histograms are empty
  102. if (hist1Drawn.GetEntries()==0):
  103. raise Exception('Created histogram1 is empty! Check your cuts and variable!')
  104. if (hist2Drawn.GetEntries()==0):
  105. raise Exception('Created histogram2 is empty! Check your cuts and variable!')
  106. #Check if the variable is integer
  107. isVar1Int = isInt(variable1)
  108. isVar2Int = isInt(variable2)
  109. hist1InfoList = []
  110. hist2InfoList = []
  111. dictVarPlotLimits = dictVarPlotLimitsKshort(KshortDecaysInVelo1 or KshortDecaysInVelo2) if KshortChannel() else dictVarPlotLimitsKplus()
  112. if (isVar1Int):
  113. hist1InfoList = dictVarPlotLimitsInt()[variable1]
  114. else: # Check for non-empty bins at the edges and set xaxis range accordingly
  115. nBins = hist1Drawn.GetXaxis().GetNbins()
  116. firstBin = 0
  117. lastBin = nBins+1
  118. # check if variable needs manually adjusted range
  119. if (variable1 in dictVarPlotLimits.keys()):
  120. if ("Min" in dictVarPlotLimits[variable1].keys()): # If min is defined, adjust
  121. min1 = dictVarPlotLimits[variable1]["Min"]
  122. else:
  123. while (hist1Drawn.GetBinContent(firstBin) == 0): # If not, loop over to get first bin
  124. firstBin = firstBin+1
  125. min1 = hist1Drawn.GetXaxis().GetBinLowEdge(firstBin)
  126. if ("Max" in dictVarPlotLimits[variable1].keys()): # If max is defined, adjust
  127. max1 = dictVarPlotLimits[variable1]["Max"]
  128. else:
  129. while (hist1Drawn.GetBinContent(lastBin) == 0): # If not, loop over to get the last bin
  130. lastBin = lastBin-1
  131. max1 = hist1Drawn.GetXaxis().GetBinUpEdge(lastBin)
  132. else: # if variable doesn't need manual adjustement, loop over to get edge bins
  133. while (hist1Drawn.GetBinContent(firstBin) == 0):
  134. firstBin = firstBin+1
  135. min1 = hist1Drawn.GetXaxis().GetBinLowEdge(firstBin)
  136. while (hist1Drawn.GetBinContent(lastBin) == 0):
  137. lastBin = lastBin-1
  138. max1 = hist1Drawn.GetXaxis().GetBinUpEdge(lastBin)
  139. hist1InfoList = [nBins/2, min1, max1]
  140. if (isVar2Int):
  141. hist2InfoList = dictVarPlotLimitsInt()[variable2]
  142. else: # Check for non-empty bins at the edges and set xaxis range accordingly
  143. nBins = hist2Drawn.GetXaxis().GetNbins()
  144. firstBin = 0
  145. lastBin = nBins+1
  146. # check if variable needs manually adjusted range
  147. if (variable2 in dictVarPlotLimits.keys()):
  148. if ("Min" in dictVarPlotLimits[variable2].keys()): # If min is defined, adjust
  149. min2 = dictVarPlotLimits[variable2]["Min"]
  150. else:
  151. while (hist2Drawn.GetBinContent(firstBin) == 0): # If not, loop over to get first bin
  152. firstBin = firstBin+2
  153. min2 = hist2Drawn.GetXaxis().GetBinLowEdge(firstBin)
  154. if ("Max" in dictVarPlotLimits[variable2].keys()): # If max is defined, adjust
  155. max2 = dictVarPlotLimits[variable2]["Max"]
  156. else:
  157. while (hist2Drawn.GetBinContent(lastBin) == 0): # If not, loop over to get the last bin
  158. lastBin = lastBin-2
  159. max2 = hist2Drawn.GetXaxis().GetBinUpEdge(lastBin)
  160. else: # if variable doesn't need manual adjustement, loop over to get edge bins
  161. while (hist2Drawn.GetBinContent(firstBin) == 0):
  162. firstBin = firstBin+2
  163. min2 = hist2Drawn.GetXaxis().GetBinLowEdge(firstBin)
  164. while (hist2Drawn.GetBinContent(lastBin) == 0):
  165. lastBin = lastBin-1
  166. max2 = hist2Drawn.GetXaxis().GetBinUpEdge(lastBin)
  167. hist2InfoList = [nBins/2, min2, max2]
  168. if verbose:
  169. print "[DEBUG]\t\tVariable %s with %i bins from %f to %f." %(variable1,hist1InfoList[0],hist1InfoList[1],hist1InfoList[2])
  170. print "[DEBUG]\t\tVariable %s with %i bins from %f to %f." % (variable2,hist2InfoList[0],hist2InfoList[1],hist2InfoList[2])
  171. #Set xranges and nBins to be equal for both variables
  172. #nBins are necessary for proper histogram division
  173. histInfoList = [
  174. max(hist1InfoList[0], hist2InfoList[0]),
  175. min(hist1InfoList[1], hist2InfoList[1]),
  176. max(hist1InfoList[2], hist2InfoList[2])
  177. ]
  178. #TODO have a function for Xaxis name and for tags
  179. #parse variables and cuts in a way that all needed branches are loaded
  180. variables1List = []
  181. variables1Dict = {}
  182. variables2List = []
  183. variables2Dict = {}
  184. #Create new histograms
  185. hist1 = TH1D("hist1","hist1",histInfoList[0],histInfoList[1],histInfoList[2])
  186. hist2 = TH1D("hist2","hist2",histInfoList[0],histInfoList[1],histInfoList[2])
  187. hist1.Sumw2()
  188. hist2.Sumw2()
  189. #Load variables from only branches actually used
  190. tree1.SetBranchStatus("*",0)
  191. tree2.SetBranchStatus("*",0)
  192. listOfVars1 = getListOfUsedVariables(variable1,cut1)
  193. listOfVars2 = getListOfUsedVariables(variable2,cut2)
  194. #add weight branches
  195. if (sWeighted1): listOfVars1 = np.append(listOfVars1,"N_Bplus_sw")
  196. if (sWeighted2): listOfVars2 = np.append(listOfVars2,"N_Bplus_sw")
  197. if (bWeighted1 and TM1): listOfVars1 = np.append(listOfVars1,"weight_nLongTracks") #TODO: check the branch name
  198. elif (b2Dweighted1 and TM1): listOfVars1 = np.append(listOfVars1,"weight2D_nLongTracks")
  199. if (bWeighted2 and TM2): listOfVars2 = np.append(listOfVars2,"weight_nLongTracks")
  200. elif (b2Dweighted2 and TM2): listOfVars2 = np.append(listOfVars2,"weight2D_nLongTracks")
  201. if verbose:
  202. print "[DEBUG]\t\tActivating branches in tree1: ", listOfVars1
  203. print "[DEBUG]\t\tActivating branches in tree2: ", listOfVars2
  204. #Assign variables with either a double or integer #WeAllHateRoot
  205. for var in listOfVars1:
  206. tree1.SetBranchStatus(var,1)
  207. if(isInt(var)): variables1Dict[var] = array('i',[0])
  208. else: variables1Dict[var] = array('d',[0])
  209. tree1.SetBranchAddress(var,variables1Dict[var])
  210. for var in listOfVars2:
  211. tree2.SetBranchStatus(var,1)
  212. if(isInt(var)): variables2Dict[var] = array('i',[0])
  213. else: variables2Dict[var] = array('d',[0])
  214. tree2.SetBranchAddress(var,variables2Dict[var])
  215. if verbose:
  216. print "[DEBUG]\t\tDefining variables for branches in tree1: ", variables1Dict
  217. print "[DEBUG]\t\tDefining variables for branches in tree2: ", variables2Dict
  218. if verbose:
  219. print "[DEBUG]\t\tUsing cuts1: ", cut1
  220. print "[DEBUG]\t\tUsing cuts2: ", cut2
  221. for evt in xrange(tree1.GetEntries()):
  222. if ( (evt+1) % 10000 < 0.01): print "[INFO]\tReding event ", evt+1, " from tree1"
  223. tree1.GetEntry(evt)
  224. if not evaluateCut(cut1,variables1Dict): continue
  225. hist1.Fill(evaluateVariable(variable1,variables1Dict),evaluateWeight(variables1Dict,optionsDictionary1))
  226. for evt in xrange(tree2.GetEntries()):
  227. if ( (evt+1) % 10000 < 0.01): print "[INFO]\tReding event ", evt+1, " from tree2"
  228. tree2.GetEntry(evt)
  229. if not evaluateCut(cut2,variables2Dict): continue
  230. hist2.Fill(evaluateVariable(variable2,variables2Dict),evaluateWeight(variables2Dict,optionsDictionary2))
  231. #Clone histograms to make a ratio
  232. #TODO check if it's really necessary
  233. hist1Clone = hist1.Clone('hist1Clone')
  234. hist2Clone = hist2.Clone('hist2Clone')
  235. #Normalize histograms
  236. if (hist1Clone.Integral() == 0):
  237. raise Exception('Filled histogram1 is empty! Check your options!')
  238. if (hist2Clone.Integral() == 0):
  239. raise Exception('Filled histogram2 is empty! Check your options!')
  240. hist1Clone.Scale(1.0/hist1Clone.Integral())
  241. hist2Clone.Scale(1.0/hist2Clone.Integral())
  242. histRatio = hist2Clone.Clone('histRatio')
  243. histRatio.Divide(hist1Clone)
  244. histRatio.Draw()
  245. #Plotting
  246. lowerPlotHeight = 0.6;
  247. canvas = TCanvas('canvas','ratio and superposition')
  248. pad1 = TPad("pad1", "ratio",0.0,lowerPlotHeight,1.0,1.0,0);
  249. pad2 = TPad("pad2", "superposition",0.0,0.0,1.0,lowerPlotHeight,0);
  250. pad1.Draw();
  251. pad2.Draw();
  252. xAxisLabel = defineXAxisLabels(variable1,variable2)
  253. makePlot(hist1Clone, hist2Clone, histRatio, pad1, pad2, xAxisLabel, histInfoList[1], histInfoList[2], lowerPlotHeight)
  254. #TODO put this into plotting function, where it god-knows-why doesn't work
  255. pad1.cd()
  256. unityline = TLine(histInfoList[1], 1.0, histInfoList[2], 1.0)
  257. unityline.SetLineStyle(2)
  258. unityline.SetLineColor(4)
  259. unityline.Draw()
  260. #Legend definition and drawing
  261. LegendXposition = 0.4;
  262. LegendYposition = 0.62;
  263. pad2.cd()
  264. leg = TLegend(LegendXposition,LegendYposition,LegendXposition + 0.25, LegendYposition + 0.28);
  265. tag1, tag2 = defineLegendTags(optionsDictionary1,optionsDictionary2)
  266. pad2.cd()
  267. if (len(variable1) > 30):
  268. leg.AddEntry(hist1Clone,"#splitline{%s}{#splitline{%s}{%s}}" % (variable1, tag1, cut1), "lpe");
  269. else:
  270. leg.AddEntry(hist1Clone,"#splitline{%s%s}{%s}" % (variable1, tag1, cut1), "lpe");
  271. if (len(variable2) > 30):
  272. leg.AddEntry(hist2Clone,"#splitline{%s}{#splitline{%s}{%s}}" % (variable2, tag2, cut2), "lpe");
  273. else:
  274. leg.AddEntry(hist2Clone,"#splitline{%s%s}{%s}" % (variable2, tag2, cut2), "lpe");
  275. leg.SetTextSize(0.04/lowerPlotHeight);
  276. leg.Draw()
  277. canvas.Print(getPlotFileName(variable1, optionsDictionary1, cut1, variable2, optionsDictionary2, cut2))
  278. return
  279. if __name__ == '__main__':
  280. compareUltimate()