Пример #1
0
def test_consistent_init():
    rdx = pyradex.Radex(species='co',
                        collider_densities={'H2': 1e4},
                        column_per_bin=1e14,
                        deltav=1.0,
                        temperature=30,
                        tbackground=2.73)
    log.debug('crate at init: {0}'.format(rdx.radex.collie.crate[0, 1]))
    log.debug(str((rdx.density, rdx.temperature, rdx.column, rdx._cddv)))
    rdx.run_radex()
    log.debug('crate at run: {0}'.format(rdx.radex.collie.crate[0, 1]))
    tex0 = rdx.tex[0].value
    crate0 = np.copy(rdx.radex.collie.crate)
    rdx = pyradex.Radex(species='co',
                        collider_densities={'H2': 1e4},
                        column_per_bin=1e14,
                        deltav=1.0,
                        temperature=25,
                        tbackground=2.73)
    log.debug('crate at temchange: {0}'.format(rdx.radex.collie.crate[0, 1]))
    rdx = pyradex.Radex(species='co',
                        collider_densities={'H2': 1e4},
                        column_per_bin=1e14,
                        deltav=1.0,
                        temperature=30,
                        tbackground=2.73)
    log.debug('crate at init2: {0}'.format(rdx.radex.collie.crate[0, 1]))
    log.debug(str((rdx.density, rdx.temperature, rdx.column, rdx._cddv)))
    rdx.run_radex()
    log.debug('crate at run2: {0}'.format(rdx.radex.collie.crate[0, 1]))
    tex1 = rdx.tex[0].value
    crate1 = np.copy(rdx.radex.collie.crate)
    assert tex0 == tex1
    assert np.all(crate0 == crate1)
Пример #2
0
def test_thermal_opr():
    # Check if H2 is specified as total H2, the thermal fraction of O/P H2 is used
    rdx = pyradex.Radex(species='co',
                        collider_densities={'H2': 1e4},
                        column_per_bin=1e14,
                        deltav=1.0,
                        temperature=30,
                        tbackground=2.73)
    opr = 9.0 * np.exp(-170.6 / 30)
    fortho = opr / (1 + opr)
    np.testing.assert_almost_equal(rdx.density['oH2'].value, fortho * 1e4)
    np.testing.assert_almost_equal(rdx.density['pH2'].value,
                                   (1 - fortho) * 1e4)

    rdx.temperature = 50
    opr = 9.0 * np.exp(-170.6 / 50)
    fortho = opr / (1 + opr)
    np.testing.assert_almost_equal(rdx.density['oH2'].value, fortho * 1e4)
    np.testing.assert_almost_equal(rdx.density['pH2'].value,
                                   (1 - fortho) * 1e4)

    # Check that if ortho is specified, density remains unchanged
    rdx = pyradex.Radex(species='co',
                        collider_densities={
                            'oH2': 1e4,
                            'pH2': 0
                        },
                        column_per_bin=1e14,
                        deltav=1.0,
                        temperature=30,
                        tbackground=2.73)
    assert rdx.density['oH2'].value == 1e4
    rdx.temperature = 50
    assert rdx.density['oH2'].value == 1e4
Пример #3
0
def test_radex_class():
    R = pyradex.Radex(datapath='examples/',
                      species='co',
                      abundance=1e-4,
                      column=1e15,
                      collider_densities=None,
                      temperature=20)
    assert hasattr(R, 'radex')
Пример #4
0
def test_synthspec():
    R = pyradex.Radex(column=1e15, temperature=20, density=1e3)
    R.run_radex()
    wcs = np.linspace(103.0, 103.1, 1000) * u.GHz
    S = pyradex.synthspec.SyntheticSpectrum.from_RADEX(wcs,
                                                       R,
                                                       linewidth=10 * u.km /
                                                       u.s)
Пример #5
0
def test_change_abundance():
    R = pyradex.Radex(datapath='examples/',
                      species='co',
                      abundance=1e-4,
                      column=1e15,
                      collider_densities=None,
                      temperature=20)
    totdens = R.total_density
    R.abundance = 1e-6
    assert totdens == R.total_density
Пример #6
0
def formaldehyde_pyradex(xarr,
                         density=4,
                         column=13,
                         temperature=20,
                         xoff_v=0.0,
                         opr=1.0,
                         width=1.0,
                         tbackground=2.73,
                         grid_vwidth=1.0,
                         debug=False,
                         verbose=False,
                         **kwargs):
    """
    Use a grid of RADEX-computed models to make a model line spectrum

    The RADEX models have to be available somewhere.
    OR they can be passed as arrays.  If as arrays, the form should be:
    texgrid = ((minfreq1,maxfreq1,texgrid1),(minfreq2,maxfreq2,texgrid2))

    xarr must be a SpectroscopicAxis instance
    xoff_v, width are both in km/s

    grid_vwidth is the velocity assumed when computing the grid in km/s
    this is important because tau = modeltau / width (see, e.g.,
    Draine 2011 textbook pgs 219-230)
    """

    raise NotImplementedError("Not done yet.")
    import pyradex

    # Convert X-units to frequency in GHz
    xarr = xarr.as_unit('Hz', quiet=True)

    tb_nu_cumul = np.zeros(len(xarr))

    R = pyradex.Radex(
        molecule='oh2co-h2',
        column=column,
        temperature=temperature,
        density=10**density,
        tbackground=tbackground,
    )

    spec = np.sum(
        [(formaldehyde_vtau(xarr,
                            Tex=float(tex[ii]),
                            tau=float(tau[ii]),
                            xoff_v=xoff_v,
                            width=width,
                            **kwargs) * (xarr.as_unit('GHz') > minfreq[ii]) *
          (xarr.as_unit('GHz') < maxfreq[ii])) for ii in xrange(len(tex))],
        axis=0)

    return spec
