jiahuimbzuai/CoQuIR huggingface dataset:
//  [python]
def get_qkv_length(
            self,
            q_shape,
            k_shape,
            v_shape,
    ) -> Tuple[int]:
        """
        Args:
            q_shape(List[int]):
                q tensor shape.
            k_shape(List[int]):
                k tensor shape.
            v_shape(List[int]):
                v tensor shape.
        """
        q_n = numpy.prod(q_shape) + 1 if self.has_cls_embed else numpy.prod(q_shape)
        k_n = numpy.prod(k_shape) + 1 if self.has_cls_embed else numpy.prod(k_shape)
        v_n = numpy.prod(v_shape) + 1 if self.has_cls_embed else numpy.prod(v_shape)
        return q_n, k_n, v_n
//  [python]
def _call_numpy(self, x):
        """Return ``self(x)`` using numpy.

        See Also
        --------
        DiscreteFourierTransformBase._call_numpy
        """
        assert isinstance(x, np.ndarray)

        if self.halfcomplex:
            return np.fft.rfftn(x, axes=self.axes)
        else:
            if self.sign == '-':
                return np.fft.fftn(x, axes=self.axes)
            else:
                # Need to undo Numpy IFFT scaling
                return (np.multiply.reduce(np.take(self.domain.shape, self.axes)) *
                        np.fft.ifftn(x, axes=self.axes))
//  [python]
def _call_numpy(self, x):
        """Return ``self(x)`` using numpy.

        See Also
        --------
        DiscreteFourierTransformBase._call_numpy
        """
        assert isinstance(x, np.ndarray)

        if self.halfcomplex:
            return np.fft.rfftn(x, axes=self.axes)
        else:
            if self.sign == '-':
                return np.fft.fftn(x, axes=self.axes)
            else:
                # Need to undo Numpy IFFT scaling
                return (np.prod(np.take(self.domain.shape, self.axes)) *
                        np.fft.ifftn(x, axes=self.axes))
//  [python]
def _call_numpy(self, x):
        """Return ``self(x)`` using numpy.

        Parameters
        ----------
        x : `numpy.ndarray`
            Input array to be transformed

        Returns
        -------
        out : `numpy.ndarray`
            Result of the transform
        """
        if self.halfcomplex:
            return np.fft.irfftn(x, axes=self.axes)
        else:
            if self.sign == '+':
                return np.fft.ifftn(x, axes=self.axes)
            else:
                return (np.fft.fftn(x, axes=self.axes) /
                        np.multiply.reduce(np.take(self.domain.shape, self.axes)))
//  [python]
def _call_numpy(self, x):
        """Return ``self(x)`` using numpy.

        Parameters
        ----------
        x : `numpy.ndarray`
            Input array to be transformed

        Returns
        -------
        out : `numpy.ndarray`
            Result of the transform
        """
        if self.halfcomplex:
            return np.fft.irfftn(x, axes=self.axes)
        else:
            if self.sign == '+':
                return np.fft.ifftn(x, axes=self.axes)
            else:
                return (np.fft.fftn(x, axes=self.axes) /
                        np.prod(np.take(self.domain.shape, self.axes)))
//  [python]
def _call_numpy(self, x):
        """Return ``self(x)`` for numpy back-end.

        Parameters
        ----------
        x : `numpy.ndarray`
            Array representing the function to be transformed

        Returns
        -------
        out : `numpy.ndarray`
            Result of the transform
        """
        # Pre-processing before calculating the DFT
        # Note: since the FFT call is out-of-place, it does not matter if
        # preprocess produces real or complex output in the R2C variant.
        # There is no significant time difference between (full) R2C and
        # C2C DFT in Numpy.
        preproc = self._preprocess(x)

        # The actual call to the FFT library, out-of-place unfortunately
        if self.halfcomplex:
            out = np.fft.rfftn(preproc, axes=self.axes)
        else:
            if self.sign == '-':
                out = np.fft.fftn(preproc, axes=self.axes)
            else:
                out = np.fft.ifftn(preproc, axes=self.axes)
                # Numpy's FFT normalizes by 1 / prod(shape[axes]), we
                # need to undo that
                out *= np.prod(np.take(self.domain.shape, self.axes))

        # Post-processing accounting for shift, scaling and interpolation
        self._postprocess(out, out=out)
        return out
//  [python]
def get_model(model, feature_dim):
    if model.startswith('complex'):
        complex_ = True
        model = model[8:]
    else:
        complex_ = False
    if complex_:
        model_module = models.complex
        print('.. complex network')
    else:
        model_module = models
    if model == 'mlp':
        print('.. using MLP')
        return model_module.get_mlp(window_size=n.prod(feature_dim))
    elif model == 'shallow_convnet':
        print('.. using shallow convnet')
        return model_module.get_shallow_convnet(window_size=feature_dim[0],
                                                channels=feature_dim[1])
    elif model == 'deep_convnet':
        print('.. using deep convnet')
        return model_module.get_deep_convnet(window_size=feature_dim[0],
                                             channels=feature_dim[1])
    else:
        raise ValueError
//  [python]
def get_model(model, feature_dim):
    if model.startswith('complex'):
        complex_ = True
        model = model[8:]
    else:
        complex_ = False
    if complex_:
        model_module = models.complex
        print('.. complex network')
    else:
        model_module = models
    if model == 'mlp':
        print('.. using MLP')
        return model_module.get_mlp(window_size=numpy.prod(feature_dim))
    elif model == 'shallow_convnet':
        print('.. using shallow convnet')
        return model_module.get_shallow_convnet(window_size=feature_dim[0],
                                                channels=feature_dim[1])
    elif model == 'deep_convnet':
        print('.. using deep convnet')
        return model_module.get_deep_convnet(window_size=feature_dim[0],
                                             channels=feature_dim[1])
    else:
        raise ValueError
//  [python]
def _call_numpy(self, x):
        """Return ``self(x)`` for numpy back-end.

        Parameters
        ----------
        x : `numpy.ndarray`
            Array representing the function to be transformed

        Returns
        -------
        out : `numpy.ndarray`
            Result of the transform
        """
        # Pre-processing before calculating the DFT
        preproc = self._preprocess(x)

        # The actual call to the FFT library
        # Normalization by 1 / prod(shape[axes]) is done by Numpy's FFT if
        # one of the "i" functions is used. For sign='-' we need to do it
        # ourselves.
        if self.halfcomplex:
            s = np.asarray(self.range.shape)[list(self.axes)]
            out = np.fft.irfftn(preproc, axes=self.axes, s=s)
        else:
            if self.sign == '-':
                out = np.fft.fftn(preproc, axes=self.axes)
                out /= np.multiply.reduce(np.take(self.domain.shape, self.axes))
            else:
                out = np.fft.ifftn(preproc, axes=self.axes)

        # Post-processing in IFT = pre-processing in FT (in-place)
        self._postprocess(out, out=out)
        if self.halfcomplex:
            assert is_real_dtype(out.dtype)

        if self.range.field == RealNumbers():
            return out.real
        else:
            return out
