# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/30_slcs.ipynb.

# %% auto 0
__all__ = ['safeslice', 'sdim', 'slice_dimensions', 'slice_dims', 'match_slice_format', 'guess_slice_format', 'flip_slice_format',
           'slcchain', 'slice2list', 'format_slice', 'asslcfmt', 'tosliceformat', 'tocoordformat', 'trysfmt', 'try2slc',
           'asslc', 'asslice', 'makeslc', 'makeslice', 'makeslcs', 'make_slices', 'asslcs']

# %% ../nbs/30_slcs.ipynb 6
from functools import wraps, partial

# %% ../nbs/30_slcs.ipynb 8
#| export


# %% ../nbs/30_slcs.ipynb 10
#| export


# %% ../nbs/30_slcs.ipynb 12
from nlit import (COORD, SLICE,)
from quac import ints, intq, slicespec, slicespecs
from chck import isnone, notnone, isslice, isiter
from sigr import applyfns

# %% ../nbs/30_slcs.ipynb 14
from .cons import WRAPS_ASSIGN_ANNDOCS
from .atyp import P, SliceFormats, SliceSpec, SliceSpecs

# %% ../nbs/30_slcs.ipynb 17
def safeslice(s: slice) -> slice:
    '''Corrects a slice object, replacing None values with defaults to prevent errors.
    
    Returns a slice with default values instead None values from the input slice.
    e.g. slice(IntQ, IntQ, IntQ) -> slice(0, 1, 1)
    
    Parameters
    ----------
    s : slice
        The slice object to correct.
        
    Returns
    -------
    slice
        A corrected slice object with no None values.
    '''
    if not isslice(s): return s
    start = s.start if notnone(s.start) else 0
    stop  = s.stop  if notnone(s.stop)  else min(0, start, max(1, start))
    step  = s.step  if notnone(s.step)  else 1
    return slice(start, stop, step)

# %% ../nbs/30_slcs.ipynb 19
def sdim(*slcs: SliceSpecs, axes: ints | None = None, ndim: intq = None) -> int:
     '''
     Calculate the number of dimensions to which the slices apply.

     Parameters
     ----------
     slcs : slicespecs | tuple[tuple[int, int, int], ...] | tuple[tuple[int, ...], ...]
          The slices for which the dimensionality is to be determined.

     axes : tuple[int, ...], optional
          The axes that the slices apply to, defaults to None.

     ndim : int, optional
          The number of dimensions of the target tensor, defaults to None.

     Returns
     -------
     int
          The number of dimensions to which the slices apply.

     Notes
     -----
     slice : SliceFormats
          The default representations of a python slice, i.e. 
          `(start: int, stop: int, step: int)`
          
     coord : SliceFormats
          The coordinate repesentation of a python slice i.e. 
          `(x0, y0, ...), (x1, y1, ...), ...`
          
     __nones_ok : bool
          A sometimes optional parameter for slice utility functions.
          If `True`, the result is not corrected to prevent None values.
          i.e. `slice(0, 10, None)` would become `slice(0, 10, 1)`
          
                    
     Definitions
     -----------
     :slice: `slice`
          The standard representation for a python slice, e.g.
          `(start: int, stop: int, step: int)` or `slice(0, 10, 2)`


     :svals: `tuple[int | None, int, int | None]`
          The integer representation for a python slice, e.g.
          `(start: int | None, stop: int, step: int | None)` or `slice(0, 10, None)`
          
     :slices: `tuple[slice | svals, ...] `
          An iterable of like representation for a python slice, e.g.
          `slice(0, 10, 2)`, `tuple(0, 10, 2)`, `tuple(0, 10, None)`, etc

     :coord: `tuple[int, ...]`
          The coordinate representation for a python slice, e.g.
          `(x0, y0, ...), (x1, y1, ...), ...`
          
     :coords: `tuple[coord, ...]`
          An iterable of like coordinate representation for a python slice, e.g.
          `(x0, y0, ...), (x1, y1, ...), ...`
    
     Examples
     -------- 
     >>> sdim((0, 10), (2, 10))
     2

     >>> slices = (0, 5), (2, 10) # slice format: (x0, x1), (y0, y1)
     ... tocoordformat(slices) # convert to coordinate format
     ((0, 2), (5, 10)) 

     >>> coords = (0, 2), (5, 10) # coord format: (x0, y0), (x1, y1)
     ... tosliceformat(coords) # convert to slice format
     ((0, 5), (2, 10))

     See Also
     --------
     slice_dims : Alias for sdim
     slice_dimensions : Alias for sdim
     asto.slcs.tocoordformat: convert slices in slice format to coordinate format
     asto.slcs.tosliceformat: convert slices in coordinate format to slice format
     '''
     if notnone(ndim): 
          return ndim
     
     if isnone(axes): 
          return len(slcs)
     
     if isiter(axes): 
          return max(max(axes) + 1, len(axes))
     
     return axes

