Esempio n. 1
0
def normal_ordered_form(expr,
                        independent=False,
                        recursive_limit=10,
                        _recursive_depth=0):
    """Write an expression with bosonic or fermionic operators on normal
    ordered form, where each term is normally ordered. Note that this
    normal ordered form is equivalent to the original expression.

    Parameters
    ==========

    expr : expression
        The expression write on normal ordered form.

    recursive_limit : int (default 10)
        The number of allowed recursive applications of the function.

    Examples
    ========

    >>> from sympy.physics.quantum import Dagger
    >>> from sympy.physics.quantum.boson import BosonOp
    >>> from sympy.physics.quantum.operatorordering import normal_ordered_form
    >>> a = BosonOp("a")
    >>> normal_ordered_form(a * Dagger(a))
    1 + Dagger(a)*a
    """

    if _recursive_depth > recursive_limit:
        warn.warning("Warning: too many recursions, aborting")
        return expr

    if isinstance(expr, Add):
        return _normal_ordered_form_terms(expr,
                                          recursive_limit=recursive_limit,
                                          _recursive_depth=_recursive_depth,
                                          independent=independent)
    elif isinstance(expr, Mul):
        return _normal_ordered_form_factor(expr,
                                           recursive_limit=recursive_limit,
                                           _recursive_depth=_recursive_depth,
                                           independent=independent)
    else:
        return expr
Esempio n. 2
0
def normal_ordered_form(expr, independent=False, recursive_limit=10,
                        _recursive_depth=0):
    """Write an expression with bosonic or fermionic operators on normal
    ordered form, where each term is normally ordered. Note that this
    normal ordered form is equivalent to the original expression.

    Parameters
    ==========

    expr : expression
        The expression write on normal ordered form.

    recursive_limit : int (default 10)
        The number of allowed recursive applications of the function.

    Examples
    ========

    >>> from sympy.physics.quantum import Dagger
    >>> from sympy.physics.quantum.boson import BosonOp
    >>> from sympy.physics.quantum.operatorordering import normal_ordered_form
    >>> a = BosonOp("a")
    >>> normal_ordered_form(a * Dagger(a))
    1 + Dagger(a)*a
    """

    if _recursive_depth > recursive_limit:
        warn.warning("Warning: too many recursions, aborting")
        return expr

    if isinstance(expr, Add):
        return _normal_ordered_form_terms(expr,
                                          recursive_limit=recursive_limit,
                                          _recursive_depth=_recursive_depth,
                                          independent=independent)
    elif isinstance(expr, Mul):
        return _normal_ordered_form_factor(expr,
                                           recursive_limit=recursive_limit,
                                           _recursive_depth=_recursive_depth,
                                           independent=independent)
    else:
        return expr
Esempio n. 3
0
def normal_order(expr, recursive_limit=10, _recursive_depth=0):
    """Normal order an expression with bosonic or fermionic operators. Note
    that this normal order is not equivalent to the original expression, but
    the creation and annihilation operators in each term in expr is reordered
    so that the expression becomes normal ordered.

    Parameters
    ==========

    expr : expression
        The expression to normal order.

    recursive_limit : int (default 10)
        The number of allowed recursive applications of the function.

    Examples
    ========

    >>> from sympy.physics.quantum import Dagger
    >>> from sympy.physics.quantum.boson import BosonOp
    >>> from sympy.physics.quantum.operatorordering import normal_order
    >>> a = BosonOp("a")
    >>> normal_order(a * Dagger(a))
    Dagger(a)*a
    """
    if _recursive_depth > recursive_limit:
        warn.warning("Warning: too many recursions, aborting")
        return expr

    if isinstance(expr, Add):
        return _normal_order_terms(expr,
                                   recursive_limit=recursive_limit,
                                   _recursive_depth=_recursive_depth)
    elif isinstance(expr, Mul):
        return _normal_order_factor(expr,
                                    recursive_limit=recursive_limit,
                                    _recursive_depth=_recursive_depth)
    else:
        return expr
Esempio n. 4
0
def normal_order(expr, recursive_limit=10, _recursive_depth=0):
    """Normal order an expression with bosonic or fermionic operators. Note
    that this normal order is not equivalent to the original expression, but
    the creation and annihilation operators in each term in expr is reordered
    so that the expression becomes normal ordered.

    Parameters
    ==========

    expr : expression
        The expression to normal order.

    recursive_limit : int (default 10)
        The number of allowed recursive applications of the function.

    Examples
    ========

    >>> from sympy.physics.quantum import Dagger
    >>> from sympy.physics.quantum.boson import BosonOp
    >>> from sympy.physics.quantum.operatorordering import normal_order
    >>> a = BosonOp("a")
    >>> normal_order(a * Dagger(a))
    Dagger(a)*a
    """
    if _recursive_depth > recursive_limit:
        warn.warning("Warning: too many recursions, aborting")
        return expr

    if isinstance(expr, Add):
        return _normal_order_terms(expr, recursive_limit=recursive_limit,
                                   _recursive_depth=_recursive_depth)
    elif isinstance(expr, Mul):
        return _normal_order_factor(expr, recursive_limit=recursive_limit,
                                    _recursive_depth=_recursive_depth)
    else:
        return expr