Пример #7
0
def test_consistent_abund():
    with pytest.raises(ValueError):
        R = pyradex.Radex(datapath='examples/',
                          species='co',
                          abundance=1e-4,
                          column=1e15,
                          density=1e3)
    with pytest.raises(ValueError):
        R = pyradex.Radex(datapath='examples/',
                          species='co',
                          abundance=1e-4,
                          column=1e15,
                          collider_densities={'H2': 1e3})
    with pytest.raises(ValueError):
        R = pyradex.Radex(datapath='examples/',
                          species='co',
                          abundance=1e-4,
                          column_per_bin=1e15)
    with pytest.raises(ValueError):
        R = pyradex.Radex(datapath='examples/',
                          species='co',
                          abundance=None,
                          column=None)
Пример #8
0
def test_selfconsistent_density():
    rdx = pyradex.Radex(species='co',
                        collider_densities={'H2': 1e3},
                        column_per_bin=1e13,
                        temperature=20)
    np.testing.assert_almost_equal(rdx.total_density.value, 1e3)
    rdx.temperature = 30
    np.testing.assert_almost_equal(rdx.total_density.value, 1e3)
    rdx.density = rdx.density
    np.testing.assert_almost_equal(rdx.total_density.value, 1e3)
    rdx.density = {'H2': 1e3}
    np.testing.assert_almost_equal(rdx.total_density.value, 1e3)
    rdx.density = {'oH2': 990, 'pH2': 10}
    np.testing.assert_almost_equal(rdx.total_density.value, 1e3)
Пример #9
0
def test_consistent_parchanges():
    rdx = pyradex.Radex(species='co',
                        collider_densities={'H2': 1e3},
                        column_per_bin=1e13,
                        temperature=20)
    np.testing.assert_almost_equal(rdx.abundance,
                                   1e13 / (1e3 * (u.pc.to(u.cm))))
    assert rdx.locked_parameter == 'column'
    rdx.abundance = 1e-9
    assert rdx.locked_parameter == 'abundance'
    np.testing.assert_almost_equal(
        rdx.total_density.to(u.cm**-3).value, 1e13 / 1e-9 / u.pc.to(u.cm))
    rdx.density = 1e3
    rdx.column_per_bin = 1e13
    np.testing.assert_almost_equal(rdx.abundance,
                                   1e13 / (1e3 * (u.pc.to(u.cm))))
Пример #10
0
def debugging_function_2():
    abundance = 1e-8

    # Here we have to specify 2 of 3: abundance, temperature, density.
    R = pyradex.Radex(species='h13cn@xpol',
                      abundance=abundance,
                      temperature=100,
                      column=1e16,
                      escapeProbGeom='lvg')

    density_array = np.logspace(4, 8.5, 100)
    temperature_list = [50, 100, 200]

    f_c_array_50K = np.zeros_like(density_array)
    f_c_array_100K = np.zeros_like(density_array)
    f_c_array_200K = np.zeros_like(density_array)

    f_c_array_list = [f_c_array_50K, f_c_array_100K, f_c_array_200K]

    list_of_tables = []

    for j, temp in enumerate(temperature_list):

        R.temperature = temp

        for i, rho in enumerate(density_array):

            new_T = R(collider_densities={'H2': rho}, temperature=temp)
            list_of_tables.append(new_T)

            # use the correction_factor code here!
            f_c = correction_factor_given_radex_table(new_T,
                                                      h13cn_J_lower_list)

            if min(new_T['Tex']) < 0:
                print "negative Tex encountered"
                print "conditions: T={0}, n={1}".format(temp, rho)
                f_c_array_list[j][i] = np.nan
            elif np.sum(new_T['lowerlevelpop']) < 0.99:
                print "unphysical population statistics encountered"
                print "conditions: T={0}, n={1}".format(temp, rho)
                f_c_array_list[j][i] = np.nan
            else:
                f_c_array_list[j][i] = f_c

    return list_of_tables, f_c_array_list
Пример #11
0
def test_radex_results():
    # default parameters for radex online
    rdx = pyradex.Radex(species='co',
                        collider_densities={'H2': 1e4},
                        column_per_bin=1e14,
                        deltav=1.0,
                        temperature=30,
                        tbackground=2.73)
    rdx.run_radex()
    assert rdx.temperature.value == 30.0  # no approximates allowed
    assert rdx.column.value == 1e14
    #       LINE         E_UP       FREQ        WAVEL     T_EX      TAU        T_R       POP        POP       FLUX        FLUX
    #                    (K)        (GHz)       (um)      (K)                  (K)        UP        LOW      (K*km/s) (erg/cm2/s)
    # 1      -- 0          5.5    115.2712   2600.7576   56.131  1.786E-03  9.378E-02  3.640E-01  1.339E-01  9.983E-02  1.969E-09
    # RADEX online:
    # Transition        Frequency       Tex     tau             TR
    # 1   --   0        115.2712        54.863  1.824E-03       9.349E-02
    np.testing.assert_approx_equal(rdx.tex[0].value, 56.131, 5)
    np.testing.assert_approx_equal(rdx.tau[0], 1.786E-03, 4)
    np.testing.assert_approx_equal(rdx.upperlevelpop[0], 3.640E-01, 4)
    np.testing.assert_approx_equal(rdx.lowerlevelpop[0], 1.339E-01, 4)
