Beispiel #1
0
def test_molecules(molecule):
    if os.path.isfile('examples/%s.dat' % molecule):
        molecule = 'examples/%s' % molecule
    elif os.path.isfile('Radex/data/%s.dat' % molecule):
        molecule = 'Radex/data/%s' % molecule
    else:
        return

    data = pyradex.pyradex(executable=exepath,species=molecule,minfreq=1,maxfreq=250)
    data.pprint(show_unit=True)
Beispiel #2
0
def test_molecules(molecule):
    if os.path.isfile('examples/%s.dat' % molecule):
        molecule = 'examples/%s' % molecule
    elif os.path.isfile('Radex/data/%s.dat' % molecule):
        molecule = 'Radex/data/%s' % molecule
    else:
        return

    data = pyradex.pyradex(executable=exepath,
                           species=molecule,
                           minfreq=1,
                           maxfreq=250)
    data.pprint(show_unit=True)
Beispiel #3
0
import timeit
import numpy as np
import textwrap

# 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 = []
Beispiel #4
0
def test_call():
    data = pyradex.pyradex(executable=exepath,species='Radex/data/hco+',minfreq=50)
    data.pprint(show_unit=True)
Beispiel #5
0
import timeit
import numpy as np
import textwrap
import warnings
warnings.filterwarnings('ignore')
from astropy import log
log.setLevel(1000)

# 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])

R_reuse_pop = []
for n in 10**np.arange(12,18):
    R.column = n
    R.run_radex(reload_molfile=False, validate_colliders=False, reuse_last=True)