@wraps(sdim, assigned=WRAPS_ASSIGN_ANNDOCS)
def slice_dimensions(*slcs: slicespecs, axes: ints | None = None, ndim: intq = None) -> int:
     '''Alias for `sdim`'''
     return sdim(*slcs, axes=axes, ndim=ndim)

@wraps(sdim, assigned=WRAPS_ASSIGN_ANNDOCS)
def slice_dims(*slcs: slicespecs, axes: ints | None = None, ndim: intq = None) -> int:
     '''Alias for `sdim`'''
     return sdim(*slcs, axes=axes, ndim=ndim)

# %% ../nbs/30_slcs.ipynb 22
def match_slice_format(fmt: str) -> SliceFormats:
    '''Matches the given format to the closest valid format.
    Parameters
    ----------
    fmt : str
        The format to match.
    
    Returns
    -------
    fmt : {`'coord'`, `'slice'`}
        The matched slice format.
        
    Notes
    -----
    slice : SliceFormats
        The default representations of a python slice, i.e. 
        `(start: int, stop: int, step: int)`
        
    coord : SliceFormats
        The coordinate repesentation of a python slice i.e. 
        `(x0, y0, ...), (x1, y1, ...), ...`
        
    __nones_ok : bool
        A sometimes optional parameter for slice utility functions.
        If `True`, the result is not corrected to prevent None values.
        i.e. `slice(0, 10, None)` would become `slice(0, 10, 1)`
        
                
    Definitions
    -----------
    :slice: `slice`
        The standard representation for a python slice, e.g.
        `(start: int, stop: int, step: int)` or `slice(0, 10, 2)`


    :svals: `tuple[int | None, int, int | None]`
        The integer representation for a python slice, e.g.
        `(start: int | None, stop: int, step: int | None)` or `slice(0, 10, None)`
        
    :slices: `tuple[slice | svals, ...] `
        An iterable of like representation for a python slice, e.g.
        `slice(0, 10, 2)`, `tuple(0, 10, 2)`, `tuple(0, 10, None)`, etc

    :coord: `tuple[int, ...]`
        The coordinate representation for a python slice, e.g.
        `(x0, y0, ...), (x1, y1, ...), ...`
        
    :coords: `tuple[coord, ...]`
        An iterable of like coordinate representation for a python slice, e.g.
        `(x0, y0, ...), (x1, y1, ...), ...`

    Examples
    -------- 
    >>> sdim((0, 10), (2, 10))
    2

    >>> slices = (0, 5), (2, 10) # slice format: (x0, x1), (y0, y1)
    ... tocoordformat(slices) # convert to coordinate format
    ((0, 2), (5, 10)) 

    >>> coords = (0, 2), (5, 10) # coord format: (x0, y0), (x1, y1)
    ... tosliceformat(coords) # convert to slice format
    ((0, 5), (2, 10))

    See Also
    --------
    slice_dims : Alias for sdim
    slice_dimensions : Alias for sdim
    asto.slcs.tocoordformat: convert slices in slice format to coordinate format
    asto.slcs.tosliceformat: convert slices in coordinate format to slice format
    '''
    match fmt:
        case 'coord': return COORD
        case 'slice': return SLICE
        case _: return SLICE