Пример #12
0
def test_thick_co():
    density = {
        'oH2': 100,
        'pH2': 900,
    }
    RR = pyradex.Radex(datapath='examples/',
                       species='co',
                       column=1e17,
                       density=density,
                       temperature=20)
    FF = pyradex.fjdu.Fjdu(datapath='examples/',
                           species='co',
                           column=1e17,
                           density=density,
                           temperature=20)

    rtbl = RR()
    ftbl = FF()

    diff = rtbl['upperlevelpop'] - ftbl['upperlevelpop']
    log.info(diff)
Пример #13
0
def debugging_function():
    abundance = 1e-8
    n_points = 20

    # Here we have to specify 2 of 3: abundance, temperature, density.
    R = pyradex.Radex(species='h13cn@xpol',
                      abundance=abundance,
                      column=1e16,
                      temperature=50,
                      escapeProbGeom='lvg')

    density_list = [1e6]
    temperature_array = np.linspace(10, 400, n_points)

    f_c_array_n6 = np.zeros_like(temperature_array)

    f_c_array_list = [f_c_array_n6]

    list_of_tables = []

    for j, density in enumerate(density_list):

        R.density = density

        for i, temp in enumerate(temperature_array):

            R.temperature = temp

            new_T = R(temperature=temp)
            list_of_tables.append(new_T)

            # use the correction_factor code here!
            f_c = correction_factor_given_radex_table(new_T,
                                                      h13cn_J_lower_list)

            f_c_array_list[j][i] = f_c

    return list_of_tables, f_c_array_list[0]
m_logdensities = 8
min_logdens = 4
max_logdens = 9

temperatures = np.linspace(min_temp, max_temp, n_temperatures)
logdensities = np.linspace(min_logdens, max_logdens, m_logdensities)

sanity_grid = np.zeros((n_temperatures, m_logdensities))
iters_grid = np.zeros((n_temperatures, m_logdensities))

# Initialize radex object
initial_column = 1e08
initial_density = 1e4
R = pyradex.Radex(species='h13cn@xpol',
                  temperature=20,
                  density=initial_density,
                  column=initial_column)
R.maxiter = 1000

# abundance_list = [2e-9, 2e-8, 7e-8]

# for abundance in abundance_list:

# R.abundance = abundance

for i, temp in enumerate(temperatures):

    R.temperature = temp

    for j, logdens in enumerate(logdensities):
Пример #15
0
    flux = CO_data['flux'].data * Jykms
    eflux = CO_data['eflux'].data * Jykms

    return z, T_d, line_width, Jup, flux, eflux


# the pyradex.Radex object MUST be declared at the module level for
# lnprob to work properly
#  ....  Setup the Radex parameters

# Note that N_CO is totaly degenerated with deltav, so in
# principle we should fit for N_CO/deltav
R = pyradex.Radex(species='co', datapath="radex_moldata",
                  density={'oH2':fortho*10.**10.0,'pH2':(1-fortho)*10.**10.0},
                  column=10.**6.0,
                  temperature=20.0,
                  tbackground=2.7315,
                  deltav=1.0,
                  escapeProbGeom='lvg')

# R = pyradex.fjdu.Fjdu(species='co', datapath="radex_moldata",
#                   density={'oH2':fortho*10.**10,'pH2':(1-fortho)*10.**10},
#                   column=10**6,
#                   temperature=20,
#                   tbg=2.7315,
#                   deltav=1,
#                   escapeProbGeom='lvg')


def replot(source):
Пример #16
0
import pyradex
import pylab as pl
import numpy as np

R = pyradex.Radex(column=1e16, temperature=20)
R.maxiter = 1000
#print R.radex.impex.molfile,R.molpath

for column in np.linspace(1e14, 1e17, 10):
    R.column = column

    #R.debug = 1

    R.run_radex(reuse_last=True)

    pl.figure(1)
    pl.plot(R.level_population, label="c=%e" % column)

    pl.figure(2)
    pl.plot(R.frequency, R.tau, label="c=%e" % column)

    pl.figure(3)
    pl.plot(R.frequency, R.tex, label="c=%e" % column)

f1 = pl.figure(1)
ax1 = f1.gca()
ax1.set_xlim(0, 10)
ax1.set_xlabel("Energy Level")
ax1.set_ylabel("Population")