Esempio n. 5
0
def get_residual(
    s1,
    s2,
    var,
    norm="L2",
    ignore_nan=False,
    diff_window=0,
    normalize=False,
    normalize_how="max",
):
    # type: (Spectrum, Spectrum, str, bool, int) -> np.array, np.array
    """Returns L2 norm of ``s1`` and ``s2``

    For ``I1``, ``I2``, the values of variable ``var`` in ``s1`` and ``s2``,
    respectively, residual is calculated as:

    For ``L2`` norm:

        .. math::

            res = \\frac{\\sqrt{\\sum_i {(s_1[i]-s_2[i])^2}}}{N}.

    For ``L1`` norm:

        .. math::

            res = \\frac{\\sqrt{\\sum_i {|s_1[i]-s_2[i]|}}}{N}.


    Parameters
    ----------

    s1, s2: :class:`~radis.spectrum.spectrum.Spectrum` objects
        if not on the same range, ``s2`` is resampled on ``s1``.

    var: str
        spectral quantity

    norm: 'L2', 'L1'
        which norm to use

    Other Parameters
    ----------------

    ignore_nan: boolean
        if ``True``, ignore nan in the difference between s1 and s2 (ex: out of bound)
        when calculating residual. Default ``False``. Note: ``get_residual`` will still
        fail if there are nan in initial Spectrum.

    normalize: bool, or tuple
        if ``True``, normalize the two spectra before calculating the residual.
        If a tuple (ex: ``(4168, 4180)``), normalize on this range only. The unit
        is that of the first Spectrum. Ex::

            s_exp   # in 'nm'
            s_calc  # in 'cm-1'
            get_residual(s_exp, s_calc, normalize=(4178, 4180))  # interpreted as 'nm'

    normalize_how: ``'max'``, ``'area'``, ``'mean'``
        how to normalize. ``'max'`` is the default but may not be suited for very
        noisy experimental spectra. ``'area'`` will normalize the integral to 1.
        ``'mean'`` will normalize by the mean amplitude value

    Notes
    -----

    0 values for I1 yield nans except if I2 = I1 = 0

    when s1 and s2 dont have the size wavespace range, they are automatically
    resampled through get_diff on 's1' range

    Implementation of ``L2`` norm::

        np.sqrt((dI**2).sum())/len(dI)

    Implementation of ``L1`` norm::

        np.abs(dI).sum()/len(dI)

    See Also
    --------

    :func:`~radis.spectrum.compare.get_diff`,
    :func:`~radis.spectrum.compare.get_ratio`,
    :func:`~radis.spectrum.compare.get_distance`,
    :func:`~radis.spectrum.compare.plot_diff`,
    :func:`~radis.spectrum.compare.get_residual_integral`,
    :meth:`~radis.spectrum.spectrum.compare_with`
    """

    if normalize:
        if isinstance(normalize, tuple):
            wrange = normalize
        else:
            wrange = ()
        wdiff, dI = get_diff(
            s1.take(var).normalize(wrange=wrange, normalize_how=normalize_how),
            s2.take(var).normalize(wrange=wrange, normalize_how=normalize_how),
            var,
            resample=True,
            diff_window=diff_window,
        )
    else:
        wdiff, dI = get_diff(s1,
                             s2,
                             var,
                             resample=True,
                             diff_window=diff_window)

    if ignore_nan:
        b = np.isnan(dI)
        wdiff, dI = wdiff[~b], dI[~b]
    warningText = (
        'NaN output in residual. You should use "ignore_nan=True". Read the help.'
    )
    if norm == "L2":
        output = np.sqrt((dI**2).sum()) / len(dI)
        if np.isnan(output):
            warn(warningText, UserWarning)
        return output
    elif norm == "L1":
        output = (np.abs(dI)).sum() / len(dI)
        if np.isnan(output):
            warn.warning(warningText, UserWarning)
        return output
    else:
        raise ValueError("unexpected value for norm")