# %% ../nbs/30_slcs.ipynb 24
def guess_slice_format(*slcs: SliceSpecs) -> SliceFormats:
    '''Guesses the slice format based on the given slices.

    Parameters
    ----------
    slcs : slicespecs | tuple[tuple[int, int, int], ...] | tuple[tuple[int, ...], ...]
        The slices to evaluate.

    Returns
    -------
    fmt : {`'coord'`, `'slice'`}
        The guessed slice format.
        
    Notes
    -----
    slice : SliceFormats
        The default representations of a python slice, i.e. 
        `(start: int, stop: int, step: int)`
        
    coord : SliceFormats
        The coordinate repesentation of a python slice i.e. 
        `(x0, y0, ...), (x1, y1, ...), ...`
        
    __nones_ok : bool
        A sometimes optional parameter for slice utility functions.
        If `True`, the result is not corrected to prevent None values.
        i.e. `slice(0, 10, None)` would become `slice(0, 10, 1)`
        
                
    Definitions
    -----------
    :slice: `slice`
        The standard representation for a python slice, e.g.
        `(start: int, stop: int, step: int)` or `slice(0, 10, 2)`


    :svals: `tuple[int | None, int, int | None]`
        The integer representation for a python slice, e.g.
        `(start: int | None, stop: int, step: int | None)` or `slice(0, 10, None)`
        
    :slices: `tuple[slice | svals, ...] `
        An iterable of like representation for a python slice, e.g.
        `slice(0, 10, 2)`, `tuple(0, 10, 2)`, `tuple(0, 10, None)`, etc

    :coord: `tuple[int, ...]`
        The coordinate representation for a python slice, e.g.
        `(x0, y0, ...), (x1, y1, ...), ...`
        
    :coords: `tuple[coord, ...]`
        An iterable of like coordinate representation for a python slice, e.g.
        `(x0, y0, ...), (x1, y1, ...), ...`

    Examples
    -------- 
    >>> guess_slice_format((0, 10), (0, 10))
    'slice'

    >>> slices = (0, 5), (2, 10) # slice format: (x0, x1), (y0, y1)
    ... tocoordformat(slices) # convert to coordinate format
    ((0, 2), (5, 10)) 

    >>> coords = (0, 2), (5, 10) # coord format: (x0, y0), (x1, y1)
    ... tosliceformat(coords) # convert to slice format
    ((0, 5), (2, 10))

    See Also
    --------
    asto.slcs.tocoordformat: convert slices in slice format to coordinate format
    asto.slcs.tosliceformat: convert slices in coordinate format to slice format
    '''
    if any(isslice(slc) for slc in slcs): return SLICE
    if any([len(slc) > 3 for slc in slcs]): return COORD
    return SLICE

# %% ../nbs/30_slcs.ipynb 26
def flip_slice_format(*slcs: SliceSpecs) -> SliceSpecs:
    '''
    Flips the format of the given slices between 'coord' and 'slice'.

    Parameters
    ----------
    slcs : slicespecs | tuple[tuple[int, int, int], ...] | tuple[tuple[int, ...], ...]
        The slices to flip. Can be in 'coord' or 'slice' format.

    Returns
    -------
    slices: slicespecs | tuple[tuple[int, int, int], ...] | tuple[tuple[int, ...], ...]
        The slices flipped to the opposite format.

    Notes
    -----
    slice : SliceFormats
        The default representations of a python slice, i.e. 
        `(start: int, stop: int, step: int)`
        
    coord : SliceFormats
        The coordinate repesentation of a python slice i.e. 
        `(x0, y0, ...), (x1, y1, ...), ...`
        
    __nones_ok : bool
        A sometimes optional parameter for slice utility functions.
        If `True`, the result is not corrected to prevent None values.
        i.e. `slice(0, 10, None)` would become `slice(0, 10, 1)`
        
                
    Definitions
    -----------
    :slice: `slice`
        The standard representation for a python slice, e.g.
        `(start: int, stop: int, step: int)` or `slice(0, 10, 2)`


    :svals: `tuple[int | None, int, int | None]`
        The integer representation for a python slice, e.g.
        `(start: int | None, stop: int, step: int | None)` or `slice(0, 10, None)`
        
    :slices: `tuple[slice | svals, ...] `
        An iterable of like representation for a python slice, e.g.
        `slice(0, 10, 2)`, `tuple(0, 10, 2)`, `tuple(0, 10, None)`, etc

    :coord: `tuple[int, ...]`
        The coordinate representation for a python slice, e.g.
        `(x0, y0, ...), (x1, y1, ...), ...`
        
    :coords: `tuple[coord, ...]`
        An iterable of like coordinate representation for a python slice, e.g.
        `(x0, y0, ...), (x1, y1, ...), ...`

    Examples
    --------    
    >>> flip_slice_format((0, 10), (0, 10))
    ((0, 0), (10, 10)) # coordinate format

    >>> slices = (0, 5), (2, 10) # slice format: (x0, x1), (y0, y1)
    ... tocoordformat(slices) # convert to coordinate format
    ((0, 2), (5, 10)) 

    >>> coords = (0, 2), (5, 10) # coord format: (x0, y0), (x1, y1)
    ... tosliceformat(coords) # convert to slice format
    ((0, 5), (2, 10))

    See Also
    --------
    asto.slcs.tocoordformat: convert slices in slice format to coordinate format
    asto.slcs.tosliceformat: convert slices in coordinate format to slice format
    '''
    return tuple(zip(*slcs))

