def normalize_efd(coeffs, size_invariant=True):
<EOL>theta_1 = <NUM_LIT:0.5> * np.arctan2(<EOL><NUM_LIT:2> * ((coeffs[<NUM_LIT:0>, <NUM_LIT:0>] * coeffs[<NUM_LIT:0>, <NUM_LIT:1>]) + (coeffs[<NUM_LIT:0>, <NUM_LIT:2>] * coeffs[<NUM_LIT:0>, <NUM_LIT:3>])),<EOL>((coeffs[<NUM_LIT:0>, <NUM_LIT:0>] ** <NUM_LIT:2>) - (coeffs[<NUM_LIT:0>, <NUM_LIT:1>] ** <NUM_LIT:2>) + (coeffs[<NUM_LIT:0>, <NUM_LIT:2>] ** <NUM_LIT:2>) - (coeffs[<NUM_LIT:0>, <NUM_LIT:3>] ** <NUM_LIT:2>)))<EOL>for n in _range(<NUM_LIT:1>, coeffs.shape[<NUM_LIT:0>] + <NUM_LIT:1>):<EOL><INDENT>coeffs[n - <NUM_LIT:1>, :] = np.dot(<EOL>np.array([[coeffs[n - <NUM_LIT:1>, <NUM_LIT:0>], coeffs[n - <NUM_LIT:1>, <NUM_LIT:1>]],<EOL>[coeffs[n - <NUM_LIT:1>, <NUM_LIT:2>], coeffs[n - <NUM_LIT:1>, <NUM_LIT:3>]]]),<EOL>np.array([[np.cos(n * theta_1), -np.sin(n * theta_1)],<EOL>[np.sin(n * theta_1), np.cos(n * theta_1)]])).flatten()<EOL><DEDENT>psi_1 = np.arctan2(coeffs[<NUM_LIT:0>, <NUM_LIT:2>], coeffs[<NUM_LIT:0>, <NUM_LIT:0>])<EOL>psi_rotation_matrix = np.array([[np.cos(psi_1), np.sin(psi_1)],<EOL>[-np.sin(psi_1), np.cos(psi_1)]])<EOL>for n in _range(<NUM_LIT:1>, coeffs.shape[<NUM_LIT:0>] + <NUM_LIT:1>):<EOL><INDENT>coeffs[n - <NUM_LIT:1>, :] = psi_rotation_matrix.dot(<EOL>np.array([[coeffs[n - <NUM_LIT:1>, <NUM_LIT:0>], coeffs[n - <NUM_LIT:1>, <NUM_LIT:1>]],<EOL>[coeffs[n - <NUM_LIT:1>, <NUM_LIT:2>], coeffs[n - <NUM_LIT:1>, <NUM_LIT:3>]]])).flatten()<EOL><DEDENT>if size_invariant:<EOL><INDENT>coeffs /= np.abs(coeffs[<NUM_LIT:0>, <NUM_LIT:0>])<EOL><DEDENT>return coeffs<EOL>
Normalizes an array of Fourier coefficients.

    See [#a]_ and [#b]_ for details.

    :param numpy.ndarray coeffs: A ``[n x 4]`` Fourier coefficient array.
    :param bool size_invariant: If size invariance normalizing should be done as well.
        Default is ``True``.
    :return: The normalized ``[n x 4]`` Fourier coefficient array.
    :rtype: :py:class:`numpy.ndarray`