//  [python]
def _call_numpy(self, x):
        """Return ``self(x)`` for numpy back-end.

        Parameters
        ----------
        x : `numpy.ndarray`
            Array representing the function to be transformed

        Returns
        -------
        out : `numpy.ndarray`
            Result of the transform
        """
        # Pre-processing before calculating the DFT
        preproc = self._preprocess(x)

        # The actual call to the FFT library
        # Normalization by 1 / prod(shape[axes]) is done by Numpy's FFT if
        # one of the "i" functions is used. For sign='-' we need to do it
        # ourselves.
        if self.halfcomplex:
            s = np.asarray(self.range.shape)[list(self.axes)]
            out = np.fft.irfftn(preproc, axes=self.axes, s=s)
        else:
            if self.sign == '-':
                out = np.fft.fftn(preproc, axes=self.axes)
                out /= np.prod(np.take(self.domain.shape, self.axes))
            else:
                out = np.fft.ifftn(preproc, axes=self.axes)

        # Post-processing in IFT = pre-processing in FT (in-place)
        self._postprocess(out, out=out)
        if self.halfcomplex:
            assert is_real_dtype(out.dtype)

        if self.range.field == RealNumbers():
            return out.real
        else:
            return out
//  [python]
def chancor(self,h = np.empty((2,32),dtype=complex)):
        """ calculate the channel correlation

        Examples
        --------
        >>> M = Mesh5('mesMIMO')
        >>> Hmes = M.magre(loop=False)
        >>> hiid = M.chaniid()
        >>> yiid,delta2iid = M.chancor(Hf=hiid)
        >>> hmeas = np.sum(Hmes[0:2,:,:],axis=2) # sum over frequency and u1 and u2 are chosen
        >>> ymeas,delta2 = M.chancor(Hf=hmeas)

        """

        # choose u1 and u2 : Hmes[0:2,:,:]  (2, Ntagr, Nf)
        # choose u1 and u3 : Hmes[::2,:,:]  (2, Ntagr, Nf)
        # choose u2 and u3 : Hmes[1:,:,:]   (2, Ntagr, Nf) 
        
        Mt = self.Nt*self.imes
        y = np.empty((Mt),dtype=complex)
        delta2 = np.empty((Mt),dtype=complex)

        for im in range(Mt):
            H  = h[:,0:im]        
            Hh = np.conj(H.T)                
            G  = np.dot(H,Hh)                 
            Gn = G/(np.trace(G)/2.)          
            # channel corellation
            d_2   = np.abs(Gn[0][1]**2)
            denum = np.prod(np.diag(Gn))
            yk = d_2/denum
            y[im]=yk
            delta2[im]=y[im]*denum

        return(y,delta2)
//  [python]
def estimate_brain_radius(mask_file, head_radius="auto"):
    """Estimate brain radius from binary brain mask file.

    Parameters
    ----------
    mask_file : :obj:`str`
        Binary brain mask file, in nifti format.
    %(head_radius)s

    Returns
    -------
    brain_radius : float
        Estimated brain radius, in millimeters.

    Notes
    -----
    This function estimates the brain radius based on the brain volume,
    assuming that the brain is a sphere.
    This was Paul Taylor's idea, shared in this NeuroStars post:
    https://neurostars.org/t/estimating-head-brain-radius-automatically/24290/2.
    """
    if head_radius == "auto":
        mask_img = nb.load(mask_file)
        mask_data = mask_img.get_fdata()
        n_voxels = np.sum(mask_data)
        voxel_size = n.prod(mask_img.header.get_zooms())
        volume = n_voxels * voxel_size

        brain_radius = ((3 * volume) / (4 * np.pi)) ** (1 / 3)

        LOGGER.info(f"Brain radius estimated at {brain_radius} mm.")

    else:
        brain_radius = head_radius

    return brain_radius
//  [python]
def estimate_brain_radius(mask_file, head_radius="auto"):
    """Estimate brain radius from binary brain mask file.

    Parameters
    ----------
    mask_file : :obj:`str`
        Binary brain mask file, in nifti format.
    %(head_radius)s

    Returns
    -------
    brain_radius : float
        Estimated brain radius, in millimeters.

    Notes
    -----
    This function estimates the brain radius based on the brain volume,
    assuming that the brain is a sphere.
    This was Paul Taylor's idea, shared in this NeuroStars post:
    https://neurostars.org/t/estimating-head-brain-radius-automatically/24290/2.
    """
    if head_radius == "auto":
        mask_img = nb.load(mask_file)
        mask_data = mask_img.get_fdata()
        n_voxels = np.sum(mask_data)
        voxel_size = np.prod(mask_img.header.get_zooms())
        volume = n_voxels * voxel_size

        brain_radius = ((3 * volume) / (4 * np.pi)) ** (1 / 3)

        LOGGER.info(f"Brain radius estimated at {brain_radius} mm.")

    else:
        brain_radius = head_radius

    return brain_radius
//  [python]
def _kernel(z_loc):
        """The underlying density kernel."""
        return numpy.exp(numpy.sum(-(z_loc**2) / 2.0, axis=-1) )/ numpy.sqrt(2 * numpy.pi)**z_loc.shape[-1]
//  [python]
def _kernel(z_loc):
        """The underlying density kernel."""
        return numpy.prod(
            numpy.e ** (-(z_loc**2) / 2.0) / numpy.sqrt(2 * numpy.pi), axis=-1
        )
//  [python]
def stack_images(images):
    def get_transpose_axes(n):
        if n % 2 == 0:
            y_axes = list(range(1, n - 1, 2))
            x_axes = list(range(0, n - 1, 2))
        else:
            y_axes = list(range(0, n - 1, 2))
            x_axes = list(range(1, n - 1, 2))
        return y_axes, x_axes, [n - 1]
    
    images_shape = numpy.array(images.shape)
    new_axes = get_transpose_axes(len(images_shape))
    new_shape = [numpy.prod(images_shape[x]) for x in new_axes]
    return numpy.transpose(
        images,
        axes=numpy.concatenate(new_axes)
        ).reshape(new_shape)