# %% ../nbs/30_slcs.ipynb 28
def slcchain(x, funcs, *args: P.args, **kwargs: P.kwargs): 
    '''Applies a sequence of functions (`funcs`) to an initial value `x`, 
    optionally stopping when the typeguard function `isslice` returns `True`.
    
    See Also
    --------
    sigr.applyfns
    ''' 
    return applyfns(x, funcs, *args, check=isslice, **kwargs)

# %% ../nbs/30_slcs.ipynb 31
def slice2list(s: slice) -> tuple[intq, int, intq]:
    '''Converts a slice object to a list of integers it represents.
    
    Returns a list of integers from a slice.
    
    Parameters
    ----------
    s : slice
        The slice object to convert.
        
    Returns
    -------
    list
        A list of integers represented by the slice.
    '''
    s = safeslice(s)
    try:
        return list(range(s.start, s.stop, s.step))
    except: 
        return list()

# %% ../nbs/30_slcs.ipynb 33
def format_slice(*slcs: SliceSpecs, fmt: SliceFormats = SLICE, cur: SliceFormats | None = None) -> SliceSpecs:
    '''
    Format the given slices as either coordinates ('coord') or 'slice'.

    Parameters
    ----------
    slcs : slicespecs | tuple[tuple[int, int, int], ...] | tuple[tuple[int, ...], ...]
        The slices to flip. Can be in 'coord' or 'slice' format.

    Returns
    -------
    slices: slicespecs | tuple[tuple[int, int, int], ...] | tuple[tuple[int, ...], ...]
        The slices flipped to the opposite format.
    
    Notes
    -----
    slice : SliceFormats
        The default representations of a python slice, i.e. 
        `(start: int, stop: int, step: int)`
        
    coord : SliceFormats
        The coordinate repesentation of a python slice i.e. 
        `(x0, y0, ...), (x1, y1, ...), ...`
        
    __nones_ok : bool
        A sometimes optional parameter for slice utility functions.
        If `True`, the result is not corrected to prevent None values.
        i.e. `slice(0, 10, None)` would become `slice(0, 10, 1)`
                
    Definitions
    -----------
    :slice: `slice`
        The standard representation for a python slice, e.g.
        `(start: int, stop: int, step: int)` or `slice(0, 10, 2)`


    :svals: `tuple[int | None, int, int | None]`
        The integer representation for a python slice, e.g.
        `(start: int | None, stop: int, step: int | None)` or `slice(0, 10, None)`
        
    :slices: `tuple[slice | svals, ...] `
        An iterable of like representation for a python slice, e.g.
        `slice(0, 10, 2)`, `tuple(0, 10, 2)`, `tuple(0, 10, None)`, etc

    :coord: `tuple[int, ...]`
        The coordinate representation for a python slice, e.g.
        `(x0, y0, ...), (x1, y1, ...), ...`
        
    :coords: `tuple[coord, ...]`
        An iterable of like coordinate representation for a python slice, e.g.
        `(x0, y0, ...), (x1, y1, ...), ...`

    Examples
    --------
    >>> slices = (0, 5), (2, 10) # slice format: (x0, x1), (y0, y1)
    ... tocoordformat(slices) # convert to coordinate format
    ((0, 2), (5, 10)) 

    >>> coords = (0, 2), (5, 10) # coord format: (x0, y0), (x1, y1)
    ... tosliceformat(coords) # convert to slice format
    ((0, 5), (2, 10))

    See Also
    --------
    asto.slcs.tocoordformat: convert slices in slice format to coordinate format
    asto.slcs.tosliceformat: convert slices in coordinate format to slice format
    '''
    fmt = match_slice_format(fmt)
    if isnone(cur): 
        cur = guess_slice_format(*slcs)
        
    if cur == fmt: 
        return slcs
    
    else: 
        return flip_slice_format(*slcs)
    
