def test_line_survey_CO2(verbose=True, plot=True, warnings=True, *args, **kwargs): setup_test_line_databases() try: pl = SpectrumFactory( wavenum_min=2380, wavenum_max=2400, # wavelength_min=4170, # wavelength_max=4200, mole_fraction=400e-6, path_length=100, # cm parallel=False, cutoff=1e-30, isotope=[1], save_memory=True, db_use_cached=True, ) # 0.2) pl.warnings["MissingSelfBroadeningWarning"] = "ignore" pl.load_databank("HITRAN-CO2-TEST") s = pl.eq_spectrum(Tgas=1500) s.apply_slit(0.5) if plot: s.line_survey(overlay="transmittance", barwidth=0.01) if verbose: printm("no boolean defined for test_line_survey") return True # test not defined (just testing methods work) except DatabankNotFound as err: assert IgnoreMissingDatabase(err, __file__, warnings)
def test_CDSD_calc_vs_tab(verbose=True, warnings=True, *args, **kwargs): ''' Test 1: compare calculated PartFunc to the tabulated one ''' from radis.misc.config import getDatabankEntries try: iso = 1 database = 'CDSD-HITEMP-PC' # Compare tab to hardcoded parfunc = getDatabankEntries(database)['parfunc'] Qf = PartFuncCO2_CDSDtab(iso, parfunc) assert np.isclose(Qf.at(300), 291.0447781984652, rtol=0.001) assert np.isclose(Qf.at(3000), 114689.88454184022, rtol=0.001) if verbose: printm('Tested CDSD tabulated is correct: OK') # Compare tab to calculated energies = getDatabankEntries(database)['levels'] levelsfmt = getDatabankEntries(database)['levelsfmt'] Qfc = PartFuncCO2_CDSDcalc(energies[iso], levelsfmt=levelsfmt, isotope=iso, use_cached=True) assert np.isclose(Qf.at(300), Qfc.at(300), rtol=0.001) assert np.isclose(Qf.at(3000), Qfc.at(3000), rtol=0.001) if verbose: printm('Tested CDSD Q_calc vs Q_tab give same output: OK') return True except DatabankNotFound as err: assert IgnoreMissingDatabase(err, __file__, warnings)
def test_CDSD_calc_vs_ref(warnings=True, verbose=True, *args, **kwargs): ''' Test partition functions calculated with CDSD energy levels against hardcoded values ''' from radis.misc.config import getDatabankEntries iso = 1 try: energies = getDatabankEntries('CDSD-HITEMP-PC')['levels'] levelsfmt = getDatabankEntries('CDSD-HITEMP-PC')['levelsfmt'] Qf = PartFuncCO2_CDSDcalc(energy_levels=energies[iso], isotope=iso, use_cached=True, levelsfmt=levelsfmt) assert np.isclose(Qf.at(300), 291.0447781984652, rtol=0.001) assert np.isclose(Qf.at(3000), 114689.88454184022, rtol=0.001) assert np.isclose(Qf.at_noneq(300, 300), 291.0447781984652, rtol=0.001) assert np.isclose(Qf.at_noneq(3000, 3000), 114689.88454184022, rtol=0.001) assert np.isclose(Qf.at_noneq(3000, 3000, overpopulation={'(0,1)': 3}, returnQvibQrot=True)[0], 120053.34252537244, rtol=0.001) if verbose: printm('Tested Q_CDSD values are correct : OK') return True except DatabankNotFound as err: assert IgnoreMissingDatabase(err, __file__, warnings)
def test_media_line_shift(plot=False, verbose=True, warnings=True, *args, **kwargs): ''' See wavelength difference in air and vacuum ''' if plot: # Make sure matplotlib is interactive so that test are not stuck in pytest plt.ion() try: if verbose: printm('>>> _test_media_line_shift') setup_test_line_databases( ) # add HITRAN-CO-TEST in ~/.radis if not there sf = SpectrumFactory(wavelength_min=4500, wavelength_max=4600, wstep=0.001, parallel=False, bplot=False, cutoff=1e-30, path_length=0.1, mole_fraction=400e-6, isotope=[1], db_use_cached=True, medium='vacuum', broadening_max_width=10, verbose=verbose) sf.warnings['MissingSelfBroadeningWarning'] = 'ignore' sf.warnings['GaussianBroadeningWarning'] = 'ignore' sf.load_databank('HITRAN-CO-TEST') # Calculate a spectrum s = sf.eq_spectrum(2000) # Compare if plot: fig = plt.figure(fig_prefix + 'Propagating media line shift') s.plot('radiance_noslit', wunit='nm_vac', nfig=fig.number, lw=2, label='Vacuum') plt.title('CO spectrum (2000 K)') s.plot('radiance_noslit', wunit='nm', nfig=fig.number, lw=2, color='r', label='Air') # ... there should be about ~1.25 nm shift at 4.5 µm: assert np.isclose( s.get('radiance_noslit', wunit='nm_vac')[0][0] - s.get('radiance_noslit', wunit='nm')[0][0], 1.2540436086346745) except DatabankNotFound as err: assert IgnoreMissingDatabase(err, __file__, warnings)
def test_rescaling_path_length(debug=False, plot=False, verbose=True, warnings=True, *args, **kwargs): """ Test rescaling functions """ if plot: # Make sure matplotlib is interactive so that test are not stuck plt.ion() try: from radis.lbl import SpectrumFactory setup_test_line_databases( ) # add HITRAN-CO-TEST in ~/.radis if not there Tgas = 1500 sf = SpectrumFactory( wavelength_min=4400, wavelength_max=4800, mole_fraction=0.01, # path_length=0.1, cutoff=1e-25, wstep=0.005, isotope=[1], db_use_cached=True, self_absorption=True, verbose=verbose, ) sf.warnings["MissingSelfBroadeningWarning"] = "ignore" # sf.warnings['NegativeEnergiesWarning'] = 'ignore' sf.load_databank("HITRAN-CO-TEST") s1 = sf.non_eq_spectrum(Tgas, Tgas, path_length=0.01) s2 = sf.non_eq_spectrum(Tgas, Tgas, path_length=3) s1.rescale_path_length(3) if plot: fig = plt.figure(fig_prefix + "Rescaling path length") s2.plot("radiance_noslit", nfig=fig.number, lw=3, label="L=3m") s1.plot( "radiance_noslit", nfig=fig.number, color="r", label="L=0.01m, rescaled to 3m", ) plt.title("Non optically thin rescaling") plt.legend() plt.tight_layout() if verbose: printm("Test rescaling:") printm("... Difference: {0:.2f}%".format( abs(s1.get_power() / s2.get_power() - 1) * 100)) assert np.isclose(s2.get_power(), s1.get_power(), 2e-3) except DatabankNotFound as err: assert IgnoreMissingDatabase(err, __file__, warnings)
def test_load_lines_pops(plot=False, verbose=True, warnings=True, *args, **kwargs): """ Test load / save Full version: save lines, populations (hundreds of MB for CO2, much less for CO), compare everything """ temp_file_name = "_test_database_co_tempfile.spec" assert not exists(temp_file_name) try: sf = SpectrumFactory( wavelength_min=4500, wavelength_max=4800, mole_fraction=400e-6, path_length=0.1, # cm isotope=[1, 2], db_use_cached=True, cutoff=1e-20, verbose=verbose, ) sf.warnings["MissingSelfBroadeningWarning"] = "ignore" sf.load_databank("HITRAN-CO-TEST") s1 = sf.non_eq_spectrum(Tvib=300, Trot=300) s1.apply_slit(2, verbose=False) s1.update() s2 = load_spec( s1.store( temp_file_name, discard=[], # we're actually saving lines and # populations here! expect hundreds # of megabytes for big molecules # :line CO2 ... here CO is fine # (by default lines and populations # are discarded) compress=True # only removes some spectral # quantities, cant change population # or lines size ), binary=True, # uncompress ) s2.update() assert s1.compare_with(s2, spectra_only=False, plot=False) # Test with json-tricks directly # Does not work yet # from json_tricks import dumps, loads # s2b = loads(dumps(s1)) # assert s1.compare_with(s2b, spectra_only=False, plot=False) except DatabankNotFound as err: assert IgnoreMissingDatabase(err, __file__, warnings) finally: # cleaning if exists(temp_file_name): os.remove(temp_file_name) return True
def test_eq_vs_noneq_isotope(verbose=True, plot=False, warnings=True, *args, **kwargs): ''' Test same spectrum for 2 different calculation codes (equilibrium, non-equilibrium) in the presence of isotopes Notes ----- On the old NeQ package the test used [HITEMP-2010]_ Starting from RADIS 1.0.1, the test is run on [HITRAN-2016]_, which is not valid for these temperatures but can be more conveniently downloaded automatically and thus executed everytime with [Travis]_ ''' try: Tgas = 1500 sf = SpectrumFactory(wavelength_min=4250, wavelength_max=4350, mole_fraction=1, path_length=1, cutoff=1e-25, molecule='CO2', isotope='1,2', db_use_cached=True, verbose=verbose) sf.warnings['MissingSelfBroadeningWarning'] = 'ignore' sf.warnings['NegativeEnergiesWarning'] = 'ignore' sf.warnings['HighTemperatureWarning'] = 'ignore' sf.fetch_databank( ) # uses HITRAN: not really valid at this temperature, but runs on all machines without install # sf.load_databank('HITEMP-CO2-DUNHAM') s_nq = sf.non_eq_spectrum(Tvib=Tgas, Trot=Tgas, name='Non-eq') s_eq = sf.eq_spectrum(Tgas=Tgas, name='Eq') rtol = 5e-3 # 2nd isotope calculated with placeholder energies match_eq_vs_non_eq = s_eq.compare_with(s_nq, spectra_only='abscoeff', rtol=rtol, plot=plot) match_eq_vs_non_eq *= s_eq.compare_with(s_nq, spectra_only='radiance_noslit', rtol=rtol, plot=plot) if verbose: printm('Tested eq vs non-eq (<{0:.1f}% error) with isotopes: {1}'. format(rtol * 100, bool(match_eq_vs_non_eq))) assert match_eq_vs_non_eq except DatabankNotFound as err: assert IgnoreMissingDatabase(err, __file__, warnings)
def test_recompute_Q_from_QvibQrot_CDSD_PC(verbose=True, warnings=True, *args, **kwargs): ''' Calculate vibrational and rotational partition functions: - in CDSD with (p,c) convention for vibrational levels - under nonequilibrium Recompute total partition function, and compare Test if partition function can be recomputed correctly from vibrational populations and rotational partition function (note that we are in a coupled case so partition function is not simply the product of Qvib, Qrot) ''' from radis.misc.config import getDatabankEntries iso = 1 try: energies = getDatabankEntries('CDSD-HITEMP-PC')['levels'] levelsfmt = getDatabankEntries('CDSD-HITEMP-PC')['levelsfmt'] Tvib = 1500 Trot = 300 Qf = PartFuncCO2_CDSDcalc(energies[iso], isotope=iso, use_cached=True, levelsfmt=levelsfmt) Q = Qf.at_noneq(Tvib, Trot) _, Qvib, dfQrot = Qf.at_noneq(Tvib, Trot, returnQvibQrot=True) if verbose: printm('Q', Q) if verbose: printm('Qvib', Qvib) # 1) Test Q vs Q recomputed from Qrot, Qvib # Recompute Qtot df = dfQrot Q2 = ((df.gvib * exp(-df.Evib * hc_k / Tvib)) * df.Qrot).sum() # Todo: non Boltzmann case assert np.isclose(Q, Q2) if verbose: printm('Tested Q vs recomputed from (Qvib, Qrot) are the same: OK') return True except DatabankNotFound as err: assert IgnoreMissingDatabase(err, __file__, warnings)
def test_medium(plot=False, verbose=True, debug=False, warnings=True, *args, **kwargs): """ Test effect of propagating medium """ from radis.lbl.factory import SpectrumFactory if plot: # Make sure matplotlib is interactive so that test are not stuck plt.ion() T = 300 try: setup_test_line_databases( ) # add HITRAN-CO-TEST in ~/.radis if not there pl = SpectrumFactory( wavenum_min=2171.5, wavenum_max=2174, mole_fraction=0.01, medium="vacuum", isotope="1,2", ) pl.warnings["MissingSelfBroadeningWarning"] = "ignore" pl.load_databank("HITRAN-CO-TEST") s = pl.non_eq_spectrum(Tvib=T, Trot=T) # , Ttrans=300) pla = SpectrumFactory( wavenum_min=2171.5, wavenum_max=2174, mole_fraction=0.01, medium="air", isotope="1,2", ) pla.load_databank("HITRAN-CO-TEST") s_air = pla.non_eq_spectrum(Tvib=T, Trot=T) # , Ttrans=300) if plot: plt.figure(fig_prefix + "Propagating medium conversions") s.plot(wunit="nm_vac", nfig="same", lw=3, label="vacuum") s.plot(wunit="nm", nfig="same", label="air") assert np.allclose(s.get_wavenumber(), s_air.get_wavenumber()) assert np.allclose(s.get_wavelength(medium="vacuum"), s_air.get_wavelength(medium="vacuum")) assert np.allclose(s.get_wavelength(medium="air"), s_air.get_wavelength(medium="air")) assert all( s.get_wavelength(medium="vacuum") > s.get_wavelength(medium="air")) except DatabankNotFound as err: assert IgnoreMissingDatabase(err, __file__, warnings)
def test_rescaling_mole_fraction(debug=False, plot=False, verbose=True, warnings=True, *args, **kwargs): ''' Test rescaling functions ''' from radis.lbl import SpectrumFactory if plot: # Make sure matplotlib is interactive so that test are not stuck plt.ion() try: setup_test_line_databases() # add HITRAN-CO-TEST in ~/.radis if not there Tgas = 1500 sf = SpectrumFactory( wavelength_min=4400, wavelength_max=4800, # mole_fraction=1, path_length=0.1, mole_fraction=0.01, cutoff=1e-25, wstep=0.005, isotope=[1], db_use_cached=True, self_absorption=True, verbose=verbose) sf.warnings['MissingSelfBroadeningWarning'] = 'ignore' sf.warnings['NegativeEnergiesWarning'] = 'ignore' sf.load_databank('HITRAN-CO-TEST') error = [] N = [1e-3, 1e-2, 1e-1, 0.3, 0.6, 1] # first is ref for Ni in N: s1 = sf.non_eq_spectrum(Tgas, Tgas, mole_fraction=N[0]) sN = sf.non_eq_spectrum(Tgas, Tgas, mole_fraction=Ni) s1.rescale_mole_fraction(Ni) error.append(sN.get_power() / s1.get_power()) if plot: plt.figure(fig_prefix+'Rescaling mole fractions') plt.plot(N, error, '-ok') plt.scatter(N[0], error[0], s=200, facecolors='none', edgecolors='r', label='reference') plt.xlabel('Mole fraction') plt.ylabel('scaled energy / ab initio energy') plt.xscale('log') plt.legend() plt.title('Effect of scaling mole fraction w/o lineshape update') plt.tight_layout() # less than 1% error when rescaling from 1e-3 to 0.6 assert abs(error[-2]-1) < 0.01 except DatabankNotFound as err: assert IgnoreMissingDatabase(err, __file__, warnings)
def test_load_spectrum(plot=False, verbose=True, warnings=True, *args, **kwargs): ''' Test load / save Fast version: dont save lines / populations, compare spectra only ''' setup_test_line_databases() temp_file_name = '_test_database_co2_tempfile.spec' assert (not exists(temp_file_name)) try: sf = SpectrumFactory( wavelength_min=4190, wavelength_max=4200, mole_fraction=400e-6, path_length=0.1, # cm isotope=[1], db_use_cached=True, cutoff=1e-20, verbose=verbose) sf.warnings['MissingSelfBroadeningWarning'] = 'ignore' sf.load_databank('HITRAN-CO2-TEST') s1 = sf.eq_spectrum(Tgas=300) s1.apply_slit(2, verbose=False) s1.update() s2 = load_spec(s1.store(temp_file_name, compress=True)) s2.update() if plot: fig = plt.figure(fig_prefix + 'Calculated vs stored+retrieved') s1.plot('absorbance', nfig=fig.number, lw=3, label='calculated') s2.plot('absorbance', nfig=fig.number, color='r', label='stored (compressed) and retrieved') plt.legend() assert s1.compare_with(s2, spectra_only=True, plot=False) except DatabankNotFound as err: assert IgnoreMissingDatabase(err, __file__, warnings) finally: # cleaning if exists(temp_file_name): os.remove(temp_file_name) return True
def test_medium(plot=False, verbose=True, debug=False, warnings=True, *args, **kwargs): ''' Test effect of propagating medium ''' from radis.lbl.factory import SpectrumFactory if plot: # Make sure matplotlib is interactive so that test are not stuck plt.ion() T = 300 try: setup_test_line_databases() # add HITRAN-CO-TEST in ~/.radis if not there pl = SpectrumFactory( wavenum_min=2171.5, wavenum_max=2174, mole_fraction=0.01, medium='vacuum', isotope='1,2') pl.warnings['MissingSelfBroadeningWarning'] = 'ignore' pl.load_databank('HITRAN-CO-TEST') s = pl.non_eq_spectrum(Tvib=T, Trot=T) # , Ttrans=300) pla = SpectrumFactory( wavenum_min=2171.5, wavenum_max=2174, mole_fraction=0.01, medium='air', isotope='1,2') pla.load_databank('HITRAN-CO-TEST') s_air = pla.non_eq_spectrum(Tvib=T, Trot=T) # , Ttrans=300) if plot: plt.figure(fig_prefix+'Propagating medium conversions') s.plot(nfig='same', lw=3, medium='vacuum', label='vacuum') s.plot(nfig='same', medium='air', label='air') assert np.allclose(s.get_wavenumber(), s_air.get_wavenumber()) assert np.allclose(s.get_wavelength(medium='vacuum'), s_air.get_wavelength(medium='vacuum')) assert np.allclose(s.get_wavelength(medium='air'), s_air.get_wavelength(medium='air')) assert all(s.get_wavelength(medium='vacuum') > s.get_wavelength(medium='air')) except DatabankNotFound as err: assert IgnoreMissingDatabase(err, __file__, warnings)
def test_klarenaar_validation_case(verbose=True, plot=False, warnings=True, *args, **kwargs): ''' Reproduce the Klarenaar 2018 validation case, as given in the [RADIS-2018]_ article. References ---------- Klarenaar et al, "Time evolution of vibrational temperatures in a CO 2 glow discharge measured with infrared absorption spectroscopy", doi 10.1088/1361-6595/aa902e, and the references there in. ''' setup_test_line_databases() try: # %% Data from Dang, adapted by Klarenaar s_exp = Spectrum.from_txt(getValidationCase(join('test_CO2_3Tvib_vs_klarenaar_data', 'klarenaar_2017_digitized_data.csv')), 'transmittance_noslit', waveunit='cm-1', unit='I/I0', delimiter=',', name='Klarenaar 2017') # %% Calculate Klarenaar test case conditions sf = SpectrumFactory(2284.2, 2284.6, wstep=0.001, # cm-1 pressure=20*1e-3, # bar db_use_cached=True, cutoff=1e-25, molecule='CO2', isotope='1,2', path_length=10, # cm-1 # warning! 10% in mass fraction -> less in mole fraction mole_fraction=0.1*28.97/44.07, broadening_max_width=1, # cm-1 medium='vacuum', export_populations='vib', ) sf.warnings['MissingSelfBroadeningWarning'] = 'ignore' # sf.load_databank('HITEMP-CO2-DUNHAM') sf.load_databank('HITEMP-CO2-TEST') # Calculate with Klarenaar fitted values T12 = 517 T3 = 2641 Trot = 491 s = sf.non_eq_spectrum((T12, T12, T3), Trot, Ttrans=Trot, vib_distribution='treanor', name='RADIS') if plot: plot_diff(s, s_exp, 'transmittance_noslit') # plt.savefig('test_CO2_3Tvib_vs_klarenaar.png') assert get_residual(s, s_exp, 'transmittance_noslit', ignore_nan=True) < 0.003 return True except DatabankNotFound as err: assert IgnoreMissingDatabase(err, __file__, warnings)
def test_noneq_continuum(plot=False, verbose=2, warnings=True, *args, **kwargs): """ Test calculation with pseudo-continuum under nonequilibrium Assert results on emisscoeff dont change Notes ----- Uses HITRAN so it can deployed and tested on [Travis]_, but we should switch to HITEMP if some HITEMP files can be downloaded automatically at the execution time. """ if plot: # Make sure matplotlib is interactive so that test are not stuck in pytest plt.ion() try: if verbose: printm(">>> test_noneq_continuum") sf = SpectrumFactory( wavelength_min=4200, wavelength_max=4500, parallel=False, bplot=False, cutoff=1e-23, molecule="CO2", isotope="1,2", db_use_cached=True, broadening_max_width=10, path_length=0.1, mole_fraction=1e-3, medium="vacuum", verbose=verbose, ) sf.warnings.update({ "MissingSelfBroadeningWarning": "ignore", "NegativeEnergiesWarning": "ignore", "LinestrengthCutoffWarning": "ignore", "HighTemperatureWarning": "ignore", }) sf.fetch_databank( ) # uses HITRAN: not really valid at this temperature, but runs on all machines without install # sf.load_databank('HITEMP-CO2-DUNHAM') # to take a real advantage of abscoeff continuum, should calculate with HITEMP sf._export_continuum = True # activate it # Calculate one without pseudo-continuum sf.params.pseudo_continuum_threshold = 0 s1 = sf.non_eq_spectrum(Tvib=2000, Trot=1000) s1.name = "All lines resolved ({0}) ({1:.1f}s)".format( s1.conditions["lines_calculated"], s1.conditions["calculation_time"]) assert s1.conditions["pseudo_continuum_threshold"] == 0 # Calculate one with pseudo-continuum sf.params.pseudo_continuum_threshold = 0.05 s2 = sf.non_eq_spectrum(Tvib=2000, Trot=1000) s2.name = "Semi-continuum + {0} lines ({1:.1f}s)".format( s2.conditions["lines_calculated"], s2.conditions["calculation_time"]) assert s2.conditions["pseudo_continuum_threshold"] == 0.05 assert "abscoeff_continuum" in s2.get_vars() assert "emisscoeff_continuum" in s2.get_vars() # Plot if plot: plot_diff( s1, s2, "radiance_noslit", Iunit="µW/cm2/sr/nm", nfig="test_noneq_continuum: diff", ) plt.figure("test_noneq_continuum: show continuum").clear() s2.plot("emisscoeff", label=s2.name, nfig="test_noneq_continuum: show continuum") s2.plot( "emisscoeff_continuum", nfig="same", label="Pseudo-continuum (aggreg. {0:g} lines)".format( s2.conditions["lines_in_continuum"]), force=True, ) # Compare res = get_residual(s1, s2, "abscoeff") + get_residual( s1, s2, "emisscoeff") if verbose: printm("residual:", res) assert res < 5.2e-6 except DatabankNotFound as err: assert IgnoreMissingDatabase(err, __file__, warnings)
def test_retrieve_from_database(plot=True, verbose=True, warnings=True, *args, **kwargs): """ Test autoretrieve from a database: first generate an empty :py:class:`~radis.tools.database.SpecDatabase` associated to a :py:class`~radis.lbl.factory.SpectrumFactory`, then calculate a first spectrum, then calculate it again and make sure it is retrieved from the database """ if plot: # Make sure matplotlib is interactive so that test are not stuck in pytest plt.ion() temp_database_name = "temp_spec_database" try: if verbose: printm(">>> test_retrieve_from_database") assert not exists(temp_database_name) setup_test_line_databases( ) # add HITEMP-CO2-TEST in ~/.radis if not there sf = SpectrumFactory( 2284.2, 2284.6, wstep=0.001, # cm-1 pressure=20 * 1e-3, # bar cutoff=0, path_length=0.1, mole_fraction=400e-6, molecule="CO2", isotope=[1], db_use_cached=True, medium="vacuum", broadening_max_width=10, export_populations="rovib", verbose=verbose, ) sf.warnings["MissingSelfBroadeningWarning"] = "ignore" sf.init_databank( "HITEMP-CO2-TEST" ) # unlike load_databank, will automatically be built when needed db = sf.init_database(temp_database_name, autoretrieve=True) assert len(db) == 0 # Calculate a first spectrum s1 = sf.non_eq_spectrum(2000, 1000) assert len(db) == 1 # Note that the Spectrum in database is not s1 because populations # are not stored by default # hack: now change the `autoretrieve` status to `force` to make sure # the spectrum is retrieved. Else, an error will be raised sf.autoretrievedatabase = "force" # Calculate spectrum under the same conditions s2 = sf.non_eq_spectrum(2000, 1000) # Note that s1 == s2 won't work because populations are not stored # by default in the database assert s1.compare_with(s2, spectra_only=True) return True except DatabankNotFound as err: assert IgnoreMissingDatabase(err, __file__, warnings) finally: rmtree(temp_database_name)
def test_all_calc_methods( verbose=True, plot=False, warnings=True, rtol=1e-3, *args, **kwargs ): """ Test same spectrum for 3 different calculation variants (equilibrium, non-equilibrium, per band and recombine """ if plot: # Make sure matplotlib is interactive so that test are not stuck in pytest import matplotlib.pyplot as plt plt.ion() try: Tgas = 1500 iso = 1 sf = SpectrumFactory( wavelength_min=4170, wavelength_max=4175, mole_fraction=1, path_length=0.025, cutoff=1e-25, molecule="CO2", isotope=iso, db_use_cached=True, lvl_use_cached=True, verbose=verbose, ) sf.warnings["MissingSelfBroadeningWarning"] = "ignore" sf.warnings["NegativeEnergiesWarning"] = "ignore" sf.warnings["HighTemperatureWarning"] = "ignore" # sf.fetch_databank() # uses HITRAN: not really valid at this temperature, but runs on all machines without install sf.load_databank("CDSD-HITEMP-PC") s_bands = sf.non_eq_bands(Tvib=Tgas, Trot=Tgas) lvl = LevelsList(sf.parsum_calc["CO2"][iso]["X"], s_bands, sf.params.levelsfmt) s_bd = lvl.non_eq_spectrum(Tvib=Tgas, Trot=Tgas) s_nq = sf.non_eq_spectrum(Tvib=Tgas, Trot=Tgas) s_eq = sf.eq_spectrum(Tgas=Tgas) # if plot: fig = plt.figure(fig_prefix + "Compare all calc methods") s_bd.plot(nfig=fig.number, color="b", lw=5, label="from bands code") s_nq.plot(nfig=fig.number, lw=3, label="non eq code") s_eq.plot(nfig=fig.number, lw=2, color="r", label="equilibrum code") plt.legend() assert np.isclose(s_bd.get_power(), s_nq.get_power(), rtol=rtol) assert np.isclose(s_bd.get_power(), s_eq.get_power(), rtol=rtol) if verbose: printm( "Eq == non-eq:\t", np.isclose(s_eq.get_power(), s_nq.get_power(), rtol=rtol), ) printm( "Bands == Non-eq:\t", np.isclose(s_bd.get_power(), s_nq.get_power(), rtol=rtol), ) if verbose: printm("Test all methods comparison: OK") return True except DatabankNotFound as err: assert IgnoreMissingDatabase(err, __file__, warnings)
def test_calc_spectrum(verbose=True, plot=True, warnings=True, *args, **kwargs): """ Basic example, used as a non-regression test Notes ----- How long it tooks to calculate this Spectrum? Performance test on old NeQ package, with the [CDSD-HITEMP-JMIN] databank. See the caveats in the E. Pannier "Limits of CO2 NonEquilibrium Models" paper. (just used here as a performance monitoring) - neq 0.9.20: 18.7s - neq 0.9.20*: 15.4s (removed 2nd loop on 1st isotope because of groupby().apply()) - neq 0.9.20**: 11.7s (after replacing fill_Evib with map() ) - neq 0.9.21: 9.4s (improve Qrot / nrot fetching performance) - neq 0.9.22: 8.4s Starting from RADIS 1.0.1, the test is run on [HITRAN-2016]_, which is not valid for these temperatures but can be more conveniently downloaded automatically and thus executed everytime with [Travis]_ (we also expect the test to be much faster than above, but that's just because the database is smaller!) - radis 0.9.20 : 2.49 s on [HITRAN-2016] 4.05 s on [CDSD-HITEMP-JMIN] """ if verbose: printm("Testing calc_spectrum match reference") if plot: # Make sure matplotlib is interactive so that test are not stuck in pytest import matplotlib.pyplot as plt plt.ion() try: s = calc_spectrum( wavelength_min=4165, wavelength_max=4200, # databank='CDSD-HITEMP-JMIN', 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", verbose=verbose, warnings={ "MissingSelfBroadeningWarning": "ignore", "NegativeEnergiesWarning": "ignore", "HighTemperatureWarning": "ignore", }, ) s.apply_slit((2, 2.5), "nm", shape="trapezoidal") if plot: s.plot(wunit="nm") w, I = s.get("radiance", wunit="nm") w_ref = w[::100] # Compare against hardcoded results (neq 0.9.22, 28/06/18) # I_ref = np.array([0.28694463, 0.29141711, 0.32461613, 0.32909566, 0.21939511, 0.18606445, # 0.19740763, 0.16948599, 0.16780345, 0.15572173, 0.16770853, 0.14966064, # 0.13041356, 0.11751016, 0.10818072, 0.11592531, 0.04666677, 0.00177108, # 0.00069339]) # Harcoded results changed for RADIS with the change of # database (HITEMP-2010 -> HITRAN-2016) and of Tvib model # CDSD with (P,C,Jmin,N) in CDSD polyad -> RADIS built-in constants) # I_ref = np.array([ 0.29148768, 0.29646856, 0.32999337, 0.32249701, 0.2078451 , # 0.18974631, 0.2019285 , 0.17346687, 0.17211401, 0.15939359, # 0.17240575, 0.15395179, 0.13374185, 0.11997065, 0.10858693, # 0.11114162, 0.04575873, 0.00163863, 0.00062654]) # Updated again in RADIS 0.9.20 (19/08/19) to account for the use of DLM (difference # not significant) # I_ref = np.array([ 0.29060991, 0.29756722, 0.32972058, 0.3206278 , 0.20696867, # 0.19218358, 0.20155747, 0.17336405, 0.17218653, 0.1589136 , # 0.17110649, 0.15403513, 0.13376804, 0.11932659, 0.10882006, # 0.11112725, 0.0458288 , 0.00247956, 0.00144128]) # Updated again in RADIS 0.9.20 (02/09/19) with switch to tabulated Q(Tref) I_ref = np.array( [ 0.29048064, 0.29743104, 0.32955513, 0.32047172, 0.20688813, 0.19210952, 0.20148265, 0.17330909, 0.17213373, 0.15887159, 0.17106096, 0.15400039, 0.13374285, 0.11930822, 0.10880631, 0.11111394, 0.04582291, 0.00247955, 0.00144128, ] ) if plot: plt.plot(w_ref, I_ref, "or", label="ref") plt.legend() assert np.allclose(I[::100], I_ref, atol=1e-6) return True except DatabankNotFound as err: assert IgnoreMissingDatabase(err, __file__, warnings)
def DISCARDED_test_parallel_internal(plot=False, verbose=True, warnings=True, *args, **kwargs): ''' Core of the parallel test routine Test than parallel is at least faster than sequential mode. Note that this is not necessary: parallelization becomes much faster during the convolution steps, hence for large number of lines ''' # TODO: there is a line missing in the parallel case at 2283nm. # I expect the merging of different wave ranges to fail. # Test is not run for the moment if plot: # Make sure matplotlib is interactive so that test are not stuck in pytest import matplotlib.pyplot as plt plt.ion() setup_test_line_databases() try: # Performance test Tvib = 1000 # , 1200, 1400] Trot = 900 path_length = 0.1 mole_fraction = 0.5 cutoff = 0 broadening_max_width = 1 wstep = 0.0001 # .. parallel sfp = SpectrumFactory( wavelength_min=4377.134, wavelength_max=4377.9, pressure=0.020, # bar cutoff=cutoff, db_use_cached=True, lvl_use_cached=True, parallel=True, isotope='1', broadening_max_width=broadening_max_width, wstep=wstep, verbose=verbose) sfp.warnings['MissingSelfBroadeningWarning'] = 'ignore' sfp.warnings['NegativeEnergiesWarning'] = 'ignore' sfp.warnings['EmptyDatabaseWarning'] = 'ignore' sfp.load_databank('HITEMP-CO2-TEST') s_parallel = sfp.non_eq_spectrum(Tvib, Trot, path_length=path_length, mole_fraction=mole_fraction) s_parallel.name = 'Parallel ({0:.1f}s)'.format( s_parallel.conditions['calculation_time']) # ... non parallel sf = SpectrumFactory( wavelength_min=4377.134, wavelength_max=4377.9, pressure=0.020, # bar cutoff=cutoff, db_use_cached=True, lvl_use_cached=True, isotope='1,2', broadening_max_width=broadening_max_width, wstep=wstep, verbose=verbose) sf.warnings['MissingSelfBroadeningWarning'] = 'ignore' sf.warnings['NegativeEnergiesWarning'] = 'ignore' sf.warnings['EmptyDatabaseWarning'] = 'ignore' sf.load_databank('HITEMP-CO2-TEST') s_sequential = sf.non_eq_spectrum(Tvib, Trot, path_length=path_length, mole_fraction=mole_fraction) s_sequential.name = 'Sequential ({0:.1f}s)'.format( s_sequential.conditions['calculation_time']) t0 = s_parallel.conditions['calculation_time'] t1 = s_sequential.conditions['calculation_time'] if verbose: printm('\nSpectrumFactory with internal parallel test') printm('-------------------') printm(('Parallel version: {0:.1f}s'.format(t0))) printm(('Normal version: {0:.1f}s'.format(t1))) printm('-------------------') # Assert that spectra are the same assert s_parallel.compare_with(s_sequential, spectra_only=True, plot=False) if verbose: printm('Ensured that spectra are the same: OK') if t0 > t1: warn( 'Parallel version ({0:.1f}s) is slower than the Serial version ({1:.1f}s) !' .format(t0, t1)) return True # no plot implemented except DatabankNotFound as err: assert IgnoreMissingDatabase(err, __file__, warnings)
def test_direct_overpopulation_vs_recombined_bands(verbose=True, plot=False, warnings=True, rtol=0.05, *args, **kwargs): """ Compare a non-equilibrium spectrum calculated directly with overpopulations, or by recombining pre-calculated vibrational bands. The later allows for almost instantaneous changes of the overpopulation factors, (mostly useful in fitting algorithms), but is only valid for optically thin emission spectra Expected output: when x_CO2 = 1e-3, radiance in both cases match when x_CO2 = 1, they dont """ # Notes # ----- # # On the old NeQ package the test used [HITEMP-2010]_ # # Starting from RADIS 1.0.1, the test is run on [HITRAN-2016]_, which # is not valid for these temperatures but can be more conveniently # downloaded automatically and thus executed everytime with [Travis]_ # # Note: only with iso1 at the moment if plot: # Make sure matplotlib is interactive so that test are not stuck in pytest plt.ion() try: # Generate factory iso = 1 sf = SpectrumFactory( wavelength_min=4220, wavelength_max=4280, mole_fraction=1e-3, path_length=10, cutoff=1e-25, molecule="CO2", isotope=iso, db_use_cached=True, wstep=0.01, broadening_max_width=5, medium="air", verbose=verbose, ) sf.warnings["MissingSelfBroadeningWarning"] = "ignore" sf.warnings["NegativeEnergiesWarning"] = "ignore" sf.load_databank("CDSD-HITEMP-PCN") # sf.fetch_databank() # uses HITRAN: not really valid at this temperature, but runs on all machines without install # Generate bands to recombine parfunc = sf.parsum_calc["CO2"][iso]["X"] Tref = 1500 # , return_lines=False) s_bands = sf.non_eq_bands(Tvib=Tref, Trot=Tref) lvlist = LevelsList(parfunc, s_bands, sf.params.levelsfmt) # Compare ab initio and recombined from bands at M = 1e-3 s_recombined = lvlist.non_eq_spectrum(Tvib=Tref, Trot=Tref, overpopulation={"(4,1,3)": 3}) sref = sf.non_eq_spectrum(Tvib=Tref, Trot=Tref, overpopulation={"(4,1,3)": 1}) if verbose: printm( "Testing x_CO2 = 1e-3: ab initio ~ recombined bands (<{0:.1f}%):\t" .format(rtol * 100)) if plot: plot_diff( sref, s_recombined, var="radiance_noslit", label1="ab initio", label2="recombined bands", title="x_CO2 = 1e-3", ) assert np.allclose(s_recombined.get_radiance_noslit(), sref.get_radiance_noslit(), rtol=rtol) # Rescale and try again for x_CO2 = 1 s_recombined.rescale_mole_fraction(1) sref.rescale_mole_fraction(1) if plot: plot_diff( sref, s_recombined, var="radiance_noslit", label1="ab initio", label2="recombined bands", title="x_CO2 = 1", ) if verbose: printm( "Testing x_CO2 = 1: ab initio ~ recombined bands (<{0:.1f}%):\t{1}" .format( rtol * 100, np.allclose( s_recombined.get_radiance_noslit(), sref.get_radiance_noslit(), rtol=rtol, ), )) with pytest.raises(AssertionError): assert np.allclose( s_recombined.get_radiance_noslit(), sref.get_radiance_noslit(), rtol=rtol, ) return True except DatabankNotFound as err: assert IgnoreMissingDatabase(err, __file__, warnings)
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 ''' if plot: # Make sure matplotlib is interactive so that test are not stuck in pytest plt.ion() try: 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, # 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:.1f}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: # ... >>> np.savetxt('output.txt', np.vstack(s.get('abscoeff', wunit='nm', medium='air')).T[::10]) # ... and header contains all input conditions: # ... >>> 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', medium='air')[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', medium='air')[1][::10] / Iref - 1)) * 100)) # Store the faulty spectrum s.store('test_factory_failed_{0}.spec'.format(neq.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 except DatabankNotFound as err: assert IgnoreMissingDatabase(err, __file__, warnings)
def test_populations(plot=True, verbose=True, warnings=True, *args, **kwargs): """ See wavelength difference in air and vacuum """ if plot: # Make sure matplotlib is interactive so that test are not stuck in pytest plt.ion() try: if verbose: printm(">>> _test_media_line_shift") setup_test_line_databases( ) # add HITRAN-CO-TEST in ~/.radis if not there sf = SpectrumFactory( wavelength_min=4500, wavelength_max=4600, wstep=0.001, parallel=False, bplot=False, cutoff=1e-30, path_length=0.1, mole_fraction=400e-6, isotope=[1], db_use_cached=True, medium="vacuum", broadening_max_width=10, export_populations="rovib", verbose=verbose, ) sf.warnings["MissingSelfBroadeningWarning"] = "ignore" sf.load_databank("HITRAN-CO-TEST") # Populations cannot be calculated at equilibrium (no access to energy levels) s = sf.eq_spectrum(300) with pytest.raises(ValueError): # .. we expect this error here! pops = s.get_populations("CO", isotope=1, electronic_state="X") # Calculate populations using the non-equilibrium module: s = sf.non_eq_spectrum(300, 300) pops = s.get_populations("CO", isotope=1, electronic_state="X") if not "n" in list(pops["rovib"].keys()): raise ValueError("Populations not calculated") if plot: s.plot_populations() # Compare with factory # Plot populations: with pytest.raises(ValueError): sf.plot_populations() # no isotope given: error expected if plot: sf.plot_populations("rovib", isotope=1) plt.close() # no need to keep it open, we just tested the function # Test calculated quantities are there assert hasattr(sf.df1, "Qref") assert hasattr(sf.df1, "Qvib") assert hasattr(sf.df1, "Qrotu") assert hasattr(sf.df1, "Qrotl") # Test hardcoded populations assert np.isclose(pops["rovib"]["n"].iloc[0], 0.0091853446840826653) assert np.isclose(pops["rovib"]["n"].iloc[1], 0.027052543988733215) assert np.isclose(pops["rovib"]["n"].iloc[2], 0.04345502115897712) return True except DatabankNotFound as err: assert IgnoreMissingDatabase(err, __file__, warnings)
def test_parallel(plot=False, verbose=True, warnings=True, *args, **kwargs): ''' Core of the parallel test routine Test than parallel is at least faster than sequential mode. Note that this is not necessary: parallelization becomes much faster during the convolution steps, hence for large number of lines ''' if plot: # Make sure matplotlib is interactive so that test are not stuck in pytest import matplotlib.pyplot as plt plt.ion() setup_test_line_databases() try: # Performance test Tvib = 1000 # , 1200, 1400] Trot = [900, 1200, 1250, 1300, 1400, 1600] path_length = 0.1 mole_fraction = 0.5 cutoff = 0 broadening_max_width = 50 wstep = 0.01 # .. parallel pf = ParallelFactory(wavelength_min=4165, wavelength_max=4200, cutoff=cutoff, db_use_cached=True, lvl_use_cached=True, isotope='1', broadening_max_width=broadening_max_width, wstep=wstep, verbose=verbose) pf.warnings['MissingSelfBroadeningWarning'] = 'ignore' pf.warnings['NegativeEnergiesWarning'] = 'ignore' pf.warnings['EmptyDatabaseWarning'] = 'ignore' pf.load_databank('HITRAN-CO2-TEST') t0 = time() s_parallel = pf.non_eq_spectrum(Tvib, Trot, path_length=path_length, mole_fraction=mole_fraction) t0 = time() - t0 # ... non parallel sf = SpectrumFactory(wavelength_min=4165, wavelength_max=4200, cutoff=cutoff, db_use_cached=True, lvl_use_cached=True, isotope='1,2', broadening_max_width=broadening_max_width, wstep=wstep, verbose=verbose) sf.warnings['MissingSelfBroadeningWarning'] = 'ignore' sf.warnings['NegativeEnergiesWarning'] = 'ignore' sf.warnings['EmptyDatabaseWarning'] = 'ignore' sf.load_databank('HITRAN-CO2-TEST') t1 = time() s_sequential = [] for Troti in Trot: s_sequential.append( sf.non_eq_spectrum(Tvib, Troti, path_length=path_length, mole_fraction=mole_fraction)) t1 = time() - t1 if verbose: printm(('\nParallelFactory performance test ({0} cases)'.format( len(Trot)))) printm('-------------------') printm(('Parallel version: {0:.1f}s'.format(t0))) printm(('Normal version: {0:.1f}s'.format(t1))) printm('-------------------') # Assert that spectra are the same for i in range(len(Trot)): assert s_parallel[i].compare_with(s_sequential[i], spectra_only=True, plot=False) if verbose: printm('Ensured that spectra are the same: OK') # # parallel version should be at least faster! # # note: ... may not be the case if the calculated ranges are too small # # ......... as is the case in the test database. Better use // for spectra # # ......... with calculation times > 5s # assert t0 > t1 if t0 > t1: warn( 'Parallel version ({0:.1f}s) is slower than the Serial version ({1:.1f}s) !' .format(t0, t1)) return True # no plot implemented except DatabankNotFound as err: assert IgnoreMissingDatabase(err, __file__, warnings)
def test_power_integral(verbose=True, warnings=True, *args, **kwargs): ''' Test direct calculation of power integral from Einstein coefficients matches integration of broadened spectrum in the optically thin case We compare: - direct calculation of power integral with equilibrium code :meth:`~radis.lbl.SpectrumFactory.optically_thin_power` (T) - direct calculation of power integral with non equilibrium code :meth:`~radis.lbl.SpectrumFactory.optically_thin_power` (T,T) - numerical integration of non equilibrium spectrum under optically thin conditions: :meth:`~radis.spectrum.spectrum.Spectrum.get_power` Test passes if error < 0.5% ''' try: if verbose: printm('>>> _test_power_integral') setup_test_line_databases( ) # add HITRAN-CO-TEST in ~/.radis if not there sf = SpectrumFactory(wavelength_min=4300, wavelength_max=4666, wstep=0.001, parallel=False, bplot=False, cutoff=1e-30, path_length=10, mole_fraction=400e-6, isotope=[1], db_use_cached=True, broadening_max_width=10, verbose=verbose) sf.warnings.update({ 'MissingSelfBroadeningWarning': 'ignore', 'OutOfRangeLinesWarning': 'ignore', 'HighTemperatureWarning': 'ignore', }) sf.load_databank('HITRAN-CO-TEST') unit = 'µW/sr/cm2' T = 600 # Calculate: # ... direct calculation of power integral with equilibrium code Peq = sf.optically_thin_power(Tgas=T, unit=unit) # ... direct calculation of power integral with non equilibrium code Pneq = sf.optically_thin_power(Tvib=T, Trot=T, unit=unit) # ... numerical integration of non equilibrium spectrum under optically thin # ... conditions sf.input.self_absorption = False s = sf.non_eq_spectrum(T, T) assert s.conditions['self_absorption'] == False # Compare err = abs(Peq - s.get_power(unit=unit)) / Peq if verbose: printm('Emission integral:\t{0:.4g}'.format(Peq), unit) printm('Emission (noneq code):\t{0:.4g}'.format(Pneq), unit) printm( 'Integrated spectrum:\t{0:.4g}'.format(s.get_power(unit=unit)), unit) printm('Error: {0:.2f}%'.format(err * 100)) assert err < 0.005 except DatabankNotFound as err: assert IgnoreMissingDatabase(err, __file__, warnings)
def test_resampling(rtol=1e-2, verbose=True, plot=True, warnings=True, *args, **kwargs): """ Test what happens when a spectrum in nm or cm-1, is convolved with a slit function in nm. In particular, slit function is generated in the spectrum unit, and spectrum is resampled if not evenly spaced""" if verbose: printm("Test auto resampling") if plot: # Make sure matplotlib is interactive so that test are not stuck in pytest plt.ion() try: setup_test_line_databases( ) # add HITRAN-CO-TEST in ~/.radis if not there plCO = SpectrumFactory( wavenum_min=2230, wavenum_max=2260, mole_fraction=0.02, path_length=100, # cm broadening_max_width=20, # cm^-1 wstep=0.02, isotope=[1, 2, 3], verbose=verbose, ) plCO.warnings["MissingSelfBroadeningWarning"] = "ignore" plCO.load_databank("HITRAN-CO-TEST") sCO = plCO.eq_spectrum(Tgas=300) w_nm, T_nm = sCO.get("transmittance_noslit", wunit="nm") w_nm, I_nm = sCO.get("radiance_noslit", wunit="nm", Iunit="mW/cm2/sr/nm") sCO_nm = transmittance_spectrum( w_nm, T_nm, wunit="nm") # a new spectrum stored in nm # sCO_nm = theoretical_spectrum(w_nm, I_nm, wunit='nm', Iunit='mW/cm2/sr/nm') # a new spectrum stored in nm if plot: fig = plt.figure(fig_prefix + "auto-resampling") sCO.plot( "transmittance_noslit", wunit="cm-1", nfig=fig.number, marker="o", color="k", lw=3, ms=10, label="(stored in cm-1)", ) plt.title("No slit function") sCO_nm.plot( "transmittance_noslit", wunit="cm-1", nfig=fig.number, marker="o", color="r", label="(stored in nm)", ) # plt.xlim((2246.58, 2247.52)) # plt.ylim((0.87, 1.01)) plt.legend() slit_function = 0.8 slit_unit = "cm-1" sCO.apply_slit(slit_function, unit=slit_unit) sCO_nm.apply_slit(slit_function, unit=slit_unit) if plot: fig = plt.figure(fig_prefix + "auto-resampling (after convolution)") sCO.plot( "transmittance", wunit="cm-1", nfig=fig.number, marker="o", color="k", lw=3, ms=10, label="(stored in cm-1)", ) plt.title("Slit function: {0} {1}".format(slit_function, slit_unit)) sCO_nm.plot( "transmittance", wunit="cm-1", nfig=fig.number, marker="o", color="r", label="(stored in nm)", ) # plt.xlim((2246.58, 2247.52)) # plt.ylim((0.87, 1.01)) plt.legend() w_conv, T_conv = sCO.get("transmittance", wunit="cm-1") w_nm_conv, T_nm_conv = sCO_nm.get("transmittance", wunit="cm-1") error = abs( (trapz(1 - T_conv, w_conv) - trapz(1 - T_nm_conv, w_nm_conv)) / trapz(1 - T_nm_conv, w_nm_conv)) if verbose: printm("\n>>> _test_resampling\n") if verbose: printm("Error between 2 spectra ({0:.2f}%) < {1:.2f}%: {2}".format( error * 100, rtol * 100, bool(error < rtol))) assert bool(error < rtol) except DatabankNotFound as err: assert IgnoreMissingDatabase(err, __file__, warnings)
def test_3Tvib_vs_1Tvib(verbose=True, plot=False, warnings=True, *args, **kwargs): if plot: # Make sure matplotlib is interactive so that test are not stuck in pytest plt.ion() setup_test_line_databases() try: T = 1500 iso = [1] sf = SpectrumFactory( wavenum_min=2380, wavenum_max=2400, pressure=20 * 1e-3, db_use_cached=True, cutoff=1e-25, isotope=iso, # ,2', path_length=10, mole_fraction=0.1, broadening_max_width=1, medium="vacuum", verbose=verbose, ) sf.warnings.update({ "MissingSelfBroadeningWarning": "ignore", "VoigtBroadeningWarning": "ignore", }) sf.load_databank("HITRAN-CO2-TEST") # Compare energies for I in iso: energies = sf.get_energy_levels("CO2", I, "X") assert (energies.Evib == energies.Evib1 + energies.Evib2 + energies.Evib3).all() if verbose: printm("Tested Evib == Evib1+Evib2+Evib3: OK") s3 = sf.non_eq_spectrum((T, T, T), T) s1 = sf.non_eq_spectrum(T, T) s3.name = "Tvib=({0},{0},{0}) K, Trot={0} K".format(T) s1.name = "Tvib={0} K, Trot={0} K".format(T) if plot: s1.plot( "transmittance_noslit", wunit="cm-1", color="k", lw=3, label="Tvib = {0}K".format(T), ) s3.plot( "transmittance_noslit", wunit="cm-1", color="r", lw=3, nfig="same", label="Tvib1 = Tvib2 = Tvib3 = {0}K".format(T), ) assert s1.compare_with(s3, spectra_only=True, verbose=verbose, plot=plot) if verbose: printm( "Tested Spectra 3Tvib(T1=T2=T3=T) and 1Tvib(T) are the same: OK" ) return True except DatabankNotFound as err: assert IgnoreMissingDatabase(err, __file__, warnings)
def test_calc_spectrum_overpopulations(verbose=True, plot=False, warnings=True, *args, **kwargs): ''' Non-regression test: Example using overpopulation of the 001 asymmetric stretch first level of CO2, which is written (p,c,N) = (3,1,4) in [CDSD-4000]_ notation Notes ----- In old Neq package (before RADIS): the test uses a CDSD-PCN notation for vibrational energy assignation, i.e, Evib = minimal energy of a (p,c,N) polyad. See the discussion on the implications in the E. Pannier "Limits of CO2 NonEquilibrium models" paper. Better use the assignation scheme suggested in the paper. But it's okay here as a non-regression test. Starting from RADIS 1.0.1, the test is run on [HITRAN-2016]_, which is not valid for these temperatures but can be more conveniently downloaded automatically and thus executed everytime with [Travis]_ ''' if plot: # Make sure matplotlib is interactive so that test are not stuck in pytest import matplotlib.pyplot as plt plt.ion() try: s = calc_spectrum( wavelength_min=4165, wavelength_max=4200, # databank='CDSD-HITEMP-PCN', databank= 'fetch', # not appropriate for these temperatures, but convenient for automatic testings Tgas=300, Tvib=1700, Trot=1550, # overpopulation={'(3,1,4)': 3}, # 00'0'1 in spectroscopic notation overpopulation={'(0,0,0,1)': 3}, # 00'0'1 in spectroscopic notation path_length=0.1, mole_fraction=0.5, molecule='CO2', isotope='1,2', wstep=0.01, cutoff=1e-25, use_cached=True, medium='vacuum', verbose=verbose, warnings={ 'MissingSelfBroadeningWarning': 'ignore', 'NegativeEnergiesWarning': 'ignore', 'HighTemperatureWarning': 'ignore' }) s.apply_slit((2, 2.5), 'nm', shape='trapezoidal') if plot: s.plot() w, I = s.get('radiance', wunit='nm') w_ref = w[::100] # Compare against hardcoded results (neq 0.9.22, 28/06/18) I_ref = np.array([ 0.61826008, 0.65598262, 0.79760003, 0.7958013, 0.5792486, 0.56727691, 0.60361258, 0.51549598, 0.51012651, 0.47133131, 0.50770568, 0.45093953, 0.39129824, 0.35125324, 0.32238316, 0.34542781, 0.13908073, 0.00506012, 0.00189535 ]) # Harcoded results changed for RADIS v1.0.1 with the change of # database (HITEMP-2010 -> HITRAN-2016) and of Tvib model # CDSD with (P,C,Jmin,N) in CDSD polyad -> RADIS built-in constants) I_ref = np.array([ 0.62299838, 0.66229013, 0.81037059, 0.79899315, 0.57215806, 0.57626389, 0.61424273, 0.52454807, 0.5200812, 0.47920924, 0.51843533, 0.46058817, 0.3983277, 0.35582979, 0.32095204, 0.32821575, 0.13525543, 0.00469489, 0.00174166 ]) if plot: plt.plot(w_ref, I_ref, 'or', label='ref') plt.legend() s.plot_populations() assert np.allclose(I[::100], I_ref, atol=1e-6) if verbose: printm('Test overpopulations: OK') return True except DatabankNotFound as err: assert IgnoreMissingDatabase(err, __file__, warnings)
def test_noneq_continuum(plot=False, verbose=2, warnings=True, *args, **kwargs): ''' Test calculation with pseudo-continuum under nonequilibrium Assert results on emisscoeff dont change Notes ----- Uses HITRAN so it can deployed and tested on [Travis]_, but we should switch to HITEMP if some HITEMP files can be downloaded automatically at the execution time. ''' if plot: # Make sure matplotlib is interactive so that test are not stuck in pytest plt.ion() try: if verbose: printm('>>> test_noneq_continuum') sf = SpectrumFactory(wavelength_min=4200, wavelength_max=4500, parallel=False, bplot=False, cutoff=1e-23, molecule='CO2', isotope='1,2', db_use_cached=True, broadening_max_width=10, path_length=0.1, mole_fraction=1e-3, medium='vacuum', verbose=verbose) sf.warnings.update({ 'MissingSelfBroadeningWarning': 'ignore', 'NegativeEnergiesWarning': 'ignore', 'LinestrengthCutoffWarning': 'ignore', 'HighTemperatureWarning': 'ignore' }) sf.fetch_databank( ) # uses HITRAN: not really valid at this temperature, but runs on all machines without install # sf.load_databank('HITEMP-CO2-DUNHAM') # to take a real advantage of abscoeff continuum, should calculate with HITEMP sf._export_continuum = True # activate it # Calculate one without pseudo-continuum sf.params.pseudo_continuum_threshold = 0 s1 = sf.non_eq_spectrum(Tvib=2000, Trot=1000) s1.name = 'All lines resolved ({0}) ({1:.1f}s)'.format( s1.conditions['lines_calculated'], s1.conditions['calculation_time']) assert s1.conditions['pseudo_continuum_threshold'] == 0 # Calculate one with pseudo-continuum sf.params.pseudo_continuum_threshold = 0.05 s2 = sf.non_eq_spectrum(Tvib=2000, Trot=1000) s2.name = 'Semi-continuum + {0} lines ({1:.1f}s)'.format( s2.conditions['lines_calculated'], s2.conditions['calculation_time']) assert s2.conditions['pseudo_continuum_threshold'] == 0.05 assert 'abscoeff_continuum' in s2.get_vars() assert 'emisscoeff_continuum' in s2.get_vars() # Plot if plot: plot_diff(s1, s2, 'radiance_noslit', Iunit='µW/cm2/sr/nm', nfig='test_noneq_continuum: diff') s2.plot('emisscoeff', label=s2.name, nfig='test_noneq_continuum: show continuum') s2.plot('emisscoeff_continuum', nfig='same', label='Pseudo-continuum (aggreg. {0:g} lines)'.format( s2.conditions['lines_in_continuum']), force=True) # Compare res = get_residual(s1, s2, 'abscoeff') + get_residual( s1, s2, 'emisscoeff') if verbose: printm('residual:', res) assert res < 5e-6 except DatabankNotFound as err: assert IgnoreMissingDatabase(err, __file__, warnings)
def test_calc_spectrum(verbose=True, plot=True, warnings=True, *args, **kwargs): ''' Basic example, used as a non-regression test Note: test case not physically valid as overpopulation is currently calculated with a post processing method that is only valid in optically thin cases Notes ----- How long it tooks to calculate this Spectrum? Performance test on old NeQ package, with the [CDSD-HITEMP-JMIN] databank. See the caveats in the E. Pannier "Limits of CO2 NonEquilibrium Models" paper. (just used here as a performance monitoring) - 0.9.20: 18.7s - 0.9.20*: 15.4s (removed 2nd loop on 1st isotope because of groupby().apply()) - 0.9.20**: 11.7s (after replacing fill_Evib with map() ) - 0.9.21: 9.4s (improve Qrot / nrot fetching performance) - 0.9.22: 8.4s Starting from RADIS 1.0.1, the test is run on [HITRAN-2016]_, which is not valid for these temperatures but can be more conveniently downloaded automatically and thus executed everytime with [Travis]_ (we also expect the test to be much faster than above, but that's just because the database is smaller!) ''' if verbose: printm('Testing calc_spectrum match reference') if plot: # Make sure matplotlib is interactive so that test are not stuck in pytest import matplotlib.pyplot as plt plt.ion() try: s = calc_spectrum( wavelength_min=4165, wavelength_max=4200, # databank='CDSD-HITEMP-JMIN', 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', verbose=verbose, warnings={ 'MissingSelfBroadeningWarning': 'ignore', 'NegativeEnergiesWarning': 'ignore', 'HighTemperatureWarning': 'ignore' }) s.apply_slit((2, 2.5), 'nm', shape='trapezoidal') if plot: s.plot(wunit='nm') w, I = s.get('radiance', wunit='nm') w_ref = w[::100] # Compare against hardcoded results (neq 0.9.22, 28/06/18) # I_ref = np.array([0.28694463, 0.29141711, 0.32461613, 0.32909566, 0.21939511, 0.18606445, # 0.19740763, 0.16948599, 0.16780345, 0.15572173, 0.16770853, 0.14966064, # 0.13041356, 0.11751016, 0.10818072, 0.11592531, 0.04666677, 0.00177108, # 0.00069339]) # Harcoded results changed for RADIS v1.0.1 with the change of # database (HITEMP-2010 -> HITRAN-2016) and of Tvib model # CDSD with (P,C,Jmin,N) in CDSD polyad -> RADIS built-in constants) I_ref = np.array([ 0.29148768, 0.29646856, 0.32999337, 0.32249701, 0.2078451, 0.18974631, 0.2019285, 0.17346687, 0.17211401, 0.15939359, 0.17240575, 0.15395179, 0.13374185, 0.11997065, 0.10858693, 0.11114162, 0.04575873, 0.00163863, 0.00062654 ]) if plot: plt.plot(w_ref, I_ref, 'or', label='ref') plt.legend() assert np.allclose(I[::100], I_ref, atol=1e-6) return True except DatabankNotFound as err: assert IgnoreMissingDatabase(err, __file__, warnings)
def test_calc_spectrum_overpopulations( verbose=True, plot=False, warnings=True, *args, **kwargs ): """ Non-regression test: Example using overpopulation of the 001 asymmetric stretch first level of CO2, which is written (p,c,N) = (3,1,4) in [CDSD-4000]_ notation Notes ----- In old Neq package (before RADIS): the test uses a CDSD-PCN notation for vibrational energy assignation, i.e, Evib = minimal energy of a (p,c,N) polyad. See the discussion on the implications in the E. Pannier "Limits of CO2 NonEquilibrium models" paper. Better use the assignation scheme suggested in the paper. But it's okay here as a non-regression test. Starting from RADIS 1.0.1, the test is run on [HITRAN-2016]_, which is not valid for these temperatures but can be more conveniently downloaded automatically and thus executed everytime with [Travis]_ """ if plot: # Make sure matplotlib is interactive so that test are not stuck in pytest import matplotlib.pyplot as plt plt.ion() try: s = calc_spectrum( wavelength_min=4165, wavelength_max=4200, # databank='CDSD-HITEMP-PCN', databank="fetch", # not appropriate for these temperatures, but convenient for automatic testings Tgas=300, Tvib=1700, Trot=1550, # overpopulation={'(3,1,4)': 3}, # 00'0'1 in spectroscopic notation overpopulation={"(0,0,0,1)": 3}, # 00'0'1 in spectroscopic notation path_length=0.1, mole_fraction=0.5, molecule="CO2", isotope="1,2", wstep=0.01, cutoff=1e-25, use_cached=True, medium="vacuum", verbose=verbose, warnings={ "MissingSelfBroadeningWarning": "ignore", "NegativeEnergiesWarning": "ignore", "HighTemperatureWarning": "ignore", }, ) s.apply_slit((2, 2.5), "nm", shape="trapezoidal") if plot: s.plot() w, I = s.get("radiance", wunit="nm") w_ref = w[::100] # Compare against hardcoded results (neq 0.9.22, 28/06/18) # I_ref = np.array([0.61826008, 0.65598262, 0.79760003, 0.7958013 , 0.5792486 , # 0.56727691, 0.60361258, 0.51549598, 0.51012651, 0.47133131, # 0.50770568, 0.45093953, 0.39129824, 0.35125324, 0.32238316, # 0.34542781, 0.13908073, 0.00506012, 0.00189535]) # Harcoded results changed for RADIS v1.0.1 with the change of # database (HITEMP-2010 -> HITRAN-2016) and of Tvib model # CDSD with (P,C,Jmin,N) in CDSD polyad -> RADIS built-in constants) # # I_ref = np.array([ 0.62299838, 0.66229013, 0.81037059, 0.79899315, 0.57215806, # 0.57626389, 0.61424273, 0.52454807, 0.5200812 , 0.47920924, # 0.51843533, 0.46058817, 0.3983277 , 0.35582979, 0.32095204, # 0.32821575, 0.13525543, 0.00469489, 0.00174166]) # Updated again in RADIS 0.9.20 (16/08/19) to account for the use of DLM (difference # not significant) # I_ref = np.array([ 0.62134142, 0.66722021, 0.81016539, 0.79387937, 0.56974945, # 0.58280035, 0.6120114 , 0.52319075, 0.5193041 , 0.47686282, # 0.51374777, 0.46022548, 0.3979033 , 0.3534643 , 0.32129239, # 0.32786479, 0.1351593 , 0.0068877 , 0.00387545]) # Updated again in RADIS 0.9.20 (02/09/19) with switch to tabulated Q(Tref) I_ref = np.array( [ 0.62109562, 0.66695661, 0.80983176, 0.79356445, 0.56958189, 0.58264143, 0.61185167, 0.52307454, 0.51919288, 0.47677519, 0.51365307, 0.46015383, 0.39785172, 0.35342697, 0.32126465, 0.32783797, 0.13514737, 0.00688769, 0.00387544, ] ) if plot: plt.plot(w_ref, I_ref, "or", label="ref") plt.legend() s.plot_populations() assert np.allclose(I[::100], I_ref, atol=1e-6) if verbose: printm("Test overpopulations: OK") return True except DatabankNotFound as err: assert IgnoreMissingDatabase(err, __file__, warnings)
def test_compare_torch_CO2(verbose=True, plot=False, save=False, warnings=True, use_cache=True, *args, **kwargs): """ Reproduce the plasma torch experiment of Packan 2003 in in atmospheric air Notes ----- Thresholds parameters are reduced for a faster calculation time. For instance: - broadening_max_width should be 50 rather than 20 - cutoff should be 1e-27 rather than 1e-25 - wstep should be 0.01 or even 0.008 rather than 0.1 Performance: - neq==0.9.20: Finished test_compare_torch_CO2 in 758.640324s - neq==0.9.21: Finished test_compare_torch_CO2 in 672s - neq==0.9.21*: (with ParallelFactory) Finished test_compare_torch_CO2 in 298s - neq==0.9.22: (Parallel + continuum) Finished in 65s RADIS 1.0.0 == neq 0.9.24 Reference -------- Packan et al 2003 "Measurement and Modeling of OH, NO, and CO Infrared Radiation at 3400 K", JTHT """ if plot: # Make sure matplotlib is interactive so that test are not stuck in pytest plt.ion() t0 = time() try: # %% Conditions wlmin = 4100 wlmax = 4900 wmin = nm2cm(wlmax) wmax = nm2cm(wlmin) wstep = 0.1 # Load concentration profile conds = pd.read_csv( getValidationCase( "test_compare_torch_CO2_data/test_compare_torch_CO2_conditions_JTHT2003.dat" ), comment="#", delim_whitespace=True, ) slab_width = 0.05 # cm, WARNING. Hardcoded (look up the table) # %% Calculate slabs # CO2 sf = ParallelFactory( wmin, wmax, mole_fraction=None, path_length=None, molecule="CO2", isotope="1,2", parallel=False, wstep=wstep, db_use_cached=use_cache, export_lines=False, # saves some memory export_populations=False, # saves some memory cutoff=1e-25, pseudo_continuum_threshold=0.01, Nprocs=cpu_count() - 1, # warning with memory if too many procs broadening_max_width=20, verbose=False, ) sf.warnings["MissingSelfBroadeningWarning"] = "ignore" sf.warnings["NegativeEnergiesWarning"] = "ignore" # # Init database: only if we want to save all spectra being calculated # (discarded for the moment) # if use_cache: # sf.init_database('test_compare_torch_CO2_SpectrumDatabase_HITEMP_1e25', # add_info=['Tgas']) sf.init_databank("HITEMP-CO2-DUNHAM", load_energies=False) # saves some memory # sf.init_databank('CDSD-4000') # CO sfco = ParallelFactory( wmin, wmax, mole_fraction=None, path_length=None, molecule="CO", isotope="1,2", parallel=False, wstep=wstep, db_use_cached=use_cache, export_lines=False, # saves some memory export_populations=False, # saves some memory cutoff=1e-25, Nprocs=cpu_count() - 1, broadening_max_width=20, verbose=False, ) sfco.warnings["MissingSelfBroadeningWarning"] = "ignore" # Init database: only if we want to save all spectra being calculated # (discarded for the moment) # if use_cache: # sfco.init_database( # 'test_compare_torch_CO_SpectrumDatabase_HITEMP_1e25', add_info=['Tgas']) sfco.init_databank("HITEMP-CO-DUNHAM") # Calculate all slabs # .. CO2 at equilibrium slabsco2 = sf.eq_spectrum(list(conds.T_K), mole_fraction=list(conds.CO2), path_length=slab_width) # .. CO at equilibrium, but with non_eq to calculate PartitionFunctions instead of using # ... tabulated ones (which are limited to 3000 K in HAPI) slabsco = sfco.non_eq_spectrum( list(conds.T_K), list(conds.T_K), mole_fraction=list(conds.CO), path_length=slab_width, ) # Room absorption with pytest.warns( UserWarning ): # we expect a "using ParallelFactory for single case" warning s0 = sf.eq_spectrum(Tgas=300, mole_fraction=330e-6, path_length=600)[0] # Warning: This slab includes the CO2 emission from the 300 K air # within the spectrometer. But experimentally it is substracted # by there the chopper (this is corrected below) # ... see RADIS Article for more details # Add radiance for everyone if not calculated (ex: loaded from database) for s in slabsco2 + slabsco + [s0]: s.update() # Merge CO + CO2 for each slab slabstot = [MergeSlabs(s, sco) for (s, sco) in zip(slabsco2, slabsco)] # %% Line-of-sight # Solve ETR along line of sight # -------- # two semi profile, + room absortion line_of_sight = slabstot[1:][::-1] + slabstot + [s0] stot = SerialSlabs(*line_of_sight) # stot = SerialSlabs(*slabstot[1:][::-1], *slabstot, s0) # Python 3 syntax only # Also calculate the contribution of pure CO # --------- s0tr = s0.copy() # transmittance only s0tr.conditions["thermal_equilibrium"] = False s0tr._q["radiance_noslit"] *= 0 # hack to remove CO2 emission s0tr._q["emisscoeff"] *= 0 # hack to remove CO2 emission line_of_sight = slabsco[1:][::-1] + slabsco + [s0tr] sco = SerialSlabs(*line_of_sight) # sco = SerialSlabs(*slabsco[1:][::-1], *slabsco, s0tr) # Python 3 syntax only # Generate Slit # ------ disp = 4 # dispersion conversion function (nm/mm) s_in = 1 # entrance slit (mm) s_out = 2.8 # exit slit (mm) top = (s_out - s_in) * disp base = (s_out + s_in) * disp slit_function = (top, base) # (nm) # Final plot unit unit = "µW/cm2/sr" norm_by = "max" # should be 'max' if unit ~ 'µW/cm2/sr', # 'area' if unit ~ 'µW/cm2/sr/nm' # Convolve with Slit # ------- sco.apply_slit(slit_function, unit="nm", norm_by=norm_by, shape="trapezoidal") stot.apply_slit(slit_function, unit="nm", norm_by=norm_by, shape="trapezoidal") # Remove emission from within the spectrometer (substracted # by the chopper experimentaly) # ------- s0spectro = s0.copy() s0spectro.rescale_path_length(75 * 4) # spectrometer length s0spectro.apply_slit(slit_function, unit="nm", norm_by=norm_by, shape="trapezoidal") _, I0spectro = s0spectro.get("radiance", Iunit=unit) wtot, Itot = stot.get("radiance", Iunit=unit) stot_corr = experimental_spectrum( wtot, Itot - I0spectro, # hack to remove # emission from within # spectrometer Iunit=unit, conditions={"medium": "air"}, ) # %% Compare with experiment data # Plot experimental data # ------ exp = pd.read_csv( getValidationCase( "test_compare_torch_CO2_data/test_compare_torch_CO2_spectrum_JTHT2003.dat" ), skiprows=5, delim_whitespace=True, ) exp.w /= 10 # Angstrom to nm exp = exp[(exp.w > wlmin) & (exp.w < wlmax)] sexp = experimental_spectrum(exp.w, exp.I, Iunit="mW/cm2/sr", conditions={"medium": "air"}) if plot: sexp.plot("radiance", wunit="nm", Iunit=unit, lw=2, label="Packan 2003") # Plot calculated # ---------- stot.plot( "radiance", wunit="nm", Iunit=unit, nfig="same", color="r", ls="--", label="All: CO$_2$+CO", ) # Plot internal spectrometer emission s0spectro.plot( "radiance", wunit="nm", Iunit=unit, nfig="same", color="b", label="CO$_2$ in Spectrometer", ) stot_corr.plot( "radiance", wunit="nm", Iunit=unit, nfig="same", color="r", lw=2, label="All-CO$_2$ in Spectro", zorder=10, ) sco.plot( "radiance", wunit="nm", Iunit=unit, nfig="same", color="g", ls="-", label="CO", ) plt.ylim((0, 9)) plt.legend(loc="upper right") if save: plt.savefig("test_compare_torch_CO2_brd20.png") plt.savefig("test_compare_torch_CO2_brd20k.pdf") assert get_residual(stot_corr, sexp, "radiance") < 0.02 except DatabankNotFound as err: assert IgnoreMissingDatabase(err, __file__, warnings) if verbose: print(("Finished test_compare_torch_CO2 in {0:.0f}s".format(time() - t0)))