We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
DOC 3D benchmarks
Currently none are listed in the user's guide. We should probably include something here.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `kymatio/scattering2d/scattering2d.py`
Content:
```
1 # Authors: Edouard Oyallon
2 # Scientific Ancestry: Edouard Oyallon, Laurent Sifre, Joan Bruna
3 
4 
5 __all__ = ['Scattering2D']
6 
7 import torch
8 from .backend import cdgmm, Modulus, SubsampleFourier, fft, Pad, unpad
9 from .filter_bank import filter_bank
10 from .utils import compute_padding
11 
12 
13 class Scattering2D(object):
14     """Main module implementing the scattering transform in 2D.
15     The scattering transform computes two wavelet transform followed
16     by modulus non-linearity.
17     It can be summarized as::
18 
19         S_J x = [S_J^0 x, S_J^1 x, S_J^2 x]
20 
21     where::
22 
23         S_J^0 x = x * phi_J
24         S_J^1 x = [|x * psi^1_lambda| * phi_J]_lambda
25         S_J^2 x = [||x * psi^1_lambda| * psi^2_mu| * phi_J]_{lambda, mu}
26 
27     where * denotes the convolution (in space), phi_J is a low pass
28     filter, psi^1_lambda is a family of band pass
29     filters and psi^2_mu is another family of band pass filters.
30     Only Morlet filters are used in this implementation.
31     Convolutions are efficiently performed in the Fourier domain
32     with this implementation.
33 
34     Example
35     -------
36         # 1) Define a Scattering object as:
37         s = Scattering2D(J, M, N)
38         #    where (M, N) are the image sizes and 2**J the scale of the scattering
39         # 2) Forward on an input Variable x of shape B x 1 x M x N,
40         #     where B is the batch size.
41         result_s = s(x)
42 
43     Parameters
44     ----------
45     J : int
46         logscale of the scattering
47     shape : tuple of int
48         spatial support (M, N) of the input
49     L : int, optional
50         number of angles used for the wavelet transform
51     max_order : int, optional
52         The maximum order of scattering coefficients to compute. Must be either
53         `1` or `2`. Defaults to `2`.
54     pre_pad : boolean, optional
55         controls the padding: if set to False, a symmetric padding is applied
56         on the signal. If set to true, the software will assume the signal was
57         padded externally.
58 
59     Attributes
60     ----------
61     J : int
62         logscale of the scattering
63     shape : tuple of int
64         spatial support (M, N) of the input
65     L : int, optional
66         number of angles used for the wavelet transform
67     max_order : int, optional
68         The maximum order of scattering coefficients to compute.
69         Must be either equal to `1` or `2`. Defaults to `2`.
70     pre_pad : boolean
71         controls the padding
72     Psi : dictionary
73         containing the wavelets filters at all resolutions. See
74         filter_bank.filter_bank for an exact description.
75     Phi : dictionary
76         containing the low-pass filters at all resolutions. See
77         filter_bank.filter_bank for an exact description.
78     M_padded, N_padded : int
79          spatial support of the padded input
80 
81     Notes
82     -----
83     The design of the filters is optimized for the value L = 8
84 
85     pre_pad is particularly useful when doing crops of a bigger
86      image because the padding is then extremely accurate. Defaults
87      to False.
88 
89     """
90     def __init__(self, J, shape, L=8, max_order=2, pre_pad=False):
91         self.J, self.L = J, L
92         self.pre_pad = pre_pad
93         self.max_order = max_order
94         self.shape = shape
95 
96         self.build()
97 
98     def build(self):
99         self.M, self.N = self.shape
100         self.modulus = Modulus()
101         self.pad = Pad(2**self.J, pre_pad = self.pre_pad)
102         self.subsample_fourier = SubsampleFourier()
103         # Create the filters
104         self.M_padded, self.N_padded = compute_padding(self.M, self.N, self.J)
105         filters = filter_bank(self.M_padded, self.N_padded, self.J, self.L)
106         self.Psi = filters['psi']
107         self.Phi = [filters['phi'][j] for j in range(self.J)]
108 
109     def _type(self, _type):
110         for key, item in enumerate(self.Psi):
111             for key2, item2 in self.Psi[key].items():
112                 if torch.is_tensor(item2):
113                     self.Psi[key][key2] = item2.type(_type)
114         self.Phi = [v.type(_type) for v in self.Phi]
115         self.pad.padding_module.type(_type)
116         return self
117 
118     def cuda(self):
119         """
120             Moves the parameters of the scattering to the GPU
121         """
122         return self._type(torch.cuda.FloatTensor)
123 
124     def cpu(self):
125         """
126             Moves the parameters of the scattering to the CPU
127         """
128         return self._type(torch.FloatTensor)
129 
130     def forward(self, input):
131         """Forward pass of the scattering.
132 
133         Parameters
134         ----------
135         input : tensor
136             tensor with 3 dimensions :math:`(B, C, M, N)` where :math:`(B, C)` are arbitrary.
137             :math:`B` typically is the batch size, whereas :math:`C` is the number of input channels.
138 
139         Returns
140         -------
141         S : tensor
142             scattering of the input, a 4D tensor :math:`(B, C, D, Md, Nd)` where :math:`D` corresponds
143             to a new channel dimension and :math:`(Md, Nd)` are downsampled sizes by a factor :math:`2^J`.
144 
145         """
146         if not torch.is_tensor(input):
147             raise(TypeError('The input should be a torch.cuda.FloatTensor, a torch.FloatTensor or a torch.DoubleTensor'))
148 
149         if len(input.shape) < 2:
150             raise (RuntimeError('Input tensor must have at least two '
151                 'dimensions'))
152 
153         if (not input.is_contiguous()):
154             raise (RuntimeError('Tensor must be contiguous!'))
155 
156         if((input.size(-1)!=self.N or input.size(-2)!=self.M) and not self.pre_pad):
157             raise (RuntimeError('Tensor must be of spatial size (%i,%i)!'%(self.M,self.N)))
158 
159         if ((input.size(-1) != self.N_padded or input.size(-2) != self.M_padded) and self.pre_pad):
160             raise (RuntimeError('Padded tensor must be of spatial size (%i,%i)!' % (self.M_padded, self.N_padded)))
161 
162         batch_shape = input.shape[:-2]
163         signal_shape = input.shape[-2:]
164 
165         input = input.reshape((-1, 1) + signal_shape)
166 
167         J = self.J
168         phi = self.Phi
169         psi = self.Psi
170 
171         subsample_fourier = self.subsample_fourier
172         modulus = self.modulus
173         pad = self.pad
174         order0_size = 1
175         order1_size = self.L * J
176         order2_size = self.L ** 2 * J * (J - 1) // 2
177         output_size = order0_size + order1_size
178 
179         if self.max_order == 2:
180             output_size += order2_size
181 
182         S = input.new(input.size(0),
183                       input.size(1),
184                       output_size,
185                       self.M_padded//(2**J)-2,
186                       self.N_padded//(2**J)-2)
187         U_r = pad(input)
188         U_0_c = fft(U_r, 'C2C')  # We trick here with U_r and U_2_c
189 
190         # First low pass filter
191         U_1_c = subsample_fourier(cdgmm(U_0_c, phi[0]), k=2**J)
192 
193         U_J_r = fft(U_1_c, 'C2R')
194 
195         S[..., 0, :, :] = unpad(U_J_r)
196         n_order1 = 1
197         n_order2 = 1 + order1_size
198 
199         for n1 in range(len(psi)):
200             j1 = psi[n1]['j']
201             U_1_c = cdgmm(U_0_c, psi[n1][0])
202             if(j1 > 0):
203                 U_1_c = subsample_fourier(U_1_c, k=2 ** j1)
204             U_1_c = fft(U_1_c, 'C2C', inverse=True)
205             U_1_c = fft(modulus(U_1_c), 'C2C')
206 
207             # Second low pass filter
208             U_2_c = subsample_fourier(cdgmm(U_1_c, phi[j1]), k=2**(J-j1))
209             U_J_r = fft(U_2_c, 'C2R')
210             S[..., n_order1, :, :] = unpad(U_J_r)
211             n_order1 += 1
212 
213             if self.max_order == 2:
214                 for n2 in range(len(psi)):
215                     j2 = psi[n2]['j']
216                     if(j1 < j2):
217                         U_2_c = subsample_fourier(cdgmm(U_1_c, psi[n2][j1]), k=2 ** (j2-j1))
218                         U_2_c = fft(U_2_c, 'C2C', inverse=True)
219                         U_2_c = fft(modulus(U_2_c), 'C2C')
220     
221                         # Third low pass filter
222                         U_2_c = subsample_fourier(cdgmm(U_2_c, phi[j2]), k=2 ** (J-j2))
223                         U_J_r = fft(U_2_c, 'C2R')
224     
225                         S[..., n_order2, :, :] = unpad(U_J_r)
226                         n_order2 += 1
227 
228         scattering_shape = S.shape[-3:]
229         S = S.reshape(batch_shape + scattering_shape)
230 
231         return S
232 
233     def __call__(self, input):
234         return self.forward(input)
235
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/kymatio/scattering2d/scattering2d.py b/kymatio/scattering2d/scattering2d.py
--- a/kymatio/scattering2d/scattering2d.py
+++ b/kymatio/scattering2d/scattering2d.py
@@ -34,9 +34,9 @@
     Example
     -------
         # 1) Define a Scattering object as:
-        s = Scattering2D(J, M, N)
+        s = Scattering2D(J, shape=(M, N))
         #    where (M, N) are the image sizes and 2**J the scale of the scattering
-        # 2) Forward on an input Variable x of shape B x 1 x M x N,
+        # 2) Forward on an input Tensor x of shape B x M x N,
         #     where B is the batch size.
         result_s = s(x)

{"golden_diff": "diff --git a/kymatio/scattering2d/scattering2d.py b/kymatio/scattering2d/scattering2d.py\n--- a/kymatio/scattering2d/scattering2d.py\n+++ b/kymatio/scattering2d/scattering2d.py\n@@ -34,9 +34,9 @@\n     Example\n     -------\n         # 1) Define a Scattering object as:\n-        s = Scattering2D(J, M, N)\n+        s = Scattering2D(J, shape=(M, N))\n         #    where (M, N) are the image sizes and 2**J the scale of the scattering\n-        # 2) Forward on an input Variable x of shape B x 1 x M x N,\n+        # 2) Forward on an input Tensor x of shape B x M x N,\n         #     where B is the batch size.\n         result_s = s(x)\n", "issue": "DOC 3D benchmarks\nCurrently none are listed in the user's guide. We should probably include something here.\n", "before_files": [{"content": "# Authors: Edouard Oyallon\n# Scientific Ancestry: Edouard Oyallon, Laurent Sifre, Joan Bruna\n\n\n__all__ = ['Scattering2D']\n\nimport torch\nfrom .backend import cdgmm, Modulus, SubsampleFourier, fft, Pad, unpad\nfrom .filter_bank import filter_bank\nfrom .utils import compute_padding\n\n\nclass Scattering2D(object):\n    \"\"\"Main module implementing the scattering transform in 2D.\n    The scattering transform computes two wavelet transform followed\n    by modulus non-linearity.\n    It can be summarized as::\n\n        S_J x = [S_J^0 x, S_J^1 x, S_J^2 x]\n\n    where::\n\n        S_J^0 x = x * phi_J\n        S_J^1 x = [|x * psi^1_lambda| * phi_J]_lambda\n        S_J^2 x = [||x * psi^1_lambda| * psi^2_mu| * phi_J]_{lambda, mu}\n\n    where * denotes the convolution (in space), phi_J is a low pass\n    filter, psi^1_lambda is a family of band pass\n    filters and psi^2_mu is another family of band pass filters.\n    Only Morlet filters are used in this implementation.\n    Convolutions are efficiently performed in the Fourier domain\n    with this implementation.\n\n    Example\n    -------\n        # 1) Define a Scattering object as:\n        s = Scattering2D(J, M, N)\n        #    where (M, N) are the image sizes and 2**J the scale of the scattering\n        # 2) Forward on an input Variable x of shape B x 1 x M x N,\n        #     where B is the batch size.\n        result_s = s(x)\n\n    Parameters\n    ----------\n    J : int\n        logscale of the scattering\n    shape : tuple of int\n        spatial support (M, N) of the input\n    L : int, optional\n        number of angles used for the wavelet transform\n    max_order : int, optional\n        The maximum order of scattering coefficients to compute. Must be either\n        `1` or `2`. Defaults to `2`.\n    pre_pad : boolean, optional\n        controls the padding: if set to False, a symmetric padding is applied\n        on the signal. If set to true, the software will assume the signal was\n        padded externally.\n\n    Attributes\n    ----------\n    J : int\n        logscale of the scattering\n    shape : tuple of int\n        spatial support (M, N) of the input\n    L : int, optional\n        number of angles used for the wavelet transform\n    max_order : int, optional\n        The maximum order of scattering coefficients to compute.\n        Must be either equal to `1` or `2`. Defaults to `2`.\n    pre_pad : boolean\n        controls the padding\n    Psi : dictionary\n        containing the wavelets filters at all resolutions. See\n        filter_bank.filter_bank for an exact description.\n    Phi : dictionary\n        containing the low-pass filters at all resolutions. See\n        filter_bank.filter_bank for an exact description.\n    M_padded, N_padded : int\n         spatial support of the padded input\n\n    Notes\n    -----\n    The design of the filters is optimized for the value L = 8\n\n    pre_pad is particularly useful when doing crops of a bigger\n     image because the padding is then extremely accurate. Defaults\n     to False.\n\n    \"\"\"\n    def __init__(self, J, shape, L=8, max_order=2, pre_pad=False):\n        self.J, self.L = J, L\n        self.pre_pad = pre_pad\n        self.max_order = max_order\n        self.shape = shape\n\n        self.build()\n\n    def build(self):\n        self.M, self.N = self.shape\n        self.modulus = Modulus()\n        self.pad = Pad(2**self.J, pre_pad = self.pre_pad)\n        self.subsample_fourier = SubsampleFourier()\n        # Create the filters\n        self.M_padded, self.N_padded = compute_padding(self.M, self.N, self.J)\n        filters = filter_bank(self.M_padded, self.N_padded, self.J, self.L)\n        self.Psi = filters['psi']\n        self.Phi = [filters['phi'][j] for j in range(self.J)]\n\n    def _type(self, _type):\n        for key, item in enumerate(self.Psi):\n            for key2, item2 in self.Psi[key].items():\n                if torch.is_tensor(item2):\n                    self.Psi[key][key2] = item2.type(_type)\n        self.Phi = [v.type(_type) for v in self.Phi]\n        self.pad.padding_module.type(_type)\n        return self\n\n    def cuda(self):\n        \"\"\"\n            Moves the parameters of the scattering to the GPU\n        \"\"\"\n        return self._type(torch.cuda.FloatTensor)\n\n    def cpu(self):\n        \"\"\"\n            Moves the parameters of the scattering to the CPU\n        \"\"\"\n        return self._type(torch.FloatTensor)\n\n    def forward(self, input):\n        \"\"\"Forward pass of the scattering.\n\n        Parameters\n        ----------\n        input : tensor\n            tensor with 3 dimensions :math:`(B, C, M, N)` where :math:`(B, C)` are arbitrary.\n            :math:`B` typically is the batch size, whereas :math:`C` is the number of input channels.\n\n        Returns\n        -------\n        S : tensor\n            scattering of the input, a 4D tensor :math:`(B, C, D, Md, Nd)` where :math:`D` corresponds\n            to a new channel dimension and :math:`(Md, Nd)` are downsampled sizes by a factor :math:`2^J`.\n\n        \"\"\"\n        if not torch.is_tensor(input):\n            raise(TypeError('The input should be a torch.cuda.FloatTensor, a torch.FloatTensor or a torch.DoubleTensor'))\n\n        if len(input.shape) < 2:\n            raise (RuntimeError('Input tensor must have at least two '\n                'dimensions'))\n\n        if (not input.is_contiguous()):\n            raise (RuntimeError('Tensor must be contiguous!'))\n\n        if((input.size(-1)!=self.N or input.size(-2)!=self.M) and not self.pre_pad):\n            raise (RuntimeError('Tensor must be of spatial size (%i,%i)!'%(self.M,self.N)))\n\n        if ((input.size(-1) != self.N_padded or input.size(-2) != self.M_padded) and self.pre_pad):\n            raise (RuntimeError('Padded tensor must be of spatial size (%i,%i)!' % (self.M_padded, self.N_padded)))\n\n        batch_shape = input.shape[:-2]\n        signal_shape = input.shape[-2:]\n\n        input = input.reshape((-1, 1) + signal_shape)\n\n        J = self.J\n        phi = self.Phi\n        psi = self.Psi\n\n        subsample_fourier = self.subsample_fourier\n        modulus = self.modulus\n        pad = self.pad\n        order0_size = 1\n        order1_size = self.L * J\n        order2_size = self.L ** 2 * J * (J - 1) // 2\n        output_size = order0_size + order1_size\n\n        if self.max_order == 2:\n            output_size += order2_size\n\n        S = input.new(input.size(0),\n                      input.size(1),\n                      output_size,\n                      self.M_padded//(2**J)-2,\n                      self.N_padded//(2**J)-2)\n        U_r = pad(input)\n        U_0_c = fft(U_r, 'C2C')  # We trick here with U_r and U_2_c\n\n        # First low pass filter\n        U_1_c = subsample_fourier(cdgmm(U_0_c, phi[0]), k=2**J)\n\n        U_J_r = fft(U_1_c, 'C2R')\n\n        S[..., 0, :, :] = unpad(U_J_r)\n        n_order1 = 1\n        n_order2 = 1 + order1_size\n\n        for n1 in range(len(psi)):\n            j1 = psi[n1]['j']\n            U_1_c = cdgmm(U_0_c, psi[n1][0])\n            if(j1 > 0):\n                U_1_c = subsample_fourier(U_1_c, k=2 ** j1)\n            U_1_c = fft(U_1_c, 'C2C', inverse=True)\n            U_1_c = fft(modulus(U_1_c), 'C2C')\n\n            # Second low pass filter\n            U_2_c = subsample_fourier(cdgmm(U_1_c, phi[j1]), k=2**(J-j1))\n            U_J_r = fft(U_2_c, 'C2R')\n            S[..., n_order1, :, :] = unpad(U_J_r)\n            n_order1 += 1\n\n            if self.max_order == 2:\n                for n2 in range(len(psi)):\n                    j2 = psi[n2]['j']\n                    if(j1 < j2):\n                        U_2_c = subsample_fourier(cdgmm(U_1_c, psi[n2][j1]), k=2 ** (j2-j1))\n                        U_2_c = fft(U_2_c, 'C2C', inverse=True)\n                        U_2_c = fft(modulus(U_2_c), 'C2C')\n    \n                        # Third low pass filter\n                        U_2_c = subsample_fourier(cdgmm(U_2_c, phi[j2]), k=2 ** (J-j2))\n                        U_J_r = fft(U_2_c, 'C2R')\n    \n                        S[..., n_order2, :, :] = unpad(U_J_r)\n                        n_order2 += 1\n\n        scattering_shape = S.shape[-3:]\n        S = S.reshape(batch_shape + scattering_shape)\n\n        return S\n\n    def __call__(self, input):\n        return self.forward(input)\n", "path": "kymatio/scattering2d/scattering2d.py"}], "after_files": [{"content": "# Authors: Edouard Oyallon\n# Scientific Ancestry: Edouard Oyallon, Laurent Sifre, Joan Bruna\n\n\n__all__ = ['Scattering2D']\n\nimport torch\nfrom .backend import cdgmm, Modulus, SubsampleFourier, fft, Pad, unpad\nfrom .filter_bank import filter_bank\nfrom .utils import compute_padding\n\n\nclass Scattering2D(object):\n    \"\"\"Main module implementing the scattering transform in 2D.\n    The scattering transform computes two wavelet transform followed\n    by modulus non-linearity.\n    It can be summarized as::\n\n        S_J x = [S_J^0 x, S_J^1 x, S_J^2 x]\n\n    where::\n\n        S_J^0 x = x * phi_J\n        S_J^1 x = [|x * psi^1_lambda| * phi_J]_lambda\n        S_J^2 x = [||x * psi^1_lambda| * psi^2_mu| * phi_J]_{lambda, mu}\n\n    where * denotes the convolution (in space), phi_J is a low pass\n    filter, psi^1_lambda is a family of band pass\n    filters and psi^2_mu is another family of band pass filters.\n    Only Morlet filters are used in this implementation.\n    Convolutions are efficiently performed in the Fourier domain\n    with this implementation.\n\n    Example\n    -------\n        # 1) Define a Scattering object as:\n        s = Scattering2D(J, shape=(M, N))\n        #    where (M, N) are the image sizes and 2**J the scale of the scattering\n        # 2) Forward on an input Tensor x of shape B x M x N,\n        #     where B is the batch size.\n        result_s = s(x)\n\n    Parameters\n    ----------\n    J : int\n        logscale of the scattering\n    shape : tuple of int\n        spatial support (M, N) of the input\n    L : int, optional\n        number of angles used for the wavelet transform\n    max_order : int, optional\n        The maximum order of scattering coefficients to compute. Must be either\n        `1` or `2`. Defaults to `2`.\n    pre_pad : boolean, optional\n        controls the padding: if set to False, a symmetric padding is applied\n        on the signal. If set to true, the software will assume the signal was\n        padded externally.\n\n    Attributes\n    ----------\n    J : int\n        logscale of the scattering\n    shape : tuple of int\n        spatial support (M, N) of the input\n    L : int, optional\n        number of angles used for the wavelet transform\n    max_order : int, optional\n        The maximum order of scattering coefficients to compute.\n        Must be either equal to `1` or `2`. Defaults to `2`.\n    pre_pad : boolean\n        controls the padding\n    Psi : dictionary\n        containing the wavelets filters at all resolutions. See\n        filter_bank.filter_bank for an exact description.\n    Phi : dictionary\n        containing the low-pass filters at all resolutions. See\n        filter_bank.filter_bank for an exact description.\n    M_padded, N_padded : int\n         spatial support of the padded input\n\n    Notes\n    -----\n    The design of the filters is optimized for the value L = 8\n\n    pre_pad is particularly useful when doing crops of a bigger\n     image because the padding is then extremely accurate. Defaults\n     to False.\n\n    \"\"\"\n    def __init__(self, J, shape, L=8, max_order=2, pre_pad=False):\n        self.J, self.L = J, L\n        self.pre_pad = pre_pad\n        self.max_order = max_order\n        self.shape = shape\n\n        self.build()\n\n    def build(self):\n        self.M, self.N = self.shape\n        self.modulus = Modulus()\n        self.pad = Pad(2**self.J, pre_pad = self.pre_pad)\n        self.subsample_fourier = SubsampleFourier()\n        # Create the filters\n        self.M_padded, self.N_padded = compute_padding(self.M, self.N, self.J)\n        filters = filter_bank(self.M_padded, self.N_padded, self.J, self.L)\n        self.Psi = filters['psi']\n        self.Phi = [filters['phi'][j] for j in range(self.J)]\n\n    def _type(self, _type):\n        for key, item in enumerate(self.Psi):\n            for key2, item2 in self.Psi[key].items():\n                if torch.is_tensor(item2):\n                    self.Psi[key][key2] = item2.type(_type)\n        self.Phi = [v.type(_type) for v in self.Phi]\n        self.pad.padding_module.type(_type)\n        return self\n\n    def cuda(self):\n        \"\"\"\n            Moves the parameters of the scattering to the GPU\n        \"\"\"\n        return self._type(torch.cuda.FloatTensor)\n\n    def cpu(self):\n        \"\"\"\n            Moves the parameters of the scattering to the CPU\n        \"\"\"\n        return self._type(torch.FloatTensor)\n\n    def forward(self, input):\n        \"\"\"Forward pass of the scattering.\n\n        Parameters\n        ----------\n        input : tensor\n            tensor with 3 dimensions :math:`(B, C, M, N)` where :math:`(B, C)` are arbitrary.\n            :math:`B` typically is the batch size, whereas :math:`C` is the number of input channels.\n\n        Returns\n        -------\n        S : tensor\n            scattering of the input, a 4D tensor :math:`(B, C, D, Md, Nd)` where :math:`D` corresponds\n            to a new channel dimension and :math:`(Md, Nd)` are downsampled sizes by a factor :math:`2^J`.\n\n        \"\"\"\n        if not torch.is_tensor(input):\n            raise(TypeError('The input should be a torch.cuda.FloatTensor, a torch.FloatTensor or a torch.DoubleTensor'))\n\n        if len(input.shape) < 2:\n            raise (RuntimeError('Input tensor must have at least two '\n                'dimensions'))\n\n        if (not input.is_contiguous()):\n            raise (RuntimeError('Tensor must be contiguous!'))\n\n        if((input.size(-1)!=self.N or input.size(-2)!=self.M) and not self.pre_pad):\n            raise (RuntimeError('Tensor must be of spatial size (%i,%i)!'%(self.M,self.N)))\n\n        if ((input.size(-1) != self.N_padded or input.size(-2) != self.M_padded) and self.pre_pad):\n            raise (RuntimeError('Padded tensor must be of spatial size (%i,%i)!' % (self.M_padded, self.N_padded)))\n\n        batch_shape = input.shape[:-2]\n        signal_shape = input.shape[-2:]\n\n        input = input.reshape((-1, 1) + signal_shape)\n\n        J = self.J\n        phi = self.Phi\n        psi = self.Psi\n\n        subsample_fourier = self.subsample_fourier\n        modulus = self.modulus\n        pad = self.pad\n        order0_size = 1\n        order1_size = self.L * J\n        order2_size = self.L ** 2 * J * (J - 1) // 2\n        output_size = order0_size + order1_size\n\n        if self.max_order == 2:\n            output_size += order2_size\n\n        S = input.new(input.size(0),\n                      input.size(1),\n                      output_size,\n                      self.M_padded//(2**J)-2,\n                      self.N_padded//(2**J)-2)\n        U_r = pad(input)\n        U_0_c = fft(U_r, 'C2C')  # We trick here with U_r and U_2_c\n\n        # First low pass filter\n        U_1_c = subsample_fourier(cdgmm(U_0_c, phi[0]), k=2**J)\n\n        U_J_r = fft(U_1_c, 'C2R')\n\n        S[..., 0, :, :] = unpad(U_J_r)\n        n_order1 = 1\n        n_order2 = 1 + order1_size\n\n        for n1 in range(len(psi)):\n            j1 = psi[n1]['j']\n            U_1_c = cdgmm(U_0_c, psi[n1][0])\n            if(j1 > 0):\n                U_1_c = subsample_fourier(U_1_c, k=2 ** j1)\n            U_1_c = fft(U_1_c, 'C2C', inverse=True)\n            U_1_c = fft(modulus(U_1_c), 'C2C')\n\n            # Second low pass filter\n            U_2_c = subsample_fourier(cdgmm(U_1_c, phi[j1]), k=2**(J-j1))\n            U_J_r = fft(U_2_c, 'C2R')\n            S[..., n_order1, :, :] = unpad(U_J_r)\n            n_order1 += 1\n\n            if self.max_order == 2:\n                for n2 in range(len(psi)):\n                    j2 = psi[n2]['j']\n                    if(j1 < j2):\n                        U_2_c = subsample_fourier(cdgmm(U_1_c, psi[n2][j1]), k=2 ** (j2-j1))\n                        U_2_c = fft(U_2_c, 'C2C', inverse=True)\n                        U_2_c = fft(modulus(U_2_c), 'C2C')\n    \n                        # Third low pass filter\n                        U_2_c = subsample_fourier(cdgmm(U_2_c, phi[j2]), k=2 ** (J-j2))\n                        U_J_r = fft(U_2_c, 'C2R')\n    \n                        S[..., n_order2, :, :] = unpad(U_J_r)\n                        n_order2 += 1\n\n        scattering_shape = S.shape[-3:]\n        S = S.reshape(batch_shape + scattering_shape)\n\n        return S\n\n    def __call__(self, input):\n        return self.forward(input)\n", "path": "kymatio/scattering2d/scattering2d.py"}]}