@wraps(format_slice, assigned=WRAPS_ASSIGN_ANNDOCS)
def asslcfmt(*slcs, fmt: SliceFormats = SLICE, cur: SliceFormats | None = None) -> slicespecs:
    return format_slice(*slcs, fmt = fmt, cur = cur)

@wraps(format_slice, assigned=WRAPS_ASSIGN_ANNDOCS)
def tosliceformat(*slcs, cur: SliceFormats | None = None) -> slicespecs:
    formatter = partial(format_slice, fmt=SLICE)
    return formatter(*slcs, cur = cur)

@wraps(format_slice, assigned=WRAPS_ASSIGN_ANNDOCS)
def tocoordformat(*slcs, cur: SliceFormats | None = None) -> slicespecs:
    formatter = partial(format_slice, fmt=COORD)
    return formatter(*slcs, cur = cur)

# %% ../nbs/30_slcs.ipynb 35
def trysfmt(a: slice, fmt: SliceFormats | None = None, cur: SliceFormats | None = None) -> SliceSpec:
    '''Attempts to format `a` to the desired format.
    
    Parameters
    ----------
    a : Any
        The input object to convert.
        
    Returns
    -------
    slice
        A slice object if conversion is successful, otherwise `a`.
        
    Notes
    -----
    slice : SliceFormats
        The default representations of a python slice, i.e. 
        `(start: int, stop: int, step: int)`
        
    coord : SliceFormats
        The coordinate repesentation of a python slice i.e. 
        `(x0, y0, ...), (x1, y1, ...), ...`
        
    __nones_ok : bool
        A sometimes optional parameter for slice utility functions.
        If `True`, the result is not corrected to prevent None values.
        i.e. `slice(0, 10, None)` would become `slice(0, 10, 1)`
                
    Definitions
    -----------
    :slice: `slice`
        The standard representation for a python slice, e.g.
        `(start: int, stop: int, step: int)` or `slice(0, 10, 2)`


    :svals: `tuple[int | None, int, int | None]`
        The integer representation for a python slice, e.g.
        `(start: int | None, stop: int, step: int | None)` or `slice(0, 10, None)`
        
    :slices: `tuple[slice | svals, ...] `
        An iterable of like representation for a python slice, e.g.
        `slice(0, 10, 2)`, `tuple(0, 10, 2)`, `tuple(0, 10, None)`, etc

    :coord: `tuple[int, ...]`
        The coordinate representation for a python slice, e.g.
        `(x0, y0, ...), (x1, y1, ...), ...`
        
    :coords: `tuple[coord, ...]`
        An iterable of like coordinate representation for a python slice, e.g.
        `(x0, y0, ...), (x1, y1, ...), ...`

    Examples
    --------
    >>> slices = (0, 5), (2, 10) # slice format: (x0, x1), (y0, y1)
    ... tocoordformat(slices) # convert to coordinate format
    ((0, 2), (5, 10)) 

    >>> coords = (0, 2), (5, 10) # coord format: (x0, y0), (x1, y1)
    ... tosliceformat(coords) # convert to slice format
    ((0, 5), (2, 10))
    
    See Also
    --------
    asto.slcs.tocoordformat: convert slices in slice format to coordinate format
    asto.slcs.tosliceformat: convert slices in coordinate format to slice format
    '''
    if isslice(a) and isnone(fmt): return a
    try: return format_slice(a, fmt, cur)
    except: return a

# %% ../nbs/30_slcs.ipynb 37
def try2slc(a) -> slice:
    '''Attempts to convert `a` to a slice object, falling back to `a` if unsuccessful.
    
    Parameters
    ----------
    a : Any
        The input object to convert.
        
    Returns
    -------
    slice
        A slice object if conversion is successful, otherwise `a`.
    '''
    if isslice(a): return a
    try: return slice(*list((a, )if not isiter(a) else a))    
    except: return a