Beispiel #6
0
def myloglike(cube, ndim, nparams):
    import warnings
    
    debug=False # Change this to return likelihoods to diagnose certain problems
    
    # Calculate the log(likelihood).  Load in the measdata.pkl for our data,
    # and use pyradex to get our model.
    # If we violate any priors, limits, or have calculation errors, return -2e100 as the likelihood.
    meas=pickle.load(open("measdata.pkl","rb"))
    taumin=meas['taulimit'][0]
    taumax=meas['taulimit'][1]
    sigmacut=meas['sigmacut']
    
    # First, test that the cube parameters do not violate the mass or length priors.
    #  Warm mass cannot be greater than cold mass.
    #  Cold temperature cannot be less than warm temperature
    #  Total mass cannot be greater than dynamical mass limit
    #  Neither length can be greater than the length limits
    if ndim>4:
        if cube[6]+cube[7] > cube[2]+cube[3] or \
           cube[1] > cube[5] or \
           np.log10(np.power(10,cube[2]+cube[3])+np.power(10,cube[6]+cube[7])) > meas['masscut'] or \
           cube[2]-cube[0]-0.5*cube[3] > meas['lengthcut'] or \
           cube[6]-cube[4]-0.5*cube[7] > meas['lengthcut']:
               if debug: return 1e2
               return -2e100
    else:
        if cube[2]+cube[3] > meas['masscut'] or cube[2]-cube[0]-0.5*cube[3] > meas['lengthcut']:
            if debug: return 1e2
            return -2e100

    # Call RADEX for the first component.
    try:
        dat1=pyradex.pyradex(minfreq=1, maxfreq=1600,
                          temperature=np.power(10,cube[1]), column=np.power(10,cube[2]), 
                          collider_densities={'H2':np.power(10,cube[0])},
                          tbg=meas['tbg'], species=meas['head']['mol'], velocity_gradient=1.0, debug=False,
                          return_dict=True)
        # dat['J_up'] returned as strings; this is fine for CO...
        jup1=np.array(map(float,dat1['J_up']))
        model1=np.array(map(float,dat1['FLUX_Kkms']))*np.power(10,cube[3])
        tau1=np.array(map(float,dat1['TAU']))
        
        # Check for convergence
        if dat1['niter']==['****']: return -2e100
        
        # At this time it is too slow to use this.
        #R = pyradex.Radex(collider_densities={'h2':np.power(10,cube[0])}, 
        #     temperature=np.power(10,cube[1]), column=np.power(10,cube[2]),
        #     tbackground=meas['tbg'],species=meas['head']['mol'],deltav=1.0,debug=False)
        #niter=R.run_radex(validate_colliders=False)
        #model1=1.064575*R.T_B*np.power(10,cube[3]) # Integrating over velocity, and Filling Factor
        #model1=model1.value # Hatred of units in my way
        #tau1=R.tau
        #jup1=R.upperlevelindex        
        #cube[ndim]=np.sum(R.source_brightness_beta) # luminosity; not correct units yet.
        
    except:
        if debug: return 1e3
        return -2e100

    # Which indices are lines that we are concerned with?
    juse=np.in1d(jup1.ravel(),meas['J_up']).reshape(jup1.shape)
    jmeas=np.in1d(jup1.ravel(),meas['J_up'][meas['flux']!=0]).reshape(jup1.shape)
    
    # If applicable, call RADEX for the second component and find their sum.
    # Either way, check if any optical depths are outside of our limits.
    if ndim>4:
        try:
            dat2=pyradex.pyradex(minfreq=1, maxfreq=1600,
                               temperature=np.power(10,cube[5]), column=np.power(10,cube[6]), 
                               collider_densities={'H2':np.power(10,cube[4])},
                               tbg=meas['tbg'], species=meas['head']['mol'], velocity_gradient=1.0, debug=False,
                               return_dict=True)
            jup2=np.array(map(float,dat2['J_up']))
            model2=np.array(map(float,dat2['FLUX_Kkms']))*np.power(10,cube[7])
            tau2=np.array(map(float,dat2['TAU']))                            

            # Check for convergence
            if dat2['niter']==['****']: return -2e100
                               
            modelt=model1+model2# We want to compare the SUM of the components to our data.
            tauok=np.all([tau1<taumax,tau1>taumin,tau2<taumax,tau2>taumin],axis=0)
            
            #R.temperature=np.power(10,cube[5])
            #R.density=np.power(10,cube[4])
            #R.column=np.power(10,cube[6])
            #niter=R.run_radex(validate_colliders=False)
            
            #model2=1.064575*R.T_B*np.power(10,cube[3])# Integrating over velocity, and Filling Factor
            #model2=model2.value
            #tau2=R.tau
            #jup2=R.upperlevelindex
            #if not np.array_equal(jup1,jup2): 
            #    warnings.warn('J_up arrays NOT equal from multiple RADEX calls!')
            #    return -2e100
            #modelt=model1+model2
            #tauok=np.all([tau1<taumax,tau1>taumin,tau2<taumax,tau2>taumin],axis=0)
        except:
            if debug: return 1e3
            return -2e100
    else:
        modelt=model1# total model
        tauok=np.all([tau1<taumax,tau1>taumin],axis=0)
    
    # Check that we have at least one line with optical depth in allowable limits.
    if not np.any(tauok[jmeas]):
        if debug: return 1e4
        return -2e100
        
    # Check that we don't violate ANY line flux upper limits.
    ul=np.where(meas['flux']==0)[0]
    for i in ul:
        ulok=modelt[jup1==meas['J_up'][i]] < meas['sigma'][i]*sigmacut
        if not ulok: 
            if debug: return 1e5
            return -2e100
    
    # We've made it!  Calculate likelihood!
    nmeas=len(meas['sigma'])
    loglike=-nmeas*0.5*np.log(2.0*np.pi)
    for i in range(nmeas):
        try:
            j_ind=np.where(jup1==meas['J_up'][i])[0]
            if tauok[j_ind] and meas['flux'][i] > 0:
                loglike=loglike-np.log(meas['sigma'][i])
                loglike=loglike-0.5*(np.power((meas['flux'][i]-modelt[j_ind])/meas['sigma'][i],2))
        except:
            warnings.warn('An error occured with j_up = '+str(meas['J_up'][i])+', will be ignored.')
            loglike=loglike
            
    # Record the luminosity, pressure, and beam-averaged column density for binning later.
    # The public distribution of RADEX will not output this luminosity; sorry all users...
    if 'LogLmol' in dat1.keys():
        cube[ndim]=dat1['LogLmol']+meas['areacm']+cube[2]+cube[3]
    else: 
        cube[ndim]=1.0  # Those not using our private RADEX code will not get luminosity.
    cube[ndim+1]=cube[0]+cube[1]
    cube[ndim+2]=cube[2]+cube[3]

    # Don't include sled likelihoods with bad tau - cannot NaN them :( ?
    
    # Watch out, in the rare chance of a ridiculous RADEX value of something E+99, 
    #  MultiNest will print 0.XYZ+100 instead of X.YZE+99, and will not be read as float.
    #  You've not used this value in your likelihood because tau will be wild as well.
    model1[model1>9e98]=9e98
    if ndim>4: model2[model2>9e98]=9e98

    # If we have 2 components, also records those L, P, and BACD, as well
    # as ratios of the warm to cold (note these are in log, so they are differenced).
    if ndim>4:
        if 'LogLmol' in dat2.keys():
            cube[ndim+3]=dat2['LogLmol']+meas['areacm']+cube[6]+cube[7]
        else: 
            cube[ndim+3]=1.0  # See luminosity note above.
        cube[ndim+4]=cube[4]+cube[5]
        cube[ndim+5]=cube[6]+cube[7]
        # Ratios of WARM to COLD
        cube[ndim+6]=cube[ndim+3]-cube[ndim]
        cube[ndim+7]=cube[ndim+4]-cube[ndim+1]
        cube[ndim+8]=cube[ndim+5]-cube[ndim+2]
        # SLED likelihoods, unhappy with slice indices...
        for i,l in enumerate(model1[0:meas['sled_to_j']]): cube[ndim+9+i]=l
        for i,l in enumerate(model2[0:meas['sled_to_j']]): cube[ndim+9+meas['sled_to_j']+i]=l
        #cube[ndim+9:]=np.append(model1[0:meas['sled_to_j']].value,model2[0:meas['sled_to_j']])
    else:
        for i,l in enumerate(model1[0:meas['sled_to_j']]): cube[ndim+3+i]=l 
        #cube[ndim+3:ndim+3+meas['sled_to_j']]=model1[0:meas['sled_to_j']].value
    
    return loglike
