from functools import reduce


def thread_frame_shape(shape, thread_divisor = None, force_2d = False):
    """Computes new frame shape for threaded computaton.
    
    Parameters
    ----------
    shape : tuple of ints
        Input frame shape
    thread_divisor : int
        An integer that divides the flattend frame shape. This number determines
        number of threads.
    force_2d : bool
        If 1d data, make it 2d regardless of thread_divisor value.
        
    Returns
    -------
    shape : tuple
        A length 2 shape
    """
    new_shape = shape
    if len(new_shape) == 1 and thread_divisor is None and force_2d == True:
        thread_divisor = 1
    if thread_divisor is not None:
        total = reduce((lambda x, y: x * y), new_shape)
        try:
            new_shape = (thread_divisor, total//int(thread_divisor))
        except ValueError:
            raise ValueError("Invalid `thread_divisor`")
        
        if total != new_shape[0] * new_shape[1]:
            raise ValueError("`thread_divisor` incompatible with input array's shape")
    return new_shape