# %% ../nbs/30_slcs.ipynb 39
def asslc(a, *args: P.args, **kwargs: P.kwargs) -> slice:
    '''Ensures `a` is represented as or converted to a slice object, 
    applying corrections and conversions as needed.
    
    Parameters
    ----------
    a : Any
        The input object to convert.
        
    *args : P.args
        Additional positional arguments for conversion functions.
        
    **kwargs : P.kwargs
        Additional keyword arguments for conversion functions.
        
    Other Parameters
    ----------------
    __format: SliceFormats, optional
        The format to coerce the slice into.
        
    __current: SliceFormats, optional
        The current to format the slice is in.
        
    __nones_ok : bool, default: False
        If `True`, the result is not corrected to prevent None values.
        i.e. `slice(0, 10, None)` would become `slice(0, 10, 1)`
        
    Returns
    -------
    slice
        A slice object representing `a`, corrected if necessary.
    
    Notes
    -----
    slice : SliceFormats
        The default representations of a python slice, i.e. 
        `(start: int, stop: int, step: int)`
        
    coord : SliceFormats
        The coordinate repesentation of a python slice i.e. 
        `(x0, y0, ...), (x1, y1, ...), ...`
        
    __nones_ok : bool
        A sometimes optional parameter for slice utility functions.
        If `True`, the result is not corrected to prevent None values.
        i.e. `slice(0, 10, None)` would become `slice(0, 10, 1)`
                
    Definitions
    -----------
    :slice: `slice`
        The standard representation for a python slice, e.g.
        `(start: int, stop: int, step: int)` or `slice(0, 10, 2)`


    :svals: `tuple[int | None, int, int | None]`
        The integer representation for a python slice, e.g.
        `(start: int | None, stop: int, step: int | None)` or `slice(0, 10, None)`
        
    :slices: `tuple[slice | svals, ...] `
        An iterable of like representation for a python slice, e.g.
        `slice(0, 10, 2)`, `tuple(0, 10, 2)`, `tuple(0, 10, None)`, etc

    :coord: `tuple[int, ...]`
        The coordinate representation for a python slice, e.g.
        `(x0, y0, ...), (x1, y1, ...), ...`
        
    :coords: `tuple[coord, ...]`
        An iterable of like coordinate representation for a python slice, e.g.
        `(x0, y0, ...), (x1, y1, ...), ...`

    Examples
    --------
    >>> slices = (0, 5), (2, 10) # slice format: (x0, x1), (y0, y1)
    ... tocoordformat(slices) # convert to coordinate format
    ((0, 2), (5, 10)) 

    >>> coords = (0, 2), (5, 10) # coord format: (x0, y0), (x1, y1)
    ... tosliceformat(coords) # convert to slice format
    ((0, 5), (2, 10))
        
    See Also
    --------
    asslice : alias for asslc
    makeslc : alias for asslc
    makeslice : alias for asslc
    asto.slcs.tocoordformat: convert slices in slice format to coordinate format
    asto.slcs.tosliceformat: convert slices in coordinate format to slice format
    '''
    if isslice(a): return a
    chain = (safeslice, try2slc, )
    
    nok = kwargs.pop('__nones_ok', False)
    fmt = kwargs.pop('__format', None)
    cur = kwargs.pop('__current', None)
    
    slc = slcchain(a, chain, *args, **kwargs)
    
    # 
    if nok: 
        return slc
    
    slc = safeslice(slc)
    if notnone(fmt): 
        slc = trysfmt(slc, fmt, cur)
    return slc

@wraps(asslc, assigned=WRAPS_ASSIGN_ANNDOCS)
def asslice(a, *args: P.args, **kwargs: P.kwargs) -> slice:
    '''Alias for asslc'''
    kwargs.pop('__format', None)
    return asslc(a, *args, **kwargs, __format=SLICE)

@wraps(asslc, assigned=WRAPS_ASSIGN_ANNDOCS)
def makeslc(a, *args: P.args, **kwargs: P.kwargs) -> slice:
    '''Alias for asslc'''
    return asslc(a, *args, **kwargs)

@wraps(asslc, assigned=WRAPS_ASSIGN_ANNDOCS)
def makeslice(a, *args: P.args, **kwargs: P.kwargs) -> slice:
    '''Alias for asslc'''
    return asslc(a, *args, **kwargs)