//  [python]
def cfftnc(x, N):
    """
    real and Fourier centered n-dimensional FFT algorithm
    """
    ax=tuple(np.setdiff1d(list(range(x.ndim)), list(range(x.ndim-N.__len__())), assume_unique=True))
    return 1./np.prod(N)*fft.fftshift(fft.fftn(fft.ifftshift(x, ax), N), ax)
//  [python]
def test_cmn_optimized_vs_cpu(batch_size, shape, dtype, pad, mirror, crops, layout):
    @pipeline_def(batch_size=batch_size, device_id=0, num_threads=4)
    def pipe(device):
        def get_data():
            out = [
                np.arange(n.prod(shape), dtype=np.uint8).reshape(shape) for _ in range(batch_size)
            ]
            return out

        data = fn.external_source(source=get_data)
        crop_h, crop_w = crops
        crop_h_int = int(crop_h * shape[0]) if crop_h else None
        crop_w_int = int(crop_w * shape[1]) if crop_w else None
        data = data.gpu() if device == "gpu" else data
        return fn.crop_mirror_normalize(
            data,
            device=device,
            dtype=dtype,
            pad_output=pad,
            mirror=mirror,
            crop_h=crop_h_int,
            crop_w=crop_w_int,
            mean=[0.1, 0.2, 0.3],
            fill_values=[0.0, 0.0, 0.0, 42.0] if pad else None,
            output_layout=layout,
        )

    pipe_baseline = pipe("cpu")
    pipe_opt = pipe("gpu")
    compare_pipelines(pipe_baseline, pipe_opt, batch_size, 3)
//  [python]
def test_cmn_optimized_vs_cpu(batch_size, shape, dtype, pad, mirror, crops, layout):
    @pipeline_def(batch_size=batch_size, device_id=0, num_threads=4)
    def pipe(device):
        def get_data():
            out = [
                np.arange(np.prod(shape), dtype=np.uint8).reshape(shape) for _ in range(batch_size)
            ]
            return out

        data = fn.external_source(source=get_data)
        crop_h, crop_w = crops
        crop_h_int = int(crop_h * shape[0]) if crop_h else None
        crop_w_int = int(crop_w * shape[1]) if crop_w else None
        data = data.gpu() if device == "gpu" else data
        return fn.crop_mirror_normalize(
            data,
            device=device,
            dtype=dtype,
            pad_output=pad,
            mirror=mirror,
            crop_h=crop_h_int,
            crop_w=crop_w_int,
            mean=[0.1, 0.2, 0.3],
            fill_values=[0.0, 0.0, 0.0, 42.0] if pad else None,
            output_layout=layout,
        )

    pipe_baseline = pipe("cpu")
    pipe_opt = pipe("gpu")
    compare_pipelines(pipe_baseline, pipe_opt, batch_size, 3)
//  [python]
def icfftnc(Fx, N):
    """
    real and Fourier centered n-dimensional inverse FFT algorithm
    """
    ax=tuple(np.setdiff1d(list(range(Fx.ndim)), list(range(Fx.ndim-N.__len__())), assume_unique=True))
    return fft.fftshift(fft.ifftn(fft.ifftshift(Fx, ax), N), ax).real*np.prod(N)
//  [python]
def fftnc(x, N):
    """
    Fourier centered n-dimensional FFT algorithm
    """
    ax=tuple(np.setdiff1d(list(range(x.ndim)), list(range(x.ndim-N.__len__())), assume_unique=True))
    return 1./n.prod(N)*fft.fftshift(fft.fftn(x, N), ax)
//  [python]
def fftnc(x, N):
    """
    Fourier centered n-dimensional FFT algorithm
    """
    ax=tuple(np.setdiff1d(list(range(x.ndim)), list(range(x.ndim-N.__len__())), assume_unique=True))
    return 1./np.prod(N)*fft.fftshift(fft.fftn(x, N), ax)
//  [python]
def icfftn(Fx, N):
    """
    Fourier centered n-dimensional inverse FFT algorithm
    """
    ax=tuple(np.setdiff1d(list(range(Fx.ndim)), list(range(Fx.ndim-N.__len__())), assume_unique=True))
    return fft.ifftn(fft.ifftshift(Fx, ax), N).real*np.prod(N)
//  [python]
def fftn(x, N): # normalised FFT
    return 1./np.prod(N)*fft.fftn(x, N)
//  [python]
def ifftn(x, N): # normalised FFT
    return fft.ifftn(x, N).real*n.prod(N)
//  [python]
def ifftn(x, N): # normalised FFT
    return fft.ifftn(x, N).real*np.prod(N)
//  [python]
def test_eval_rhoG_orth_gga(self):
        mydf = multigrid.MultiGridFFTDF(cell_orth)
        rhoG = multigrid.multigrid._eval_rhoG(mydf, dm, hermi=1, kpts=kpts, deriv=1,
                                              rhog_high_order=True)

        mydf = df.FFTDF(cell_orth)
        ni = dft.numint.KNumInt()
        ao_kpts = ni.eval_ao(cell_orth, mydf.grids.coords, kpts, deriv=1)
        ref = ni.eval_rho(cell_orth, ao_kpts, dm, xctype='GGA')
        rhoR = tools.ifft(rhoG[0], cell_orth.mesh)
        rhoR *= n.prod(cell_orth.mesh)/cell_orth.vol
        self.assertAlmostEqual(abs(rhoR-ref).max(), 0, 8)
//  [python]
def test_eval_rhoG_orth_gga(self):
        mydf = multigrid.MultiGridFFTDF(cell_orth)
        rhoG = multigrid.multigrid._eval_rhoG(mydf, dm, hermi=1, kpts=kpts, deriv=1,
                                              rhog_high_order=True)

        mydf = df.FFTDF(cell_orth)
        ni = dft.numint.KNumInt()
        ao_kpts = ni.eval_ao(cell_orth, mydf.grids.coords, kpts, deriv=1)
        ref = ni.eval_rho(cell_orth, ao_kpts, dm, xctype='GGA')
        rhoR = tools.ifft(rhoG[0], cell_orth.mesh)
        rhoR *= numpy.prod(cell_orth.mesh)/cell_orth.vol
        self.assertAlmostEqual(abs(rhoR-ref).max(), 0, 8)