f2 = pl.figure(2)
Пример #17
0
def c18o_cf_iras16293(save=True,
                      print_timing=False,
                      abundance=5e-7,
                      n_points=20):
    """ Generates my version of Fig. 3 from Plume+'12 """

    # Plume '12 claims to use an abundance of 2e-7 (i.e. one C18O for every 500 x 10^4 H2 atoms)
    # but I find that 5e-7 matches the appearance much more closely.

    start = time.time()

    # Figure 3's caption says that Ju=10 is included, but the text omits it.
    # I have had better luck reproducing the plot when I omit Ju=10,
    # so I infer that the caption is incorrect.
    J_upper_list = [2, 3, 5, 6, 7, 8, 9, 10]
    J_lower_list = [x - 1 for x in J_upper_list]

    # Here we have to specify 2 of 3: abundance, temperature, density.
    R = pyradex.Radex(species='c18o',
                      abundance=abundance,
                      column=5e16,
                      temperature=50,
                      escapeProbGeom='lvg')

    fig = plt.figure()
    ax = fig.add_subplot(111)

    density_list = [1e5, 1e6, 1e7, 1e8]
    temperature_array = np.linspace(10, 400, n_points)

    f_c_array_n5 = np.zeros_like(temperature_array)
    f_c_array_n6 = np.zeros_like(temperature_array)
    f_c_array_n7 = np.zeros_like(temperature_array)
    f_c_array_n8 = np.zeros_like(temperature_array)

    f_c_array_list = [f_c_array_n5, f_c_array_n6, f_c_array_n7, f_c_array_n8]

    for j, density in enumerate(density_list):

        R.density = density

        for i, temp in enumerate(temperature_array):

            new_T = R(temperature=temp)

            # use the correction_factor code here!
            f_c = correction_factor_given_radex_table(new_T, J_lower_list)

            f_c_array_list[j][i] = f_c

    ax.plot(temperature_array,
            f_c_array_n8,
            '-.',
            color='purple',
            lw=2,
            label=r'$n = 10^8\ \rm{cm}^{-3}$')
    ax.plot(temperature_array,
            f_c_array_n7,
            'b-',
            lw=1.5,
            label=r'$n = 10^7\ \rm{cm}^{-3}$')
    ax.plot(temperature_array,
            f_c_array_n6,
            'g--',
            lw=1.5,
            label=r'$n = 10^6\ \rm{cm}^{-3}$')
    ax.plot(temperature_array,
            f_c_array_n5,
            'r:',
            lw=2,
            label=r'$n = 10^5\ \rm{cm}^{-3}$')

    ax.legend(frameon=False, loc='upper center', fontsize=18)

    ax.set_xlim(0, 400)
    ax.set_ylim(1.2, 2.4)
    ax.set_xticks([0, 100, 200, 300, 400])
    # ax.set_yticks([1.6,1.7,1.8,1.9,2])

    fontdict = {'family': 'serif', 'fontsize': 16}

    ax.set_ylabel("Correction Factor", fontdict=fontdict)
    ax.set_xlabel("Temp (K)", fontdict=fontdict)

    ax.minorticks_on()

    if save:
        fig.savefig("c18o_iras16293.pdf")
        np.savetxt("c18o_fc_v_T_myr_temperature_array.txt", temperature_array)
        np.savetxt("c18o_fc_v_T_myr_fc_array_n5.txt", f_c_array_n5)
        np.savetxt("c18o_fc_v_T_myr_fc_array_n6.txt", f_c_array_n6)
        np.savetxt("c18o_fc_v_T_myr_fc_array_n7.txt", f_c_array_n7)
        np.savetxt("c18o_fc_v_T_myr_fc_array_n8.txt", f_c_array_n8)

    plt.show()

    end = time.time()
    if print_timing:
        print end - start

    return fig
Пример #18
0
tex_nh322 = {}
tex_h2co = {}
tex_h2co321 = {}

for temperature in temperatures:

    densities = np.logspace(1, 9, 100)
    tex_nh311[temperature] = []
    tex_nh322[temperature] = []
    tex_h2co[temperature] = []
    tex_h2co321[temperature] = []

    Rh2co = pyradex.Radex(species='ph2co-h2',
                          column=1e12,
                          density={
                              'oH2': density * fortho,
                              'pH2': density * (1 - fortho)
                          },
                          temperature=temperature)

    for density in ProgressBar(densities):

        Rh2co.density = {
            'oH2': density * fortho,
            'pH2': density * (1 - fortho),
        }
        Rh2co.temperature = temperature
        Rh2co.run_radex()

        tex_h2co[temperature].append(Rh2co.Tex[2])
        tex_h2co321[temperature].append(Rh2co.Tex[9])
Пример #19
0
import paths
import pyradex
import pyradex.fjdu
import warnings

warnings.filterwarnings('once')
import matplotlib

matplotlib.rc_file(paths.pcpath('pubfiguresrc'))
pl.ion()

RR = pyradex.Radex(species='ph2co-h2',
                   column=1e14,
                   temperature=50,
                   escapeProbGeom='lvg',
                   deltav=5,
                   collider_densities={
                       'oH2': 1e3,
                       'pH2': 1e4
                   })

ff = 0.1
density = 1e5
fortho = 0.1
column = 1e14
temperatures = np.linspace(25, 200, 20)
temperatures = np.logspace(np.log10(25), np.log10(200), 40)
linewidth = 5.0

xarr = np.arange(-35, 36, 1, dtype='float')
""" I am experimenting with pyradex. """

from __future__ import division

import numpy as np
import matplotlib as plt
import pyradex

# how do I work with pyradex?

R = pyradex.Radex(species='c18o', abundance=1e-8, column=1e14, temperature=20)
R.run_radex()

# Ok CAN I DO A THING

T = R(collider_densities={'H2': 1000}, column=10**12)

T.pprint()

# tom, let's do the shameful thing and do a LOOP

rho_array = np.logspace(1, 6.5, 20)
Tex_array_1_0 = np.zeros_like(rho_array)
Tex_array_2_1 = np.zeros_like(rho_array)
Tex_array_3_2 = np.zeros_like(rho_array)

for i, rho in enumerate(np.logspace(1, 6.5, 20)):

    new_T = R(collider_densities={'H2': rho})

    Tex_array_1_0[i] = new_T[0]['Tex']
Пример #21
0
def crude_attempt_at_matching():
    """ 
    Here we are trying to... convince correction_factor and RADEX to be 
    consistent across different kinds of runs!

    Step 1: do temperature then density
    Step 2: do density then temperature

    Step 3: make sure they are consistent dude
    Step 4: do them in reverse order and try again

    I have a vague sense that (because stuff is directly interfacing with 
    underlying FORTRAN code) 

    """

    # Here we have to specify 2 of 3: abundance, temperature, density.
    R_step1 = pyradex.Radex(species='h13cn@xpol',
                            abundance=1e-8,
                            temperature=100,
                            column=1e16,
                            escapeProbGeom='lvg')

    density = 1e6
    temperature_list = [50, 100, 200]

    f_c_dict = {}

    for j, temp in enumerate(temperature_list):

        R_step1.temperature = temp

        new_T = R_step1(collider_densities={'H2': density})

        f_c = correction_factor_given_radex_table(new_T, h13cn_J_lower_list)

        f_c_dict[temp] = f_c

    print f_c_dict

    del R_step1

    # Step 2
    R_step2 = pyradex.Radex(species='h13cn@xpol',
                            abundance=1e-8,
                            column=1e16,
                            temperature=50,
                            escapeProbGeom='lvg')

    f_c_dict_2 = {}

    R_step2.density = density

    for i, temp in enumerate(temperature_list):

        new_T = R_step2(temperature=temp)

        # use the correction_factor code here!
        f_c = correction_factor_given_radex_table(new_T, h13cn_J_lower_list)

        f_c_dict_2[temp] = f_c

    print f_c_dict_2

    return
