Ejemplo n.º 1
0
def test_multiplyAndAddition(verbose=True, plot=False, *args, **kwargs):

    s = load_spec(getTestFile("CO_Tgas1500K_mole_fraction0.01.spec"), binary=True)
    s.update("radiance_noslit", verbose=False)
    s.apply_slit(0.1)
    s = Radiance(s)
    assert s.units["radiance"] == "mW/cm2/sr/nm"

    s_bis = add_constant(s, 1, "mW/cm2/sr/nm")
    w, Idiff = get_diff(s_bis, s, "radiance")
    test = Idiff[1] - 1
    assert np.all(test < 1e-10)

    s_ter = multiply(multiply(s, 50), 1 / 50)
    #    plot_diff(s_ter, s_5)
    diff = get_diff(s_ter, s, "radiance")
    ratio = abs(np.trapz(diff[1], x=diff[0]) / s.get_integral("radiance"))
    assert ratio < 1e-10
Ejemplo n.º 2
0
def test_invariants(*args, **kwargs):
    """ Ensures adding 0 or multiplying by 1 does not change the spectra """
    from radis import load_spec
    from radis.test.utils import getTestFile

    s = load_spec(getTestFile("CO_Tgas1500K_mole_fraction0.01.spec"))
    s.update()
    s = Radiance_noslit(s)

    assert s.compare_with(
        add_constant(s, 0, "W/cm2/sr/nm"), plot=False, spectra_only="radiance_noslit"
    )
    assert s.compare_with(multiply(s, 1), plot=False, spectra_only="radiance_noslit")

    assert 3 * s / 3 == s
    assert (1 + s) - 1 == s
Ejemplo n.º 3
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')