Recursively builds a tree for proposing new position and momentum

def _build_tree(self, position, momentum, slice_var, direction, depth, stepsize):
        """
        Recursively builds a tree for proposing new position and momentum
        """

        # Parameter names in algorithm (here -> representation in algorithm)
        # position -> theta, momentum -> r, slice_var -> u, direction -> v, depth ->j, stepsize -> epsilon
        # candidate_set_size -> n, accept_set_bool -> s
        if depth == 0:
            # Take single leapfrog step in the given direction (direction * stepsize)
            position_bar, momentum_bar, candidate_set_size, accept_set_bool =\
                self._initalize_tree(position, momentum, slice_var, direction * stepsize)

            return (position_bar, momentum_bar, position_bar, momentum_bar, position_bar,
                    candidate_set_size, accept_set_bool)

        else:
            # Build left and right subtrees
            (position_backward, momentum_backward, position_forward, momentum_forward, position_bar,
             candidate_set_size, accept_set_bool) = self._build_tree(position, momentum,
                                                                     slice_var, direction, depth - 1, stepsize)
            if accept_set_bool == 1:
                if direction == -1:
                    # Build tree in backward direction
                    (position_backward, momentum_backward, _, _, position_bar2, candidate_set_size2,
                     accept_set_bool2) = self._build_tree(position_backward, momentum_backward,
                                                          slice_var, direction, depth - 1, stepsize)
                else:
                    # Build tree in forward direction
                    (_, _, position_forward, momentum_forward, position_bar2, candidate_set_size2,
                     accept_set_bool2) = self._build_tree(position_forward, momentum_forward,
                                                          slice_var, direction, depth - 1, stepsize)

                if np.random.rand() < candidate_set_size2 / (candidate_set_size2 + candidate_set_size):
                    position_bar = position_bar2

                accept_set_bool, candidate_set_size =\
                    self._update_acceptance_criteria(position_forward, position_backward, momentum_forward,
                                                     momentum_backward, accept_set_bool2, candidate_set_size,
                                                     candidate_set_size2)

            return (position_backward, momentum_backward, position_forward, momentum_forward,
                    position_bar, candidate_set_size, accept_set_bool)