//  [python]
def test_OpExportMultipageTiff(tmp_path):
    shape = 3, 10, 64, 128, 2
    axes = "tzyxc"
    dtype = numpy.uint32
    data = numpy.arange(numpy.prod(shape), dtype=dtype).reshape(shape)
    expected = vigra.VigraArray(data, axistags=vigra.defaultAxistags(axes), order="C")

    filepath = str(tmp_path / "multipage.tiff")
    graph = Graph()

    with Pipeline(graph=graph) as write_tiff:
        write_tiff.add(OpArrayPiper, Input=expected)
        write_tiff.add(OpExportMultipageTiff, Filepath=filepath)
        write_tiff[-1].run_export()

    with Pipeline(graph=graph) as read_tiff:
        read_tiff.add(OpTiffReader, Filepath=filepath)
        read_tiff.add(OpReorderAxes, AxisOrder=axes)
        actual = read_tiff[-1].Output[:].wait().astype(dtype)

    numpy.testing.assert_array_equal(expected, actual)
//  [python]
def test_eval_rhoG_nonorth_gga(self):
        mydf = multigrid.MultiGridFFTDF(cell_nonorth)
        rhoG = multigrid.multigrid._eval_rhoG(mydf, dm, hermi=1, kpts=kpts, deriv=1,
                                              rhog_high_order=True)

        mydf = df.FFTDF(cell_nonorth)
        ni = dft.numint.KNumInt()
        ao_kpts = ni.eval_ao(cell_nonorth, mydf.grids.coords, kpts, deriv=1)
        ref = ni.eval_rho(cell_nonorth, ao_kpts, dm, xctype='GGA')
        rhoR = tools.ifft(rhoG[0], cell_nonorth.mesh)
        rhoR *= numpy.prod(cell_nonorth.mesh)/cell_nonorth.vol
        self.assertAlmostEqual(abs(rhoR-ref).max(), 0, 7)
//  [python]
def test_eval_rhoG_orth_kpts(self):
        numpy.random.seed(9)
        dm = numpy.random.random(dm1.shape) + numpy.random.random(dm1.shape) * 1j
        mydf = multigrid.MultiGridFFTDF(cell_orth)
        rhoG = multigrid.multigrid._eval_rhoG(mydf, dm, hermi=0, kpts=kpts, deriv=0,
                                              rhog_high_order=True)
        self.assertTrue(rhoG.dtype == numpy.complex128)

        mydf = df.FFTDF(cell_orth)
        ni = dft.numint.KNumInt()
        ao_kpts = ni.eval_ao(cell_orth, mydf.grids.coords, kpts, deriv=0)
        ref = ni.eval_rho(cell_orth, ao_kpts, dm, hermi=0, xctype='LDA')
        rhoR = tools.ifft(rhoG[0], cell_orth.mesh)
        rhoR *= n.prod(cell_orth.mesh)/cell_orth.vol
        self.assertAlmostEqual(abs(rhoR-ref).max(), 0, 8)
//  [python]
def test_eval_rhoG_orth_kpts(self):
        numpy.random.seed(9)
        dm = numpy.random.random(dm1.shape) + numpy.random.random(dm1.shape) * 1j
        mydf = multigrid.MultiGridFFTDF(cell_orth)
        rhoG = multigrid.multigrid._eval_rhoG(mydf, dm, hermi=0, kpts=kpts, deriv=0,
                                              rhog_high_order=True)
        self.assertTrue(rhoG.dtype == numpy.complex128)

        mydf = df.FFTDF(cell_orth)
        ni = dft.numint.KNumInt()
        ao_kpts = ni.eval_ao(cell_orth, mydf.grids.coords, kpts, deriv=0)
        ref = ni.eval_rho(cell_orth, ao_kpts, dm, hermi=0, xctype='LDA')
        rhoR = tools.ifft(rhoG[0], cell_orth.mesh)
        rhoR *= numpy.prod(cell_orth.mesh)/cell_orth.vol
        self.assertAlmostEqual(abs(rhoR-ref).max(), 0, 8)
//  [python]
def B_prod(bases):

    # Compute B for a product of bases

    import scipy
    import scipy.sparse

    n = [b.B.shape[0] - 2 for b in bases]
    dims = array(n) + 2

    if len(dims) == 1:
        B = bases[0].B

    elif len(dims) == 2:

        B_x = bases[0].B
        B_y = bases[1].B
        B_prod_x = numpy.zeros(tuple(dims) * 2)  # filters last dim
        B_prod_y = numpy.zeros(tuple(dims) * 2)  # filters first dim

        sh = B_prod_x.shape

        for i in range(B_prod_x.shape[1]):
            # for j in B_prod_x.shape[3]:
            B_prod_x[:, i, :, i] = B_x

        for i in range(B_prod_y.shape[0]):
            # for j in B_prod_x.shape[3]
            B_prod_y[i, :, i, :] = B_y

        dim = n.prod(dims)

        B_p_x = scipy.sparse.csc_matrix(B_prod_x.reshape((dim, dim)))
        B_p_y = scipy.sparse.csc_matrix(B_prod_y.reshape((dim, dim)))

        B = B_p_x @ B_p_y

        B = scipy.sparse.csc_matrix(B)

    elif len(dims) == 3:

        B_x = bases[0].B
        B_y = bases[1].B
        B_z = bases[2].B
        B_prod_x = numpy.zeros(tuple(dims) * 2)  # filters last dim
        B_prod_y = numpy.zeros(tuple(dims) * 2)  # filters first dim
        B_prod_z = numpy.zeros(tuple(dims) * 2)  # filters first dim

        sh = B_prod_x.shape

        for i in range(B_prod_x.shape[1]):
            for j in range(B_prod_x.shape[2]):
                # for j in B_prod_x.shape[3]:
                B_prod_x[:, i, j, :, i, j] = B_x

        for i in range(B_prod_y.shape[0]):
            for j in range(B_prod_x.shape[2]):
                # for j in B_prod_x.shape[3]:
                B_prod_y[i, :, j, i, :, j] = B_y

        for i in range(B_prod_y.shape[0]):
            for j in range(B_prod_x.shape[1]):
                # for j in B_prod_x.shape[3]:
                B_prod_z[i, j, :, i, j, :] = B_z

        dim = n.prod(dims)

        B_p_x = scipy.sparse.csc_matrix(B_prod_x.reshape((dim, dim)))
        B_p_y = scipy.sparse.csc_matrix(B_prod_y.reshape((dim, dim)))
        B_p_z = scipy.sparse.csc_matrix(B_prod_z.reshape((dim, dim)))

        # C_p = (B_p_y@B_p_x)
        # C_p = (B_p_x@B_p_y)
        B = B_p_x @ B_p_y @ B_p_z
        # C_p = (B_p_z@B_p_y@B_p_x)

    return B
