docs: def Draw(self,
               expression,
               selection="",
               options="",
               hist=None,
               create_hist=False,
               **kwargs):
          """
          Draw a TTree with a selection as usual, but return the created
          histogram.
  
          Parameters
          ----------
          expression : str
              The expression to draw. Multidimensional expressions are separated
              by ":". rootpy reverses the expressions along each dimension so the
              order matches the order of the elements identifying a location in
              the resulting histogram. By default ROOT takes the expression "Y:X"
              to mean Y versus X but we argue that this is counterintuitive and
              that the order should be "X:Y" so that the expression along the
              first dimension identifies the location along the first axis, etc.
  
          selection : str or rootpy.tree.Cut, optional (default="")
              The cut expression. Only entries satisfying this selection are
              included in the filled histogram.
  
          options : str, optional (default="")
              Draw options passed to ROOT.TTree.Draw
  
          hist : ROOT.TH1, optional (default=None)
              The histogram to be filled. If not specified, rootpy will attempt
              to find what ROOT created and return that.
  
          create_hist : bool (default=False)
              If True and `hist`` is not specified and a histogram name is not
              specified in the draw expression, then override ROOT's
              default behaviour and fill a new histogram. ROOT will otherwise add
              points to a TGraph or TPolyMarker3D if not drawing in more than
              two dimensions.
  
          kwargs : dict, optional
              Remaining keword arguments are used to set the style attributes of
              the histogram.
  
          Returns
          -------
          If ``hist`` is specified, None is returned. If ``hist`` is left
          unspecified, an attempt is made to retrieve the generated histogram
          which is then returned.
  
          """
          if isinstance(expression, string_types):
              # Check that we have a valid draw expression
              exprmatch = re.match(BaseTree.DRAW_PATTERN, expression)
              if not exprmatch:
                  raise ValueError(
                      "not a valid draw expression: `{0}`".format(expression))
              exprdict = exprmatch.groupdict()
  
              # Reverse variable order to match order in hist constructor
              fields = re.split('(?<!:):(?!:)', exprdict['branches'])
              num_dimensions = len(fields)
              expression = ':'.join(fields[:3][::-1] + fields[3:])
              if exprdict['redirect'] is not None:
                  expression += exprdict['redirect']
  
          else:  # expression is list, tuple, ...
              fields = expression
              num_dimensions = len(fields)
              expression = ':'.join(fields[:3][::-1] + fields[3:])
              exprdict = {
                  'branches': None,
                  'redirect': None,
                  'name': None,
                  'binning': None,
                  }
  
          if not isinstance(selection, Cut):
              # Let Cut handle any extra processing (i.e. ternary operators)
              selection = Cut(selection)
  
          graphics = 'goff' not in options
  
          if hist is not None:
              if not isinstance(hist, ROOT.TH1):
                  raise TypeError("Cannot draw into a `{0}`".format(type(hist)))
  
              # Check that the dimensionality of the expression and object match
              if num_dimensions != hist.GetDimension():
                  raise TypeError(
                      "The dimensionality of the expression `{0}` ({1:d}) "
                      "does not match the dimensionality of a `{2}`".format(
                          expression, num_dimensions, hist.__class__.__name__))
              # Handle graphics ourselves
              if graphics:
                  if options:
                      options += ' '
                  options += 'goff'
              if exprdict['name'] is None:
                  # Draw into histogram supplied by user
                  expression = '{0}>>+{1}'.format(expression, hist.GetName())
              else:
                  if exprdict['name'] != hist.GetName():
                      # If the user specified a name to draw into then check that
                      # this is consistent with the specified object.
                      raise ValueError(
                          "The name specified in the draw "
                          "expression `{0}` does not match the "
                          "name of the specified object `{1}`".format(
                              exprdict['name'],
                              hist.GetName()))
                  # Check that binning is not specified
                  if exprdict['binning'] is not None:
                      raise ValueError(
                          "When specifying the object to draw into, do not "
                          "specify a binning in the draw expression")
          else:
              if create_hist and exprdict['name'] is None:
                  if num_dimensions > 4:
                      raise ValueError(
                          "Cannot create a histogram for expressions with "
                          "more than 4 dimensions")
                  newname = '{0}_{1}'.format(self.__class__.__name__, uuid())
                  expression += '>>{0}'.format(newname)
                  exprdict['name'] = newname
  
              pad = ROOT.gPad
              own_pad = False
  
              if graphics and not pad:
                  # Create a new canvas if one doesn't exist yet
                  own_pad = True
                  pad = Canvas()
  
          #  Note: TTree.Draw() pollutes gDirectory, make a temporary one
          with thread_specific_tmprootdir():
              if hist is not None:
                  # If a custom histogram is specified (i.e, it's not being
                  # created root side), then temporarily put it into the
                  # temporary thread-specific directory.
                  context = set_directory(hist)
              else:
                  context = do_nothing()
              with context:
                  super(BaseTree, self).Draw(expression, selection, options)
  
          if hist is None:
              # Retrieve histogram made by TTree.Draw
              if num_dimensions == 1 or exprdict['name'] is not None:
                  # a TH1
                  hist = asrootpy(self.GetHistogram(), warn=False)
              elif num_dimensions == 2:
                  # a TGraph
                  hist = asrootpy(pad.GetPrimitive('Graph'), warn=False)
              else:
                  # ROOT: For a three and four dimensional Draw the TPolyMarker3D
                  # is unnamed, and cannot be retrieved. Why, ROOT?
                  log.warning(
                      "Cannot retrieve the TPolyMarker3D for "
                      "3D and 4D expressions")
                  if graphics and own_pad:
                      # Since we cannot access the TPolyMarker3D we use self to
                      # keep the canvas alive
                      keepalive(self, pad)
              if hist: # is not None
                  if isinstance(hist, Plottable):
                      hist.decorate(**kwargs)
                  # ROOT, don't try to delete this object! (See issue #277)
                  hist.SetBit(ROOT.kCanDelete, False)
                  if graphics:
                      if own_pad:
                          # The usual bug is that the histogram is garbage
                          # collected and we want the canvas to keep the
                          # histogram alive, but here the canvas has been
                          # created locally and we are returning the histogram,
                          # so we want the histogram to keep the canvas alive.
                          keepalive(hist, pad)
                      # Redraw the histogram since we may have specified style
                      # attributes in **kwargs
                      hist.Draw()
              if graphics:
                  pad.Modified()
                  pad.Update()
          return hist