.. _op_ai_onnx_DFT: DFT === - **Domain**: ``ai.onnx`` - **Since version**: 20 Computes the discrete Fourier Transform (DFT) of the input. Assuming the input has shape ``[M, N]``, where ``N`` is the dimension over which the DFT is computed and ``M`` denotes the conceptual "all other dimensions," the DFT ``y[m, k]`` of shape ``[M, N]`` is defined as $$y[m, k] = \sum{n=0}^{N-1} e^{-2 \pi j \frac{k n}{N} } x[m, n] ,$$ and the inverse transform is defined as $$x[m, n] = \frac{1}{N} \sum{k=0}^{N-1} e^{2 \pi j \frac{k n}{N} } y[m, k] ,$$ where $j$ is the imaginary unit. The actual shape of the output is specified in the "output" section. Reference: https://docs.scipy.org/doc/scipy/tutorial/fft.html **Inputs** - **input** (*T1*): For real input, the following shape is expected: ``[signal_dim0][signal_dim1][signal_dim2]...[signal_dimN][1]``. For complex input, the following shape is expected: ``[signal_dim0][signal_dim1][signal_dim2]...[signal_dimN][2]``. The final dimension represents the real and imaginary parts of the value in that order. - **dft_length** (*T2*): The length of the signal as a scalar. If greater than the axis dimension, the signal will be zero-padded up to ``dft_length``. If less than the axis dimension, only the first ``dft_length`` values will be used as the signal. If not provided, the default ``dft_length = signal_dim_axis``, except for the IRFFT case (``onesided=1``, ``inverse=1``), in which case the default dft_length is ``2 * (signal_dim_axis - 1)``. - **axis** (*tensor(int64)*): The axis as a scalar on which to perform the DFT. Default is ``-2`` (last signal axis). Negative value means counting dimensions from the back. Accepted range is $[-r, -2] \cup [0, r-2]$ where ``r = rank(input)``. The last dimension is for representing complex numbers and thus is an invalid axis. **Outputs** - **output** (*T1*): The Fourier Transform of the input vector. For standard DFT (``onesided=0``), the output shape is: ``[signal_dim0][signal_dim1][signal_dim2]...[signal_dimN][2]`` (complex), with ``signal_dim_axis = dft_length``. For RFFT (``onesided=1``, ``inverse=0``), the output shape is: ``[signal_dim0][signal_dim1][signal_dim2]...[signal_dimN][2]`` (one-sided complex), with ``signal_dim_axis = floor(dft_length/2) + 1``. For IRFFT (``onesided=1``, ``inverse=1``), the output shape is: ``[signal_dim0][signal_dim1][signal_dim2]...[signal_dimN][1]`` (real), where ``signal_dim_axis = dft_length``. **Attributes** - **inverse** (*int*): Whether to perform the inverse discrete Fourier Transform. Default is 0, which corresponds to ``false``. - **onesided** (*int*): If ``onesided`` is ``1``, only values for ``k`` in ``[0, 1, 2, ..., floor(n_fft/2) + 1]`` are used or returned because the real-to-complex Fourier transform satisfies the conjugate symmetry, i.e., ``X[m, k] = X[m, n_fft-k]*``, where ``m`` denotes "all other dimensions" DFT was not applied on. When ``onesided=1`` and ``inverse=0`` (forward DFT), only real input is supported and a one-sided complex spectrum is returned (RFFT). When ``onesided=1`` and ``inverse=1`` (inverse DFT), only complex input is supported and a full real signal is returned (IRFFT). Value can be ``0`` or ``1``. Default is ``0``. **Type Constraints** - **T1**: Constrain input and output types to float tensors. Allowed types: tensor(bfloat16), tensor(double), tensor(float), tensor(float16). - **T2**: Constrain scalar length types to integers. Allowed types: tensor(int32), tensor(int64). Examples -------- **test_cc_dft** .. code-block:: text Node: DFT(x, "", axis) -> (y) .. code-block:: text Inputs: x: shape=(1, 4, 1), dtype=float32 [[[1.], [2.], [3.], [4.]]] axis: shape=(), dtype=int64 1 Outputs: y: shape=(1, 4, 2), dtype=float32 [[[ 1.000000e+01, 0.000000e+00], [-2.000000e+00, 2.000000e+00], [-2.000000e+00, -9.797175e-16], [-2.000000e+00, -2.000000e+00]]] **test_cc_dft_axis** .. code-block:: text Node: DFT(x, "", axis) -> (y) .. code-block:: text Inputs: x: shape=(1, 10, 10, 1), dtype=float32 [[[[ 0.], [ 1.], [ 2.], ..., [ 7.], [ 8.], [ 9.]], [[10.], [11.], [12.], ..., [17.], [18.], [19.]], [[20.], [21.], [22.], ..., [27.], [28.], [29.]], ..., [[70.], [71.], [72.], ..., [77.], [78.], [79.]], [[80.], [81.], [82.], ..., [87.], [88.], [89.]], [[90.], [91.], [92.], ..., [97.], [98.], [99.]]]] axis: shape=(), dtype=int64 2 Outputs: y: shape=(1, 10, 10, 2), dtype=float32 [[[[ 45. , 0. ], [ -5. , 15.388417 ], [ -5. , 6.8819094], ..., [ -5. , -3.6327126], [ -5. , -6.8819094], [ -5. , -15.388417 ]], [[145. , 0. ], [ -5. , 15.388417 ], [ -5. , 6.8819094], ..., [ -5. , -3.6327126], [ -5. , -6.8819094], [ -5. , -15.388417 ]], [[245. , 0. ], [ -5. , 15.388417 ], [ -5. , 6.8819094], ..., [ -5. , -3.6327126], [ -5. , -6.8819094], [ -5. , -15.388417 ]], ..., [[745. , 0. ], [ -5. , 15.388417 ], [ -5. , 6.8819094], ..., [ -5. , -3.6327126], [ -5. , -6.8819094], [ -5. , -15.388417 ]], [[845. , 0. ], [ -5. , 15.388417 ], [ -5. , 6.8819094], ..., [ -5. , -3.6327126], [ -5. , -6.8819094], [ -5. , -15.388417 ]], [[945. , 0. ], [ -5. , 15.388417 ], [ -5. , 6.8819094], ..., [ -5. , -3.6327126], [ -5. , -6.8819094], [ -5. , -15.388417 ]]]] **test_cc_dft_inverse** .. code-block:: text Node: DFT(x, "", axis) -> (y) Attributes: inverse = 1 .. code-block:: text Inputs: x: shape=(1, 4, 2), dtype=float32 [[[1., 0.], [2., 0.], [3., 0.], [4., 0.]]] axis: shape=(), dtype=int64 1 Outputs: y: shape=(1, 4, 2), dtype=float32 [[[ 2.5000000e+00, 0.0000000e+00], [-5.0000000e-01, -5.0000000e-01], [-5.0000000e-01, 2.4492937e-16], [-5.0000000e-01, 5.0000000e-01]]] **test_cc_dft_irfft** .. code-block:: text Node: DFT(x, "", axis) -> (y) Attributes: inverse = 1 onesided = 1 .. code-block:: text Inputs: x: shape=(1, 6, 10, 2), dtype=float32 [[[[ 4.5000000e+02, 0.0000000e+00], [ 4.6000000e+02, 0.0000000e+00], [ 4.7000000e+02, 0.0000000e+00], ..., [ 5.2000000e+02, 0.0000000e+00], [ 5.3000000e+02, 0.0000000e+00], [ 5.4000000e+02, 0.0000000e+00]], [[-5.0000000e+01, 1.5388417e+02], [-5.0000000e+01, 1.5388417e+02], [-5.0000000e+01, 1.5388417e+02], ..., [-5.0000000e+01, 1.5388417e+02], [-5.0000000e+01, 1.5388417e+02], [-5.0000000e+01, 1.5388417e+02]], [[-5.0000000e+01, 6.8819099e+01], [-5.0000000e+01, 6.8819099e+01], [-5.0000000e+01, 6.8819099e+01], ..., [-5.0000000e+01, 6.8819099e+01], [-5.0000000e+01, 6.8819099e+01], [-5.0000000e+01, 6.8819099e+01]], [[-5.0000000e+01, 3.6327126e+01], [-5.0000000e+01, 3.6327126e+01], [-5.0000000e+01, 3.6327126e+01], ..., [-5.0000000e+01, 3.6327126e+01], [-5.0000000e+01, 3.6327126e+01], [-5.0000000e+01, 3.6327126e+01]], [[-5.0000000e+01, 1.6245985e+01], [-5.0000000e+01, 1.6245985e+01], [-5.0000000e+01, 1.6245985e+01], ..., [-5.0000000e+01, 1.6245985e+01], [-5.0000000e+01, 1.6245985e+01], [-5.0000000e+01, 1.6245985e+01]], [[-5.0000000e+01, -5.5109105e-14], [-5.0000000e+01, -5.5721429e-14], [-5.0000000e+01, -5.6333752e-14], ..., [-5.0000000e+01, -5.9395367e-14], [-5.0000000e+01, -6.0007690e-14], [-5.0000000e+01, -6.0620014e-14]]]] axis: shape=(), dtype=int64 1 Outputs: y: shape=(1, 10, 10, 1), dtype=float32 [[[[ 0.], [ 1.], [ 2.], ..., [ 7.], [ 8.], [ 9.]], [[10.], [11.], [12.], ..., [17.], [18.], [19.]], [[20.], [21.], [22.], ..., [27.], [28.], [29.]], ..., [[70.], [71.], [72.], ..., [77.], [78.], [79.]], [[80.], [81.], [82.], ..., [87.], [88.], [89.]], [[90.], [91.], [92.], ..., [97.], [98.], [99.]]]] **test_cc_dft_irfft_roundtrip** .. code-block:: text Node: DFT(x, "", axis) -> (y) Attributes: inverse = 1 onesided = 1 .. code-block:: text Inputs: x: shape=(1, 3, 2), dtype=float32 [[[10., 0.], [-2., 2.], [-2., 0.]]] axis: shape=(), dtype=int64 1 Outputs: y: shape=(1, 4, 1), dtype=float32 [[[1.], [2.], [3.], [4.]]] **test_cc_dft_rfft** .. code-block:: text Node: DFT(x, "", axis) -> (y) Attributes: onesided = 1 .. code-block:: text Inputs: x: shape=(1, 4, 1), dtype=float32 [[[1.], [2.], [3.], [4.]]] axis: shape=(), dtype=int64 1 Outputs: y: shape=(1, 3, 2), dtype=float32 [[[ 1.000000e+01, 0.000000e+00], [-2.000000e+00, 2.000000e+00], [-2.000000e+00, -9.797175e-16]]] Differences with previous version (17) -------------------------------------- **SchemaDiff**: ``DFT`` (domain ``'ai.onnx'``) * old version: 17 * new version: 20 * breaking: **yes** **Breaking reasons:** * input 'axis' (added): at position 2; option=Single; type_str='tensor(int64)' * attribute 'axis' (removed): type=INT; required=False **Inputs:** * [BREAKING] added 'axis': at position 2; option=Single; type_str='tensor(int64)' **Attributes:** * [BREAKING] removed 'axis': type=INT; required=False **Documentation:** * line similarity: 0.00 (+17/-1 lines) .. code-block:: diff --- DFT v17 +++ DFT v20 @@ -1 +1,17 @@ -Computes the discrete Fourier transform of input. +Computes the discrete Fourier Transform (DFT) of the input. + +Assuming the input has shape `[M, N]`, where `N` is the dimension over which the +DFT is computed and `M` denotes the conceptual "all other dimensions," +the DFT `y[m, k]` of shape `[M, N]` is defined as + +$$y[m, k] = \sum_{n=0}^{N-1} e^{-2 \pi j \frac{k n}{N} } x[m, n] ,$$ + +and the inverse transform is defined as + +$$x[m, n] = \frac{1}{N} \sum_{k=0}^{N-1} e^{2 \pi j \frac{k n}{N} } y[m, k] ,$$ + +where $j$ is the imaginary unit. + +The actual shape of the output is specified in the "output" section. + +Reference: https://docs.scipy.org/doc/scipy/tutorial/fft.html Version History --------------- - :doc:`Version 17 `