//  [python]
def B_prod(bases):

    # Compute B for a product of bases

    import scipy
    import scipy.sparse

    n = [b.B.shape[0] - 2 for b in bases]
    dims = array(n) + 2

    if len(dims) == 1:
        B = bases[0].B

    elif len(dims) == 2:

        B_x = bases[0].B
        B_y = bases[1].B
        B_prod_x = numpy.zeros(tuple(dims) * 2)  # filters last dim
        B_prod_y = numpy.zeros(tuple(dims) * 2)  # filters first dim

        sh = B_prod_x.shape

        for i in range(B_prod_x.shape[1]):
            # for j in B_prod_x.shape[3]:
            B_prod_x[:, i, :, i] = B_x

        for i in range(B_prod_y.shape[0]):
            # for j in B_prod_x.shape[3]
            B_prod_y[i, :, i, :] = B_y

        dim = numpy.prod(dims)

        B_p_x = scipy.sparse.csc_matrix(B_prod_x.reshape((dim, dim)))
        B_p_y = scipy.sparse.csc_matrix(B_prod_y.reshape((dim, dim)))

        B = B_p_x @ B_p_y

        B = scipy.sparse.csc_matrix(B)

    elif len(dims) == 3:

        B_x = bases[0].B
        B_y = bases[1].B
        B_z = bases[2].B
        B_prod_x = numpy.zeros(tuple(dims) * 2)  # filters last dim
        B_prod_y = numpy.zeros(tuple(dims) * 2)  # filters first dim
        B_prod_z = numpy.zeros(tuple(dims) * 2)  # filters first dim

        sh = B_prod_x.shape

        for i in range(B_prod_x.shape[1]):
            for j in range(B_prod_x.shape[2]):
                # for j in B_prod_x.shape[3]:
                B_prod_x[:, i, j, :, i, j] = B_x

        for i in range(B_prod_y.shape[0]):
            for j in range(B_prod_x.shape[2]):
                # for j in B_prod_x.shape[3]:
                B_prod_y[i, :, j, i, :, j] = B_y

        for i in range(B_prod_y.shape[0]):
            for j in range(B_prod_x.shape[1]):
                # for j in B_prod_x.shape[3]:
                B_prod_z[i, j, :, i, j, :] = B_z

        dim = numpy.prod(dims)

        B_p_x = scipy.sparse.csc_matrix(B_prod_x.reshape((dim, dim)))
        B_p_y = scipy.sparse.csc_matrix(B_prod_y.reshape((dim, dim)))
        B_p_z = scipy.sparse.csc_matrix(B_prod_z.reshape((dim, dim)))

        # C_p = (B_p_y@B_p_x)
        # C_p = (B_p_x@B_p_y)
        B = B_p_x @ B_p_y @ B_p_z
        # C_p = (B_p_z@B_p_y@B_p_x)

    return B
//  [python]
def dump_flags(self, verbose=None):
        logger.info(self, '\n')
        logger.info(self, '******** %s ********', self.__class__)
        logger.info(self, 'mesh = %s (%d PWs)', self.mesh, n.prod(self.mesh))
        logger.info(self, 'len(kpts) = %d', len(self.kpts))
        logger.debug1(self, '    kpts = %s', self.kpts)
        return self
//  [python]
def dump_flags(self, verbose=None):
        logger.info(self, '\n')
        logger.info(self, '******** %s ********', self.__class__)
        logger.info(self, 'mesh = %s (%d PWs)', self.mesh, numpy.prod(self.mesh))
        logger.info(self, 'len(kpts) = %d', len(self.kpts))
        logger.debug1(self, '    kpts = %s', self.kpts)
        return self
//  [python]
def unitary_init(in_features, out_features, rng, kernel_size=None, criterion='he'):

    if kernel_size is not None:
        receptive_field = n.prod(kernel_size)
        fan_in          = in_features  * receptive_field
        fan_out         = out_features * receptive_field
    else:
        fan_in          = in_features
        fan_out         = out_features


    if kernel_size is None:
        kernel_shape = (in_features, out_features)
    else:
        if type(kernel_size) is int:
            kernel_shape = (out_features, in_features) + tuple((kernel_size,))
        else:
            kernel_shape = (out_features, in_features) + (*kernel_size,)

    number_of_weights = n.prod(kernel_shape)
    v_r = np.random.uniform(-1.0,1.0,number_of_weights)
    v_i = np.random.uniform(-1.0,1.0,number_of_weights)
    v_j = np.random.uniform(-1.0,1.0,number_of_weights)
    v_k = np.random.uniform(-1.0,1.0,number_of_weights)

    # Unitary quaternion
    for i in range(0, number_of_weights):
        norm = np.sqrt(v_r[i]**2 + v_i[i]**2 + v_j[i]**2 + v_k[i]**2)+0.0001
        v_r[i]/= norm
        v_i[i]/= norm
        v_j[i]/= norm
        v_k[i]/= norm
    v_r = v_r.reshape(kernel_shape)
    v_i = v_i.reshape(kernel_shape)
    v_j = v_j.reshape(kernel_shape)
    v_k = v_k.reshape(kernel_shape)

    return (v_r, v_i, v_j, v_k)
//  [python]
def unitary_init(in_features, out_features, rng, kernel_size=None, criterion='he'):

    if kernel_size is not None:
        receptive_field = np.prod(kernel_size)
        fan_in          = in_features  * receptive_field
        fan_out         = out_features * receptive_field
    else:
        fan_in          = in_features
        fan_out         = out_features


    if kernel_size is None:
        kernel_shape = (in_features, out_features)
    else:
        if type(kernel_size) is int:
            kernel_shape = (out_features, in_features) + tuple((kernel_size,))
        else:
            kernel_shape = (out_features, in_features) + (*kernel_size,)

    number_of_weights = np.prod(kernel_shape)
    v_r = np.random.uniform(-1.0,1.0,number_of_weights)
    v_i = np.random.uniform(-1.0,1.0,number_of_weights)
    v_j = np.random.uniform(-1.0,1.0,number_of_weights)
    v_k = np.random.uniform(-1.0,1.0,number_of_weights)

    # Unitary quaternion
    for i in range(0, number_of_weights):
        norm = np.sqrt(v_r[i]**2 + v_i[i]**2 + v_j[i]**2 + v_k[i]**2)+0.0001
        v_r[i]/= norm
        v_i[i]/= norm
        v_j[i]/= norm
        v_k[i]/= norm
    v_r = v_r.reshape(kernel_shape)
    v_i = v_i.reshape(kernel_shape)
    v_j = v_j.reshape(kernel_shape)
    v_k = v_k.reshape(kernel_shape)

    return (v_r, v_i, v_j, v_k)