Пример #22
0
def ph2cogrid(ntemp=50, trange=[10,200], abundances=(1.2e-9,),
              logdensities=(4,5), opr=3, 
              deltav=5.0, # km/s
             ):
    import pyradex

    temperatures=np.linspace(trange[0],trange[1],ntemp)

    # initial density; will be modified later
    density = 1e4


    fortho = opr/(1.+opr)

    R = pyradex.Radex(species='ph2co-h2',
                      abundance=abundances[0],
                      collider_densities={'H2':density},
                      deltav=deltav,
                      column=None,
                      temperature=temperatures[0],
                      )

    Xarr = {}
    for abundance in abundances:
        Xarr[abundance] = {}

        densities = [10**x for x in logdensities]
        ratio1 = {d:[] for d in densities}
        ratio2 = {d:[] for d in densities}
        f1 = {d:[] for d in densities}
        f2 = {d:[] for d in densities}
        f3 = {d:[] for d in densities}


        for density in densities:
            #R.density = {'H2': density}
            R.density = {'oH2':density*fortho,'pH2':density*(1.-fortho)}
            for temperature in temperatures:
                R.temperature = temperature
                R.abundance = abundance
                log.info("niter={0} col={1:0.1f} dens={2:0.1f} tem={3:0.1f} abund={4:0.2g}"
                         .format(R.run_radex(validate_colliders=False,
                                          reload_molfile=False),
                              np.log10(R.column.value),
                              np.log10(R.density['oH2'].value),
                              R.temperature,
                              R.abundance))

                #import ipdb; ipdb.set_trace()

                F1 = R.T_B[2]  # 218.222192 3_0_3
                F2 = R.T_B[12] # 218.760066 3_2_1
                F3 = R.T_B[9]  # 218.475632 3_2_2

                ratio1[density].append(F2/F1)
                ratio2[density].append(F3/F1)
                f3[density].append(F3)
                f2[density].append(F2)
                f1[density].append(F1)
            print()

        f1 = {d:np.array([x.value for x in f1[d]]) for d in densities}
        f2 = {d:np.array([x.value for x in f2[d]]) for d in densities}
        f3 = {d:np.array([x.value for x in f3[d]]) for d in densities}
        ratio1 = {d:np.array(ratio1[d]) for d in densities}
        ratio2 = {d:np.array(ratio2[d]) for d in densities}

        Xarr[abundance] = {'flux1':f1,
                           'flux2':f2,
                           'flux3':f3,
                           'ratio1':ratio1,
                           'ratio2':ratio2}

    return Xarr