# %% ../nbs/30_slcs.ipynb 41
def makeslcs(
    *slcs: SliceSpecs, 
    axes: ints | None = None, 
    ndim: intq = None, 
    fmt: SliceFormats = SLICE,
) -> list[slice]:     
    '''Convert tuples representing slices into actual Python slice objects.

    Parameters
    ----------
    slcs : slicespecs | tuple[tuple[int, int, int], ...] | tuple[tuple[int, ...], ...]
        Tuples representing the slices.
        
    axes : tuple[int, ...], optional
        The axes that the slices apply to, defaults to None.

    ndim : int, optional
        The number of dimensions of the target tensor, defaults to None.

    fmt : SliceFormats, default: 'slice'
        The format of the input slices, either 'coord' or 'slice', defaults to 'slice'.

    Returns
    -------
    list[slice]
        A list of Python slice objects (i.e. slices in slice format)
        
    Notes
    -----
    slice : SliceFormats
        The default representations of a python slice, i.e. 
        `(start: int, stop: int, step: int)`
        
    coord : SliceFormats
        The coordinate repesentation of a python slice i.e. 
        `(x0, y0, ...), (x1, y1, ...), ...`
        
    __nones_ok : bool
        A sometimes optional parameter for slice utility functions.
        If `True`, the result is not corrected to prevent None values.
        i.e. `slice(0, 10, None)` would become `slice(0, 10, 1)`
                
    Definitions
    -----------
    :slice: `slice`
        The standard representation for a python slice, e.g.
        `(start: int, stop: int, step: int)` or `slice(0, 10, 2)`


    :svals: `tuple[int | None, int, int | None]`
        The integer representation for a python slice, e.g.
        `(start: int | None, stop: int, step: int | None)` or `slice(0, 10, None)`
        
    :slices: `tuple[slice | svals, ...] `
        An iterable of like representation for a python slice, e.g.
        `slice(0, 10, 2)`, `tuple(0, 10, 2)`, `tuple(0, 10, None)`, etc

    :coord: `tuple[int, ...]`
        The coordinate representation for a python slice, e.g.
        `(x0, y0, ...), (x1, y1, ...), ...`
        
    :coords: `tuple[coord, ...]`
        An iterable of like coordinate representation for a python slice, e.g.
        `(x0, y0, ...), (x1, y1, ...), ...`

    Examples
    --------
    >>> makeslcs((0, 10), (0, 10))
    [slice(0, 10, None), slice(0, 10, None)]
    
    >>> slices = (0, 5), (2, 10) # slice format: (x0, x1), (y0, y1)
    ... tocoordformat(slices) # convert to coordinate format
    ((0, 2), (5, 10)) 

    >>> coords = (0, 2), (5, 10) # coord format: (x0, y0), (x1, y1)
    ... tosliceformat(coords) # convert to slice format
    ((0, 5), (2, 10))
    
    See Also
    --------
    asslcs : Alias for makeslcs
    make_slices : Alias for makeslcs
    asto.slcs.tocoordformat: convert slices in slice format to coordinate format
    asto.slcs.tosliceformat: convert slices in coordinate format to slice format
    '''
    # (x0, y0), (x1, y1) --> (x0, x1), (y0, y1)
    if isnone(fmt): 
        fmt = guess_slice_format(*slcs)
    
    if fmt == COORD: 
        slcs = flip_slice_format(*slcs)

    # Convert slcs tuples into slices
    slices = list(asslc(slc, __nones_ok=True) for slc in slcs)
    nslice = sdim(*slices, axes=axes, ndim=ndim)
    
    # Create a list of slice(None) for all dimensions
    axes = list([slice(None)] * nslice if isnone(axes) else axes)

    # Replace slices for specified axes
    slices = [slices[axes.index(i)] if i in axes else slice(None) for i in range(nslice)]
    return slices

@wraps(makeslcs, assigned=WRAPS_ASSIGN_ANNDOCS)
def make_slices(
    *slcs: slicespecs, 
    axes: ints | None = None, 
    ndim: intq = None, 
    fmt: SliceFormats = SLICE
) -> list[slice]:
    '''Alias for makeslcs'''
    return makeslcs(*slcs, axes=axes, ndim=ndim, fmt=fmt)

@wraps(makeslcs, assigned=WRAPS_ASSIGN_ANNDOCS)
def asslcs(
    *slcs: slicespecs, 
    axes: ints | None = None, 
    ndim: intq = None, 
    fmt: SliceFormats = SLICE
) -> list[slice]:
    '''Alias for makeslcs'''
    return makeslcs(*slcs, axes=axes, ndim=ndim, fmt=fmt)