Beispiel #7
0
def test_call():
    data = pyradex.pyradex(executable=exepath,
                           species='Radex/data/hco+',
                           minfreq=50)
    data.pprint(show_unit=True)
Beispiel #8
0
def myloglike(cube, ndim, nparams):
    import warnings

    debug = False  # Change this to return likelihoods to diagnose certain problems

    # Calculate the log(likelihood).  Load in the measdata.pkl for our data,
    # and use pyradex to get our model.
    # If we violate any priors, limits, or have calculation errors, return -2e100 as the likelihood.
    meas = pickle.load(open("measdata.pkl", "rb"))
    taumin = meas['taulimit'][0]
    taumax = meas['taulimit'][1]
    sigmacut = meas['sigmacut']

    # First, test that the cube parameters do not violate the mass or length priors.
    #  Warm mass cannot be greater than cold mass.
    #  Cold temperature cannot be less than warm temperature
    #  Total mass cannot be greater than dynamical mass limit
    #  Neither length can be greater than the length limits
    if ndim > 4:
        if cube[6]+cube[7] > cube[2]+cube[3] or \
           cube[1] > cube[5] or \
           np.log10(np.power(10,cube[2]+cube[3])+np.power(10,cube[6]+cube[7])) > meas['masscut'] or \
           cube[2]-cube[0]-0.5*cube[3] > meas['lengthcut'] or \
           cube[6]-cube[4]-0.5*cube[7] > meas['lengthcut']:
            if debug: return 1e2
            return -2e100
    else:
        if cube[2] + cube[3] > meas['masscut'] or cube[2] - cube[
                0] - 0.5 * cube[3] > meas['lengthcut']:
            if debug: return 1e2
            return -2e100

    # Call RADEX for the first component.
    try:
        dat1 = pyradex.pyradex(
            minfreq=1,
            maxfreq=1600,
            temperature=np.power(10, cube[1]),
            column=np.power(10, cube[2]),
            collider_densities={'H2': np.power(10, cube[0])},
            tbg=meas['tbg'],
            species=meas['head']['mol'],
            velocity_gradient=1.0,
            debug=False,
            return_dict=True)
        # dat['J_up'] returned as strings; this is fine for CO...
        jup1 = np.array(map(float, dat1['J_up']))
        model1 = np.array(map(float, dat1['FLUX_Kkms'])) * np.power(
            10, cube[3])
        tau1 = np.array(map(float, dat1['TAU']))

        # Check for convergence
        if dat1['niter'] == ['****']: return -2e100

        # At this time it is too slow to use this.
        #R = pyradex.Radex(collider_densities={'h2':np.power(10,cube[0])},
        #     temperature=np.power(10,cube[1]), column=np.power(10,cube[2]),
        #     tbackground=meas['tbg'],species=meas['head']['mol'],deltav=1.0,debug=False)
        #niter=R.run_radex(validate_colliders=False)
        #model1=1.064575*R.T_B*np.power(10,cube[3]) # Integrating over velocity, and Filling Factor
        #model1=model1.value # Hatred of units in my way
        #tau1=R.tau
        #jup1=R.upperlevelindex
        #cube[ndim]=np.sum(R.source_brightness_beta) # luminosity; not correct units yet.

    except:
        if debug: return 1e3
        return -2e100

    # Which indices are lines that we are concerned with?
    juse = np.in1d(jup1.ravel(), meas['J_up']).reshape(jup1.shape)
    jmeas = np.in1d(jup1.ravel(),
                    meas['J_up'][meas['flux'] != 0]).reshape(jup1.shape)

    # If applicable, call RADEX for the second component and find their sum.
    # Either way, check if any optical depths are outside of our limits.
    if ndim > 4:
        try:
            dat2 = pyradex.pyradex(
                minfreq=1,
                maxfreq=1600,
                temperature=np.power(10, cube[5]),
                column=np.power(10, cube[6]),
                collider_densities={'H2': np.power(10, cube[4])},
                tbg=meas['tbg'],
                species=meas['head']['mol'],
                velocity_gradient=1.0,
                debug=False,
                return_dict=True)
            jup2 = np.array(map(float, dat2['J_up']))
            model2 = np.array(map(float, dat2['FLUX_Kkms'])) * np.power(
                10, cube[7])
            tau2 = np.array(map(float, dat2['TAU']))

            # Check for convergence
            if dat2['niter'] == ['****']: return -2e100

            modelt = model1 + model2  # We want to compare the SUM of the components to our data.
            tauok = np.all(
                [tau1 < taumax, tau1 > taumin, tau2 < taumax, tau2 > taumin],
                axis=0)

            #R.temperature=np.power(10,cube[5])
            #R.density=np.power(10,cube[4])
            #R.column=np.power(10,cube[6])
            #niter=R.run_radex(validate_colliders=False)

            #model2=1.064575*R.T_B*np.power(10,cube[3])# Integrating over velocity, and Filling Factor
            #model2=model2.value
            #tau2=R.tau
            #jup2=R.upperlevelindex
            #if not np.array_equal(jup1,jup2):
            #    warnings.warn('J_up arrays NOT equal from multiple RADEX calls!')
            #    return -2e100
            #modelt=model1+model2
            #tauok=np.all([tau1<taumax,tau1>taumin,tau2<taumax,tau2>taumin],axis=0)
        except:
            if debug: return 1e3
            return -2e100
    else:
        modelt = model1  # total model
        tauok = np.all([tau1 < taumax, tau1 > taumin], axis=0)

    # Check that we have at least one line with optical depth in allowable limits.
    if not np.any(tauok[jmeas]):
        if debug: return 1e4
        return -2e100

    # Check that we don't violate ANY line flux upper limits.
    ul = np.where(meas['flux'] == 0)[0]
    for i in ul:
        ulok = modelt[jup1 == meas['J_up'][i]] < meas['sigma'][i] * sigmacut
        if not ulok:
            if debug: return 1e5
            return -2e100

    # We've made it!  Calculate likelihood!
    nmeas = len(meas['sigma'])
    loglike = -nmeas * 0.5 * np.log(2.0 * np.pi)
    for i in range(nmeas):
        try:
            j_ind = np.where(jup1 == meas['J_up'][i])[0]
            if tauok[j_ind] and meas['flux'][i] > 0:
                loglike = loglike - np.log(meas['sigma'][i])
                loglike = loglike - 0.5 * (np.power(
                    (meas['flux'][i] - modelt[j_ind]) / meas['sigma'][i], 2))
        except:
            warnings.warn('An error occured with j_up = ' +
                          str(meas['J_up'][i]) + ', will be ignored.')
            loglike = loglike

    # Record the luminosity, pressure, and beam-averaged column density for binning later.
    # The public distribution of RADEX will not output this luminosity; sorry all users...
    if 'LogLmol' in dat1.keys():
        cube[ndim] = dat1['LogLmol'] + meas['areacm'] + cube[2] + cube[3]
    else:
        cube[
            ndim] = 1.0  # Those not using our private RADEX code will not get luminosity.
    cube[ndim + 1] = cube[0] + cube[1]
    cube[ndim + 2] = cube[2] + cube[3]

    # Don't include sled likelihoods with bad tau - cannot NaN them :( ?

    # Watch out, in the rare chance of a ridiculous RADEX value of something E+99,
    #  MultiNest will print 0.XYZ+100 instead of X.YZE+99, and will not be read as float.
    #  You've not used this value in your likelihood because tau will be wild as well.
    model1[model1 > 9e98] = 9e98
    if ndim > 4: model2[model2 > 9e98] = 9e98

    # If we have 2 components, also records those L, P, and BACD, as well
    # as ratios of the warm to cold (note these are in log, so they are differenced).
    if ndim > 4:
        if 'LogLmol' in dat2.keys():
            cube[ndim +
                 3] = dat2['LogLmol'] + meas['areacm'] + cube[6] + cube[7]
        else:
            cube[ndim + 3] = 1.0  # See luminosity note above.
        cube[ndim + 4] = cube[4] + cube[5]
        cube[ndim + 5] = cube[6] + cube[7]
        # Ratios of WARM to COLD
        cube[ndim + 6] = cube[ndim + 3] - cube[ndim]
        cube[ndim + 7] = cube[ndim + 4] - cube[ndim + 1]
        cube[ndim + 8] = cube[ndim + 5] - cube[ndim + 2]
        # SLED likelihoods, unhappy with slice indices...
        for i, l in enumerate(model1[0:meas['sled_to_j']]):
            cube[ndim + 9 + i] = l
        for i, l in enumerate(model2[0:meas['sled_to_j']]):
            cube[ndim + 9 + meas['sled_to_j'] + i] = l
        #cube[ndim+9:]=np.append(model1[0:meas['sled_to_j']].value,model2[0:meas['sled_to_j']])
    else:
        for i, l in enumerate(model1[0:meas['sled_to_j']]):
            cube[ndim + 3 + i] = l
        #cube[ndim+3:ndim+3+meas['sled_to_j']]=model1[0:meas['sled_to_j']].value

    return loglike
