def setup(self):
        self.test_options = opt = {
            "wavelength_min": 4165,
            "wavelength_max": 4200,
            "databank": "fetch",  # not appropriate for these temperatures, but convenient for automatic testing
            "Tgas": 300,
            "Tvib": 1700,
            "Trot": 1550,
            "path_length": 0.1,
            "mole_fraction": 0.5,
            "molecule": "CO2",
            "isotope": "1,2",
            "wstep": 0.01,
            "cutoff": 1e-25,
            "use_cached": True,
            "medium": "vacuum",
            "optimization": "simple",
            "export_lines": False,
            "warnings": {
                "MissingSelfBroadeningWarning": "ignore",
                "NegativeEnergiesWarning": "ignore",
                "HighTemperatureWarning": "ignore",
            },
        }

        # Backward compatibility
        # ----------------------

        # Old version of RADIS do not necessary work with the latest parameters
        # Fix it :
        version = get_version(add_git_number=False)
        if version < "0.9.26":
            del self.test_options["optimization"]

        # Also fix problems with cache files :

        # First run to check there are no problems with Line database cache-files
        # ... Note @dev : as of 0.9.26 encountering a cache file generated with a future version
        # ... raises an error with no option to automatically regenerate the cache file
        sf = SpectrumFactory(
            **{
                k: v
                for (k, v) in opt.items()
                if k
                in [
                    "wavelength_min",
                    "wavelength_max",
                    "molecule",
                    "isotope",
                    "broadening_max_width",
                    "medium",
                ]
            }
        )

        for attempt in range(15):  # max number of failed cache files
            try:
                sf.fetch_databank()
            except ValueError as err:
                if "generated with a future version" in str(err):
                    # Get failing cache file :
                    fcache = re.search(
                        r"(?<=Cache file \().*(?=\) generated)", str(err)
                    )
                    if fcache is not None:
                        fcache = fcache.group()
                        printm(
                            "Backward compatibility : regenerating cache file",
                            fcache,
                        )
                        os.remove(fcache)
                        continue
                raise
            else:
                break