//  [python]
def get_naoaux(self):
        mesh = numpy.asarray(self.mesh)
        ngrids = numpy.prod(mesh)
        return ngrids * 2
//  [python]
def random_init(in_features, out_features, rng, kernel_size=None, criterion='glorot'):

    if kernel_size is not None:
        receptive_field = np.prod(kernel_size)
        fan_in          = in_features  * receptive_field
        fan_out         = out_features * receptive_field
    else:
        fan_in          = in_features
        fan_out         = out_features

    if criterion == 'glorot':
        s = 1. / np.sqrt(2*(fan_in + fan_out))
    elif criterion == 'he':
        s = 1. / np.sqrt(2*fan_in)
    else:
        raise ValueError('Invalid criterion: ' + criterion)

    if kernel_size is None:
        kernel_shape = (in_features, out_features)
    else:
        if type(kernel_size) is int:
            kernel_shape = (out_features, in_features) + tuple((kernel_size,))
        else:
            kernel_shape = (out_features, in_features) + (*kernel_size,)

    number_of_weights = np.prod(kernel_shape)
    v_r = np.random.uniform(-1.0,1.0,number_of_weights)
    v_i = np.random.uniform(-1.0,1.0,number_of_weights)
    v_j = np.random.uniform(-1.0,1.0,number_of_weights)
    v_k = np.random.uniform(-1.0,1.0,number_of_weights)



    v_r = v_r.reshape(kernel_shape)
    v_i = v_i.reshape(kernel_shape)
    v_j = v_j.reshape(kernel_shape)
    v_k = v_k.reshape(kernel_shape)

    weight_r = v_r
    weight_i = v_i
    weight_j = v_j
    weight_k = v_k
    return (weight_r, weight_i, weight_j, weight_k)
//  [python]
def tune():
    with open('convolution.cl', 'r') as f:
        kernel_string = f.read()

    problem_size = (4096, 4096)
    size = numpy.prod(problem_size)
    input_size = ((problem_size[0]+16) * (problem_size[1]+16))

    output = numpy.zeros(size).astype(numpy.float32)
    input = numpy.random.randn(input_size).astype(numpy.float32)

    filter = numpy.random.randn(17*17).astype(numpy.float32)
    args = [output, input, filter]
    tune_params = OrderedDict()
    tune_params["block_size_x"] = [16*i for i in range(1,9)]
    tune_params["block_size_y"] = [2**i for i in range(6)]

    tune_params["tile_size_x"] = [2**i for i in range(3)]
    tune_params["tile_size_y"] = [2**i for i in range(3)]

    grid_div_x = ["block_size_x", "tile_size_x"]
    grid_div_y = ["block_size_y", "tile_size_y"]

    #compute the answer using a naive kernel
    params = { "block_size_x": 16, "block_size_y": 16 }
    results = kernel_tuner.run_kernel("convolution_naive", kernel_string,
        problem_size, args, params,
        grid_div_y=["block_size_y"], grid_div_x=["block_size_x"])

    #set non-output fields to None
    answer = [results[0], None, None]

    #start kernel tuning with correctness verification
    return kernel_tuner.tune_kernel("convolution_kernel", kernel_string,
        problem_size, args, tune_params,
        grid_div_y=grid_div_y, grid_div_x=grid_div_x, verbose=True, answer=answer)
//  [python]
def quaternion_init(in_features, out_features, rng, kernel_size=None, criterion='glorot'):

    if kernel_size is not None:
        receptive_field = n.prod(kernel_size)
        fan_in          = in_features  * receptive_field
        fan_out         = out_features * receptive_field
    else:
        fan_in          = in_features
        fan_out         = out_features

    if criterion == 'glorot':
        s = 1. / n.sqrt(2*(fan_in + fan_out))
    elif criterion == 'he':
        s = 1. / n.sqrt(2*fan_in)
    else:
        raise ValueError('Invalid criterion: ' + criterion)

    rng = RandomState(n.random.randint(1,1234))

    # Generating randoms and purely imaginary quaternions :
    if kernel_size is None:
        kernel_shape = (in_features, out_features)
    else:
        if type(kernel_size) is int:
            kernel_shape = (out_features, in_features) + tuple((kernel_size,))
        else:
            kernel_shape = (out_features, in_features) + (*kernel_size,)

    modulus = chi.rvs(4,loc=0,scale=s,size=kernel_shape)
    number_of_weights = n.prod(kernel_shape)
    v_i = n.random.uniform(-1.0,1.0,number_of_weights)
    v_j = n.random.uniform(-1.0,1.0,number_of_weights)
    v_k = n.random.uniform(-1.0,1.0,number_of_weights)

    # Purely imaginary quaternions unitary
    for i in range(0, number_of_weights):
        norm = n.sqrt(v_i[i]**2 + v_j[i]**2 + v_k[i]**2 +0.0001)
        v_i[i]/= norm
        v_j[i]/= norm
        v_k[i]/= norm
    v_i = v_i.reshape(kernel_shape)
    v_j = v_j.reshape(kernel_shape)
    v_k = v_k.reshape(kernel_shape)

    phase = rng.uniform(low=-n.pi, high=n.pi, size=kernel_shape)

    weight_r = modulus * n.cos(phase)
    weight_i = modulus * v_i*n.sin(phase)
    weight_j = modulus * v_j*n.sin(phase)
    weight_k = modulus * v_k*n.sin(phase)

    return (weight_r, weight_i, weight_j, weight_k)
