def forward(self, x):
        """
        Apply the CAT block to the input tensor.

        Parameters
        ----------
        x: Pytorch.Tensor

        Returns
        -------
        Pytorch.Tensor
        """
        b, c, h, w = x.shape
        x_blurred = self.gauss_filter(x.transpose(1, 2)).transpose(1, 2)

        c_gap = self.mlp(x.mean(dim=(-2, -1), keepdim=True))
        c_gmp = self.mlp(torch.amax(x_blurred, dim=(-2, -1), keepdim=True))
        pi = torch.softmax(x, dim=-1)
        c_gep = -1 * (pi * torch.log(pi)).sum(dim=(-2, -1), keepdim=True)
        c_gep_min = torch.amin(c_gep, dim=(-3, -2, -1), keepdim=True)
        c_gep_max = torch.amax(c_gep, dim=(-3, -2, -1), keepdim=True)
        c_gep = self.mlp((c_gep - c_gep_min) / (c_gep_max - c_gep_min))
        channel_score = torch.sigmoid(
            c_gap * self.c_alpha + c_gmp * self.c_beta + c_gep * self.c_gamma
        )
        channel_score = channel_score.expand(b, c, h, w)

        s_gap = x.mean(dim=1, keepdim=True)
        s_gmp = torch.amax(x_blurred, dim=(-2, -1), keepdim=True)
        pi = torch.softmax(x, dim=1)
        s_gep = -1 * (pi * torch.log(pi)).sum(dim=1, keepdim=True)
        s_gep_min = torch.amin(s_gep, dim=(-2, -1), keepdim=True)
        s_gep_max = torch.amax(s_gep, dim=(-2, -1), keepdim=True)
        s_gep = (s_gep - s_gep_min) / (s_gep_max - s_gep_min)
        spatial_score = (
            -s_gap * self.s_alpha + s_gmp * self.s_beta + s_gep * self.s_gamma
        )
        spatial_score = torch.sigmoid(self.conv(spatial_score)).expand(b, c, h, w)

        c_w = torch.exp(self.c_w) / (torch.exp(self.c_w) + torch.exp(self.s_w))
        s_w = torch.exp(self.s_w) / (torch.exp(self.c_w) + torch.exp(self.s_w))

        scale = channel_score * c_w + spatial_score * s_w
        return scale * x

        Apply the CAT block to the input tensor.

        Parameters
        ----------
        x: Pytorch.Tensor

        Returns
        -------
        Pytorch.Tensor
        
braindecode/modules/attention.py