Пример #1
0
def diffDatabankEntries(dict_entries1, dict_entries2, verbose=True):
    """ Compare two Databank entries under dict format (i.e: output of 
    getDatabankEntries)

    Returns None if no differences are found, or the first different key 
    """

    k = None

    try:
        verbose_compare = "if_different" if verbose else False
        assert len(dict_entries1) == len(dict_entries2)
        assert (
            compare_lists(
                list(dict_entries1.keys()),
                list(dict_entries2.keys()),
                verbose=verbose_compare,
            )
            == 1
        )
        for k in dict_entries1.keys():
            v1 = dict_entries1[k]
            v2 = dict_entries2[k]
            if k in ["info", "format", "parfuncfmt", "levelsfmt"]:
                assert v1 == v2
            elif k in ["path"]:
                assert (
                    compare_lists(
                        [stdpath(path1) for path1 in v1],
                        [stdpath(path2) for path2 in v2],
                        verbose=verbose_compare,
                    )
                    == 1
                )
            elif k in ["levels"]:
                assert (
                    compare_dict(
                        v1,
                        v2,
                        compare_as_paths=list(v1.keys()),
                        verbose=verbose_compare,
                    )
                    == 1
                )
            else:
                raise ValueError("Unexpected key:", k)

        return None

    except AssertionError:
        if verbose:
            print("Key doesnt match:", k)
        return k
Пример #2
0
def test_hitran_names_match(verbose=True, warnings=True, *args, **kwargs):
    ''' Compare that HITRAN species defined in :mod:`radis.io.hitran` match
    the nomenclature dictionary : :py:data:`radis.io.hitran.trans`.
    
    This should be ensured by developers when adding new species. 
    '''
    from radis.io.hitran import (HITRAN_CLASS1, HITRAN_CLASS2, HITRAN_CLASS3,
                                 HITRAN_CLASS4, HITRAN_CLASS5, HITRAN_CLASS6,
                                 HITRAN_CLASS7, HITRAN_CLASS8, HITRAN_CLASS9,
                                 HITRAN_CLASS10)
    from radis.io.hitran import HITRAN_MOLECULES
    from radis.misc.basics import compare_lists

    all_hitran = (HITRAN_CLASS1 + HITRAN_CLASS2 + HITRAN_CLASS3 +
                  HITRAN_CLASS4 + HITRAN_CLASS5 + HITRAN_CLASS6 +
                  HITRAN_CLASS7 + HITRAN_CLASS8 + HITRAN_CLASS9 +
                  HITRAN_CLASS10)
    all_hitran = list(set(all_hitran))

    # All species in HITRAN groups should be valid HITRAN_MOLECULES names
    for m in all_hitran:
        if not m in HITRAN_MOLECULES:
            raise ValueError(
                '{0} is defined in HITRAN groups but has no HITRAN id'.format(
                    m))

    # Species in 'HITRAN_MOLECULES' should be classified in groups, else nonequilibrium
    # calculations are not possible.
    if warnings and all_hitran != HITRAN_MOLECULES:
        warn("Difference between HITRAN groups (left) and HITRAN id "+\
                         "dictionary (right). Some HITRAN species are not classified in "+\
                         "groups. Nonequilibrium calculations wont be possible for these!:\n"+\
                         "{0}".format(compare_lists(all_hitran, HITRAN_MOLECULES,
                          verbose=False, return_string=True)[1]))
    return
Пример #3
0
def diffDatabankEntries(dict_entries1, dict_entries2, verbose=True):
    ''' Compare two Databank entries under dict format (i.e: output of 
    getDatabankEntries)

    Returns None if no differences are found, or the first different key 
    '''

    k = None

    try:
        verbose_compare = 'if_different' if verbose else False
        assert len(dict_entries1) == len(dict_entries2)
        assert compare_lists(list(dict_entries1.keys()),
                             list(dict_entries2.keys()),
                             verbose=verbose_compare) == 1
        for k in dict_entries1.keys():
            v1 = dict_entries1[k]
            v2 = dict_entries2[k]
            if k in ['info', 'format', 'parfuncfmt', 'levelsfmt']:
                assert v1 == v2
            elif k in ['path']:
                assert compare_lists([stdpath(path1) for path1 in v1],
                                     [stdpath(path2) for path2 in v2],
                                     verbose=verbose_compare) == 1
            elif k in ['levels']:
                assert compare_dict(v1,
                                    v2,
                                    compare_as_paths=list(v1.keys()),
                                    verbose=verbose_compare) == 1
            else:
                raise ValueError('Unexpected key:', k)

        return None

    except AssertionError:
        if verbose:
            print('Key doesnt match:', k)
        return k
