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)
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)
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 = []
def test_call(): data = pyradex.pyradex(executable=exepath,species='Radex/data/hco+',minfreq=50) data.pprint(show_unit=True)
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)
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
def test_call(): data = pyradex.pyradex(executable=exepath, species='Radex/data/hco+', minfreq=50) data.pprint(show_unit=True)
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
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