Пример #23
0
    def from_pyradex(self, integrated_flux, mol_data, line_width=1.0 * u.km / u.s,
                     escapeProbGeom='lvg', iter=100,
                     collider_density={'H2': 900*2.2}):
        """
        Calculate production rate from the Non-LTE iterative code pyradex
        Presently, only the LAMDA catalog is supported by this function.
        In the future a function will be provided by sbpy to build your own
        molecular data file from JPLSpec for use in this function.
        Collider is assumed to be H2O for the default setting since we are only
        considering comet production rates. See documentation for pyradex
        installation tips

        Parameters
        ----------

        integrated_flux : `~astropy.units.Quantity`
            The integrated flux in K * km/s

        mol_data : `sbpy.data.phys`
            `sbpy.data.phys` object that contains AT LEAST the following data:

                    | mol_tag: molecule of interest as string or int JPLSpec identifier
                    | temp: kinetic temperature in gas coma (unit K)
                    | cdensity : cdensity estimate (can be calculated from cdensity_Bockelee) (unit 1/cm^2)
                    | temp_back: (optional) background temperature in K (default is 2.730 K)
                    | lamda_name: (optional) LAMDA molecule identifier to avoid ambiguity. `Lamda.molecule_dict` provides list

            Keywords that can be used for these values are found under
            `~sbpy.data.conf.fieldnames` documentation. Make sure to inform
            yourself on the values needed for each function, their units, and
            their interchangeable keywords as part of the Phys data class.

        line_width : `~astropy.units.Quantity`
            The FWHM line width (really, the single-zone velocity width to
            scale the column density by: this is most sensibly interpreted as a
            velocity gradient (dv/length)) in km/s (default is 1.0 km/s)

        escapeProbGeom : str
            Which escape probability method to use, available choices are
            'sphere', 'lvg', and 'slab'

        iter : int
            Number of iterations you wish to perform. Default is 100, more
            iterations will take more time to do but will offer a better range
            of results to compare against. The range of guesses is built by
            having the column density guess and subtracting/adding an order of
            magnitude for the start and end values of the loop, respectively.
            i.e.  a guess of 1e15 will create a range between 1e14 and 1e16

        collider_density : dict
            Dictionary of colliders and their densities in cm^-3. Allowed
            entries are any of the following : h2,oh2,ph2,e,He,H,H+
            See `~Pyradex` documentation for more information.
            Default dictionary is {'H2' : 900*2.2} where 900 is the
            collider density of H2 and 2.2 is the value for the
            square root of the ratio of reduced masses of H2O/H2
            as follows:
            (mu_H2O/mu_H2)**0.5 = ((18**2/18*2)/((18*2)/(18+2)))**0.5 = 2.2
            in order to scale the collisional excitation to H2O as the main
            collisional partner. (Walker, et al. 2014; de val Borro, et al. 2017;
            & Schoier, et al. 2004)

        Returns
        -------
        column density : `~astropy.units.Quantity`
            column density to use for the Haser model ratio calculation
            Note: it is normal for pyradex/RADEX to output warnings depending
            on the setup the user gives it (such as not having found a
            molecular data file so it searches for it on LAMDA catalog)

        Examples
        --------
        >>> from sbpy.activity import NonLTE
        >>> from sbpy.data import Phys
        >>> import astropy.units as u

        >>> transition_freq = (177.196 * u.GHz).to(u.MHz)
        >>> mol_tag =  29002
        >>> cdensity_guess = (1.89*10.**(14) / (u.cm * u.cm))
        >>> temp_estimate = 20. * u.K

        >>> mol_data = Phys.from_jplspec(temp_estimate, transition_freq,
        ...                              mol_tag)  # doctest: +REMOTE_DATA
        >>> mol_data.apply([cdensity_guess.value] * cdensity_guess.unit,
        ...                 name= 'cdensity')  # doctest: +REMOTE_DATA
        >>> mol_data.apply(['HCO+@xpol'],
        ...                 name='lamda_name')  # doctest: +REMOTE_DATA

        >>> nonLTE = NonLTE()
        >>> try:  # doctest: +SKIP
        ...     cdensity = nonLTE.from_pyradex(1.234 * u.K * u.km / u.s,
        ...                                    mol_data, iter=600,
        ...                                    collider_density={'H2': 900})  # doctest: +REMOTE_DATA
        ...     print(cdensity)  # doctest: +REMOTE_DATA
        ... except ImportError:
        ...     pass
        Closest Integrated Flux:[1.24925956] K km / s
        Given Integrated Flux: 1.234 K km / s
        [1.06363773e+14] 1 / cm2


        References
        ----------
        Haser 1957, Bulletin de la Societe Royale des Sciences de Liege
        43, 740.

        Walker, et al., On the Validity of Collider-mass Scaling for Molecular
        Rotational Excitation, APJ, August 2014.

        van der Tak, et al., A computer program for fast non-LTE analysis of
        interstellar line spectra. With diagnostic plots to interpret observed
        line intensity ratios. A&A, February 12 2013.

        de Val Borro, et al., Measuring molecular abundances in comet C/2014 Q2
        (Lovejoy) using the APEX telescope. Monthly Notices of the Royal
        Astronomical Society, October 27 2017.

        Schoier, et al., An atomic and molecular database for analysis of
        submillimetre line observations. A&A, November 4 2004.

        """

        try:
            import pyradex
        except ImportError:
            raise ImportError('Pyradex not installed. Please see \
            https://github.com/keflavich/pyradex/blob/master/INSTALL.rst')

        if not isinstance(mol_data, Phys):
            raise ValueError('mol_data must be a `sbpy.data.phys` instance.')

        register('Production Rates', {'Radex': '2007A&A...468..627V'})

        # convert mol_tag JPLSpec identifier to verbose name if needed
        try:
            mol_data['lamda_name']
            name = mol_data['lamda_name'][0]
            name = name.lower()
        except KeyError:
            if not isinstance(mol_data['mol_tag'][0], str):
                cat = JPLSpec.get_species_table()
                mol = cat[cat['TAG'] == mol_data['mol_tag'][0]]
                name = mol['NAME'].data[0]
                name = name.lower()
            else:
                name = mol_data['mol_tag'][0]
                name = name.lower()

        # try various common instances of molecule names and check them against LAMDA before complaining
        try:
            Lamda.molecule_dict[name]
        except KeyError:
            try_name = "{}@xpol".format(name)
            try:
                Lamda.molecule_dict[try_name]
                name = try_name
            except KeyError:
                print('Molecule name {} not found in LAMDA, module tried {} and also\
                       found no molecule with this identifier within LAMDA. Please\
                       enter LAMDA identifiable name using mol_data["lamda_name"]\
                       . Use Lamda.molecule_dict to see all available options.'.format(name, try_name))
                raise

        # define Temperature
        temp = mol_data['temp']

        # check for optional values within mol_data
        if 'temp_back' in mol_data:
            tbackground = mol_data['temp_back']
        else:
            tbackground = 2.730 * u.K

        # define cdensity and iteration parameters
        cdensity = mol_data['cdensity'].to(1 / (u.cm * u.cm))
        cdensity_low = cdensity - (cdensity*0.9)
        cdensity_high = cdensity + (cdensity*9)
        # range for 400 iterations
        cdensity_range = np.linspace(cdensity_low, cdensity_high, iter)
        fluxes = []
        column_density = []

        with tempfile.TemporaryDirectory() as datapath:
            for i in cdensity_range:
                R = pyradex.Radex(column=i, deltav=line_width, tbackground=tbackground,
                                  species=name, temperature=temp,
                                  datapath=datapath, escapeProbGeom=escapeProbGeom,
                                  collider_densities=collider_density)

                table = R()

                # find closest matching frequency to user defined
                indx = (np.abs(table['frequency']-mol_data['t_freq'])).argmin()
                radexfreq = table['frequency'][indx]
                # get table for that frequency
                values = table[table['frequency'] == radexfreq]
                # use eq in io.f from Pyradex to get integrated flux in K * km/s
                int_flux_pyradex = 1.0645 * values['T_B'] * line_width

                fluxes.append(int_flux_pyradex)
                column_density.append(i)

        # closest matching integrated flux from pyradex

        fluxes = np.array(fluxes)

        index_flux = (np.abs(fluxes-integrated_flux.to(u.K * u.km / u.s).value)).argmin()

        # corresponding column density in 1/cm^2
        column_density = column_density[index_flux]
        print('Closest Integrated Flux:{}'.format(fluxes[index_flux] * u.K * u.km / u.s))
        print('Given Integrated Flux: {}'.format(integrated_flux))

        return column_density
