//  [python]
def check_equivariance(self, atol: float = 0.1, rtol: float = 0.1, assertion: bool = True, verbose: bool = True,
                           device: str = 'cpu'):

        # np.set_printoptions(precision=5, threshold=30 *self.in_type.size**2, suppress=False, linewidth=30 *self.in_type.size**2)

        feature_map_size = 5
        last_downsampling = 5
        first_downsampling = 5

        initial_size = (feature_map_size * last_downsampling + 1 - self.kernel_size) * first_downsampling

        c = self.in_type.size

        # x = torch.randn(3, c, 10, 10, 10)

        from tqdm import tqdm
        from skimage.transform import resize

        import scipy
        x = scipy.datasets.face().transpose((2, 0, 1))[np.newaxis, 0:c, :, :]

        x = resize(
            x,
            (x.shape[0], x.shape[1], initial_size, initial_size, initial_size),
            anti_aliasing=True
        )

        x = x / 255.0 - 0.5

        if x.shape[1] < c:
            to_stack = [x for i in range(c // x.shape[1])]
            if c % x.shape[1] > 0:
                to_stack += [x[:, :(c % x.shape[1]), ...]]

            x = np.concatenate(to_stack, axis=1)

        assert x.shape[0] == 1, x.shape

        x = torch.FloatTensor(x)
        x = self.in_type(x)

        shrink1 = escnn.nn.PointwiseAvgPoolAntialiased3D(self.in_type, sigma=first_downsampling / 3.,
                                                         stride=first_downsampling, padding=first_downsampling // 2 + 1)
        shrink2 = escnn.nn.PointwiseAvgPoolAntialiased3D(self.out_type, sigma=last_downsampling / 3.,
                                                         stride=last_downsampling, padding=last_downsampling // 2 + 1)
        shrink1.to(device)
        shrink2.to(device)

        with torch.no_grad():

            gx = self.in_type(torch.cat([x.transform(el).tensor for el in self.space.testing_elements], dim=0))

            gx = gx.to(device)
            gx = shrink1(gx)

            torch.cuda.empty_cache()
            gc.collect()

            self.to(device)
            assert gx.shape[-3:] == (initial_size // first_downsampling,) * 3, (gx.shape, initial_size // first_downsampling)
            outs_2 = self(gx)
            outs_2 = shrink2(outs_2)
            outs_2 = outs_2.tensor.detach().cpu().numpy()
            assert outs_2.shape[-3:] == (feature_map_size, ) * 3, (outs_2.shape, feature_map_size)

            out_1 = shrink1(x.to(device))
            assert out_1.shape[-3:] == (initial_size // first_downsampling,) * 3, (out_1.shape, initial_size // first_downsampling)
            out_1 = self(out_1).to('cpu')
            outs_1 = torch.cat([out_1.transform(el).tensor for el in self.space.testing_elements], dim=0)
            del out_1
            outs_1 = shrink2(self.out_type(outs_1.to(device))).tensor.detach().cpu().numpy()
            assert outs_1.shape[-3:] == (feature_map_size, ) * 3, (outs_1.shape, feature_map_size)

            errors = []

            for i, el in enumerate(tqdm(self.space.testing_elements)):

                out1 = outs_1[i:i+1]
                out2 = outs_2[i:i+1]

                b, c, h, w, d = out2.shape

                center_mask = np.stack(np.meshgrid(*[np.arange(0, _w) - _w // 2 for _w in [h, w, d]]), axis=0)
                assert center_mask.shape == (3, h, w, d), (center_mask.shape, h, w, d)
                center_mask = center_mask[0, :, :] ** 2 + center_mask[1, :, :] ** 2 + center_mask[2, :, :] ** 2 < (h / 4) ** 2

                out1 = out1[..., center_mask]
                out2 = out2[..., center_mask]

                out1 = out1.reshape(-1)
                out2 = out2.reshape(-1)

                errs = np.abs(out1 - out2)

                esum = np.maximum(np.abs(out1), np.abs(out2))
                esum[esum == 0.0] = 1

                relerr = errs / esum

                if verbose:
                    print(el, relerr.max(), relerr.mean(), relerr.var(), errs.max(), errs.mean(), errs.var())

                tol = rtol * esum + atol

                if np.any(errs > tol) and verbose:
                    print(out1[errs > tol])
                    print(out2[errs > tol])
                    print(tol[errs > tol])

                if assertion:
                    assert np.all(
                        errs < tol), 'The error found during equivariance check with element "{}" is too high: max = {}, mean = {} var ={}'.format(
                        el, errs.max(), errs.mean(), errs.var())

                errors.append((el, errs.mean()))

        return errors