<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def tree2array(tree, branches=None, selection=None, object_selection=None, start=None, stop=None, step=None, include_weight=False, weight_name='weight', cache_size=-1):
 """Convert a tree into a numpy structured array. Convert branches of strings and basic types such as bool, int, float, double, etc. as well as variable-length and fixed-length multidimensional arrays and 1D or 2D vectors of basic types and strings. ``tree2array`` can also create columns in the output array that are expressions involving the TTree branches (i.e. ``'vect.Pt() / 1000'``) similar to ``TTree::Draw()``. See the notes below for important details. Parameters tree : ROOT TTree instance The ROOT TTree to convert into an array. branches : list of strings and tuples or a string or tuple, optional (default=None) List of branches and expressions to include as columns of the array or a single branch or expression in which case a nonstructured array is returned. If None then include all branches that can be converted. Branches or expressions that result in variable-length subarrays can be truncated at a fixed length by using the tuple ``(branch_or_expression, fill_value, length)`` or converted into a single value with ``(branch_or_expression, fill_value)`` where ``length==1`` is implied. ``fill_value`` is used when the original array is shorter than ``length``. This truncation is after any object selection performed with the ``object_selection`` argument. selection : str, optional (default=None) Only include entries fulfilling this condition. If the condition evaluates to multiple values per tree entry (e.g. conditions on array branches) then an entry will be included if the condition evaluates to true for at least one array element. object_selection : dict, optional (default=None) A dictionary mapping selection strings to branch names or lists of branch names. Only array elements passing the selection strings will be included in the output array per entry in the tree. The branches specified must be variable-length array-type branches and the length of the selection and branches it acts on must match for each tree entry. For example ``object_selection={'a > 0': ['a', 'b']}`` will include all elements of 'a' and corresponding elements of 'b' where 'a > 0' for each tree entry. 'a' and 'b' must have the same length in every tree entry. start, stop, step: int, optional (default=None) The meaning of the ``start``, ``stop`` and ``step`` parameters is the same as for Python slices. If a range is supplied (by setting some of the ``start``, ``stop`` or ``step`` parameters), only the entries in that range and fulfilling the ``selection`` condition (if defined) are used. include_weight : bool, optional (default=False) Include a column containing the tree weight ``TTree::GetWeight()``. Note that this will be the same value for all entries unless the tree is actually a TChain containing multiple trees with different weights. weight_name : str, optional (default='weight') The field name for the weight column if ``include_weight=True``. cache_size : int, optional (default=-1) Set the size (in bytes) of the TTreeCache used while reading a TTree. A value of -1 uses ROOT's default cache size. A value of 0 disables the cache. Notes ----- Types are converted according to the following table: .. _conversion_table: ======================== =============================== ROOT NumPy ======================== =============================== ``Bool_t`` ``np.bool`` ``Char_t`` ``np.int8`` ``UChar_t`` ``np.uint8`` ``Short_t`` ``np.int16`` ``UShort_t`` ``np.uint16`` ``Int_t`` ``np.int32`` ``UInt_t`` ``np.uint32`` ``Float_t`` ``np.float32`` ``Double_t`` ``np.float64`` ``Long64_t`` ``np.int64`` ``ULong64_t`` ``np.uint64`` ``string`` ``np.object`` ``vector<t>`` ``np.object`` ``vector<vector<t> >`` ``np.object`` ======================== =============================== * Variable-length arrays (such as ``x[nx][2]``) and vectors (such as ``vector<int>``) are converted to NumPy arrays of the corresponding types. * Fixed-length arrays are converted to fixed-length NumPy array fields. **Branches with different lengths:** Note that when converting trees that have branches of different lengths into numpy arrays, the shorter branches will be extended to match the length of the longest branch by repeating their last values. If all requested branches are shorter than the longest branch in the tree, this will result in a "read failure" since beyond the end of the longest requested branch no additional bytes will be read from the file and root_numpy is unable to distinguish this from other ROOT errors that result in no bytes being read. In this case, explicitly set the ``stop`` argument to the length of the longest requested branch. See Also -------- root2array array2root array2tree """

    import ROOT
    if not isinstance(tree, ROOT.TTree):
        raise TypeError("tree must be a ROOT.TTree")
    cobj = ROOT.AsCObject(tree)

    if isinstance(branches, string_types):
        # single branch selected
        flatten = branches
        branches = [branches]
    elif isinstance(branches, tuple):
        if len(branches) not in (2, 3):
            raise ValueError(
                "invalid branch tuple: {0}. "
                "A branch tuple must contain two elements "
                "(branch_name, fill_value) or three elements "
                "(branch_name, fill_value, length) "
                "to yield a single value or truncate, respectively".format(branches))
        flatten = branches[0]
        branches = [branches]
    else:
        flatten = False

    arr = _librootnumpy.root2array_fromtree(
        cobj, branches, selection, object_selection,
        start, stop, step,
        include_weight,
        weight_name,
        cache_size)

    if flatten:
        # select single column
        return arr[flatten]
    return arr