Пример #24
0
import pyradex
import pylab as pl

R = pyradex.Radex(column=1e16)
R.maxiter = 1000
#print R.radex.impex.molfile,R.molpath

for temperature in [5, 10, 20, 30, 40, 50, 60]:
    R.temperature = temperature

    R.run_radex()

    pl.figure(1)
    pl.plot(R.level_population, label="T=%s" % R.temperature._repr_latex_())

    pl.figure(2)
    pl.plot(R.frequency, R.tau, label="T=%s" % R.temperature._repr_latex_())

    pl.figure(3)
    pl.plot(R.frequency, R.tex, label="T=%s" % R.temperature._repr_latex_())

f1 = pl.figure(1)
ax1 = f1.gca()
ax1.set_xlim(0, 10)
ax1.set_xlabel("Energy Level")
ax1.set_ylabel("Population")

f2 = pl.figure(2)
ax2 = f2.gca()
ax2.set_xlabel("Frequency")
ax2.set_ylabel("Optical Depth")
Пример #25
0
texgrid_71M = np.empty([ndens,ntemp])
fluxgrid_71M = np.empty([ndens,ntemp])
taugrid_145 = np.empty([ndens,ntemp])
texgrid_145 = np.empty([ndens,ntemp])
fluxgrid_145 = np.empty([ndens,ntemp])
taugrid_355M = np.empty([ndens,ntemp])
texgrid_355M = np.empty([ndens,ntemp])
fluxgrid_355M = np.empty([ndens,ntemp])
columngrid = np.empty([ndens,ntemp])

import os
if not os.path.exists('ph2co-h2.dat'):
    import urllib
    urllib.urlretrieve('http://home.strw.leidenuniv.nl/~moldata/datafiles/ph2co-h2.dat')

R = pyradex.Radex(species='ph2co-h2', abundance=abundance)
R.run_radex()

# get the table so we can look at the frequency grid
table = R.get_table()

# Target frequencies:
table[np.array([6,1,11])].pprint()

for ii,tt in enumerate(temperatures):
    R.temperature = tt
    for jj,dd in enumerate(densities):
        R.density = {'oH2':dd*fortho,'pH2':dd*(1-fortho)}
        R.abundance = abundance # reset column to the appropriate value
        R.run_radex(reuse_last=False, reload_molfile=True)
Пример #26
0
"""
Example:
    Plot the relative intensities of the 3mm CH3CN (methyl cyanide) lines
"""
import pyradex
import pylab as pl
from astropy import units as u
import numpy as np
import matplotlib as mpl

R = pyradex.Radex(species='ch3cn', abundance=1e-11, column=None)

# There are 5 lines of interest in this band
nlines = 5
fluxes = {ii: [] for ii in xrange(nlines)}

# Temperature range: 20-500 K is allowed (by CH3CN data file)
temperatures = np.linspace(20, 500, 8)
temperatures = [20, 50, 100, 300, 500]

# set up figure
pl.figure(1)
pl.clf()

