예제 #1
0
	def __init__(self):
		super(InputRoot, self).__init__()
		self.expressions = ExpressionsDict()
예제 #2
0
파일: inputbase.py 프로젝트: whahmad/Artus
    def __init__(self):
        super(InputBase, self).__init__()

        self.binnings = BinningsDict()
        self.expressions = ExpressionsDict()
예제 #3
0
class InputRoot(inputfile.InputFile):
	def __init__(self):
		super(InputRoot, self).__init__()
		self.expressions = ExpressionsDict()
	
	def modify_argument_parser(self, parser, args):
		super(InputRoot, self).modify_argument_parser(parser, args)
		
		self.input_options.add_argument("-f", "--folders", type=str, nargs='*',
		                                help="Path(s) to ROOT objects.")
		self.input_options.add_argument("--friend-treenames", type=str, nargs="+",
		                                help="Names of trees to be used as friends. Seperate different plots with space, seperate for same plot with whitespace.", default=None)
		self.input_options.add_argument("--friend-filenames", type=str, nargs="+",
		                                help="Filenames to be added as friends. Seperate different plots with space, seperate for same plot with whitespace.", default=None)
		self.input_options.add_argument("--quantities", nargs="?", type="bool", default=False, const=True,
		                                help="Print available quantities in given folder. [Default: %(default)s]")
		self.input_options.add_argument("-x", "--x-expressions", type=str, nargs="+",
		                                help="x-axis variable expression(s)")
		self.input_options.add_argument("-y", "--y-expressions", type=str, nargs="+",
		                                help="y-axis variable expression(s)")
		self.input_options.add_argument("-z", "--z-expressions", type=str, nargs="+",
		                                help="z-axis variable expression(s)")
		self.input_options.add_argument("-w", "--weights", type=str, nargs="+", default="1.0",
		                                help="Weight (cut) expression(s). [Default: %(default)s]")
		
		self.input_options.add_argument("--x-bins", type=str, nargs='+', default=[None],
		                                help="Binnings for x-axis. Possible inputs:\
		                                      --x-bins \"25\" for nBins; --x-bins \"20,0,1000\" for nBins, lower and upper limit;\
		                                      --x-bins \"0 10 20 30 50 100 100\" for custom bin widths.\
		                                      [Default: [\"25\"] for trees, no rebinning for histograms]")
		self.input_options.add_argument("--y-bins", type=str, nargs='+', default=[None],
		                                help="Binnings for y-axis of 2D/3D histograms. See help for --x-bins for more information. [Default: [\"25\"] for trees, no rebinning for histograms]")
		self.input_options.add_argument("--z-bins", type=str, nargs='+', default=[None],
		                                help="Binnings for z-axis of 3D histograms. See help for --x-bins for more information. [Default: [\"25\"] for trees, no rebinning for histograms]")
		
		self.input_options.add_argument("--tree-draw-options", nargs='+', type=str, default="",
		                                help="Optional argument for TTree:Draw() call. Use e.g. \"prof\" or \"profs\" for projections of 2D-Histograms to 1D. See also http://root.cern.ch/ooot/html/TTree.html#TTree:Draw. Specify \"TGraph\" for plotting y- vs. x-values into a TGraph. \"TGraphErrors\" leads to a graph with errors by specifying inputs with --x-expressions <x values>:<x errors> --y-expressions <y values>:<y errors>. \"TGraphAsymmErrorsX\" leads to a graph with asymmetric x-errors by specifying inputs with --x-expressions <x values>:<x errors (down)>:<x errors (up)> --y-expressions <y values>. \"TGraphAsymmErrorsY\" leads to a graph with asymmetric y-errors by specifying inputs with --x-expressions <x values> --y-expressions <y values>:<y errors (down)>:<y errors (up)>. TTree::MakeProxy and TTree::Process is usued to fill the histograms from a tree instead of TTree::Draw or TTree::Project in case you specify the option \"proxy\" This is needed e.g. for formulas containing two branches/leafs with different non-fundamental types.")
		
		self.input_options.add_argument("--read-config", nargs="?", type="bool", default=False, const=True,
		                                help="Read in the config stored in Artus ROOT outputs. [Default: %(default)s]")

	def prepare_args(self, parser, plotData):
		super(InputRoot, self).prepare_args(parser, plotData)

		if (plotData.plotdict["friend_treenames"] is not None) and (plotData.plotdict["friend_filenames"] is not None):
			plotData.plotdict["friend_trees"] = []
			for friend_treename, friend_filename in zip( 
		                     	 plotData.plotdict["friend_treenames"],
		                     	 plotData.plotdict["friend_filenames"]):
				tuple = []
				for plot_friend_treename, plot_friend_filename in zip(friend_treename.split(), friend_filename.split()):
					tuple.append((plot_friend_treename, plot_friend_filename))
				plotData.plotdict["friend_trees"].append(tuple)
		else:
			plotData.plotdict["friend_trees"] = [None]

		self.prepare_list_args(plotData, ["nicks", "x_expressions", "y_expressions", "z_expressions", "x_bins", "y_bins", "z_bins", "scale_factors", "files", "directories", "folders", "weights", "friend_trees", "tree_draw_options"])
		plotData.plotdict["folders"] = [folders.split() if folders else [""] for folders in plotData.plotdict["folders"]]
		
		inputbase.InputBase.prepare_nicks(plotData)
		
		if plotData.plotdict["read_config"]:
			self.read_input_json_dicts(plotData)

	def run(self, plotData):
		
		root_tools = roottools.RootTools()
		for index, (
				root_files,
				folders,
				x_expression,
				y_expression,
				z_expression,
				weight,
				x_bins,
				y_bins,
				z_bins,
				nick,
				friend_trees,
				option
		) in enumerate(pi.ProgressIterator(zip(
				plotData.plotdict["files"],
				plotData.plotdict["folders"],
				[self.expressions.replace_expressions(expression) for expression in plotData.plotdict["x_expressions"]],
				[self.expressions.replace_expressions(expression) for expression in plotData.plotdict["y_expressions"]],
				[self.expressions.replace_expressions(expression) for expression in plotData.plotdict["z_expressions"]],
				[self.expressions.replace_expressions(expression) for expression in plotData.plotdict["weights"]],
				plotData.plotdict["x_bins"],
				plotData.plotdict["y_bins"],
				plotData.plotdict["z_bins"],
				plotData.plotdict["nicks"],
				plotData.plotdict["friend_trees"],
				plotData.plotdict["tree_draw_options"]
		), description="Reading ROOT inputs")):
			# check whether to read from tree or directly from histograms
			root_object_type = roottools.RootTools.check_type(root_files, folders,
			                                                  print_quantities=plotData.plotdict["quantities"])
			root_tree_chain = None
			root_histogram = None
			
			if root_object_type == ROOT.TTree:
				variable_expression = "%s%s%s" % (z_expression + ":" if z_expression else "",
				                                  y_expression + ":" if y_expression else "",
				                                  x_expression)
				root_tree_chain, root_histogram = root_tools.histogram_from_tree(
						root_files, folders,
						x_expression, y_expression, z_expression,
						x_bins=["25"] if x_bins is None else x_bins,
						y_bins=["25"] if y_bins is None else y_bins,
						z_bins=["25"] if z_bins is None else z_bins,
						weight_selection=weight, option=option, name=None,
						friend_trees=friend_trees
				)
				
			elif root_object_type == ROOT.TH1:
				if x_expression is None:
					log.error('No x_expression provided.')
					sys.exit(1)
				root_objects = [os.path.join(folder, x_expression) for folder in folders]
				
				root_histogram = roottools.RootTools.histogram_from_file(
						root_files,
						root_objects,
						x_bins=x_bins,
						y_bins=y_bins,
						z_bins=z_bins,
						name=None)
			elif root_object_type == None:
				log.critical("Error getting ROOT object from file. Exiting.")
				sys.exit(1)
			
			log.debug("Input object %d (nick %s):" % (index, nick))
			if log.isEnabledFor(logging.DEBUG):
				root_histogram.Print()
			
			# save tree (chain) in plotData merging chains with same nick names
			if root_tree_chain != None:
				if nick in plotData.plotdict.setdefault("root_trees", {}):
					plotData.plotdict["root_trees"][nick].Add(root_tree_chain)
				else:
					plotData.plotdict["root_trees"][nick] = root_tree_chain
			
			# save histogram in plotData
			# merging histograms with same nick names is done in upper class
			plotData.plotdict.setdefault("root_objects", {}).setdefault(nick, []).append(root_histogram)

		# run upper class function at last
		super(InputRoot, self).run(plotData)


	def read_input_json_dicts(self, plotData):
		"""If Artus config dict is present in root file -> append to plotdict"""
		for root_files in plotData.plotdict["files"]:
			# TODO: make TChain instead of using only first file?
			with TFileContextManager(root_files[0], "READ") as tfile:
				keys, names = zip(*roottools.RootTools.walk_root_directory(tfile))
			if jsonTools.JsonDict.PATH_TO_ROOT_CONFIG in names:
				input_json_dict = jsonTools.JsonDict(root_files)
			else:
				input_json_dict = {}
			plotData.input_json_dicts.append(input_json_dict)

		# Raise warning if config dict could be read out for some, but not for all files
		if ({} in plotData.input_json_dicts and not all([i == {} for i in plotData.input_json_dicts])):
			log.warning("'config' dict could not be read for all input files! (ignore this warning if you're not using Artus output files)")