Beispiel #9
0
def myloglike(cube, ndim, nparams):
    # Calculate the log(likelihood).  Load in the measdata.pkl for our data,
    # and use pyradex to get our model.
    # If we violate any priors, limits, or have calculation errors, return -2e100 as the likelihood.

    meas=pickle.load(open("measdata.pkl","rb"))
    taumin=meas['taulimit'][0]#-0.9
    taumax=meas['taulimit'][1]#100.0
    sigmacut=meas['sigmacut']#3.0
    
    import warnings
    
    # First, test that the cube parameters do not violate the mass or length priors.
    if ndim>4:
        if cube[6]+cube[7] > cube[2]+cube[3] or \
           cube[1] > cube[5] or \
           math.log10(math.pow(10,cube[2]+cube[3])+math.pow(10,cube[6]+cube[7])) > meas['masscut'] or \
           cube[2]-cube[0]-0.5*cube[3] > meas['lengthcut'] or \
           cube[6]-cube[4]-0.5*cube[7] > meas['lengthcut']:    
               return -2e100
    else:
        if cube[2]+cube[3] > meas['masscut'] or cube[2]-cube[0]-0.5*cube[3] > meas['lengthcut']:
            return -2e100

    # Call RADEX for the first component.
    try:
        dat=pyradex.pyradex(minfreq=1, maxfreq=1600,
                          temperature=math.pow(10,cube[1]), column=math.pow(10,cube[2]), 
                          collider_densities={'H2':math.pow(10,cube[0])},
                          tbg=2.73, species='co', velocity_gradient=1.0, debug=True)
        dat['FLUX_Kkms']*=math.pow(10,cube[3])
    except:
        return -2e100
    
    # If applicable, call RADEX for the second component and find their sum.
    # Either way, check if any optical depths are outside of our limits.
    if ndim>4:
        try:
            dat2=pyradex.pyradex(minfreq=1, maxfreq=1600,
                               temperature=math.pow(10,cube[5]), column=math.pow(10,cube[6]), 
                               collider_densities={'H2':math.pow(10,cube[4])},
                               tbg=2.73, species='co', velocity_gradient=1.0, debug=False)
            dat2['FLUX_Kkms']*=math.pow(10,cube[7])
            newdat=dat['FLUX_Kkms']+dat2['FLUX_Kkms'] # We want to compare the SUM of the components to our data.
            tauok=numpy.all([dat['TAU']<taumax,dat['TAU']>taumin,dat2['TAU']<taumax,dat2['TAU']>taumin],axis=0)
        except:
            return -2e100
    else:
        newdat=dat['FLUX_Kkms']
        tauok=numpy.all([dat['TAU']<taumax,dat['TAU']>taumin],axis=0)
    
    # Check that we have at least one line with optical depth in allowable limits.
    if not numpy.any(tauok):
        return -2e100
        
    # Check that we don't violate ANY line flux upper limits.
    ulok=newdat[meas['flux']==0] < meas['sigma'][meas['flux']==0]*sigmacut
    if not numpy.all(ulok):
        return -2e100
    
    # We've made it!  Calculate likelihood!
    nmeas=len(meas['sigma'])
    loglike=-nmeas*0.5*math.log(2.0*math.pi)
    for i in range(nmeas):
        try:
            if tauok[i] and meas['flux'][i] > 0:
                loglike=loglike-math.log(meas['sigma'][i])
                loglike=loglike-0.5*(math.pow((meas['flux'][i]-newdat[dat['J_up'] == meas['J_up'][i]])/meas['sigma'][i],2))
        except:
            warnings.warn('An error occured with J_up = '+str(meas['J_up'][i])+', will be ignored.')
            loglike=loglike
            
    # Record the luminosity, pressure, and beam-averaged column density for binning later.
    cube[ndim]=dat['LogLmol']+meas['areacm']+cube[2]+cube[3] #0 
    cube[ndim+1]=cube[0]+cube[1]
    cube[ndim+2]=cube[2]+cube[3]
    # If we have 2 components, also records those L, P, and BACD, as well
    # as ratios of the warm to cold (note these are in log, so they are differenced).
    if ndim>4:
        cube[ndim+3]=dat2['LogLmol']+meas['areacm']+cube[6]+cube[7] #0
        cube[ndim+4]=cube[4]+cube[5]
        cube[ndim+5]=cube[6]+cube[7]
        # Ratios of WARM to COLD
        cube[ndim+6]=cube[ndim+3]-cube[ndim]
        cube[ndim+7]=cube[ndim+4]-cube[ndim+1]
        cube[ndim+8]=cube[ndim+5]-cube[ndim+2]
    
    return loglike