for ii, temperature in enumerate(temperatures):

    R.temperature = temperature
    R.run_radex()
    #wcs = pyradex.synthspec.FrequencyArray(91.95*u.GHz,92*u.GHz,1000)
    wcs = np.linspace(91.95, 92, 1000) * u.GHz
    S = pyradex.synthspec.SyntheticSpectrum.from_RADEX(
Пример #27
0
def runRADEX(species, widths, temperatures, densities, columns, **kwargs):
    """Calls pyradex iteratively to produce a table of intensities."""

    # Make sure all the provided values are iterable.

    temperatures, tnum, tmin, tmax = formatInput(temperatures, log=False)
    densities, dnum, dmin, dmax = formatInput(densities, log=True)
    columns, cnum, cmin, cmax = formatInput(columns, log=True)
    widths, wnum, wmin, wmax = formatInput(widths, log=False)

    # Check that the collisional rate file exists.
    # This is hardwired to where the collisional rates are.

    rates_path = os.path.expanduser(os.getenv('RADEX_DATAPATH'))
    print('{}/{}.dat'.format(rates_path, species))
    if not os.path.isfile('{}/{}.dat'.format(rates_path, species)):
        raise ValueError('Did not find collisional rates.')
    rates = ratefile('{}/{}.dat'.format(rates_path, species))

    # We assume that the density is n(H2) and the ortho/para ratio is 3.
    # Check if oH2 and pH2 are valid colliders in the collisional rate file.
    # If they are, recalculate the densities.

    opr = kwargs.get('opr', False)
    if ('oH2' in rates.partners and 'pH2' in rates.partners and opr):
        opr_flag = True
        # print 'Assuming an ortho / para ratio of {}.'.format(opr)
    else:
        opr_flag = False


    # Dummy array to hold the results.
    # Hold up the 'jmax' transition, default is 10.
    # Saves both the brightness temperature and optical depth.

    jmax = kwargs.get('jmax', 9) + 1
    Tb = np.zeros((jmax, 3, wnum, tnum, dnum, cnum))

    # First initialise pyradex, then iterate through all the permutations.
    # Select the correct escape problem geometry, by default we assume slab.

    escapegeom = kwargs.pop('escapegeom', 'slab')
    radex = pyradex.Radex(species=species, temperature=temperatures[0],
                          density=densityDict(densities[0], opr, opr_flag),
                          column=columns[0], deltav=widths[0],
                          escapeProbGeom=escapegeom, **kwargs)

    t0 = time.time()
    tlast = np.nan
    for l, width in enumerate(widths):
        radex.deltav = width
        for t, temp in enumerate(temperatures):
            radex.temperature = temp
            for d, dens in enumerate(densities):
                radex.density = densityDict(dens, opr, opr_flag)
                for c, col in enumerate(columns):
                    radex.column = col

                    # Reload the molfile if temperature has changed.
                    with np.errstate(divide='ignore'):
                        if tlast == temp:
                            radex.run_radex()
                        else:
                            radex.run_radex(reload_molfile=True)
                        tlast = temp

                    # Parse the results.
                    Tb[:, 0, l, t, d, c] = radex.T_B[:jmax]
                    Tb[:, 1, l, t, d, c] = radex.Tex[:jmax]
                    Tb[:, 2, l, t, d, c] = radex.tau[:jmax]

    Tb = np.nan_to_num(Tb)
    t1 = time.time()

    if kwargs.get('verbose', True):
        print('Generated table in {}.'.format(seconds2hms(t1-t0)))

    # Save the file.
    fn = '{}_'.format(species)
    fn += '{:.2f}_{:.2f}_{:d}_'.format(wmin, wmax, wnum)
    fn += '{:.2f}_{:.2f}_{:d}_'.format(tmin, tmax, tnum)
    fn += '{:.2f}_{:.2f}_{:d}_'.format(dmin, dmax, dnum)
    fn += '{:.2f}_{:.2f}_{:d}.npy'.format(cmin, cmax, cnum)
    np.save(kwargs.get('path', './') + fn, Tb)

    return
import pyradex
import pylab as pl
import numpy as np
import paths
import dust_emissivity
from astropy import units as u
from astropy.table import Table

rr = pyradex.Radex(species='nacl', temperature=1000, density=1e8, column=4e13)
rslt = rr()

v0_76 = (rslt['upperlevel'] == '0_7   ') & (rslt['lowerlevel'] == '0_6   ')
v1_76 = (rslt['upperlevel'] == '1_7   ') & (rslt['lowerlevel'] == '1_6   ')
v2_76 = (rslt['upperlevel'] == '2_7   ') & (rslt['lowerlevel'] == '2_6   ')
v3_76 = (rslt['upperlevel'] == '3_7   ') & (rslt['lowerlevel'] == '3_6   ')
v10 = (rslt['upperlevel'] == '1_7   ') & (rslt['lowerlevel'] == '0_6   ')
v21 = (rslt['upperlevel'] == '2_7   ') & (rslt['lowerlevel'] == '1_6   ')
v32 = (rslt['upperlevel'] == '3_7   ') & (rslt['lowerlevel'] == '2_6   ')

for density in (1e2, 1e5, 1e8, 1e11, 1e14):
    rslt = rr(density={'H2': density})
    critdens = {
        rr.quantum_number[iupp]:
        rr.radex.rmolec.aeinst[rr.radex.imolec.iupp == iupp].sum() /
        (rr.radex.collie.ctot[iupp - 1] / rr.total_density)
        for iupp in np.arange(1, rr.radex.imolec.iupp.max())
    }
    print(density, critdens[b'0_7   '], rr.level_population[7],
          critdens[b'1_7   '], rr.level_population[68], "\n",
          rslt[v0_76 | v1_76])
Пример #29
0
# Check correctness before doing timing tests
import pyradex

py_pop = [
    pyradex.pyradex(collider_densities={
        'oH2': 900,
        'pH2': 100
    },
                    column=n,
                    temperature=20)['pop_up'][0]
    for n in 10**np.arange(12, 18)
]

R = pyradex.Radex(collider_densities={
    'oH2': 900,
    'pH2': 100
},
                  column=1e15,
                  temperature=20)

R_noreload_pop = []
for n in 10**np.arange(12, 18):
    R.column = n
    R.run_radex(reload_molfile=False, validate_colliders=False)
    R_noreload_pop.append(R.level_population[1])

R_pop = []
for n in 10**np.arange(12, 18):
    R.column = n
    R.run_radex(reload_molfile=True, validate_colliders=True)
    R_pop.append(R.level_population[1])
Пример #30
0
abundance = 1.2e-9  # Johnston / Ao
opr = 0.01  # assume primarily para
opr = 3
fortho = opr / (1 + opr)

import os
if not os.path.exists('ph2co-h2.dat'):
    import urllib
    urllib.urlretrieve(
        'http://home.strw.leidenuniv.nl/~moldata/datafiles/ph2co-h2.dat')

# 1e23 from Johnston 2014
R = pyradex.Radex(species='ph2co-h2',
                  abundance=abundance,
                  temperature=50,
                  collider_densities={
                      'oH2': 2e4 * fortho,
                      'pH2': 2e4 * (1 - fortho)
                  })
print R.escapeProbGeom  # DEBUG
R.run_radex()

# get the table so we can look at the frequency grid
table = R.get_table()

# Target frequencies:
table[np.array([6, 1, 11])].pprint()

key_303 = np.where((table['upperlevel'] == '3_0_3')
                   & (table['frequency'] > 218)
                   & (table['frequency'] < 220))[0]