Esempio n. 6
0
def get_residual(s1,
                 s2,
                 var,
                 norm='L2',
                 ignore_nan=False,
                 diff_window=0,
                 normalize=False,
                 normalize_how='max'):
    # type: (Spectrum, Spectrum, str, bool, int) -> np.array, np.array
    ''' Returns L2 norm of ``s1`` and ``s2``

    For ``I1``, ``I2``, the values of variable ``var`` in ``s1`` and ``s2``, 
    respectively, residual is calculated as:
        
    For ``L2`` norm:

        .. math::
    
            res = \\frac{\\sqrt{\\sum_i {(s_1[i]-s_2[i])^2}}}{N}.

    For ``L1`` norm:
            
        .. math::
    
            res = \\frac{\\sqrt{\\sum_i {|s_1[i]-s_2[i]|}}}{N}.


    Parameters    
    ----------

    s1, s2: :class:`~radis.spectrum.spectrum.Spectrum` objects
        if not on the same range, ``s2`` is resampled on ``s1``.

    var: str
        spectral quantity

    norm: 'L2', 'L1'
        which norm to use 

    Other Parameters
    ----------------

    ignore_nan: boolean
        if ``True``, ignore nan in the difference between s1 and s2 (ex: out of bound)
        when calculating residual. Default ``False``. Note: ``get_residual`` will still 
        fail if there are nan in initial Spectrum. 

    normalize: bool, or tuple
        if ``True``, normalize the two spectra before calculating the residual. 
        If a tuple (ex: ``(4168, 4180)``), normalize on this range only. The unit
        is that of the first Spectrum. Ex::
            
            s_exp   # in 'nm'
            s_calc  # in 'cm-1'
            get_residual(s_exp, s_calc, normalize=(4178, 4180))  # interpreted as 'nm'

    normalize_how: ``'max'``, ``'area'``, ``'mean'``
        how to normalize. ``'max'`` is the default but may not be suited for very
        noisy experimental spectra. ``'area'`` will normalize the integral to 1.
        ``'mean'`` will normalize by the mean amplitude value

    Notes
    -----

    0 values for I1 yield nans except if I2 = I1 = 0

    when s1 and s2 dont have the size wavespace range, they are automatically
    resampled through get_diff on 's1' range 

    Implementation of ``L2`` norm::

        np.sqrt((dI**2).sum())/len(dI)
    
    Implementation of ``L1`` norm::
        
        np.abs(dI).sum()/len(dI)

    See Also
    --------

    :func:`~radis.spectrum.compare.get_diff`, 
    :func:`~radis.spectrum.compare.get_ratio`, 
    :func:`~radis.spectrum.compare.get_distance`, 
    :func:`~radis.spectrum.compare.plot_diff`, 
    :func:`~radis.spectrum.compare.get_residual_integral`, 
    :meth:`~radis.spectrum.spectrum.compare_with` 
    '''

    if normalize:
        from radis.spectrum.operations import multiply
        if isinstance(normalize, tuple):
            wmin, wmax = normalize
            w1, I1 = s1.get(var, copy=False)  # (faster not to copy)
            b = (w1 > wmin) & (w1 < wmax)
            if normalize_how == 'max':
                norm1 = I1[b].max()
            elif normalize_how == 'mean':
                norm1 = I1[b].mean()
            elif normalize_how == 'area':
                norm1 = np.abs(np.trapz(I1[b], w1[b]))
            else:
                raise ValueError(
                    'Unexpected `normalize_how`: {0}'.format(normalize_how))
            # now normalize s2. Ensure we use the same unit system!
            w2, I2 = s2.get(var, Iunit=s1.units[var], wunit=s1.get_waveunit())
            b = (w2 > wmin) & (w2 < wmax)
            if normalize_how == 'max':
                norm2 = I2[b].max()
            elif normalize_how == 'mean':
                norm2 = I2[b].mean()
            elif normalize_how == 'area':
                norm2 = np.abs(np.trapz(I2[b], w2[b]))
            else:
                raise ValueError(
                    'Unexpected `normalize_how`: {0}'.format(normalize_how))
            s1 = multiply(s1, 1 / norm1, var=var)
            s2 = multiply(s2, 1 / norm2, var=var)
        else:
            if normalize_how == 'max':
                norm1 = s1.get(var, copy=False)[1].max()
                norm2 = s2.get(var)[1].max()
            elif normalize_how == 'mean':
                norm1 = s1.get(var, copy=False)[1].mean()
                norm2 = s2.get(var)[1].mean()
            elif normalize_how == 'area':
                norm1 = s1.get_integral(var)
                norm2 = s2.get_integral(var,
                                        wunit=s1.get_waveunit(),
                                        Iunit=s1.units[var])
            else:
                raise ValueError(
                    'Unexpected `normalize_how`: {0}'.format(normalize_how))
            # Ensure we use the same unit system!
            s1 = multiply(s1, 1 / norm1, var=var)
            s2 = multiply(s2, 1 / norm2, var=var)

    # mask for 0
    wdiff, dI = get_diff(s1, s2, var, resample=True, diff_window=diff_window)

    if ignore_nan:
        b = np.isnan(dI)
        wdiff, dI = wdiff[~b], dI[~b]
    warningText = 'NaN output in residual. You should use "ignore_nan=True". Read the help.'
    if norm == 'L2':
        output = np.sqrt((dI**2).sum()) / len(dI)
        if np.isnan(output):
            warn(warningText, UserWarning)
        return output
    elif norm == 'L1':
        output = (np.abs(dI)).sum() / len(dI)
        if np.isnan(output):
            warn.warning(warningText, UserWarning)
        return output
    else:
        raise ValueError('unexpected value for norm')