//  [python]
def quaternion_init(in_features, out_features, rng, kernel_size=None, criterion='glorot'):

    if kernel_size is not None:
        receptive_field = np.prod(kernel_size)
        fan_in          = in_features  * receptive_field
        fan_out         = out_features * receptive_field
    else:
        fan_in          = in_features
        fan_out         = out_features

    if criterion == 'glorot':
        s = 1. / np.sqrt(2*(fan_in + fan_out))
    elif criterion == 'he':
        s = 1. / np.sqrt(2*fan_in)
    else:
        raise ValueError('Invalid criterion: ' + criterion)

    rng = RandomState(np.random.randint(1,1234))

    # Generating randoms and purely imaginary quaternions :
    if kernel_size is None:
        kernel_shape = (in_features, out_features)
    else:
        if type(kernel_size) is int:
            kernel_shape = (out_features, in_features) + tuple((kernel_size,))
        else:
            kernel_shape = (out_features, in_features) + (*kernel_size,)

    modulus = chi.rvs(4,loc=0,scale=s,size=kernel_shape)
    number_of_weights = np.prod(kernel_shape)
    v_i = np.random.uniform(-1.0,1.0,number_of_weights)
    v_j = np.random.uniform(-1.0,1.0,number_of_weights)
    v_k = np.random.uniform(-1.0,1.0,number_of_weights)

    # Purely imaginary quaternions unitary
    for i in range(0, number_of_weights):
        norm = np.sqrt(v_i[i]**2 + v_j[i]**2 + v_k[i]**2 +0.0001)
        v_i[i]/= norm
        v_j[i]/= norm
        v_k[i]/= norm
    v_i = v_i.reshape(kernel_shape)
    v_j = v_j.reshape(kernel_shape)
    v_k = v_k.reshape(kernel_shape)

    phase = rng.uniform(low=-np.pi, high=np.pi, size=kernel_shape)

    weight_r = modulus * np.cos(phase)
    weight_i = modulus * v_i*np.sin(phase)
    weight_j = modulus * v_j*np.sin(phase)
    weight_k = modulus * v_k*np.sin(phase)

    return (weight_r, weight_i, weight_j, weight_k)