Пример #4
0
def compare_spectra(first,
                    other,
                    spectra_only=False,
                    plot=True,
                    wunit="default",
                    verbose=True,
                    rtol=1e-5,
                    ignore_nan=False,
                    ignore_outliers=False,
                    normalize=False,
                    **kwargs):
    """Compare Spectrum with another Spectrum object

    Parameters
    ----------

    first: type Spectrum
        a Spectrum to be compared

    other: type Spectrum
        another Spectrum to compare with

    spectra_only: boolean, or str
        if ``True``, only compares spectral quantities (in the same waveunit)
        and not lines or conditions. If str, compare a particular quantity
        name. If False, compare everything (including lines and conditions
        and populations). Default ``False``

    plot: boolean
        if ``True``, use plot_diff to plot all quantities for the 2 spectra
        and the difference between them. Default ``True``.

    wunit: 'nm', 'cm-1', 'default'
        in which wavespace to compare (and plot). If default, natural wavespace
        of first Spectrum is taken

    rtol: float
        relative difference to use for spectral quantities comparison

    ignore_nan: boolean
        if ``True``, nans are ignored when comparing spectral quantities

    ignore_outliers: boolean, or float
        if not False, outliers are discarded. i.e, output is determined by::

            out = (~np.isclose(I, Ie, rtol=rtol, atol=0)).sum()/len(I) < ignore_outliers

    normalize: bool
        Normalize the spectra to be plotted

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

    kwargs: dict
        arguments are forwarded to :func:`~radis.spectrum.compare.plot_diff`

    Returns
    -------

    equals: boolean
        return True if spectra are equal (respective to tolerance defined by
        rtol and other input conditions)


    Examples
    --------

    Compare two Spectrum objects, or specifically the transmittance::

        s1.compare_with(s2)
        s1.compare_with(s2, 'transmittance')


    Note that you can also simply use `s1 == s2`, that uses
    :meth:`~radis.spectrum.spectrum.Spectrum.compare_with` internally::

        s1 == s2       # will return True or False

    """

    # Check inputs
    if not 0 <= ignore_outliers < 1:
        raise ValueError("ignore_outliers should be < 1, or False")
    if not is_spectrum(other):
        raise TypeError("2nd object is not a Spectrum: got class {0}".format(
            other.__class__))
    if isinstance(spectra_only, str):  # case where we compare all quantities
        if not spectra_only in first.get_vars():
            raise ValueError(
                "{0} is not a spectral quantity in our Spectrum ({1})".format(
                    spectra_only, first.get_vars()))
        if not spectra_only in other.get_vars():
            raise ValueError(
                "{0} is not a spectral quantity in the other Spectrum ({1})".
                format(spectra_only, other.get_vars()))
    if verbose:  # print conditions
        what = spectra_only if isinstance(spectra_only,
                                          str) else "all quantities"
        msg = "compare {0} with rtol={1}".format(what, rtol)
        if ignore_nan:
            msg += ", ignore_nan"
        if ignore_outliers:
            msg += ", ignore_outliers={0}".format(ignore_outliers)
        print(msg)
    if not plot and len(kwargs) > 0:
        raise ValueError("Unexpected argument: {0}".format(kwargs))

    if wunit == "default":
        wunit = first.get_waveunit()

    def _compare_dataframes(df1, df2, name):
        """

        Parameters
        ----------

        df1, df2: pandas Dataframe
            lines, or vib/rovib levels dataframes

        name: str
            for error message
        """

        #            if compare_lists(df1.keys(), df2.keys(), verbose=False) != 1:
        #                if verbose: print('... keys in {0} dont match:'.format(name))
        #                compare_lists(list(df1.keys()), list(df2.keys()),
        #                              verbose=True)
        #                out = False
        #            elif compare_lists(df1.index, df2.index, verbose=False) != 1:
        #                if verbose: print('... index in {0} dont match:'.format(name))
        #                compare_lists(list(df1.index), list(df2.index),
        #                              verbose=True)
        #                out = False
        #            else:
        #                out = (df1 == df2).all().all()
        #
        #            return out

        from pandas.util.testing import assert_frame_equal

        try:
            assert_frame_equal(
                df1.sort_index(axis=0).sort_index(axis=1),
                df2.sort_index(axis=0).sort_index(axis=1),
                check_names=True,
                check_column_type=
                False,  # solves problem in Python 2/3 dataframes (unicode/str)
            )
            out = True

        except AssertionError as err:
            if verbose:
                print("Comparing ", name)
                print(err.args[0])
            out = False

        return out

    def _compare_variables(I, Ie):
        """ Compare spectral quantities I and Ie """

        if ignore_nan:
            b = ~(np.isnan(I) + np.isnan(Ie))
            I = I[b]
            Ie = Ie[b]

        if ignore_outliers:
            out = (~np.isclose(I, Ie, rtol=rtol,
                               atol=0)).sum() / len(I) < ignore_outliers
        else:
            out = np.allclose(I, Ie, rtol=rtol, atol=0)

        return bool(out)

    def _display_difference(q, q0):
        error = np.nanmax(abs(q / q0 - 1))
        avgerr = np.nanmean(abs(q / q0 - 1))
        print(
            "...",
            k,
            "don't match (up to {0:.3}% diff.,".format(error * 100) +
            " average {0:.3f}%)".format(avgerr * 100),
        )

    b = True
    if isinstance(spectra_only, str):  # compare this quantity
        vars = [spectra_only]
    else:  # compare all quantities
        b = set(first.get_vars()) == set(other.get_vars())
        if not b and verbose:
            print("... list of quantities dont match: {0} vs {1}".format(
                first.get_vars(), other.get_vars()))
        vars = [k for k in first.get_vars() if k in other.get_vars()]

    if spectra_only:
        # Compare spectral variables
        # -----------
        for k in vars:
            w, q = first.get(k, wunit=wunit)
            w0, q0 = other.get(k, wunit=wunit)
            if len(w) != len(w0):
                print("Wavespaces have different length (for {0}: {1} vs {2})".
                      format(k, len(w), len(w0)))
                print("We interpolate one spectrum on the other one")

                from scipy.interpolate import interp1d

                if len(q) > len(q0):
                    f = interp1d(w, q, kind="cubic")
                    new_q = f(w0)
                    b1 = _compare_variables(new_q, q0)
                    if not b1 and verbose:
                        _display_difference(new_q, q0)
                else:
                    f = interp1d(w0, q0, kind="cubic")
                    new_q0 = f(w)
                    b1 = _compare_variables(q, new_q0)
                    if not b1 and verbose:
                        _display_difference(q, new_q0)

            else:  # no need to interpolate
                b1 = np.allclose(w, w0, rtol=rtol, atol=0)
                b1 *= _compare_variables(q, q0)

                if not b1 and verbose:
                    _display_difference(q, q0)
            b *= b1

            if plot:
                try:
                    plot_diff(first,
                              other,
                              var=k,
                              wunit=wunit,
                              normalize=normalize,
                              verbose=verbose,
                              **kwargs)
                except:
                    print("... couldn't plot {0}".format(k))

    else:
        # Compare spectral variables
        # -----------
        for k in vars:
            w, q = first.get(k, wunit=wunit)
            w0, q0 = other.get(k, wunit=wunit)
            if len(w) != len(w0):
                print("Wavespaces have different length (for {0}: {1} vs {2})".
                      format(k, len(w), len(w0)))
                b1 = False
            else:
                b1 = np.allclose(w, w0, rtol=rtol, atol=0)
                b1 *= _compare_variables(q, q0)
                if not b1 and verbose:
                    error = np.nanmax(abs(q / q0 - 1))
                    avgerr = np.nanmean(abs(q / q0 - 1))
                    print(
                        "...",
                        k,
                        "don't match (up to {0:.3}% diff.,".format(error * 100)
                        + " average {0:.3f}%)".format(avgerr * 100),
                    )
            b *= b1

            if plot:
                try:
                    plot_diff(first,
                              other,
                              var=k,
                              wunit=wunit,
                              normalize=normalize,
                              verbose=verbose,
                              **kwargs)
                except:
                    print(
                        "... there was an error while plotting {0}".format(k))

        # Compare conditions and units
        # -----------
        verbose_dict = "if_different" if verbose else False
        b1 = compare_dict(first.conditions,
                          other.conditions,
                          verbose=verbose_dict) == 1
        b2 = compare_dict(first.cond_units,
                          other.cond_units,
                          verbose=verbose_dict) == 1
        b3 = compare_dict(first.units, other.units, verbose=verbose_dict) == 1
        if not b1 and verbose:
            print("... conditions don't match")
        if not b2 and verbose:
            print("... conditions units don't match")
        if not b3 and verbose:
            print("... units don't match")
        b *= b1 * b2 * b3

        # Compare lines
        # -----------
        if first.lines is None and other.lines is None:
            b4 = True
        elif first.lines is None:
            b4 = False
        elif other.lines is None:
            b4 = False
        else:
            b4 = _compare_dataframes(first.lines, other.lines, "lines")
        if not b4 and verbose:
            print("... lines dont match")
        b *= b4

        # Compare populations
        # -----------
        if first.populations is None and other.populations is None:
            b5 = True
        elif first.populations is None:
            b5 = False
        elif other.populations is None:
            b5 = False
        else:
            # Compare keys in populations
            b5 = True
            if (compare_lists(first.populations,
                              other.populations,
                              verbose="if_different") == 1):
                # same molecules, compare isotopes
                for molecule, isotopes in first.populations.items():
                    if (compare_lists(
                            isotopes,
                            other.populations[molecule],
                            verbose="if_different",
                    ) == 1):
                        # same isotopes, compare electronic states
                        for isotope, states in isotopes.items():
                            if (compare_lists(
                                    states,
                                    other.populations[molecule][isotope],
                                    verbose="if_different",
                            ) == 1):
                                # same electronic states, compare levels + other information
                                for state, content in states.items():
                                    for k, v in content.items():
                                        if k in ["vib", "rovib"]:
                                            b5 *= _compare_dataframes(
                                                v,
                                                other.populations[molecule]
                                                [isotope][state][k],
                                                "populations of {0}({1})(iso{2})"
                                                .format(
                                                    molecule, state, isotope),
                                            )
                                        else:
                                            b5 *= (v == other.populations[
                                                molecule][isotope][state][k])
                            else:
                                b5 = False
                                if verbose:
                                    print(
                                        "{0}(iso{1}) states are different (see above)"
                                        .format(molecule, isotope))
                    else:
                        b5 = False
                        if verbose:
                            print("{0} isotopes are different (see above)".
                                  format(molecule))
            else:
                b5 = False
                if verbose:
                    print("Molecules are different (see above)")
        if not b5 and verbose:
            print("... populations dont match (see detail above)")
        b *= b5

        # Compare slit
        # -----------

        if len(first._slit) == len(other._slit) == 0:
            # no slit anywhere
            b6 = True
        elif len(first._slit) != len(other._slit):
            b6 = False
            if verbose:
                print(
                    "A spectrum has slit function array but the other doesnt")
        else:
            ws, Is = first.get_slit()
            ws0, Is0 = other.get_slit()
            if len(ws) != len(ws0):
                if verbose:
                    print("Slits have different length")
                b6 = False
            else:
                b6 = np.allclose(ws, ws0, rtol=rtol, atol=0)
                b6 *= _compare_variables(Is, Is0)
                if not b6 and verbose:
                    print("Slit functions dont match")
        b *= b6

    return bool(b)