def _make_random_patches(x, y, patch_size, permutations, size=3):
    batch_size = x.get_shape().as_list()[0]
    crop_size = x.get_shape().as_list()[1]

    perm_idx = tf.expand_dims(y, 1)
    perm = tf.gather_nd(permutations, perm_idx)


    WINDOW_SIZE = crop_size // size

    N = x.get_shape().as_list()[0]
    C = x.get_shape().as_list()[3]

    patches = []

    for i, j in dd.multi_range(size, size):
        #tf.slice(x, [

        M = WINDOW_SIZE - patch_size + 1
        assert M > 0, f'Jigsaw: Window size ({WINDOW_SIZE}) and patch size ({patch_size}) not compatible'
        limit = np.array([1, M, M, 1])
        offset = np.array([0, i * WINDOW_SIZE, j * WINDOW_SIZE, 0]) + tf.random_uniform(
                [4], dtype=tf.int32,
                maxval=M,
                ) % limit
        patch = tf.slice(x, offset, [N, patch_size, patch_size, C])
        patches.append(patch)

    patches1 = tf.stack(patches, axis=1)
    xyz = np.arange(batch_size)[:, np.newaxis] * size**2 + (perm - 1)
    #import ipdb
    #ipdb.set_trace()
    perm0 = tf.reshape(xyz, [-1])

    patches_flat = tf.reshape(patches1, [-1] + patches1.get_shape().as_list()[2:])
    #import ipdb
    ##ipdb.set_trace()
    patches2 = tf.gather(patches_flat, perm0)

    #return tf.reshape(patches2, [-1, PATCH_SIZE, PATCH_SIZE, C])
    return patches2