Beispiel #2
0
def test_spec_generation(plot=True, verbose=2, warnings=True, *args, **kwargs):
    """ Test spectrum generation
    Can be used as a base to generate spectra in your codes

    Non-regression test: compare with past version (see conditions below)

    Compare results from a reference case to results calculated on 30/12/2017
    This is not a validation case (30/12/2017 results are not a physically validated
    case), but it makes sure results dont change over time

    Conditions (30/12/2017)::

        Physical Conditions
        ----------------------------------------
           Tgas                 300 K
           Trot                 300 K
           Tvib                 300 K
           pressure             1.01325 bar
           isotope              1,2
           mole_fraction        1
           molecule             CO2
           path_length          1 cm
           wavelength_max       4400.0 nm
           wavelength_min       4150.0 nm
           wavenum_max          2409.6385542168673 cm-1
           wavenum_min          2272.7272727272725 cm-1
        Computation Parameters
        ----------------------------------------
           Tref                 296 K
           broadening_max_width  10 cm-1
           cutoff               1e-25 cm-1/(#.cm-2)
           db_assumed_sorted    True
           db_use_cached        True
           dbformat             cdsd
           dbpath               # USER-DEPENDANT: CDSD-HITEMP
           fillmissinglevelswithzero  False
           levelsfmt            cdsd
           levelspath           # USER-DEPENDANT: CDSD-4000
           medium               vacuum
           parfuncfmt           cdsd
           parfuncpath          # USER-DEPENDANT: CDSD-4000
           rot_distribution     boltzmann
           self_absorption      True
           vib_distribution     boltzmann
           wavenum_max_calc     2414.6385542168673 cm-1
           wavenum_min_calc     2267.7272727272725 cm-1
           waveunit             cm-1
           wstep                0.01 cm-1
        ----------------------------------------

    Notes
    -----

    Performance test. How long it tooks to calculate this Spectrum?
    Test with cutoff 1e-25, broadening_max_width=10 

    - 0.9.15: >>> 33s

    - 0.9.16*: (replaced groupby().apply() with iteration over indexes) >>> 32s  
            [but large impact expected on big files]

    - 0.9.16*: (upgraded cache files to h5) >>> 25s 

    - 0.9.16*: (also added h5 cache file for levels) >>> 21s

    - 0.9.16*: (with Whiting slit voigt function) >>> 5.8s

    Test with cutoff 1e-27, broadening_max_width=50 :  
    ("Spectrum calculated in ... ", including database loading time)

    - 0.9.16*: (same code as last) >>> 12.5s including 7.6s of broadening

    - 0.9.16**: (with pseudo_continuum_threshold=0.01) >>> 7.8s including 2.3s of broadening

    - 0.9.18 (normal code, no pseudo continuum). >>> ?
    
    - 0.9.21 (normal code) >>> 13.7s, including 8.7s of broadening
             (with pseudo_continuum_threshold=0.01) >>> 4.3s, including 2.6s of broadening

    - 0.9.21*              >>> 14.0s  (added the manual lineshape normalization instead of
                                       Whitings's polynomial)
    
    - 0.9.22 (normal code) >>> 11.3s   (without energy level lookup, for eq. calculations)
             (with pseudo_continuum_threshold=0.01) >>> 5.9s

    - 0.9.23 (normal code) >>> 7.2s   (added jit in Voigt broadening)
                           >>> 7.1s   (chunksize = None)  (and much faster for more lines)
             (with pseudo_continuum_threshold=0.01) >>> 4.9s
             
    RADIS:
        
    - 0.9.19 (normal code) >>> 6.3 s
    
    - 0.9.20 (normal code) >>> 6.3 s
             (with pseudo_continuum_threshold=0.01) >>> ???
             (with DLM) >>> 2.3 s
    
    """

    if plot:  # Make sure matplotlib is interactive so that test are not stuck in pytest
        plt.ion()

    from time import time

    t0 = time()
    if verbose:
        printm(">>> _test_spec_generation")

    # This is how you get a spectrum (see calc.py for front-end functions
    # that do just that)
    sf = SpectrumFactory(
        wavelength_min=4150,
        wavelength_max=4400,
        parallel=False,
        bplot=False,
        cutoff=1e-27,
        isotope="1,2",
        db_use_cached=True,
        broadening_max_width=50,
        #                             chunksize='DLM',
        #                             pseudo_continuum_threshold=0.01,
        medium="vacuum",
        verbose=verbose,
    )
    sf.warnings["MissingSelfBroadeningWarning"] = "ignore"
    sf.warnings["NegativeEnergiesWarning"] = "ignore"
    sf.load_databank(
        "HITEMP-CO2-DUNHAM",
        load_energies=False,  # no need to load energies at equilibrium
    )
    s = sf.eq_spectrum(Tgas=300)
    if verbose:
        printm(
            ">>> _test_spec_generation: Spectrum calculated in {0:.2f}s".format(
                time() - t0
            )
        )

    if plot:
        plt.figure(fig_prefix + "Reference spectrum CDSD-HITEMP (radiance)")
        # Iunit is arbitrary. Use whatever makes sense
        s.plot("radiance_noslit", Iunit="µW/cm2/sr/nm", nfig="same")
    s.rescale_path_length(0.01)

    # Here we get some extra informations:
    if plot:
        sf.plot_broadening(i=0)  # show broadening of one line
        plt.xlim((2267.20, 2268.30))

    # Compare with harcoded results
    # ... code previously used to export hardcoded results:
    # ... and header contains all input conditions:
    #        np.savetxt('output.txt', np.vstack(s.get('abscoeff', wunit='nm')).T[::10])
    #        print(s)
    # ................
    from radis.test.utils import getTestFile

    wref, Iref = np.loadtxt(getTestFile("CO2abscoeff_300K_4150_4400nm.txt")).T
    match_reference = np.allclose(s.get("abscoeff", wunit="nm")[1][::10], Iref)
    if not match_reference:
        # give some more information before raising error
        printm(
            "Error: {0:.2f}%".format(
                np.mean(abs(s.get("abscoeff", wunit="nm")[1][::10] / Iref - 1)) * 100
            )
        )
        # Store the faulty spectrum
        s.store(
            "test_factory_failed_{0}.spec".format(radis.get_version()),
            if_exists_then="replace",
        )

    # Plot comparison
    if plot:
        plt.figure(fig_prefix + "Reference spectrum (abscoeff)")
        # , show_points=True)  # show_points to have an
        s.plot(
            "abscoeff",
            wunit="nm",
            medium="air",
            nfig="same",
            lw=3,
            label="RADIS, this version",
        )
        # idea of the resolution
        plt.plot(wref, Iref, "or", ms=3, label="version NEQ 0.9.20 (12/05/18)")
        plt.legend()
        plt.title("All close: {0}".format(match_reference))
        plt.tight_layout()

    # Another example, at higher temperature.
    # Removed because no test is associated with it and it takes time for
    # nothing
    #        s2 = sf.non_eq_spectrum(Tvib=1000, Trot=300)
    #        if plot: s2.plot('abscoeff', wunit='nm')

    if verbose:
        printm(
            "Spectrum calculation (no database loading) took {0:.1f}s\n".format(
                s.conditions["calculation_time"]
            )
        )
        printm("_test_spec_generation finished in {0:.1f}s\n".format(time() - t0))

    assert match_reference
    def setup(self):
        self.test_options = opt = {
            "wavenum_min": 2000,
            "wavenum_max": 2250,
            "molecule": "CO2",
            "isotope": "1,2,3",
            "verbose": 3,
            "wstep": 0.01,
            "cutoff": 0,
            "chunksize": "auto",
            "broadening_max_width": 10,
            "path": [
                r"D:\Dropbox\Data ECP\14_Databases\CDSD-HITEMP\cdsd_hitemp_07",
                r"D:\Dropbox\Data ECP\14_Databases\CDSD-HITEMP\cdsd_hitemp_08",
                r"D:\Dropbox\Data ECP\14_Databases\CDSD-HITEMP\cdsd_hitemp_09",
            ],
            "use_cached": True,
            "dbformat": "cdsd-hitemp",
        }

        # Chunksize : number of lines to proceed at the same time (doestn apply if LDM)
        if opt["chunksize"] == "auto":
            opt["chunksize"] = digits(
                virtual_memory().available
                / sys.getsizeof(
                    _generate_broadening_range(
                        opt["wstep"], opt["broadening_max_width"]
                    )
                ),
                n=1,
            )
            printm("chunksize auto : ", opt["chunksize"])

        # Backward compatibility
        # ----------------------

        # Old version of RADIS do not necessary work with the latest parameters
        # Fix it :
        version = get_version(add_git_number=False)
        if version < "0.9.21":
            opt["dbformat"] = "cdsd"

        # Also fix problems with cache files :

        # First run to check there are no problems with Line database cache-files
        # ... Note @dev : as of 0.9.26 encountering a cache file generated with a future version
        # ... raises an error with no option to automatically regenerate the cache file
        sf = SpectrumFactory(
            **{
                k: opt[k]
                for k in [
                    "wavenum_min",
                    "wavenum_max",
                    "molecule",
                    "isotope",
                    "wstep",
                    "cutoff",
                    "verbose",
                ]
            }
        )

        for attempt in range(15):  # max number of failed cache files
            try:
                sf.load_databank(
                    path=opt["path"],
                    format=opt["dbformat"],
                    parfuncfmt="hapi",
                    levelsfmt="radis",
                )
            except ValueError as err:
                if "generated with a future version" in str(err):
                    # Get failing cache file :
                    fcache = re.search(
                        r"(?<=Cache file \().*(?=\) generated)", str(err)
                    )
                    if fcache is not None:
                        fcache = fcache.group()
                        printm(
                            "Backward compatibility : regenerating cache file",
                            fcache,
                        )
                        os.remove(fcache)
                        continue
                raise
            else:
                break