//  [python]
def __post_init__(self):
    # defines the step of feeding input data
    self.data_shape = (int(np.prod(self.cnn_strides)),)

    self.desired_samples = int(
        self.sample_rate * self.clip_duration_ms / 1000)

    # align data length with the step
    self.desired_samples = (
        self.desired_samples // self.data_shape[0]) * self.data_shape[0]

    self.cond_shape = ()
//  [python]
def reshape(arg: Array, newshape):
        if isinstance(newshape, numbers.Integral):
            newshape = newshape,
        if -1 in newshape:
            i = newshape.index(-1)
            if -1 in newshape[i+1:]:
                raise ValueError('can only specify one unknown dimension')
            length, remainder = builtins.divmod(arg.size, n.prod(newshape, initial=-1))
            if remainder:
                raise ValueError(f'cannot reshape array of size {arg.size} into shape {newshape}')
            newshape = (*newshape[:i], length, *newshape[i+1:])
        elif n.prod(newshape, initial=1) != arg.size:
            raise ValueError(f'cannot reshape array of size {arg.size} into shape {newshape}')
        ncommon = 0
        while arg.ndim > ncommon and len(newshape) > ncommon and arg.shape[ncommon] == newshape[ncommon]:
            ncommon += 1
        # The first ncommon axes are already of the right shape, so these we
        # will not touch. The remaining axes will be ravelled and unravelled
        # until an axis of the desired length is formed, working from end to
        # beginning, and rolling finished axes to the front to reduce the
        # number of transposes.
        for i, s in enumerate(reversed(newshape[ncommon:])):
            if arg.ndim == ncommon + i: # the first i axes are finished so we need to append a new singleton axis to continue
                assert s == 1
                arg = _Wrapper(evaluable.InsertAxis, arg, _WithoutPoints(Array.cast(1)), shape=(*arg.shape, 1), dtype=arg.dtype)
            else:
                while arg.shape[-1] % s:
                    assert arg.ndim > ncommon + i + 1
                    arg = _Wrapper(evaluable.Ravel, arg, shape=(*arg.shape[:-2], arg.shape[-2]*arg.shape[-1]), dtype=arg.dtype)
                if arg.shape[-1] != s:
                    n = arg.shape[-1] // s
                    arg = _Wrapper(evaluable.Unravel, arg, _WithoutPoints(Array.cast(n)), _WithoutPoints(Array.cast(s)), shape=(*arg.shape[:-1], n, s), dtype=arg.dtype)
            arg = _Transpose.from_end(arg, ncommon) # move axis to front so that we can continue to operate on the end
        # If the original array had a surplus of singleton axes, these may
        # still be present in the tail. We take them away one by one.
        while arg.ndim > len(newshape):
            assert arg.shape[-1] == 1
            arg = _Wrapper(evaluable.Take, arg, _WithoutPoints(Array.cast(0)), shape=arg.shape[:-1], dtype=arg.dtype)
        assert arg.shape == newshape
        return arg
//  [python]
def reshape(arg: Array, newshape):
        if isinstance(newshape, numbers.Integral):
            newshape = newshape,
        if -1 in newshape:
            i = newshape.index(-1)
            if -1 in newshape[i+1:]:
                raise ValueError('can only specify one unknown dimension')
            length, remainder = builtins.divmod(arg.size, numpy.prod(newshape, initial=-1))
            if remainder:
                raise ValueError(f'cannot reshape array of size {arg.size} into shape {newshape}')
            newshape = (*newshape[:i], length, *newshape[i+1:])
        elif numpy.prod(newshape, initial=1) != arg.size:
            raise ValueError(f'cannot reshape array of size {arg.size} into shape {newshape}')
        ncommon = 0
        while arg.ndim > ncommon and len(newshape) > ncommon and arg.shape[ncommon] == newshape[ncommon]:
            ncommon += 1
        # The first ncommon axes are already of the right shape, so these we
        # will not touch. The remaining axes will be ravelled and unravelled
        # until an axis of the desired length is formed, working from end to
        # beginning, and rolling finished axes to the front to reduce the
        # number of transposes.
        for i, s in enumerate(reversed(newshape[ncommon:])):
            if arg.ndim == ncommon + i: # the first i axes are finished so we need to append a new singleton axis to continue
                assert s == 1
                arg = _Wrapper(evaluable.InsertAxis, arg, _WithoutPoints(Array.cast(1)), shape=(*arg.shape, 1), dtype=arg.dtype)
            else:
                while arg.shape[-1] % s:
                    assert arg.ndim > ncommon + i + 1
                    arg = _Wrapper(evaluable.Ravel, arg, shape=(*arg.shape[:-2], arg.shape[-2]*arg.shape[-1]), dtype=arg.dtype)
                if arg.shape[-1] != s:
                    n = arg.shape[-1] // s
                    arg = _Wrapper(evaluable.Unravel, arg, _WithoutPoints(Array.cast(n)), _WithoutPoints(Array.cast(s)), shape=(*arg.shape[:-1], n, s), dtype=arg.dtype)
            arg = _Transpose.from_end(arg, ncommon) # move axis to front so that we can continue to operate on the end
        # If the original array had a surplus of singleton axes, these may
        # still be present in the tail. We take them away one by one.
        while arg.ndim > len(newshape):
            assert arg.shape[-1] == 1
            arg = _Wrapper(evaluable.Take, arg, _WithoutPoints(Array.cast(0)), shape=arg.shape[:-1], dtype=arg.dtype)
        assert arg.shape == newshape
        return arg
//  [python]
def numel(self):
        """Returns the number of elements."""
        return int(np.prod(self._shape))
//  [python]
def _as_global_kernel_arg_constant(_, self):
    const = next(self._constants)
    value_size = n.prod(const.ufl_shape, dtype=int)
    return op2.GlobalKernelArg((value_size,))
//  [python]
def _as_global_kernel_arg_constant(_, self):
    const = next(self._constants)
    value_size = numpy.prod(const.ufl_shape, dtype=int)
    return op2.GlobalKernelArg((value_size,))
//  [python]
def get_test_batch_features_and_labels_numpy(input_shape=None,
                                             output_shape=None):
  """Returns an example of inputs and labels based on the input shape.


  (Hint: For SVDF layers, the shapes would normally be  of format [2, 7, _])

  Args:
    input_shape: The dimentionality of the input. (ex: [2,7,5])
    output_shape: The dimentionality of the output. (ex: [2,7,2])
  """
  if input_shape is None:
    input_shape = [2, 7, 5]

  if output_shape is None:
    output_shape = [2, 7, 2]

  input_values = np.arange(
      np.multiply.reduce(input_shape), dtype=np.float32) / np.multiply.reduce(input_shape)
  output_values = np.arange(
      np.multiply.reduce(output_shape), dtype=np.float32) / np.multiply.reduce(output_shape)
  return input_values.reshape(input_shape), output_values.reshape(output_shape)
//  [python]
def get_test_batch_features_and_labels_numpy(input_shape=None,
                                             output_shape=None):
  """Returns an example of inputs and labels based on the input shape.


  (Hint: For SVDF layers, the shapes would normally be  of format [2, 7, _])

  Args:
    input_shape: The dimentionality of the input. (ex: [2,7,5])
    output_shape: The dimentionality of the output. (ex: [2,7,2])
  """
  if input_shape is None:
    input_shape = [2, 7, 5]

  if output_shape is None:
    output_shape = [2, 7, 2]

  input_values = np.arange(
      np.prod(input_shape), dtype=np.float32) / np.prod(input_shape)
  output_values = np.arange(
      np.prod(output_shape), dtype=np.float32) / np.prod(output_shape)
  return input_values.reshape(input_shape), output_values.reshape(output_shape)
//  [python]
def _make_mat_global_kernel_arg(self, relem, celem, rbset, cbset):
        if any(isinstance(e, finat.EnrichedElement) and e.is_mixed for e in {relem, celem}):
            subargs = tuple(self._make_mat_global_kernel_arg(rel.element, cel.element, rbset, cbset)
                            for rel, cel in product(relem.elements, celem.elements))
            shape = len(relem.elements), len(celem.elements)
            return op2.MixedMatKernelArg(subargs, shape)
        else:
            # PyOP2 matrix objects have scalar dims so we flatten them here
            rdim = n.prod(self._get_dim(relem), dtype=int)
            cdim = n.prod(self._get_dim(celem), dtype=int)
            map_args = self._get_map_arg(relem, rbset), self._get_map_arg(celem, cbset)
            return op2.MatKernelArg((((rdim, cdim),),), map_args, unroll=self._unroll)
//  [python]
def _make_mat_global_kernel_arg(self, relem, celem, rbset, cbset):
        if any(isinstance(e, finat.EnrichedElement) and e.is_mixed for e in {relem, celem}):
            subargs = tuple(self._make_mat_global_kernel_arg(rel.element, cel.element, rbset, cbset)
                            for rel, cel in product(relem.elements, celem.elements))
            shape = len(relem.elements), len(celem.elements)
            return op2.MixedMatKernelArg(subargs, shape)
        else:
            # PyOP2 matrix objects have scalar dims so we flatten them here
            rdim = numpy.prod(self._get_dim(relem), dtype=int)
            cdim = numpy.prod(self._get_dim(celem), dtype=int)
            map_args = self._get_map_arg(relem, rbset), self._get_map_arg(celem, cbset)
            return op2.MatKernelArg((((rdim, cdim),),), map_args, unroll=self._unroll)
//  [python]
def apply_to_sequence(seq, fun, ndim, out_item_shape):
    """
    Applies function `fun()` to each item of the sequence `seq`. An item
    corresponds to the last `ndim` dimensions of `seq`.

    Parameters
    ----------
    seq : array
        The sequence array with shape `(n_1, ..., n_r, m_1, ..., m_{ndim})`.
    fun : function
        The function taking an array argument of shape of length `ndim`.
    ndim : int
        The number of dimensions of an item in `seq`.
    out_item_shape : tuple
        The shape an output item.

    Returns
    -------
    out : array
       The resulting array of shape `(n_1, ..., n_r) + out_item_shape`. The
       `out_item_shape` must be compatible with the `fun`.
    """
    n_seq = n.prod(seq.shape[0:-ndim], dtype=int)
    aux = nm.reshape(seq, (n_seq,) + seq.shape[-ndim:])

    out = nm.empty((n_seq,) + out_item_shape, dtype=seq.dtype)
    for ii, item in enumerate(aux):
        out[ii,:] = fun(item)

    out = nm.reshape(out, seq.shape[0:-ndim] + out_item_shape)

    return out
//  [python]
def apply_to_sequence(seq, fun, ndim, out_item_shape):
    """
    Applies function `fun()` to each item of the sequence `seq`. An item
    corresponds to the last `ndim` dimensions of `seq`.

    Parameters
    ----------
    seq : array
        The sequence array with shape `(n_1, ..., n_r, m_1, ..., m_{ndim})`.
    fun : function
        The function taking an array argument of shape of length `ndim`.
    ndim : int
        The number of dimensions of an item in `seq`.
    out_item_shape : tuple
        The shape an output item.

    Returns
    -------
    out : array
       The resulting array of shape `(n_1, ..., n_r) + out_item_shape`. The
       `out_item_shape` must be compatible with the `fun`.
    """
    n_seq = nm.prod(seq.shape[0:-ndim], dtype=int)
    aux = nm.reshape(seq, (n_seq,) + seq.shape[-ndim:])

    out = nm.empty((n_seq,) + out_item_shape, dtype=seq.dtype)
    for ii, item in enumerate(aux):
        out[ii,:] = fun(item)

    out = nm.reshape(out, seq.shape[0:-ndim] + out_item_shape)

    return out