<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def nonuniform_partition(*coord_vecs, **kwargs):
 """Return a partition with un-equally sized cells. Parameters Arrays of coordinates of the mid-points of the partition cells. min_pt, max_pt : float or sequence of floats, optional Vectors defining the lower/upper limits of the intervals in an `IntervalProd` (a rectangular box). ``None`` entries mean "compute the value". nodes_on_bdry : bool or sequence, optional If a sequence is provided, it determines per axis whether to place the last grid point on the boundary (``True``) or shift it by half a cell size into the interior (``False``). In each axis, an entry may consist in a single bool or a 2-tuple of bool. In the latter case, the first tuple entry decides for the left, the second for the right boundary. The length of the sequence must be ``array.ndim``. A single boolean is interpreted as a global choice for all boundaries. Cannot be given with both min_pt and max_pt since they determine the same thing. Default: ``False`` See Also -------- uniform_partition : uniformly spaced points uniform_partition_fromintv : partition an existing set uniform_partition_fromgrid : use an existing grid as basis Examples -------- With uniformly spaced points the result is the same as a uniform partition: uniform_partition(-0.5, 3.5, 4) uniform_partition([-0.5, 0.5], [ 3.5, 2.5], (4, 2)) If the points are not uniformly spaced, a nonuniform partition is created. Note that the containing interval is calculated by assuming that the points are in the middle of the sub-intervals: nonuniform_partition( [ 0., 1., 3.] ) Higher dimensional partitions are created by specifying the gridpoints along each dimension: nonuniform_partition( [ 0., 1., 3.], [ 1., 2.] ) Partitions with a single element are by default degenerate uniform_partition(1.0, 1.0, 1, nodes_on_bdry=True) If the endpoints should be on the boundary, the ``nodes_on_bdry`` parameter can be used: nonuniform_partition( [ 0., 1., 3.], nodes_on_bdry=True ) Users can also manually specify the containing intervals dimensions by using the ``min_pt`` and ``max_pt`` arguments: nonuniform_partition( [ 0., 1., 3.], min_pt=-2.0, max_pt=3.0 ) """

    # Get parameters from kwargs
    min_pt = kwargs.pop('min_pt', None)
    max_pt = kwargs.pop('max_pt', None)
    nodes_on_bdry = kwargs.pop('nodes_on_bdry', False)

    # np.size(None) == 1
    sizes = [len(coord_vecs)] + [np.size(p) for p in (min_pt, max_pt)]
    ndim = int(np.max(sizes))

    min_pt = normalized_scalar_param_list(min_pt, ndim, param_conv=float,
                                          keep_none=True)
    max_pt = normalized_scalar_param_list(max_pt, ndim, param_conv=float,
                                          keep_none=True)
    nodes_on_bdry = normalized_nodes_on_bdry(nodes_on_bdry, ndim)

    # Calculate the missing parameters in min_pt, max_pt
    for i, (xmin, xmax, (bdry_l, bdry_r), coords) in enumerate(
            zip(min_pt, max_pt, nodes_on_bdry, coord_vecs)):
        # Check input for redundancy
        if xmin is not None and bdry_l:
            raise ValueError('in axis {}: got both `min_pt` and '
                             '`nodes_on_bdry=True`'.format(i))
        if xmax is not None and bdry_r:
            raise ValueError('in axis {}: got both `max_pt` and '
                             '`nodes_on_bdry=True`'.format(i))

        # Handle length 1 inputs
        coords = np.array(coords, copy=False, ndmin=1)

        # Compute boundary position if not given by user
        if xmin is None:
            if bdry_l or len(coords) == 1:
                min_pt[i] = coords[0]
            else:
                min_pt[i] = coords[0] - (coords[1] - coords[0]) / 2.0
        if xmax is None:
            if bdry_r or len(coords) == 1:
                max_pt[i] = coords[-1]
            else:
                max_pt[i] = coords[-1] + (coords[-1] - coords[-2]) / 2.0

    interval = IntervalProd(min_pt, max_pt)
    grid = RectGrid(*coord_vecs)
    return RectPartition(interval, grid)