예제 #1
0
def spire_postprocess1(indir, outdir, obsid, obj):
    """
    Dedicated for 1-D spectra analysis.
    convert the ASCII format of the spectra to a better format for reading, and perform spectrum trimming.
    """
    from astropy.io import ascii, fits
    import numpy as np

    # read in the spectrum
    spire_spec = ascii.read(indir + obsid + 'spire_sect.txt', data_start=4)
    # convert it to the usual format
    spire_wl = np.hstack((
        spire_spec['wave_segm1_0'][spire_spec['wave_segm1_0'] >= 310].data,
        spire_spec['wave_segm2_0'][(spire_spec['wave_segm2_0'] < 310)
                                   & (spire_spec['wave_segm2_0'] > 195)].data))
    spire_flux = np.hstack((
        spire_spec['flux_segm1_0'][spire_spec['wave_segm1_0'] >= 310].data,
        spire_spec['flux_segm2_0'][(spire_spec['wave_segm2_0'] < 310)
                                   & (spire_spec['wave_segm2_0'] > 195)].data))

    sorter = np.argsort(spire_wl)
    spire_wl = spire_wl[sorter].data
    spire_flux = spire_flux[sorter].data

    # Write to file
    foo = open(outdir + obj + '/spire/data/' + obj + '_spire_corrected.txt',
               'w')
    foo.write('%s \t %s \n' % ('Wavelength(um)', 'Flux_Density(Jy)'))
    for i in range(len(spire_wl)):
        foo.write('%f \t %f \n' % (spire_wl[i], spire_flux[i]))
    foo.close()

    # perform line fitting
    import pidly
    # grad13yy
    # idl = pidly.IDL('/Applications/exelis/idl83/bin/idl')
    # bettyjo
    idl = pidly.IDL('/opt/local/exelis/idl83/bin/idl')
    idl('.r ' + os.path.expanduser('~') +
        '/programs/line_fitting/extract_spire.pro')
    # read the coordinates from cube fits file
    hdu = fits.open(obsid + '_spectrum_extended_HR_aNB_15.fits')
    ra = hdu[0].header['RA']
    dec = hdu[0].header['DEC']
    idl.pro('extract_spire',
            indir=outdir + obj + '/spire/data/',
            filename=obj + '_spire_corrected',
            outdir=outdir + obj + '/spire/advanced_products/',
            plotdir=outdir + obj + '/spire/advanced_products/plots/',
            localbaseline=10,
            global_noise=20,
            ra=ra,
            dec=dec,
            noiselevel=3,
            fx=1,
            object=obj,
            flat=1,
            continuum=1,
            double_gauss=1,
            no_plot=0)
예제 #2
0
파일: sheq.py 프로젝트: pdvanmeter/meSXR
def sheq_averages(shot, time, return_all=False):
    """
    Returns flux-surface averaged quantities of physical significance.
    
    Inputs:
        - shot = MST shot number, corresponding to an existing NCT run.
        - time = Time point in ms, corresponding to an existing NCT run.
        - return_all = Set to True to instead return the full sh_averages.pro structure.
    """
    idl = pidly.IDL()
    idl('.r /home/pdvanmeter/lib/idl/startup.pro')
    idl('.r run_sheq')
    idl('averages = sheq_flux_avg({0:}, {1:})'.format(shot, time))
    avg = AttrDict(idl.ev('averages'))
    idl.close()
    
    if return_all:
        return avg
    else:
        return AttrDict({
            'rhop':avg.rhop,
            'rhoh':avg.rhoh,
            'J_pol':avg.jpol/1e6,
            'J_tor':avg.jtor/1e6,
            'B_pol':avg.bpol,
            'B_tor':avg.btor,
            'B':avg.b,
            'B2':avg.b2,
            'JB':-avg.jb/1e6,
            'J_para':-avg.jb/avg.b/1e6,
            'mua':-avg.mua,
            'q':-avg.q,
            'delta':float(avg.delta_axis)
        })
예제 #3
0
def get_flux(burst_data, t, ftopt, band):
    '''
    do this in the burst#_fitting folder.
    burst_data = file path to the burst_data.dat file containing photometry
    t = time in seconds you wish to obtain the flux
    ftopt = file path to the ftopt fitting parameter file 
    band = string of desired band (J, H, or K)
    '''
    band = band.upper()  #making sure band in upper case
    import pidly
    idl_path = '/Applications/itt/idl71/bin/idl'
    idl = pidly.IDL(idl_path)
    #Performing Fit

    IDL_command = "lcurve, '" + str(
        burst_data) + "', reffilt='J', ftopt='" + str(
            ftopt) + "', timeunit='sec', yr=[21,12], tspec=" + str(
                t) + "., captionfmt='(F6.2)', /residual"
    idl(IDL_command)

    #Read the filename
    filename = burst_data.rstrip('.dat') + 'datased.dat'
    f = open(filename, 'r')
    lines = f.readlines()
    for line in lines:
        if band in line:
            flux = (line.split()[1], line.split()[2])

    return flux
예제 #4
0
def kelly(x1, x2, x1err=[], x2err=[], cerr=[], logify=True,
          miniter=5000, maxiter=1e5, metro=True,
          silent=True):
    """
    Python wrapper for the linear regression MCMC of Kelly (2007).
    Requires pidly (http://astronomy.sussex.ac.uk/~anthonys/pidly/) and
    an IDL license.

    Parameters
    ----------
      x1        : array of floats
                  Independent variable, or observable
      x2        : array of floats
                  Dependent variable
      x1err     : array of floats (optional)
                  Uncertainties on the independent variable
      x2err     : array of floats (optional)
                  Uncertainties on the dependent variable
      cerr      : array of floats (optional)
                  Covariances of the uncertainties in the dependent and
                  independent variables
    """
    import pidly
    
    n = len(x1)
    if len(x2) != n:
        raise ValueError('x1 and x2 must have same length')
    if len(x1err) == 0:
        x1err = numpy.zeros(n)
    if len(x2err) == 0:
        x2err = numpy.zeros(n)
    if logify:
        x1, x2, x1err, x2err = to_log(x1, x2, x1err, x2err)
    idl = pidly.IDL()
    idl('x1 = %s' %list(x1))
    idl('x2 = %s' %list(x2))
    cmd = 'linmix_err, x1, x2, fit'
    if len(x1err) == n:
        idl('x1err = %s' %list(x1err))
        cmd += ', xsig=x1err'
    if len(x2err) == n:
        idl('x2err = %s' %list(x2err))
        cmd += ', ysig=x2err'
    if len(cerr) == n:
        idl('cerr = %s' %list(cerr))
        cmd += ', xycov=cerr'
    cmd += ', miniter=%d, maxiter=%d' %(miniter, maxiter)
    if metro:
        cmd += ', /metro'
    if silent:
        cmd += ', /silent'
    idl(cmd)
    alpha = idl.ev('fit.alpha')
    beta = idl.ev('fit.beta')
    sigma = numpy.sqrt(idl.ev('fit.sigsqr'))
    return alpha, beta, sigma
예제 #5
0
def find(fits_file,thresh=100, fwhm=18 ):


    idl = pidly.IDL()
    idl('.compile find')
    idl('.compile fits_read')
    idl('fits_read, "'+fits_file+'", im, hdr')
    idl('find, im, x, y, flux, sharp, round, '+str(thresh)+','+str(fwhm)+', [0.1,1.0] , [-1.0,1.0]')
    import pdb;pdb.set_trace()
    return idl.x, idl.y, idl.flux
예제 #6
0
def idl_init():
    """Initialise IDL by setting paths and compiling relevant files.
    """
    idl = pidly.IDL()
    idl("!path = '/home/thomasn/idl_libraries/coyote:' + !path")
    idl(".compile /home/thomasn/grids/gaussbroad.pro")
    idl(".compile /home/thomasn/grids/get_spec.pro")
    idl("grid='/home/thomasn/grids/grid_synthspec.sav'")
    
    return idl
예제 #7
0
def find(imfile,psffile,  xr, yr, abs_thresh=.1, corr=0.5):
    '''
    uses a known reference psf to find the positions for a star in the new frame
    '''

    idl = pidly.IDL()
    idl.xr = np.array(xr)
    idl.yr = np.array(yr)
    idl('corr = '+str(corr))
    idl("fits_read, '"+imfile+"', image, hdr")
    idl("fits_read, '"+psffile+"', psf, hdr")
    idl('starfinder, image, psf, background = background,'+str(abs_thresh)+',corr, N_ITER = 2, x, y, f, sx, sy, sf, c,STARS = stars')
    return idl.x, idl.y, idl.f, idl.c
예제 #8
0
파일: nickal2.py 프로젝트: pdvanmeter/meSXR
def load_brightness(shot_num, t_start=8.0, t_end=28.0, delta=0.1, smooth=10.0):
    """
    Function: st = load_brightness(shot_num, t_start, t_end, delta, smooth)
        This version of load_brightness interfaces directly with the IDL implementation, via the pidly interface.
    Inputs:
        - shot_num = [INT] The MST shot ID for the desired set of data
        - t_start = [FLOAT] The start time for the desired interval of SXR data.
        - t_end = [FLOAT] The end time for the desired interval of SXR data.
        - delta = [FLOAT] The desired sampling window for SXR data.
        - smooth = [FLOAT] The size of the smoothing window (10.0 is standard).
    Outputs:
        - st['key'] = [DICT] Nested dictionary containing the SXR tomography diagnostic data, indexed by camera label.
    """
    # Access (and initialize, if needed) the pidly object and assemble the command string
    idl = pidly.IDL()
    idl_str = "n2d = NICKAL2_signal(" + str(shot_num) + ", tstart=" + str(
        t_start)
    idl_str += ", tend=" + str(t_end) + ", delta=" + str(
        delta) + ", sm=" + str(smooth) + ")"
    idl('cd, "/home/pdvanmeter/lib/idl"')
    idl('.r NICKAL2_signal')
    idl(idl_str)

    # Extract the data from IDL and format
    data = {
        'AlBe': idl.ev('n2d.data.al'),
        'SiBe': idl.ev('n2d.data.si'),
        'ZrMylar': idl.ev('n2d.data.zr')
    }

    error = {
        'AlBe': idl.ev('n2d.err.al'),
        'SiBe': idl.ev('n2d.err.si'),
        'ZrMylar': idl.ev('n2d.err.zr')
    }

    noise = {
        'AlBe': idl.ev('n2d.noise.al'),
        'SiBe': idl.ev('n2d.noise.si'),
        'ZrMylar': idl.ev('n2d.noise.zr')
    }

    tiempo = idl.ev('n2d.time')

    # Put the result together
    st = {'bright': data, 'sigma': error, 'noise': noise, 'time': tiempo}

    idl.close()
    return AttrDict(st)
예제 #9
0
    def __init__(self, shell, gdl=False):
        """
        Parameters
        ----------
        shell : IPython shell

        """
        super(IDLMagics, self).__init__(shell)
        #TODO: allow specifying path, executible on %load_ext
        try:
            self._idl = pidly.IDL()
        except ExceptionPexpect:
            try:
                # NB that pidly returns when it reads the text prompt--needs to
                # match that of the interpreter!
                self._idl = pidly.IDL('gdl', idl_prompt='GDL>')
                print 'IDL not found, using GDL'
            except ExceptionPexpect:
                raise IDLMagicError('Neither IDL or GDL interpreters found')
        self._plot_format = 'png'

        # Allow publish_display_data to be overridden for
        # testing purposes.
        self._publish_display_data = publish_display_data
예제 #10
0
def idl_track(query, max_disp, min_appearances, memory=3):
    """Call Crocker/Weeks track.pro from IDL using pidly module.
    Returns one big array, where the last column is the probe ID."""
    idl = pidly.IDL()
    logger.info("Opened IDL process.")
    idl('pt = get_sql("{}")'.format(query))
    logger.info(
        "IDL is done loading features from the database. Now tracking....")
    idl('t=track(pt, {}, goodenough={}, memory={})'.format(
        max_disp, min_appearances, memory))
    logger.info("IDL finished tracking. Now piping data into Python....")
    # 0: x, 1: y, 2: mass, 3: size, 4: ecc, 5: frame, 6: probe_id
    t = idl.ev('t')
    idl.close()
    return t
예제 #11
0
    def __init__(self, gdl_path='/usr/bin/gdl'):

        self.idl = pidly.IDL(gdl_path, idl_prompt='GDL> ')
        self.l1b_data = None
        self.bands = {
            'PARASOL': [
                '443', '490p', '490u', '490q', '565', '670p', '670u', '670q',
                '763', '765', '865p', '865u', '865q', '910', '1020'
            ],
            'MERIS': [
                '412', '443', '490', '510', '560', '620', '665', '681', '708',
                '753', '761', '778', '865', '885', '900'
            ]
        }  ## !!! these are the same as DIMITRI FOR NOW!! CHECK
        self.sensor_name = 'PARASOL'
        self.num_bands = 16
예제 #12
0
def extract_im(imfile,
               xr,
               yr,
               fr,
               sigfile,
               psf_size,
               abs_thresh=15,
               corr=0.5,
               residual_file='none',
               back=False,
               find_pos=True):
    '''
    runs starfinder
    '''

    idl = pidly.IDL()
    idl.xr = np.array(xr)
    idl.yr = np.array(yr)
    idl.fr = np.array(fr)
    idl('corr = ' + str(corr))
    #import pdb;pdb.set_trace()
    idl("fits_read, '" + imfile + "', image, hdr")
    idl('fits_read, "' + sigfile + '", std_noise, hdr')

    idl('psf_extract, xr, yr, [0], [0], image,' + str(psf_size) +
        ', psf, psf_fwhm, background, iter=2,/rad_norm')
    #smarter version of postfix
    pf = imfile.split('.')[-1]
    #import pdb;pdb.set_trace()
    idl('fits_write,"' + imfile.replace('.' + pf, '_psf.' + pf) + '", psf')
    #import pdb;pdb.set_trace()
    if back:
        idl('fits_read, "back.fits", background, bhdr')
    if find_pos:
        idl('starfinder, image, psf, background = background,' +
            str(abs_thresh) +
            ',corr, N_ITER = 2, x, y, f, sx, sy, sf, c,STARS = stars')
    else:
        idl('starfinder, image, psf, background = background,' +
            str(abs_thresh) +
            ',corr, N_ITER = 2, x, y, f, sx, sy, sf, c,X_INPUT=xr, Y_INPUT=yr, F_INPUT=fr,STARS = stars'
            )
    if residual_file != 'none':
        idl('fits_write,"' + residual_file + '", image-stars, hdr')
        #idl('fits_write,"'+residual_file.replace('res', 'stars')+'", stars, hdr')

    return idl.x, idl.y, idl.f, idl.c
예제 #13
0
파일: sheq.py 프로젝트: pdvanmeter/meSXR
def get_flux_grid(shot, time, phi=222.5*deg2rad):
    """
    Use SHEq to directly access the NCT output to evaluate rho on a grid of (R,Z) points.
    
    Inputs:
        - shot = MST shot number, corresponding to an existing NCT run.
        - time = Time point in ms, corresponding to an existing NCT run.
        - phi = Toroidal angle in radians.
    """
    idl = pidly.IDL()
    idl('.r /home/pdvanmeter/lib/idl/startup.pro')
    idl('.r run_sheq')
    idl('flux = run_sheq({0:}, {1:}, phi0={2:})'.format(shot, time, phi))
    flux_grid = idl.ev('flux')
    idl.close()
    
    flux_grid['rho'] = flux_grid['rho'].T
    return AttrDict(flux_grid)
예제 #14
0
def SPIRE1d_fit(indir, objname, global_dir, wl_shift=0):
    import os
    from astropy.io import ascii
    if not os.path.isfile(indir+'data/'+objname+'_spire_corrected.txt'):
        print(objname+' is not found.')
        return None

    # read RA/Dec
    radec_slw = ascii.read(indir+'/data/cube/'+objname+'_radec_slw.txt')

    import pidly
    idl = pidly.IDL('/opt/local/exelis/idl83/bin/idl')
    idl('.r /home/bettyjo/yaolun/programs/line_fitting/gauss.pro')
    idl('.r /home/bettyjo/yaolun/programs/line_fitting/extract_spire.pro')
    idl.pro('extract_spire', indir=indir+'data/', filename=objname+'_spire_corrected',
            outdir=indir+'advanced_products/', plotdir=indir+'advanced_products/plots/', noiselevel=3,
            ra=radec_slw['RA(deg)'][radec_slw['Pixel'] == 'SLWC3'], dec=radec_slw['Dec(deg)'][radec_slw['Pixel'] == 'SLWC3'],
            global_noise=20, localbaseline=10, continuum=1, flat=1, object=objname, double_gauss=1, fx=1, current_pix=1,
            print_all=global_dir+'_lines', wl_shift=wl_shift)
예제 #15
0
def dewarp(cam, pardir, indir=None, outdir=None):
    '''Do the dewarping following the NICI campaign paper 
    ( http://iopscience.iop.org/article/10.1086/679508/pdf ). This uses IDL,
    so make sure it is installed. Wrapper is pidly'''
    import pidly

    fnwarp = os.path.join(pardir, 'niciwarp_' + cam + '.sav')
    print('Dewarping using IDL. Assuming dewarp file is {}'.format(fnwarp))
    filetable = ascii.read(os.path.join(indir, 'filetable_bkgrnd.csv'),
                           delimiter=',')
    filetable[
        'fndewarped'] = 'error_in_dewarping_the_filename' * 3  #make sure string is long enough
    nfiles = len(filetable)
    print('Dewarping the {} files'.format(nfiles))
    idl = pidly.IDL()
    idl('restore,"' + fnwarp + '"')
    for ifile in range(nfiles):
        if (ifile % 10) == 0:
            #somehow IDL crashes after ~25 images. restart it more often
            print('Dewarping file {} / {} files'.format(ifile, nfiles))
            #if (ifile != 0) and (ifile != nfiles-1): idl.close()
            #idl = pidly.IDL()
            #idl('restore,"'+fnwarp+'"')
        fn = filetable['fninterm'][ifile]
        fnout = os.path.join(outdir, os.path.split(fn)[-1])
        filetable['fndewarped'][ifile] = fnout
        idl('fits_open,"' + fn + '", fcb')
        idl('fits_read, fcb, im, hdr')
        idl('fits_close,fcb')
        idl('im_w = poly_2d(im, kx, ky, 2, cubic=-0.5)')
        idl('fits_open,"' + fnout + '",fout,/WRITE')
        idl('fits_write,fout,im_w,hdr')
        idl('fits_close,fout')

    idl.close()
    ascii.write(filetable,
                output=os.path.join(outdir, 'filetable_bkgrnd.csv'),
                delimiter=',',
                overwrite=True)
예제 #16
0
파일: cdf_pacs_1d.py 프로젝트: yaolun/sa
def cdf_pacs_1d(osbid, objname, outdir, fits_for_header, line_fitting_dir):
    """
    cubedir: the directory contains FITS rebinned cube
    outcubedir: the directory contains ASCII style spectra for each spaxel
    out1ddir: the directory contains ASCII style 1-D spectrum
    """

    from pacs_weight import pacs_weight
    import numpy as np
    import matplotlib.pyplot as plt
    from astropy.io import ascii, fits
    import pidly
    idl = pidly.IDL('/Applications/exelis/idl83/bin/idl')

    # outdir = '/Users/yaolun/bhr71/best_calibrated/'
    # cubedir = '/Users/yaolun/bhr71/data/HSA/'
    # photpath = '/Users/yaolun/bhr71/best_calibrated/bhr71.txt'

    cubedir = outdir+'data/fits/'

    cubefile = [cubedir+'OBSID_'+obsid[0]+'_blue_finalcubes_slice00_os8_sf7.fits',
                cubedir+'OBSID_'+obsid[0]+'_red_finalcubes_slice00_os8_sf7.fits',
                cubedit+'OBSID_'+obsid[1]+'_blue_finalcubes_slice00_os8_sf7.fits',
                cubedir+'OBSID_'+obsid[1]+'_red_finalcubes_slice00_os8_sf7.fits',]

    idl('.r '+line_fitting_dir+'get_pacs.pro')
    idl.pro('get_pacs', outdir=outdir+'data/cube/', objname=objname, filename=cubefile, suffix='os8_sf7')

    wl, flux = pacs_weight(outdir+'data/cube/', objname, 31.8, outdir+'data/', fits_for_header, suffix='os8_sf7')

    idl('.r '+line_fitting_dir+'gauss.pro')
    idl('.r '+line_fitting_dir+'extract_pacs.pro')

    idl.pro('extract_pacs', indir=outdir+'data/', filename=objname+'_pacs_weighted',
            outdir=outdir+'advanced_products/',
            plotdir=outdir+'advanced_products/plots/', noiselevel=3, ra=0, dec=0, global_noise=20,
            localbaseline=10, opt_width=1, continuum=1, flat=1, object=objname, double_gauss=1, fixed_width=1)
예제 #17
0
def call_func(func_name, idl_path='idl', *func_args, **func_kwargs):
    idl = pidly.IDL(idl_path)
    result = idl.func(func_name, *func_args, **func_kwargs)
    idl.close()
    return result
예제 #18
0
def setup_model(outdir,record_dir,outname,params,dust_file,tsc=True,idl=False,plot=False,\
                low_res=True,flat=True,scale=1,radmc=False,mono=False,mono_wave=None,
                record=True,dstar=200.,aperture=None,dyn_cav=False,fix_params=None,
                power=2,better_im=False,ellipsoid=False,TSC_dir='~/programs/misc/TSC/',
                IDL_path='/Applications/exelis/idl83/bin/idl',auto_disk=0.25,fast_plot=False,
                image_only=False, tsc_com=False, ext_source=None):
    """
    params = dictionary of the model parameters
    'alma' keyword is obsoleted
    outdir: The directory for storing Hyperion input files
    record_dir: The directory contains "model_list.txt" for recording parameters
    TSC_dir: Path the TSC-related IDL routines
    IDL_path: The IDL executable
    fast_plot: Do not plot the polar plot of the density because the rendering
               takes quite a lot of time.
    mono: monochromatic radiative transfer mode (need to specify the wavelength
          or a list of wavelength with 'mono_wave')
    image_only: only run for images
    """
    import numpy as np
    import astropy.constants as const
    from astropy.io import ascii
    import scipy as sci
    # to avoid X server error
    import matplotlib as mpl
    mpl.use('Agg')
    #
    import matplotlib.pyplot as plt
    import os
    from matplotlib.colors import LogNorm
    from scipy.integrate import nquad
    from hyperion.model import Model
    from record_hyperion import record_hyperion
    from outflow_inner_edge import outflow_inner_edge
    from pprint import pprint

    # Constants setup
    c         = const.c.cgs.value
    AU        = const.au.cgs.value     # Astronomical Unit       [cm]
    pc        = const.pc.cgs.value     # Parsec                  [cm]
    MS        = const.M_sun.cgs.value  # Solar mass              [g]
    LS        = const.L_sun.cgs.value  # Solar luminosity        [erg/s]
    RS        = const.R_sun.cgs.value  # Solar radius            [cm]
    G         = const.G.cgs.value      # Gravitational constant  [cm3/g/s^2]
    yr        = 60*60*24*365           # Years in seconds
    PI        = np.pi                  # PI constant
    sigma     = const.sigma_sb.cgs.value  # Stefan-Boltzmann constant
    mh        = const.m_p.cgs.value + const.m_e.cgs.value
    g2d       = 100.
    mmw       = 2.37                   # Kauffmann 2008

    m = Model()

    # min and max wavelength to compute (need to define them first for checking dust properties)
    # !!!
    wav_min = 2.0
    wav_max = 1400.
    wav_num = 1400

    # Create dust properties
    # Hyperion needs nu, albedo, chi, g, p_lin_max
    from hyperion.dust import HenyeyGreensteinDust
    # Read in the dust opacity table used by RADMC-3D
    dust = dict()
    [dust['nu'], dust['albedo'], dust['chi'], dust['g']] = np.genfromtxt(dust_file).T
    d = HenyeyGreensteinDust(dust['nu'], dust['albedo'], dust['chi'], dust['g'], dust['g']*0)
    # dust sublimation option
    d.set_sublimation_temperature('slow', temperature=1600.0)
    d.set_lte_emissivities(n_temp=3000,
                           temp_min=0.1,
                           temp_max=2000.)
    # if the min and/or max wavelength fall out of range
    if c/wav_min/1e-4 > dust['nu'].max():
        d.optical_properties.extrapolate_nu(dust['nu'].min(), c/wav_min/1e-4)
        print 'minimum wavelength is out of dust model.  The dust model is extrapolated.'
    if c/wav_max/1e-4 < dust['nu'].min():
        d.optical_properties.extrapolate_nu(c/wav_max/1e-4, dust['nu'].max())
        print 'maximum wavelength is out of dust model.  The dust model is extrapolated.'

    # try to solve the freq. problem
    d.optical_properties.extrapolate_nu(3.28e15, 5e15)
    #
    d.write(outdir+os.path.basename(dust_file).split('.')[0]+'.hdf5')
    d.plot(outdir+os.path.basename(dust_file).split('.')[0]+'.png')
    plt.clf()

    # Grids and Density

    # Grid Parameters
    nx        = 300L
    if low_res == True:
        nx    = 100L
    ny        = 400L
    nz        = 50L
    [nx, ny, nz] = [int(scale*nx), int(scale*ny), int(scale*nz)]

    # TSC model input setting
    dict_params = params
    # TSC model parameter
    cs        = dict_params['Cs']*1e5
    t         = dict_params['age']  # year
    omega     = dict_params['Omega0']
    # calculate related parameters
    M_env_dot = 0.975*cs**3/G
    mstar     = M_env_dot * t * yr
    R_cen     = omega**2 * G**3 * mstar**3 /(16*cs**8)
    R_inf     = cs * t * yr
    # protostar parameter
    tstar     = dict_params['tstar']
    R_env_max = dict_params['R_env_max']*AU
    theta_cav = dict_params['theta_cav']
    rho_cav_center = dict_params['rho_cav_center']
    rho_cav_edge   = dict_params['rho_cav_edge']*AU
    rstar     = dict_params['rstar']*RS
    # Mostly fixed parameter
    M_disk    = dict_params['M_disk']*MS
    beta      = dict_params['beta']
    h100      = dict_params['h100']*AU
    rho_cav   = dict_params['rho_cav']
    # make M_disk varies with mstar, which is the mass of star+disk
    if auto_disk != None:
        if M_disk != 0:
            print 'M_disk is reset to %4f of mstar (star+disk)' % auto_disk
            M_disk = mstar * auto_disk
        else:
            print 'M_disk = 0 is found.  M_disk is set to 0.'

    # ellipsoid cavity parameter
    if ellipsoid == True:
        # the numbers are given in arcsec
        a_out = 130 * dstar * AU
        b_out = 50  * dstar * AU
        z_out = a_out
        a_in  = dict_params['a_in'] * dstar * AU
        b_in  = a_in/a_out*b_out
        z_in  = a_in
        rho_cav_out = dict_params['rho_cav_out'] * mh
        rho_cav_in  = dict_params['rho_cav_in']  * mh
    # Calculate the dust sublimation radius
    T_sub = 1600
    a     = 1   # in micron
    # realistic dust
    # d_sub = 2.9388e7*(a/0.1)**-0.2 * (4*np.pi*rstar**2*sigma*tstar**4/LS)**0.5 / T_sub**3 *AU
    # black body dust
    d_sub = (LS/16./np.pi/sigma/AU**2*(4*np.pi*rstar**2*sigma*tstar**4/LS)/T_sub**4)**0.5 *AU
    # use the dust sublimation radius as the inner radius of disk and envelope
    R_disk_min = d_sub
    R_env_min  = d_sub
    rin        = rstar
    rout       = R_env_max
    R_disk_max = R_cen

    # print the variables
    print 'Dust sublimation radius %6f AU' % (d_sub/AU)
    print 'M_star %4f Solar mass' % (mstar/MS)
    print 'Infall radius %4f AU' % (R_inf / AU)

    # if there is any parameter found in fix_params, then fix them
    if fix_params != None:
        if 'R_min' in fix_params.keys():
            R_disk_min = fix_params['R_min']*AU
            R_env_min  = fix_params['R_min']*AU

    # Make the Coordinates
    #
    # if ext_source != None:
    #     rout = R_env_max*1.1
    ri           = rin * (rout/rin)**(np.arange(nx+1).astype(dtype='float')/float(nx))
    ri           = np.hstack((0.0, ri))
    thetai       = PI*np.arange(ny+1).astype(dtype='float')/float(ny)
    phii         = PI*2.0*np.arange(nz+1).astype(dtype='float')/float(nz)

    # Keep the constant cell size in r-direction at large radii
    #
    if flat == True:
        ri_cellsize = ri[1:-1]-ri[0:-2]
        ind = np.where(ri_cellsize/AU > 100.0)[0][0]       # The largest cell size is 100 AU
        ri = np.hstack((ri[0:ind],ri[ind]+np.arange(np.ceil((rout-ri[ind])/100/AU))*100*AU))
        nxx = nx
        nx = len(ri)-1
    # Assign the coordinates of the center of cell as its coordinates.
    #
    rc           = 0.5*( ri[0:nx]     + ri[1:nx+1] )
    thetac       = 0.5*( thetai[0:ny] + thetai[1:ny+1] )
    phic         = 0.5*( phii[0:nz]   + phii[1:nz+1] )

    # for non-TSC model
    if tsc_com:
        import hyperion as hp
        from hyperion.model import AnalyticalYSOModel

        non_tsc = AnalyticalYSOModel()

        # Define the luminsoity source
        nt_source = non_tsc.add_spherical_source()
        nt_source.luminosity = (4*PI*rstar**2)*sigma*(tstar**4)  # [ergs/s]
        nt_source.radius = rstar  # [cm]
        nt_source.temperature = tstar  # [K]
        nt_source.position = (0., 0., 0.)
        nt_source.mass = mstar

        # Envelope structure
        #
        nt_envelope = non_tsc.add_ulrich_envelope()
        nt_envelope.mdot = M_env_dot    # Infall rate
        nt_envelope.rmin = rin          # Inner radius
        nt_envelope.rc   = R_cen        # Centrifugal radius
        nt_envelope.rmax = R_env_max    # Outer radius
        nt_envelope.star = nt_source

        nt_grid = hp.grid.SphericalPolarGrid(ri, thetai, phii)

        rho_env_ulrich = nt_envelope.density(nt_grid).T
        rho_env_ulrich2d = np.sum(rho_env_ulrich**2,axis=2)/np.sum(rho_env_ulrich,axis=2)

    # Make the dust density model
    # Make the density profile of the envelope
    #
    total_mass = 0
    if tsc == False:
        print 'Calculating the dust density profile with infall solution...'
        if theta_cav != 0:
            # using R = 10000 AU as the reference point
            c0 = (10000.*AU)**(-0.5)*np.sqrt(1/np.sin(np.radians(theta_cav))**3-1/np.sin(np.radians(theta_cav)))
        else:
            c0 = 0
        rho_env  = np.zeros([len(rc),len(thetac),len(phic)])
        rho_disk = np.zeros([len(rc),len(thetac),len(phic)])
        rho      = np.zeros([len(rc),len(thetac),len(phic)])

        if dyn_cav == True:
            print 'WARNING: Calculation of interdependent cavity property has not implemented in infall-only solution!'
        # Normalization for the total disk mass
        def f(w,z,beta,rstar,h100):
            f = 2*PI*w*(1-np.sqrt(rstar/w))*(rstar/w)**(beta+1)*np.exp(-0.5*(z/(w**beta*h100/100**beta))**2)
            return f

        rho_0 = M_disk/(nquad(f,[[R_disk_min,R_disk_max],[-R_env_max,R_env_max]], args=(beta,rstar,h100)))[0]
        i = 0
        j = 0
        if 'rho_cav_center' in locals() == False:
            rho_cav_center = 5e-19
            print 'Use 5.27e-18 as the default value for cavity center'
        if 'rho_cav_edge' in locals() == False:
            rho_cav_edge = 40*AU
            print 'Use 40 AU as the default value for size of the inner region'
        discont = 1
        for ir in range(0,len(rc)):
            for itheta in range(0,len(thetac)):
                for iphi in range(0,len(phic)):
                    if rc[ir] > R_env_min:
                        # Envelope profile
                        w = abs(rc[ir]*np.cos(np.pi/2 - thetac[itheta]))
                        z = rc[ir]*np.sin(np.pi/2 - thetac[itheta])

                        if ellipsoid == False:
                            z_cav = c0*abs(w)**1.5
                            if z_cav == 0:
                                z_cav = R_env_max
                            cav_con = abs(z) > abs(z_cav)
                            if theta_cav == 90:
                                cav_con = True
                        else:
                            # condition for the outer ellipsoid
                            cav_con = (2*(w/b_out)**2 + ((abs(z)-z_out)/a_out)**2) < 1
                        if cav_con:
                            # open cavity
                            if ellipsoid == False:
                                if rho_cav_edge == 0:
                                    rho_cav_edge = R_env_min
                                if (rc[ir] <= rho_cav_edge) & (rc[ir] >= R_env_min):
                                    rho_env[ir,itheta,iphi] = g2d * rho_cav_center
                                else:
                                    rho_env[ir,itheta,iphi] = g2d * rho_cav_center*discont*(rho_cav_edge/rc[ir])**power
                                i += 1
                            else:
                                # condition for the inner ellipsoid
                                if (2*(w/b_in)**2 + ((abs(z)-z_in)/a_in)**2) > 1:
                                    rho_env[ir,itheta,iphi] = rho_cav_out
                                else:
                                    rho_env[ir,itheta,iphi] = rho_cav_in
                                i +=1
                        else:
                            j += 1
                            mu = abs(np.cos(thetac[itheta]))
                            # Implement new root finding algorithm
                            roots = np.roots(np.array([1.0, 0.0, rc[ir]/R_cen-1.0, -mu*rc[ir]/R_cen]))
                            if len(roots[roots.imag == 0]) == 1:
                                if (abs(roots[roots.imag == 0]) - 1.0) <= 0.0:
                                    mu_o_dum = roots[roots.imag == 0]
                                else:
                                    mu_o_dum = -0.5
                                    print 'Problem with cubic solving, cos(theta) = ', mu_o_dum
                                    print 'parameters are ', np.array([1.0, 0.0, rc[ir]/R_cen-1.0, -mu*rc[ir]/R_cen])
                            else:
                                mu_o_dum = -0.5
                                for imu in range(0, len(roots)):
                                    if roots[imu]*mu >= 0.0:
                                        if (abs((abs(roots[imu]) - 1.0)) <= 1e-5):
                                            mu_o_dum = 1.0 * np.sign(mu)
                                        else:
                                            mu_o_dum = roots[imu]
                                if mu_o_dum == -0.5:
                                    print 'Problem with cubic solving, roots are: ', roots
                            mu_o = mu_o_dum.real
                            rho_env[ir,itheta,iphi] = M_env_dot/(4*PI*(G*mstar*R_cen**3)**0.5)*(rc[ir]/R_cen)**(-3./2)*(1+mu/mu_o)**(-0.5)*(mu/mu_o+2*mu_o**2*R_cen/rc[ir])**(-1)
                        # Disk profile
                        if ((w >= R_disk_min) and (w <= R_disk_max)) == True:
                            h = ((w/(100*AU))**beta)*h100
                            rho_disk[ir,itheta,iphi] = rho_0*(1-np.sqrt(rstar/w))*(rstar/w)**(beta+1)*np.exp(-0.5*(z/h)**2)
                        # Combine envelope and disk
                        rho[ir,itheta,iphi] = rho_disk[ir,itheta,iphi] + rho_env[ir,itheta,iphi]
                    else:
                        rho[ir,itheta,iphi] = 1e-30
                    # add the dust mass into the total count
                    cell_mass = rho[ir, itheta, iphi] * (1/3.)*(ri[ir+1]**3 - ri[ir]**3) * (phii[iphi+1]-phii[iphi]) * -(np.cos(thetai[itheta+1])-np.cos(thetai[itheta]))
                    total_mass = total_mass + cell_mass

        rho_env  = rho_env  + 1e-40
        rho_disk = rho_disk + 1e-40
        rho      = rho      + 1e-40
    # TSC model
    else:
        print 'Calculating the dust density profile with TSC solution...'
        if theta_cav != 0:
            c0 = (1e4*AU)**(-0.5)*np.sqrt(1/np.sin(np.radians(theta_cav))**3-1/np.sin(np.radians(theta_cav)))
        else:
            c0 = 0
        # If needed, calculate the TSC model via IDL
        #
        if idl == True:
            print 'Using IDL to calculate the TSC model.  Make sure you are running this on mechine with IDL.'
            import pidly
            idl = pidly.IDL(IDL_path)
            idl('.r '+TSC_dir+'tsc.pro')
            idl('.r '+TSC_dir+'tsc_run.pro')
            #
            # only run TSC calculation within infall radius
            # modify the rc array
            ind_infall = np.where(rc >= R_inf)[0][0]
            if max(ri) > R_inf:
                rc_idl = rc[0:ind_infall+1]
            else:
                rc_idl = rc[rc < max(ri)]
            idl.pro('tsc_run', indir=TSC_dir, outdir=outdir, rc=rc_idl, thetac=thetac, time=t,
                    c_s=cs, omega=omega, renv_min=R_env_min)
            file_idl = 'rhoenv.dat'
        else:
            print 'Read the pre-computed TSC model.'
            ind_infall = np.where(rc >= R_inf)[0][0]
            if max(ri) > R_inf:
                rc_idl = rc[0:ind_infall+1]
            else:
                rc_idl = rc[rc < max(ri)]
            if idl != False:
                file_idl = idl

        # read in the exist file
        rho_env_tsc_idl = np.genfromtxt(outdir+file_idl).T
        # because only region within infall radius is calculated by IDL program,
        # need to project it to the original grid
        rho_env_tsc = np.zeros([len(rc), len(thetac)])
        for irc in range(len(rc)):
            if rc[irc] in rc_idl:
                rho_env_tsc[irc,:] = rho_env_tsc_idl[np.squeeze(np.where(rc_idl == rc[irc])),:]

        # extrapolate for the NaN values at the outer radius, usually at radius beyond the infall radius
        # using r^-2 profile at radius greater than infall radius
        # and map the 2d strcuture onto 3-D grid
        # map TSC solution from IDL to actual 2-D grid
        rho_env_tsc2d = np.empty((nx,ny))
        if max(ri) > R_inf:
            for i in range(0, len(rc)):
                if i <= ind_infall:
                    rho_env_tsc2d[i,:] = rho_env_tsc[i,:]
                else:
                    rho_env_tsc2d[i,:] =  10**(np.log10(rho_env_tsc[ind_infall,:]) - 2*(np.log10(rc[i]/rc[ind_infall])))
        else:
            rho_env_tsc2d = rho_env_tsc
        # map it to 3-D grid
        rho_env = np.empty((nx,ny,nz))
        for i in range(0, nz):
            rho_env[:,:,i] = rho_env_tsc2d

        # typical no used.  Just an approach I tried to make the size of the
        # constant desnity region self-consistent with the outflow cavity.
        if dyn_cav == True:
            print 'Calculate the cavity properties using the criteria that swept-up mass = outflowed mass'
            # using swept-up mass = flow mass to derive the edge of the extended flat density region
            v_outflow = 1e2 * 1e5
            rho_cav_edge = outflow_inner_edge(np.copy(rho_env), (ri,thetai,phii),M_env_dot,v_outflow,theta_cav, R_env_min)
            dict_params['rho_cav_edge'] = rho_cav_edge
            # assume gas-to-dust ratio = 100
            rho_cav_center = 0.01 * 0.1*M_env_dot*rho_cav_edge/v_outflow/2 / (2*np.pi/3*rho_cav_edge**3*(1-np.cos(np.radians(theta_cav))))
            dict_params['rho_cav_center'] = rho_cav_center
            print 'inner edge is %5f AU and density is %e g/cm3' % (rho_cav_edge/AU, rho_cav_center)

        # create the array of density of disk and the whole structure
        #
        rho_disk = np.zeros([len(rc),len(thetac),len(phic)])
        rho      = np.zeros([len(rc),len(thetac),len(phic)])

        # non-TSC option
        if tsc_com:
            rho_ulrich = np.zeros([len(rc),len(thetac),len(phic)])

        # Calculate the disk scale height by the normalization of h100
        def f(w,z,beta,rstar,h100):
            f = 2*PI*w*(1-np.sqrt(rstar/w))*(rstar/w)**(beta+1)*np.exp(-0.5*(z/(w**beta*h100/100**beta))**2)
            return f
        # The function for calculating the normalization of disk using the total disk mass
        #
        rho_0 = M_disk/(nquad(f,[[R_disk_min,R_disk_max],[-R_env_max,R_env_max]], args=(beta,rstar,h100)))[0]
        i = 0
        j = 0

        # put in default outflow cavity setting if nothing is specified
        if 'rho_cav_center' in locals() == False:
            rho_cav_center = 5e-19
            print 'Use 5e-19 as the default value for cavity center'
        if 'rho_cav_edge' in locals() == False:
            rho_cav_edge = 40*AU
            print 'Use 40 AU as the default value for size of the inner region'
        discont = 1
        for ir in range(0,len(rc)):
            for itheta in range(0,len(thetac)):
                for iphi in range(0,len(phic)):
                    # for external heating option
                    if (rc[ir] > R_env_min):
                        # Envelope profile
                        w = abs(rc[ir]*np.cos(np.pi/2 - thetac[itheta]))
                        z = rc[ir]*np.sin(np.pi/2 - thetac[itheta])

                        if ellipsoid == False:
                            z_cav = c0*abs(w)**1.5
                            if z_cav == 0:
                                z_cav = R_env_max
                            cav_con = abs(z) > abs(z_cav)
                        else:
                            # condition for the outer ellipsoid
                            cav_con = (2*(w/b_out)**2 + ((abs(z)-z_out)/a_out)**2) < 1
                        if cav_con:
                            # open cavity
                            if ellipsoid == False:
                                if rho_cav_edge == 0:
                                    rho_cav_edge = R_env_min
                                if (rc[ir] <= rho_cav_edge) & (rc[ir] >= R_env_min):
                                    rho_env[ir,itheta,iphi] = g2d * rho_cav_center#*((rc[ir]/AU)**2)
                                    if tsc_com:
                                        rho_env_ulrich[ir,itheta,iphi] = rho_env[ir,itheta,iphi]
                                else:
                                    rho_env[ir,itheta,iphi] = g2d * rho_cav_center*discont*(rho_cav_edge/rc[ir])**power
                                    if tsc_com:
                                        rho_env_ulrich[ir,itheta,iphi] = rho_env[ir,itheta,iphi]
                                i += 1
                            else:
                                # condition for the inner ellipsoid
                                if (2*(w/b_in)**2 + ((abs(z)-z_in)/a_in)**2) > 1:
                                    rho_env[ir,itheta,iphi] = rho_cav_out
                                    if tsc_com:
                                        rho_env_ulrich[ir,itheta,iphi] = rho_env[ir,itheta,iphi]
                                else:
                                    rho_env[ir,itheta,iphi] = rho_cav_in
                                    if tsc_com:
                                        rho_env_ulrich[ir,itheta,iphi] = rho_env[ir,itheta,iphi]
                                i +=1

                        # Disk profile
                        if ((w >= R_disk_min) and (w <= R_disk_max)) == True:
                            h = ((w/(100*AU))**beta)*h100
                            rho_disk[ir,itheta,iphi] = rho_0*(1-np.sqrt(rstar/w))*(rstar/w)**(beta+1)*np.exp(-0.5*(z/h)**2)
                        # Combine envelope and disk
                        rho[ir,itheta,iphi] = rho_disk[ir,itheta,iphi] + rho_env[ir,itheta,iphi]
                        if tsc_com:
                            rho_ulrich[ir,itheta,iphi] = rho_disk[ir,itheta,iphi] + rho_env_ulrich[ir,itheta,iphi]
                    else:
                        rho[ir,itheta,iphi] = 1e-40
                        if tsc_com:
                            rho[ir,itheta,iphi] = 1e-40
                    # add the dust mass into the total count
                    cell_mass = rho[ir, itheta, iphi] * (1/3.)*(ri[ir+1]**3 - ri[ir]**3) * (phii[iphi+1]-phii[iphi]) * -(np.cos(thetai[itheta+1])-np.cos(thetai[itheta]))
                    total_mass = total_mass + cell_mass
    # apply gas-to-dust ratio of 100
    rho_dust = rho/g2d
    if tsc_com:
        rho_ulrich_dust = rho_ulrich/g2d
    total_mass_dust = total_mass/MS/g2d
    print 'Total dust mass = %f Solar mass' % total_mass_dust

    if record == True:
        # Record the input and calculated parameters
        params = dict_params.copy()
        params.update({'d_sub': d_sub/AU, 'M_env_dot': M_env_dot/MS*yr, 'R_inf': R_inf/AU, 'R_cen': R_cen/AU, 'mstar': mstar/MS, 'M_tot_gas': total_mass/MS})
        record_hyperion(params,record_dir)

    if plot == True:
        # rho2d is the 2-D projection of gas density
        # take the weighted average
        rho2d = np.sum(rho**2,axis=2)/np.sum(rho,axis=2)

        if tsc_com:
            rho2d = np.sum(rho_ulrich**2,axis=2)/np.sum(rho_ulrich,axis=2)

        if fast_plot == False:
            # Plot the azimuthal averaged density
            fig = plt.figure(figsize=(8,6))
            ax_env  = fig.add_subplot(111,projection='polar')

            zmin = 1e-22/mmw/mh
            zmin = 1e-1
            cmap = plt.cm.CMRmap
            rho2d_exp = np.hstack((rho2d,rho2d,rho2d[:,0:1]))
            thetac_exp = np.hstack((thetac-PI/2, thetac+PI/2, thetac[0]-PI/2))
            # plot the gas density
            img_env = ax_env.pcolormesh(thetac_exp,rc/AU,rho2d_exp/mmw/mh,cmap=cmap,norm=LogNorm(vmin=zmin,vmax=1e6)) # np.nanmax(rho2d_exp/mmw/mh)

            ax_env.set_xlabel(r'$\rm{Polar\,angle\,(Degree)}$',fontsize=20)
            ax_env.set_ylabel('',fontsize=20, labelpad=-140)
            ax_env.tick_params(labelsize=18)
            ax_env.set_yticks(np.hstack((np.arange(0,(int(R_env_max/AU/10000.)+1)*10000, 10000),R_env_max/AU)))
            ax_env.set_xticklabels([r'$\rm{90^{\circ}}$',r'$\rm{45^{\circ}}$',r'$\rm{0^{\circ}}$',r'$\rm{-45^{\circ}}$',\
                                    r'$\rm{-90^{\circ}}$',r'$\rm{-135^{\circ}}$',r'$\rm{180^{\circ}}$',r'$\rm{135^{\circ}}$'])
            ax_env.set_yticklabels([])
            # fix the tick label font
            ticks_font = mpl.font_manager.FontProperties(family='STIXGeneral',size=20)
            for label in ax_env.get_yticklabels():
                label.set_fontproperties(ticks_font)

            ax_env.grid(True, color='LightGray', linewidth=1)
            cb = fig.colorbar(img_env, pad=0.1)
            cb.ax.set_ylabel(r'$\rm{Averaged\,Gas\,Density\,(cm^{-3})}$',fontsize=20)
            # cb.set_ticks([1e2,1e3,1e4,1e5,1e6,1e7,1e8,1e9])
            # cb.set_ticklabels([r'$\rm{10^{2}}$',r'$\rm{10^{3}}$',r'$\rm{10^{4}}$',r'$\rm{10^{5}}$',r'$\rm{10^{6}}$',\
            #                    r'$\rm{10^{7}}$',r'$\rm{10^{8}}$',r'$\rm{\geq 10^{9}}$'])
            # lower density ticks
            cb.set_ticks([1e-1,1e0,1e1,1e2,1e3,1e4,1e5,1e6])
            cb.set_ticklabels([r'$\rm{10^{-1}}$',r'$\rm{10^{0}}$',r'$\rm{10^{1}}$',r'$\rm{10^{2}}$',r'$\rm{10^{3}}$',
                               r'$\rm{10^{4}}$',r'$\rm{10^{5}}$',r'$\rm{\geq 10^{6}}$'])

            cb_obj = plt.getp(cb.ax.axes, 'yticklabels')
            plt.setp(cb_obj,fontsize=20)
            fig.savefig(outdir+outname+'_gas_density.png', format='png', dpi=300, bbox_inches='tight')
            fig.clf()

        # Plot the radial density profile
        fig = plt.figure(figsize=(12,9))
        ax = fig.add_subplot(111)

        plot_grid = [0,49,99,149,199]
        color_grid = ['#e41a1c','#377eb8','#4daf4a','#984ea3','#ff7f00']
        label = [r'$\rm{\theta='+str(int(np.degrees(thetai[plot_grid[0]])))+'^{\circ}}$',\
                 r'$\rm{\theta='+str(int(np.degrees(thetai[plot_grid[1]])))+'^{\circ}}$',\
                 r'$\rm{\theta='+str(1+int(np.degrees(thetai[plot_grid[2]])))+'^{\circ}}$',\
                 r'$\rm{\theta='+str(int(np.degrees(thetai[plot_grid[3]])))+'^{\circ}}$',\
                 r'$\rm{\theta='+str(1+int(np.degrees(thetai[plot_grid[4]])))+'^{\circ}}$']
        alpha = np.linspace(0.3,1.0,len(plot_grid))
        for i in plot_grid:
            ax.plot(np.log10(rc[rc > 0.14*AU]/AU), np.log10(rho2d[rc > 0.14*AU,i]/g2d/mmw/mh)+plot_grid[::-1].index(i)*-0.2,'-',color=color_grid[plot_grid.index(i)],mec='None',linewidth=2.5, \
                    markersize=3, label=label[plot_grid.index(i)]) # alpha=alpha[plot_grid.index(i)],
        ax.axvline(np.log10(R_inf/AU), linestyle='--', color='k', linewidth=1.5, label=r'$\rm{infall\,radius}$')
        ax.axvline(np.log10(R_cen/AU), linestyle=':', color='k', linewidth=1.5, label=r'$\rm{centrifugal\,radius}$')

        lg = plt.legend(fontsize=20, numpoints=1, ncol=2, framealpha=0.7, loc='upper right')

        ax.set_xlabel(r'$\rm{log(Radius)\,(AU)}$',fontsize=20)
        ax.set_ylabel(r'$\rm{log(Dust\,Density)\,(cm^{-3})}$',fontsize=20)
        [ax.spines[axis].set_linewidth(1.5) for axis in ['top','bottom','left','right']]
        ax.minorticks_on()
        ax.tick_params('both',labelsize=18,width=1.5,which='major',pad=15,length=5)
        ax.tick_params('both',labelsize=18,width=1.5,which='minor',pad=15,length=2.5)

        # fix the tick label font
        ticks_font = mpl.font_manager.FontProperties(family='STIXGeneral',size=18)
        for label in ax.get_xticklabels():
            label.set_fontproperties(ticks_font)
        for label in ax.get_yticklabels():
            label.set_fontproperties(ticks_font)

        ax.set_ylim([0,11])
        fig.gca().set_xlim(left=np.log10(0.05))
        fig.savefig(outdir+outname+'_gas_radial.pdf',format='pdf',dpi=300,bbox_inches='tight')
        fig.clf()

    # Insert the calculated grid and dust density profile into hyperion
    m.set_spherical_polar_grid(ri, thetai, phii)

    m.add_density_grid(rho_dust.T, d)
    # for non-TSC option
    if tsc_com:
        m.add_density_grid(rho_ulrich_dust.T, d)

    # Define the luminsoity source
    source = m.add_spherical_source()
    source.luminosity = (4*PI*rstar**2)*sigma*(tstar**4)  # [ergs/s]
    source.radius = rstar  # [cm]
    source.temperature = tstar  # [K]
    source.position = (0., 0., 0.)
    print 'L_center =  % 5.2f L_sun' % ((4*PI*rstar**2)*sigma*(tstar**4)/LS)

    # if ext_source != None:
    #     # add external heating - ISRF
    #     # use standard receipe from Hyperion doc
    #     isrf = ascii.read(ext_source, names=['wavelength', 'J_lambda'])
    #     isrf_nu = c/(isrf['wavelength']*1e-4)
    #     isrf_jnu = isrf['J_lambda']*isrf['wavelength']/isrf_nu
    #
    #     if 'mmp83' in ext_source:
    #         FOUR_PI_JNU = 0.0217
    #     else:
    #         FOUR_PI_JNU = raw_input('What is the FOUR_PI_JNU value?')
    #
    #     s_isrf = m.add_external_spherical_source()
    #     s_isrf.radius = R_env_max
    #     s_isrf.spectrum = (isrf_nu, isrf_jnu)
    #     s_isrf.luminosity = PI * R_env_max**2 * FOUR_PI_JNU

    m.set_raytracing(True)
    # option of using more photons for imaging
    if better_im == False:
        im_photon = 1e6
    else:
        im_photon = 5e7

    if mono == True:
        if (type(mono_wave) == int) or (type(mono_wave) == float) or (type(mono_wave) == str):
            mono_wave = float(mono_wave)
            mono_wave = [mono_wave]

        # Monochromatic radiative transfer setting
        m.set_monochromatic(True, wavelengths=mono_wave)
        m.set_n_photons(initial=1e6, imaging_sources=im_photon,
            imaging_dust=im_photon,raytracing_sources=1e6, raytracing_dust=1e6)
    else:
        # regular wavelength grid setting
        m.set_n_photons(initial=1e6, imaging=im_photon,raytracing_sources=1e6,
                        raytracing_dust=1e6)
    # number of iteration to compute dust specific energy (temperature)
    m.set_n_initial_iterations(20)
    m.set_convergence(True, percentile=dict_params['percentile'],
                            absolute=dict_params['absolute'],
                            relative=dict_params['relative'])
    m.set_mrw(True)   # Gamma = 1 by default

    # Setting up images and SEDs
    if not image_only:
        # SED setting
        # Infinite aperture
        syn_inf = m.add_peeled_images(image=False)
        # use the index of wavelength array used by the monochromatic radiative transfer
        if mono == False:
            syn_inf.set_wavelength_range(wav_num, wav_min, wav_max)
        syn_inf.set_viewing_angles([dict_params['view_angle']], [0.0])
        syn_inf.set_uncertainties(True)
        syn_inf.set_output_bytes(8)

        # aperture
        # 7.2 in 10 um scaled by lambda / 10
        # flatten beyond 20 um
        # default aperture (should always specify a set of apertures)
        if aperture == None:
            aperture = {'wave': [3.6, 4.5, 5.8, 8.0, 8.5, 9, 9.7, 10, 10.5, 11, 16, 20, 24, 30, 70, 100, 160, 250, 350, 500, 1300],\
                        'aperture': [7.2, 7.2, 7.2, 7.2, 7.2, 7.2, 7.2, 7.2, 7.2, 7.2, 20.4, 20.4, 20.4, 20.4, 24.5, 24.5, 24.5, 24.5, 24.5, 24.5, 101]}
        # assign wl_aper and aper from dictionary of aperture
        wl_aper = aperture['wave']
        aper    = aperture['aperture']
        # create the non-repetitive aperture list and index array
        aper_reduced = list(set(aper))
        index_reduced = np.arange(1, len(aper_reduced)+1)

        dict_peel_sed = {}
        for i in range(0, len(aper_reduced)):
            aper_dum = aper_reduced[i]/2 * (1/3600.*np.pi/180.)*dstar*pc
            dict_peel_sed[str(index_reduced[i])] = m.add_peeled_images(image=False)
            # use the index of wavelength array used by the monochromatic radiative transfer
            if mono == False:
                dict_peel_sed[str(index_reduced[i])].set_wavelength_range(wav_num, wav_min, wav_max)
            dict_peel_sed[str(index_reduced[i])].set_viewing_angles([dict_params['view_angle']], [0.0])
            # aperture should be given in cm and its the radius of the aperture
            dict_peel_sed[str(index_reduced[i])].set_aperture_range(1, aper_dum, aper_dum)
            dict_peel_sed[str(index_reduced[i])].set_uncertainties(True)
            dict_peel_sed[str(index_reduced[i])].set_output_bytes(8)

    # image setting
    syn_im = m.add_peeled_images(sed=False)
    # use the index of wavelength array used by the monochromatic radiative transfer
    if mono == False:
        syn_im.set_wavelength_range(wav_num, wav_min, wav_max)
    # pixel number
    # !!!
    if not mono:
        pix_num = 300
    else:
        pix_num = 8000
    #
    syn_im.set_image_size(pix_num, pix_num)
    syn_im.set_image_limits(-R_env_max, R_env_max, -R_env_max, R_env_max)
    syn_im.set_viewing_angles([dict_params['view_angle']], [0.0])
    syn_im.set_uncertainties(True)
    syn_im.set_output_bytes(8)

    # Output setting
    # Density
    m.conf.output.output_density = 'last'

    # Density difference (shows where dust was destroyed)
    m.conf.output.output_density_diff = 'none'

    # Energy absorbed (using pathlengths)
    m.conf.output.output_specific_energy = 'last'

    # Number of unique photons that passed through the cell
    m.conf.output.output_n_photons = 'last'

    m.write(outdir+outname+'.rtin')

    if radmc == True:
        # RADMC-3D still use a pre-defined aperture with lazy for-loop
        aper = np.zeros([len(lam)])
        ind = 0
        for wl in lam:
            if wl < 5:
                aper[ind] = 8.4
            elif wl >= 5 and wl < 14:
                aper[ind] = 1.8 * 4
            elif wl >= 14 and wl < 40:
                aper[ind] = 5.1 * 4
            else:
                aper[ind] = 24.5
            ind += 1

        # Write the wavelength_micron.inp file
        #
        f_wave = open(outdir+'wavelength_micron.inp','w')
        f_wave.write('%d \n' % int(nlam))
        for ilam in range(0,nlam):
            f_wave.write('%f \n' % lam[ilam])
        f_wave.close()

        # Write the camera_wavelength_micron.inp file
        #
        f_wave_cam = open(outdir+'camera_wavelength_micron.inp','w')
        f_wave_cam.write('%d \n' % int(nlam))
        for ilam in range(0,nlam):
            f_wave_cam.write('%f \n' % lam[ilam])
        f_wave_cam.close()

        # Write the aperture_info.inp
        #
        f_aper = open(outdir+'aperture_info.inp','w')
        f_aper.write('1 \n')
        f_aper.write('%d \n' % int(nlam))
        for iaper in range(0, len(aper)):
            f_aper.write('%f \t %f \n' % (lam[iaper],aper[iaper]/2))
        f_aper.close()

        # Write the stars.inp file
        #
        f_star = open(outdir+'stars.inp','w')
        f_star.write('2\n')
        f_star.write('1 \t %d \n' % int(nlam))
        f_star.write('\n')
        f_star.write('%e \t %e \t %e \t %e \t %e \n' % (rstar*0.9999,mstar,0,0,0))
        f_star.write('\n')
        for ilam in range(0,nlam):
            f_star.write('%f \n' % lam[ilam])
        f_star.write('\n')
        f_star.write('%f \n' % -tstar)
        f_star.close()

        # Write the grid file
        #
        f_grid = open(outdir+'amr_grid.inp','w')
        f_grid.write('1\n')                               # iformat
        f_grid.write('0\n')                               # AMR grid style  (0=regular grid, no AMR)
        f_grid.write('150\n')                             # Coordinate system  coordsystem<100: Cartisian; 100<=coordsystem<200: Spherical; 200<=coordsystem<300: Cylindrical
        f_grid.write('0\n')                               # gridinfo
        f_grid.write('1 \t 1 \t 1 \n')                    # Include x,y,z coordinate
        f_grid.write('%d \t %d \t %d \n' % (int(nx)-1,int(ny),int(nz)))    # Size of the grid
        [f_grid.write('%e \n' % ri[ir]) for ir in range(1,len(ri))]
        [f_grid.write('%f \n' % thetai[itheta]) for itheta in range(0,len(thetai))]
        [f_grid.write('%f \n' % phii[iphi]) for iphi in range(0,len(phii))]
        f_grid.close()

        # Write the density file
        #
        f_dust = open(outdir+'dust_density.inp','w')
        f_dust.write('1 \n')                      # format number
        f_dust.write('%d \n' % int((nx-1)*ny*nz)) # Nr of cells
        f_dust.write('1 \n')                      # Nr of dust species
        for iphi in range(0,len(phic)):
            for itheta in range(0,len(thetac)):
                for ir in range(1,len(rc)):
                    f_dust.write('%e \n' % rho_dust[ir,itheta,iphi])
        f_dust.close()

        # Write the dust opacity table
        f_dustkappa = open(outdir+'dustkappa_oh5_extended.inp','w')
        f_dustkappa.write('3 \n')                       # format index for including g-factor
        f_dustkappa.write('%d \n' % len(dust['nu']))    # number of wavlength/frequency in the table
        for i in range(len(dust['nu'])):
            f_dustkappa.write('%f \t %f \t %f \t %f \n' % (c/dust['nu'][i]*1e4, dust['chi'][i], dust['chi'][i]*dust['albedo'][i]/(1-dust['albedo'][i]), dust['g'][i]))
        f_dustkappa.close()

        # Write the Dust opacity control file
        #
        f_opac = open(outdir+'dustopac.inp','w')
        f_opac.write('2               Format number of this file\n')
        f_opac.write('1               Nr of dust species\n')
        f_opac.write('============================================================================\n')
        f_opac.write('1               Way in which this dust species is read\n')
        f_opac.write('0               0=Thermal grain\n')
        # f_opac.write('klaus           Extension of name of dustkappa_***.inp file\n')
        f_opac.write('oh5_extended    Extension of name of dustkappa_***.inp file\n')
        f_opac.write('----------------------------------------------------------------------------\n')
        f_opac.close()

        # Write the radmc3d.inp control file
        #
        f_control = open(outdir+'radmc3d.inp','w')
        f_control.write('nphot = %d \n' % 100000)
        f_control.write('scattering_mode_max = 2\n')
        f_control.write('camera_min_drr = 0.1\n')
        f_control.write('camera_min_dangle = 0.1\n')
        f_control.write('camera_spher_cavity_relres = 0.1\n')
        f_control.write('istar_sphere = 1\n')
        f_control.write('modified_random_walk = 1\n')
        f_control.close()

    return m
예제 #19
0
def mtf_plot_results(imageRoot, dataDir='/u/jlu/data/w51/09jun26/combo/',
                     starsSuffix='_0.8_stf.lis'):
    img, hdr = pyfits.getdata(dataDir + imageRoot + '.fits', header=True)

    import pidly
    idl = pidly.IDL()

    print 'MTF: Restoring IDL variables'
    mtfData = imageRoot + '_mtfdata.save'
    mtfFit = imageRoot + '_mtffit.save'
    idl('restore, "' + mtfData + '"')
    idl('restore, "' + mtfFit + '"')
    
    ##########
    # Plot the 1D and 2D power spectrum of the source distribution
    ##########
    stfLis = dataDir + 'starfinder/' + imageRoot + starsSuffix
    _lis = asciidata.open(stfLis)
    mag = _lis[1].tonumpy()
    x = _lis[3].tonumpy()
    y = _lis[4].tonumpy()
    flux = 10**((mag[0] - mag)/2.5)

    sources = np.zeros(img.shape, dtype=float)
    xpix = np.array(np.round(x), dtype=int)
    ypix = np.array(np.round(y), dtype=int)
    sources[xpix, ypix] = flux

    F = fftpack.fftshift( fftpack.fft2(sources) )
    psd2D = np.abs(F)**2 
    psd1D = radialProfile.azimuthalAverage(psd2D)
    
#     py.figure(1)
#     py.clf()
#     py.imshow(np.log10(psd2D))

#     py.figure(2)
#     py.clf()
#     py.semilogy(psd1D)
#     py.xlabel('Spatial Frequency')
#     py.ylabel('Power Spectrum')
    
#     py.figure(3)
#     py.clf()
#     py.semilogy(idl.nu, idl.spdist)
#     py.xlabel('Spatial Frequency')
#     py.ylabel('Power Spectrum')
#     py.show()

    ##########
    # Plot up the best-fit power spectrum
    ##########
    print params
    idl('pspec_fit = mtffunc_keck(nu, params, spdist=spdist)')
    idl('mtf = mtffunc_keck(nu, params)')
    
    nu = idl.nu
    power = idl.power
    pspec_fit = idl.pspec_fit
    mtf = idl.mtf
    resid = power - pspec_fit

    print nu.shape
    print pspec_fit.shape

    py.clf()
#     py.semilogy(nu, power)
    py.semilogy(nu, pspec_fit)
#     py.semilogy(nu, mtf)
#     py.semilogy(nu, np.abs(resid))
    py.xlabel('Spatial Frequency')
    py.ylabel('Power Spectrum')
    py.legend(('Data', 'Best Fit', 'MTF', 'Residuals'))
    py.show()
예제 #20
0
def mtf_play(imageRoot, dataDir='/u/jlu/data/w51/09jun26/combo/',
             starsSuffix='_0.8_stf.lis', resolvedSources=None,
             maskSize=150):
    import pidly

    idl = pidly.IDL()

    ##############################
    # H-band wide image
    ##############################
    imageFile = dataDir + imageRoot + '.fits'
    img, hdr = pyfits.getdata(imageFile, header=True)
    wavelength = hdr['CENWAVE'] * 1e-6
    
    # Mask resolved sources
    if resolvedSources != None:
        print 'MTF: Masking %d resolved sources' % len(resolvedSources)
        img = mask_image(imageFile, resolvedSources, maskSize=maskSize)
    gcutil.rmall([imageRoot + '_masked.fits'])
    pyfits.writeto(imageRoot + '_masked.fits', img)

    # Load up the image
    print 'MTF: Load the science image.'
    idl('im = readfits("' + imageRoot + '_masked.fits")')

    print 'MTF: Set initial guesses for parameters'
    #definitions of starting parameters [from fitmtf_keck.pro]
    #
    #    lambda=1.65d-6        # wavelength in meters
    #    F=557.0               # effective focal length of Keck AO (narrow)
    #    D=10.99               # primary's diameter in meters
    #    pupil=0.266           # central obscuration
    #    pupil='largehex'      # NIRC2 pupil-stop
    #    Apix=27d-6            # width of detector's pixel in meters
    #    L0=20.                # outer scale of turbulence in meters
    #    sigma=.56             # Infl Func width on primary in meters
    #    w=1.3                 # Influence Function height
    #    Delta=0               # wavefront measurement error
    #    Cmult=10.             # multiplicative constant
    #    N=1d-2                # additive noise floor constant
    #    r0=0.5                # wavelength specific fried parameter in meters
    idl('startp = {lambda:' + str(wavelength) + ', ' +
        'D:10.99, F:139.9, APIX:27e-6, ' +
        'pupil:"largehex", L0:30.0, SIGMA:0.56, ' +
        'W:1.3, Delta:0.0, Cmult:1.0, N:1e-5, R0:0.5}')
    
    # Load up the starfinder results for this image
    print 'MTF: Read in preliminary starlist.'
    stfLis = dataDir + 'starfinder/' + imageRoot + starsSuffix
    idl('readcol, "' + stfLis + '", name, mag, time, x, y, ' + 
        'snr, corr, frames, fwhm, format="(A,F,F,F,F,F,F,F,F)"')
    idl('flux = 10^((mag[0] - mag)/2.5)')

    # Create sources array (delta functions * flux) for the stars.
    print 'MTF: Creating 2D source array'
    idl('sources = im')
    idl('sources[*] = 0.')
    idl('sources[x, y] = flux')

    mtfData = imageRoot + '_mtfdata.save'
    mtfFit = imageRoot + '_mtffit.save'

    print 'MTF: Calling getmtf'
    idl('getmtf, im, startp, nu, power, error, spdist, deltas=sources')
    idl('save, nu, power, error, spdist, filename="'+mtfData+'"')

    # Fit the power spectrum
    print 'MTF: Fitting the power spectrum (round 1)'
    idl('print, startp')
    idl('fitmtf_keck, "'+mtfData+'", params, perror, ' +
        'start=startp, relstep=0.2')
예제 #21
0
# Master script for CDF reduction with the method used in BHR71 paper.

# library import
import os
import pidly
if 'bettyjo' in os.path.expanduser('~'):
    idl = pidly.IDL('/opt/local/exelis/idl83/bin/idl')
else:
    idl = pidly.IDL('/Applications/exelis/idl83/bin/idl')

from astropy.io import ascii
import sys

sys.path.append(os.path.expanduser('~') + '/programs/line_fitting/')
sys.path.append(os.path.expanduser('~') + '/programs/spectra_analysis/')
from PreFittedModify import *
from spire_spectral_index import spire_spectral_index
from cdfPacs1d import cdfPacs1d

# some info about the observational programs

# COPS-SPIRE source list
obsid_spire = [
    1342242620, 1342242621, 1342245084, 1342245094, 1342245857, 1342247625,
    1342248246, 1342248249, 1342249053, 1342249470, 1342249474, 1342249475,
    1342249476, 1342249477, 1342250509, 1342250510, 1342250512, 1342250515,
    1342251285, 1342251286, 1342251287, 1342251290, 1342253646, 1342253649,
    1342253652, 1342254037, 1342252897
]

# SECT cannot converage at L1489 1342249473, L1527 1342250511, HH100 1342252897
예제 #22
0
def setup_model(outdir,record_dir,outname,params,dust_file,tsc=True,idl=False,plot=False,\
                low_res=True,flat=True,scale=1,radmc=False,mono=False,record=True,dstar=178.,\
                aperture=None,dyn_cav=False,fix_params=None,alma=False,power=2,better_im=False,ellipsoid=False,\
                TSC_dir='~/programs/misc/TSC/', IDL_path='/Applications/exelis/idl83/bin/idl',auto_disk=0.25):
    """
    params = dictionary of the model parameters
    alma keyword is obsoleted 
    outdir: The directory for storing Hyperion input files
    record_dir: The directory contains "model_list.txt" for recording parameters
    TSC_dir: Path the TSC-related IDL routines
    IDL_path: The IDL executable 
    """
    import numpy as np
    import astropy.constants as const
    import scipy as sci
    # to avoid X server error
    import matplotlib as mpl
    mpl.use('Agg')
    #
    import matplotlib.pyplot as plt
    import os
    from matplotlib.colors import LogNorm
    from scipy.integrate import nquad
    from hyperion.model import Model
    from record_hyperion import record_hyperion
    from outflow_inner_edge import outflow_inner_edge
    from pprint import pprint
    # import pdb
    # pdb.set_trace()

    # Constants setup
    c = const.c.cgs.value
    AU = 1.49598e13  # Astronomical Unit       [cm]
    pc = 3.08572e18  # Parsec                  [cm]
    MS = 1.98892e33  # Solar mass              [g]
    LS = 3.8525e33  # Solar luminosity        [erg/s]
    RS = 6.96e10  # Solar radius            [cm]
    G = 6.67259e-8  # Gravitational constant  [cm3/g/s^2]
    yr = 60 * 60 * 24 * 365  # Years in seconds
    PI = np.pi  # PI constant
    sigma = const.sigma_sb.cgs.value  # Stefan-Boltzmann constant
    mh = const.m_p.cgs.value + const.m_e.cgs.value
    g2d = 100.
    mmw = 2.37  # Kauffmann 2008

    m = Model()

    # Create dust properties

    # Hyperion needs nu, albedo, chi, g, p_lin_max
    from hyperion.dust import HenyeyGreensteinDust
    # Read in the dust opacity table used by RADMC-3D
    dust = dict()
    # [dust_radmc['wl'], dust_radmc['abs'], dust_radmc['scat'], dust_radmc['g']] = np.genfromtxt(dust_file,skip_header=2).T
    [dust['nu'], dust['albedo'], dust['chi'],
     dust['g']] = np.genfromtxt(dust_file).T
    # opacity per mass of dust?
    # dust_hy = dict()
    # dust_hy['nu'] = c/dust_radmc['wl']*1e4
    # ind = np.argsort(dust_hy['nu'])
    # dust_hy['nu'] = dust_hy['nu'][ind]
    # dust_hy['albedo'] = (dust_radmc['scat']/(dust_radmc['abs']+dust_radmc['scat']))[ind]
    # dust_hy['chi'] = (dust_radmc['abs']+dust_radmc['scat'])[ind]
    # dust_hy['g'] = dust_radmc['g'][ind]
    # dust_hy['p_lin_max'] = 0*dust_radmc['wl'][ind]     # assume no polarization

    # d = HenyeyGreensteinDust(dust_hy['nu'], dust_hy['albedo'], dust_hy['chi'], dust_hy['g'], dust_hy['p_lin_max'])
    d = HenyeyGreensteinDust(dust['nu'], dust['albedo'], dust['chi'],
                             dust['g'], dust['g'] * 0)
    # dust sublimation option
    d.set_sublimation_temperature('slow', temperature=1600.0)
    d.set_lte_emissivities(n_temp=3000, temp_min=0.1, temp_max=2000.)
    # try to solve the freq. problem
    d.optical_properties.extrapolate_nu(3.28e15, 4e15)
    #
    d.write(outdir + os.path.basename(dust_file).split('.')[0] + '.hdf5')
    d.plot(outdir + os.path.basename(dust_file).split('.')[0] + '.png')
    plt.clf()

    # Grids and Density
    # Calculation inherited from the script used for RADMC-3D

    # Grid Parameters
    nx = 300L
    if low_res == True:
        nx = 100L
    ny = 400L
    nz = 50L
    [nx, ny, nz] = [int(scale * nx), int(scale * ny), int(scale * nz)]

    # TSC model input setting
    # params    = np.genfromtxt(indir+'/tsc_params.dat', dtype=None)
    dict_params = params  # input_reader(params_file)
    # TSC model parameter
    cs = dict_params['Cs'] * 1e5
    t = dict_params['age']  # year
    omega = dict_params['Omega0']
    # calculate related parameters
    M_env_dot = 0.975 * cs**3 / G
    mstar = M_env_dot * t * yr
    R_cen = omega**2 * G**3 * mstar**3 / (16 * cs**8)
    R_inf = cs * t * yr
    # M_env_dot = dict_params['M_env_dot']*MS/yr
    # R_cen     = dict_params['R_cen']*AU
    # R_inf     = dict_params['R_inf']*AU
    # protostar parameter
    tstar = dict_params['tstar']
    R_env_max = dict_params['R_env_max'] * AU
    theta_cav = dict_params['theta_cav']
    rho_cav_center = dict_params['rho_cav_center']
    rho_cav_edge = dict_params['rho_cav_edge'] * AU
    rstar = dict_params['rstar'] * RS
    # Mostly fixed parameter
    M_disk = dict_params['M_disk'] * MS
    beta = dict_params['beta']
    h100 = dict_params['h100'] * AU
    rho_cav = dict_params['rho_cav']
    # make M_disk varies with mstar, which is the mass of star+disk
    if auto_disk != None:
        if M_disk != 0:
            print 'M_disk is reset to %4f of mstar (star+disk)' % auto_disk
            M_disk = mstar * auto_disk
        else:
            print 'M_disk = 0 is found.  M_disk is set to 0.'

    # ellipsoid cavity parameter
    if ellipsoid == True:
        a_out = 130 * 178. * AU
        b_out = 50 * 178. * AU
        z_out = a_out
        # a_in  = 77.5 * 178. * AU
        # b_in  = 30   * 178. * AU
        a_in = dict_params['a_in'] * 178. * AU
        b_in = a_in / a_out * b_out
        z_in = a_in
        # rho_cav_out = 1e4 * mh
        # rho_cav_in  = 1e3 * mh
        rho_cav_out = dict_params['rho_cav_out'] * mh
        rho_cav_in = dict_params['rho_cav_in'] * mh
    # Calculate the dust sublimation radius
    T_sub = 1600
    a = 1  #in micron
    # realistic dust
    # d_sub = 2.9388e7*(a/0.1)**-0.2 * (4*np.pi*rstar**2*sigma*tstar**4/LS)**0.5 / T_sub**3 *AU
    # black body dust
    d_sub = (LS / 16. / np.pi / sigma / AU**2 *
             (4 * np.pi * rstar**2 * sigma * tstar**4 / LS) /
             T_sub**4)**0.5 * AU
    # use the dust sublimation radius as the inner radius of disk and envelope
    R_disk_min = d_sub
    R_env_min = d_sub
    rin = rstar
    rout = R_env_max
    R_disk_max = R_cen

    # Do the variable conversion
    # cs = (G * M_env_dot / 0.975)**(1/3.)  # cm/s
    # t = R_inf / cs / yr   # in year
    # mstar = M_env_dot * t * yr
    # omega = (R_cen * 16*cs**8 / (G**3 * mstar**3))**0.5

    # print the variables for radmc3d
    print 'Dust sublimation radius %6f AU' % (d_sub / AU)
    print 'M_star %4f Solar mass' % (mstar / MS)
    print 'Infall radius %4f AU' % (R_inf / AU)

    # if there is any parameter found in fix_params, then fix them
    if fix_params != None:
        if 'R_min' in fix_params.keys():
            R_disk_min = fix_params['R_min'] * AU
            R_env_min = fix_params['R_min'] * AU

    # Make the Coordinates
    #
    ri = rin * (rout / rin)**(np.arange(nx + 1).astype(dtype='float') /
                              float(nx))
    ri = np.hstack((0.0, ri))
    thetai = PI * np.arange(ny + 1).astype(dtype='float') / float(ny)
    phii = PI * 2.0 * np.arange(nz + 1).astype(dtype='float') / float(nz)

    # Keep the constant cell size in r-direction at large radii
    #
    if flat == True:
        ri_cellsize = ri[1:-1] - ri[0:-2]
        ind = np.where(
            ri_cellsize / AU > 100.0)[0][0]  # The largest cell size is 100 AU
        ri = np.hstack(
            (ri[0:ind],
             ri[ind] + np.arange(np.ceil(
                 (rout - ri[ind]) / 100 / AU)) * 100 * AU))
        nxx = nx
        nx = len(ri) - 1
    # Assign the coordinates of the center of cell as its coordinates.
    #
    rc = 0.5 * (ri[0:nx] + ri[1:nx + 1])
    thetac = 0.5 * (thetai[0:ny] + thetai[1:ny + 1])
    phic = 0.5 * (phii[0:nz] + phii[1:nz + 1])
    # phic         = 0.5*( phii[0:nz-1]   + phii[1:nz] )

    # Make the dust density model
    # Make the density profile of the envelope
    #
    total_mass = 0
    if tsc == False:
        print 'Calculating the dust density profile with infall solution...'
        if theta_cav != 0:
            # c0 = R_env_max**(-0.5)*np.sqrt(1/np.sin(np.radians(theta_cav))**3-1/np.sin(np.radians(theta_cav)))
            # using R = 10000 AU as the reference point
            c0 = (10000. *
                  AU)**(-0.5) * np.sqrt(1 / np.sin(np.radians(theta_cav))**3 -
                                        1 / np.sin(np.radians(theta_cav)))
        else:
            c0 = 0
        rho_env = np.zeros([len(rc), len(thetac), len(phic)])
        rho_disk = np.zeros([len(rc), len(thetac), len(phic)])
        rho = np.zeros([len(rc), len(thetac), len(phic)])

        if dyn_cav == True:
            print 'WARNING: Calculation of interdependent cavity property has not implemented in infall-only solution!'
        # Normalization for the total disk mass
        def f(w, z, beta, rstar, h100):
            f = 2 * PI * w * (1 - np.sqrt(rstar / w)) * (rstar / w)**(
                beta + 1) * np.exp(-0.5 * (z /
                                           (w**beta * h100 / 100**beta))**2)
            return f

        rho_0 = M_disk / (nquad(
            f, [[R_disk_min, R_disk_max], [-R_env_max, R_env_max]],
            args=(beta, rstar, h100)))[0]
        i = 0
        j = 0
        if 'rho_cav_center' in locals() == False:
            rho_cav_center = 5.27e-18  # 1.6e-17  # 5.27e-18
            print 'Use 5.27e-18 as the default value for cavity center'
        if 'rho_cav_edge' in locals() == False:
            rho_cav_edge = 40 * AU
            print 'Use 40 AU as the default value for size of the inner region'
        discont = 1
        for ir in range(0, len(rc)):
            for itheta in range(0, len(thetac)):
                for iphi in range(0, len(phic)):
                    if rc[ir] > R_env_min:
                        # Envelope profile
                        w = abs(rc[ir] * np.cos(np.pi / 2 - thetac[itheta]))
                        z = rc[ir] * np.sin(np.pi / 2 - thetac[itheta])

                        if ellipsoid == False:
                            z_cav = c0 * abs(w)**1.5
                            if z_cav == 0:
                                z_cav = R_env_max
                            cav_con = abs(z) > abs(z_cav)
                        else:
                            # condition for the outer ellipsoid
                            cav_con = (2 * (w / b_out)**2 +
                                       ((abs(z) - z_out) / a_out)**2) < 1
                        if cav_con:
                            # open cavity
                            if ellipsoid == False:
                                if rho_cav_edge == 0:
                                    rho_cav_edge = R_env_min
                                if (rc[ir] <= rho_cav_edge) & (rc[ir] >=
                                                               R_env_min):
                                    rho_env[
                                        ir, itheta,
                                        iphi] = g2d * rho_cav_center  #*((rc[ir]/AU)**2)
                                else:
                                    rho_env[
                                        ir, itheta,
                                        iphi] = g2d * rho_cav_center * discont * (
                                            rho_cav_edge / rc[ir])**power
                                i += 1
                            else:
                                # condition for the inner ellipsoid
                                if (2 * (w / b_in)**2 +
                                    ((abs(z) - z_in) / a_in)**2) > 1:
                                    rho_env[ir, itheta, iphi] = rho_cav_out
                                else:
                                    rho_env[ir, itheta, iphi] = rho_cav_in
                                i += 1
                        else:
                            j += 1
                            mu = abs(np.cos(thetac[itheta]))
                            # Implement new root finding algorithm
                            roots = np.roots(
                                np.array([
                                    1.0, 0.0, rc[ir] / R_cen - 1.0,
                                    -mu * rc[ir] / R_cen
                                ]))
                            if len(roots[roots.imag == 0]) == 1:
                                if (abs(roots[roots.imag == 0]) - 1.0) <= 0.0:
                                    mu_o_dum = roots[roots.imag == 0]
                                else:
                                    mu_o_dum = -0.5
                                    print 'Problem with cubic solving, cos(theta) = ', mu_o_dum
                                    print 'parameters are ', np.array([
                                        1.0, 0.0, rc[ir] / R_cen - 1.0,
                                        -mu * rc[ir] / R_cen
                                    ])
                            else:
                                mu_o_dum = -0.5
                                for imu in range(0, len(roots)):
                                    if roots[imu] * mu >= 0.0:
                                        if (abs(
                                            (abs(roots[imu]) - 1.0)) <= 1e-5):
                                            mu_o_dum = 1.0 * np.sign(mu)
                                        else:
                                            mu_o_dum = roots[imu]
                                if mu_o_dum == -0.5:
                                    print 'Problem with cubic solving, roots are: ', roots
                            mu_o = mu_o_dum.real
                            rho_env[ir, itheta, iphi] = M_env_dot / (
                                4 * PI * (G * mstar * R_cen**3)**0.5) * (
                                    rc[ir] / R_cen)**(-3. / 2) * (
                                        1 + mu / mu_o)**(-0.5) * (
                                            mu / mu_o +
                                            2 * mu_o**2 * R_cen / rc[ir])**(-1)
                        # Disk profile
                        if ((w >= R_disk_min) and (w <= R_disk_max)) == True:
                            h = ((w / (100 * AU))**beta) * h100
                            rho_disk[ir, itheta, iphi] = rho_0 * (1 - np.sqrt(
                                rstar / w)) * (rstar / w)**(beta + 1) * np.exp(
                                    -0.5 * (z / h)**2)
                        # Combine envelope and disk
                        rho[ir, itheta,
                            iphi] = rho_disk[ir, itheta,
                                             iphi] + rho_env[ir, itheta, iphi]
                    else:
                        rho[ir, itheta, iphi] = 1e-30
                    # add the dust mass into the total count
                    cell_mass = rho[ir, itheta, iphi] * (1 / 3.) * (
                        ri[ir + 1]**3 -
                        ri[ir]**3) * (phii[iphi + 1] - phii[iphi]) * -(np.cos(
                            thetai[itheta + 1]) - np.cos(thetai[itheta]))
                    total_mass = total_mass + cell_mass

        rho_env = rho_env + 1e-40
        rho_disk = rho_disk + 1e-40
        rho = rho + 1e-40
    # TSC model
    else:
        print 'Calculating the dust density profile with TSC solution...'
        if theta_cav != 0:
            # c0 = R_env_max**(-0.5)*np.sqrt(1/np.sin(np.radians(theta_cav))**3-1/np.sin(np.radians(theta_cav)))
            c0 = (1e4 *
                  AU)**(-0.5) * np.sqrt(1 / np.sin(np.radians(theta_cav))**3 -
                                        1 / np.sin(np.radians(theta_cav)))
        else:
            c0 = 0
        # If needed, calculate the TSC model via IDL
        #
        if idl == True:
            print 'Using IDL to calculate the TSC model.  Make sure you are running this on mechine with IDL.'
            import pidly
            # idl = pidly.IDL('/Applications/exelis/idl82/bin/idl')
            idl = pidly.IDL(IDL_path)
            idl('.r ' + TSC_dir + 'tsc.pro')
            # idl.pro('tsc_run', outdir=outdir, grid=[nxx,ny,nz], time=t, c_s=cs, omega=omega, rstar=rstar, renv_min=R_env_min, renv_max=R_env_max)
            # idl.pro('tsc_run', outdir=outdir, grid=[nxx,ny,nz], time=t, c_s=cs, omega=omega, rstar=rstar, renv_min=R_env_min, renv_max=min([R_inf,max(ri)])) # min([R_inf,max(ri)])
            #
            # only run TSC calculation within infall radius
            # modify the rc array
            rc_idl = rc[(rc < min([R_inf, max(ri)]))]
            idl.pro(
                'tsc_run',
                outdir=outdir,
                rc=rc_idl,
                thetac=thetac,
                time=t,
                c_s=cs,
                omega=omega,
                renv_min=R_env_min
            )  #, rstar=rstar, renv_min=R_env_min, renv_max=min([R_inf,max(ri)])) # min([R_inf,max(ri)])
        else:
            print 'Read the pre-computed TSC model.'
            rc_idl = rc[(rc < min([R_inf, max(ri)]))]
        # read in the exist file
        rho_env_tsc_idl = np.genfromtxt(outdir + 'rhoenv.dat').T
        # because only region within infall radius is calculated by IDL program, need to project it to the original grid
        rho_env_tsc = np.zeros([len(rc), len(thetac)])
        for irc in range(len(rc)):
            if rc[irc] in rc_idl:
                rho_env_tsc[irc, :] = rho_env_tsc_idl[np.where(
                    rc_idl == rc[irc]), :]

        # extrapolate for the NaN values at the outer radius, usually at radius beyond the infall radius
        # using r^-2 profile at radius greater than infall radius
        # and map the 2d strcuture onto 3d grid
        def poly(x, y, x0, deg=2):
            import numpy as np
            p = np.polyfit(x, y, deg)
            y0 = 0
            for i in range(0, len(p)):
                y0 = y0 + p[i] * x0**(len(p) - i - 1)
            return y0

        # rho_env_copy = np.array(rho_env_tsc)
        # if max(rc) > R_inf:
        #     ind_infall = np.where(rc <= R_inf)[0][-1]
        #     print ind_infall
        #     for ithetac in range(0, len(thetac)):
        #         # rho_dum = np.log10(rho_env_copy[(rc > R_inf) & (np.isnan(rho_env_copy[:,ithetac]) == False),ithetac])
        #         # rc_dum = np.log10(rc[(rc > R_inf) & (np.isnan(rho_env_copy[:,ithetac]) == False)])
        #         # rc_dum_nan = np.log10(rc[(rc > R_inf) & (np.isnan(rho_env_copy[:,ithetac]) == True)])
        #         # # print rc_dum
        #         # for i in range(0, len(rc_dum_nan)):
        #         #     rho_extrapol = poly(rc_dum, rho_dum, rc_dum_nan[i])
        #         #     rho_env_copy[(np.log10(rc) == rc_dum_nan[i]),ithetac] = 10**rho_extrapol
        #         #
        #         for i in range(ind_infall, len(rc)):
        #             rho_env_copy[i, ithetac] =  10**(np.log10(rho_env_copy[ind_infall, ithetac]) - 2*(np.log10(rc[i]/rc[ind_infall])))
        # rho_env2d = rho_env_copy
        # rho_env = np.empty((nx,ny,nz))
        # for i in range(0, nz):
        #     rho_env[:,:,i] = rho_env2d
        # map TSC solution from IDL to actual 2-D grid
        rho_env_tsc2d = np.empty((nx, ny))
        if max(ri) > R_inf:
            ind_infall = np.where(rc <= R_inf)[0][-1]
            for i in range(0, len(rc)):
                if i <= ind_infall:
                    rho_env_tsc2d[i, :] = rho_env_tsc[i, :]
                else:
                    rho_env_tsc2d[i, :] = 10**(
                        np.log10(rho_env_tsc[ind_infall, :]) - 2 *
                        (np.log10(rc[i] / rc[ind_infall])))
        else:
            rho_env_tsc2d = rho_env_tsc
        # map it to 3-D grid
        rho_env = np.empty((nx, ny, nz))
        for i in range(0, nz):
            rho_env[:, :, i] = rho_env_tsc2d

        if dyn_cav == True:
            print 'Calculate the cavity properties using the criteria that swept-up mass = outflowed mass'
            # using swept-up mass = flow mass to derive the edge of the extended flat density region
            v_outflow = 1e2 * 1e5
            rho_cav_edge = outflow_inner_edge(np.copy(rho_env),
                                              (ri, thetai, phii), M_env_dot,
                                              v_outflow, theta_cav, R_env_min)
            dict_params['rho_cav_edge'] = rho_cav_edge
            # assume gas-to-dust ratio = 100
            rho_cav_center = 0.01 * 0.1 * M_env_dot * rho_cav_edge / v_outflow / 2 / (
                2 * np.pi / 3 * rho_cav_edge**3 *
                (1 - np.cos(np.radians(theta_cav))))
            dict_params['rho_cav_center'] = rho_cav_center
            print 'inner edge is %5f AU and density is %e g/cm3' % (
                rho_cav_edge / AU, rho_cav_center)

        # create the array of density of disk and the whole structure
        #
        rho_disk = np.zeros([len(rc), len(thetac), len(phic)])
        rho = np.zeros([len(rc), len(thetac), len(phic)])

        # Calculate the disk scale height by the normalization of h100
        def f(w, z, beta, rstar, h100):
            f = 2 * PI * w * (1 - np.sqrt(rstar / w)) * (rstar / w)**(
                beta + 1) * np.exp(-0.5 * (z /
                                           (w**beta * h100 / 100**beta))**2)
            return f

        # The function for calculating the normalization of disk using the total disk mass
        #
        rho_0 = M_disk / (nquad(
            f, [[R_disk_min, R_disk_max], [-R_env_max, R_env_max]],
            args=(beta, rstar, h100)))[0]
        i = 0
        j = 0
        if 'rho_cav_center' in locals() == False:
            rho_cav_center = 5.27e-18  # 1.6e-17  # 5.27e-18
            print 'Use 5.27e-18 as the default value for cavity center'
        if 'rho_cav_edge' in locals() == False:
            rho_cav_edge = 40 * AU
            print 'Use 40 AU as the default value for size of the inner region'
        discont = 1
        for ir in range(0, len(rc)):
            for itheta in range(0, len(thetac)):
                for iphi in range(0, len(phic)):
                    if rc[ir] > R_env_min:
                        # Envelope profile
                        w = abs(rc[ir] * np.cos(np.pi / 2 - thetac[itheta]))
                        z = rc[ir] * np.sin(np.pi / 2 - thetac[itheta])

                        if ellipsoid == False:
                            z_cav = c0 * abs(w)**1.5
                            if z_cav == 0:
                                z_cav = R_env_max
                            cav_con = abs(z) > abs(z_cav)
                        else:
                            # condition for the outer ellipsoid
                            cav_con = (2 * (w / b_out)**2 +
                                       ((abs(z) - z_out) / a_out)**2) < 1
                        if cav_con:
                            # open cavity
                            if ellipsoid == False:
                                if rho_cav_edge == 0:
                                    rho_cav_edge = R_env_min
                                if (rc[ir] <= rho_cav_edge) & (rc[ir] >=
                                                               R_env_min):
                                    rho_env[
                                        ir, itheta,
                                        iphi] = g2d * rho_cav_center  #*((rc[ir]/AU)**2)
                                else:
                                    rho_env[
                                        ir, itheta,
                                        iphi] = g2d * rho_cav_center * discont * (
                                            rho_cav_edge / rc[ir])**power
                                i += 1
                            else:
                                # condition for the inner ellipsoid
                                if (2 * (w / b_in)**2 +
                                    ((abs(z) - z_in) / a_in)**2) > 1:
                                    rho_env[ir, itheta, iphi] = rho_cav_out
                                else:
                                    rho_env[ir, itheta, iphi] = rho_cav_in
                                i += 1

                        # Disk profile
                        if ((w >= R_disk_min) and (w <= R_disk_max)) == True:
                            h = ((w / (100 * AU))**beta) * h100
                            rho_disk[ir, itheta, iphi] = rho_0 * (1 - np.sqrt(
                                rstar / w)) * (rstar / w)**(beta + 1) * np.exp(
                                    -0.5 * (z / h)**2)
                        # Combine envelope and disk
                        rho[ir, itheta,
                            iphi] = rho_disk[ir, itheta,
                                             iphi] + rho_env[ir, itheta, iphi]
                    else:
                        rho[ir, itheta, iphi] = 1e-40
                    # add the dust mass into the total count
                    cell_mass = rho[ir, itheta, iphi] * (1 / 3.) * (
                        ri[ir + 1]**3 -
                        ri[ir]**3) * (phii[iphi + 1] - phii[iphi]) * -(np.cos(
                            thetai[itheta + 1]) - np.cos(thetai[itheta]))
                    total_mass = total_mass + cell_mass
        # rho_env  = rho_env  + 1e-40
        # rho_disk = rho_disk + 1e-40
        # rho      = rho      + 1e-40
    # apply gas-to-dust ratio of 100
    rho_dust = rho / g2d
    total_mass_dust = total_mass / MS / g2d
    print 'Total dust mass = %f Solar mass' % total_mass_dust

    if record == True:
        # Record the input and calculated parameters
        params = dict_params.copy()
        params.update({
            'd_sub': d_sub / AU,
            'M_env_dot': M_env_dot / MS * yr,
            'R_inf': R_inf / AU,
            'R_cen': R_cen / AU,
            'mstar': mstar / MS,
            'M_tot_gas': total_mass / MS
        })
        record_hyperion(params, record_dir)

    if plot == True:
        # rc setting
        # mat.rcParams['text.usetex'] = True
        # mat.rcParams['font.family'] = 'serif'
        # mat.rcParams['font.serif'] = 'Times'
        # mat.rcParams['font.sans-serif'] = 'Computer Modern Sans serif'

        # Plot the azimuthal averaged density
        fig = plt.figure(figsize=(8, 6))
        ax_env = fig.add_subplot(111, projection='polar')
        # take the weighted average
        # rho2d is the 2-D projection of gas density
        rho2d = np.sum(rho**2, axis=2) / np.sum(rho, axis=2)

        zmin = 1e-22 / mmw / mh
        cmap = plt.cm.CMRmap
        rho2d_exp = np.hstack((rho2d, rho2d, rho2d[:, 0:1]))
        thetac_exp = np.hstack(
            (thetac - PI / 2, thetac + PI / 2, thetac[0] - PI / 2))
        # plot the gas density
        img_env = ax_env.pcolormesh(
            thetac_exp,
            rc / AU,
            rho2d_exp / mmw / mh,
            cmap=cmap,
            norm=LogNorm(vmin=zmin, vmax=1e9))  # np.nanmax(rho2d_exp/mmw/mh)

        ax_env.set_xlabel(r'$\rm{Polar\,angle\,(Degree)}$', fontsize=20)
        ax_env.set_ylabel(r'$\rm{Radius\,(AU)}$', fontsize=20)
        ax_env.tick_params(labelsize=20)
        ax_env.set_yticks(np.arange(0, R_env_max / AU, R_env_max / AU / 5))
        # ax_env.set_ylim([0,10000])
        ax_env.set_xticklabels([r'$\rm{90^{\circ}}$',r'$\rm{45^{\circ}}$',r'$\rm{0^{\circ}}$',r'$\rm{-45^{\circ}}$',\
                                r'$\rm{-90^{\circ}}$',r'$\rm{-135^{\circ}}$',r'$\rm{180^{\circ}}$',r'$\rm{135^{\circ}}$'])
        # fix the tick label font
        ticks_font = mpl.font_manager.FontProperties(family='STIXGeneral',
                                                     size=20)
        for label in ax_env.get_yticklabels():
            label.set_fontproperties(ticks_font)

        ax_env.grid(True)
        cb = fig.colorbar(img_env, pad=0.1)
        cb.ax.set_ylabel(r'$\rm{Averaged\,Gas\,Density\,(cm^{-3})}$',
                         fontsize=20)
        cb.set_ticks([1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9])
        cb.set_ticklabels([r'$\rm{10^{2}}$',r'$\rm{10^{3}}$',r'$\rm{10^{4}}$',r'$\rm{10^{5}}$',r'$\rm{10^{6}}$',\
                           r'$\rm{10^{7}}$',r'$\rm{10^{8}}$',r'$\rm{\geq 10^{9}}$'])
        cb_obj = plt.getp(cb.ax.axes, 'yticklabels')
        plt.setp(cb_obj, fontsize=20)
        fig.savefig(outdir + outname + '_gas_density.png',
                    format='png',
                    dpi=300,
                    bbox_inches='tight')
        fig.clf()

        # Plot the radial density profile
        fig = plt.figure(figsize=(12, 9))
        ax = fig.add_subplot(111)

        plot_grid = [0, 49, 99, 149, 199]
        alpha = np.linspace(0.3, 1.0, len(plot_grid))
        for i in plot_grid:
            rho_rad, = ax.plot(np.log10(rc / AU),
                               np.log10(rho2d[:, i] / g2d / mmw / mh),
                               '-',
                               color='b',
                               linewidth=2,
                               markersize=3,
                               alpha=alpha[plot_grid.index(i)])
            tsc_only, = ax.plot(np.log10(rc / AU),
                                np.log10(rho_env_tsc2d[:, i] / mmw / mh),
                                'o',
                                color='r',
                                linewidth=2,
                                markersize=3,
                                alpha=alpha[plot_grid.index(i)])
        rinf = ax.axvline(np.log10(R_inf / AU),
                          linestyle='--',
                          color='k',
                          linewidth=1.5)
        cen_r = ax.axvline(np.log10(R_cen / AU),
                           linestyle=':',
                           color='k',
                           linewidth=1.5)
        # sisslope, = ax.plot(np.log10(rc/AU), -2*np.log10(rc/AU)+A-(-2)*np.log10(plot_r_inf), linestyle='--', color='Orange', linewidth=1.5)
        # gt_R_cen_slope, = ax.plot(np.log10(rc/AU), -1.5*np.log10(rc/AU)+B-(-1.5)*np.log10(plot_r_inf), linestyle='--', color='Orange', linewidth=1.5)
        # lt_R_cen_slope, = ax.plot(np.log10(rc/AU), -0.5*np.log10(rc/AU)+A-(-0.5)*np.log10(plot_r_inf), linestyle='--', color='Orange', linewidth=1.5)

        lg = plt.legend([rho_rad, tsc_only, rinf, cen_r],\
                        [r'$\rm{\rho_{dust}}$',r'$\rm{\rho_{tsc}}$',r'$\rm{infall\,radius}$',r'$\rm{centrifugal\,radius}$'],\
                        fontsize=20, numpoints=1)
        ax.set_xlabel(r'$\rm{log(Radius)\,(AU)}$', fontsize=20)
        ax.set_ylabel(r'$\rm{log(Gas \slash Dust\,Density)\,(cm^{-3})}$',
                      fontsize=20)
        [
            ax.spines[axis].set_linewidth(1.5)
            for axis in ['top', 'bottom', 'left', 'right']
        ]
        ax.minorticks_on()
        ax.tick_params('both',
                       labelsize=18,
                       width=1.5,
                       which='major',
                       pad=15,
                       length=5)
        ax.tick_params('both',
                       labelsize=18,
                       width=1.5,
                       which='minor',
                       pad=15,
                       length=2.5)

        # fix the tick label font
        ticks_font = mpl.font_manager.FontProperties(family='STIXGeneral',
                                                     size=18)
        for label in ax.get_xticklabels():
            label.set_fontproperties(ticks_font)
        for label in ax.get_yticklabels():
            label.set_fontproperties(ticks_font)

        ax.set_ylim([0, 15])
        fig.gca().set_xlim(left=np.log10(0.05))
        # ax.set_xlim([np.log10(0.8),np.log10(10000)])

        # subplot shows the radial density profile along the midplane
        ax_mid = plt.axes([0.2, 0.2, 0.2, 0.2], frameon=True)
        ax_mid.plot(np.log10(rc / AU),
                    np.log10(rho2d[:, 199] / g2d / mmw / mh),
                    'o',
                    color='b',
                    linewidth=1,
                    markersize=2)
        ax_mid.plot(np.log10(rc / AU),
                    np.log10(rho_env_tsc2d[:, 199] / mmw / mh),
                    '-',
                    color='r',
                    linewidth=1,
                    markersize=2)
        # ax_mid.set_ylim([0,10])
        # ax_mid.set_xlim([np.log10(0.8),np.log10(10000)])
        ax_mid.set_ylim([0, 15])
        fig.savefig(outdir + outname + '_gas_radial.pdf',
                    format='pdf',
                    dpi=300,
                    bbox_inches='tight')
        fig.clf()

    # Insert the calculated grid and dust density profile into hyperion
    m.set_spherical_polar_grid(ri, thetai, phii)
    # temperary for comparing full TSC and infall-only TSC model
    # import sys
    # sys.path.append(os.path.expanduser('~')+'/programs/misc/')
    # from tsc_comparison import tsc_com
    # rho_tsc, rho_ulrich = tsc_com()
    m.add_density_grid(rho_dust.T, d)
    # m.add_density_grid(rho.T, outdir+'oh5.hdf5')    # numpy read the array in reverse order

    # Define the luminsoity source
    source = m.add_spherical_source()
    source.luminosity = (4 * PI * rstar**2) * sigma * (tstar**4)  # [ergs/s]
    source.radius = rstar  # [cm]
    source.temperature = tstar  # [K]
    source.position = (0., 0., 0.)
    print 'L_center =  % 5.2f L_sun' % ((4 * PI * rstar**2) * sigma *
                                        (tstar**4) / LS)

    # # add an infrared source at the center
    # L_IR = 0.04
    # ir_source = m.add_spherical_source()
    # ir_source.luminosity = L_IR*LS
    # ir_source.radius = rstar      # [cm]
    # ir_source.temperature = 500 # [K]  peak at 10 um
    # ir_source.position = (0., 0., 0.)
    # print 'Additional IR source, L_IR = %5.2f L_sun' % L_IR

    # Setting up the wavelength for monochromatic radiative transfer
    lambda0 = 0.1
    lambda1 = 2.0
    lambda2 = 50.0
    lambda3 = 95.0
    lambda4 = 200.0
    lambda5 = 314.0
    lambda6 = 1000.0
    n01 = 10.0
    n12 = 20.0
    n23 = 50.0

    lam01 = lambda0 * (lambda1 / lambda0)**(np.arange(n01) / n01)
    lam12 = lambda1 * (lambda2 / lambda1)**(np.arange(n12) / n12)
    lam23 = lambda2 * (lambda6 / lambda2)**(np.arange(n23 + 1) / n23)

    lam = np.concatenate([lam01, lam12, lam23])
    nlam = len(lam)

    # Create camera wavelength points
    n12 = 70.0
    n23 = 70.0
    n34 = 70.0
    n45 = 50.0
    n56 = 50.0

    lam12 = lambda1 * (lambda2 / lambda1)**(np.arange(n12) / n12)
    lam23 = lambda2 * (lambda3 / lambda2)**(np.arange(n23) / n23)
    lam34 = lambda3 * (lambda4 / lambda3)**(np.arange(n34) / n34)
    lam45 = lambda4 * (lambda5 / lambda4)**(np.arange(n45) / n45)
    lam56 = lambda5 * (lambda6 / lambda5)**(np.arange(n56 + 1) / n56)

    lam_cam = np.concatenate([lam12, lam23, lam34, lam45, lam56])
    n_lam_cam = len(lam_cam)

    # Radiative transfer setting

    # number of photons for temp and image
    lam_list = lam.tolist()
    # print lam_list
    m.set_raytracing(True)
    # option of using more photons for imaging
    if better_im == False:
        im_photon = 1e6
    else:
        im_photon = 5e7

    if mono == True:
        # Monechromatic radiative transfer setting
        m.set_monochromatic(True, wavelengths=lam_list)
        m.set_n_photons(initial=1000000,
                        imaging_sources=im_photon,
                        imaging_dust=im_photon,
                        raytracing_sources=1000000,
                        raytracing_dust=1000000)
    else:
        # regular wavelength grid setting
        m.set_n_photons(initial=1000000,
                        imaging=im_photon,
                        raytracing_sources=1000000,
                        raytracing_dust=1000000)
    # number of iteration to compute dust specific energy (temperature)
    m.set_n_initial_iterations(20)
    # m.set_convergence(True, percentile=95., absolute=1.5, relative=1.02)
    m.set_convergence(True,
                      percentile=dict_params['percentile'],
                      absolute=dict_params['absolute'],
                      relative=dict_params['relative'])
    m.set_mrw(True)  # Gamma = 1 by default
    # m.set_forced_first_scattering(forced_first_scattering=True)

    # Setting up images and SEDs
    # SED setting

    # Infinite aperture
    syn_inf = m.add_peeled_images(image=False)
    # use the index of wavelength array used by the monochromatic radiative transfer
    if mono == False:
        syn_inf.set_wavelength_range(1400, 2.0, 1400.0)
    syn_inf.set_viewing_angles([dict_params['view_angle']], [0.0])
    syn_inf.set_uncertainties(True)
    syn_inf.set_output_bytes(8)

    # aperture
    # 7.2 in 10 um scaled by lambda / 10
    # flatten beyond 20 um
    # default aperture
    if aperture == None:
        aperture = {'wave': [3.6, 4.5, 5.8, 8.0, 8.5, 9, 9.7, 10, 10.5, 11, 16, 20, 24, 35, 70, 100, 160, 250, 350, 500, 1300],\
                    'aperture': [7.2, 7.2, 7.2, 7.2, 7.2, 7.2, 7.2, 7.2, 7.2, 7.2, 20.4, 20.4, 20.4, 20.4, 24.5, 24.5, 24.5, 24.5, 24.5, 24.5, 101]}
    # assign wl_aper and aper from dictionary of aperture
    wl_aper = aperture['wave']
    aper = aperture['aperture']
    # create the non-repetitive aperture list and index array
    aper_reduced = list(set(aper))
    index_reduced = np.arange(1, len(aper_reduced) + 1)

    # name = np.arange(1,len(wl_aper)+1)
    # aper = np.empty_like(wl_aper)
    # for i in range(0, len(wl_aper)):
    #     if wl_aper[i] < 5:
    #         # aper[i] = 1.2 * 7
    #         aper[i] = 1.8 * 4
    #     elif (wl_aper[i] < 14) & (wl_aper[i] >=5):
    #         # aper[i] = 7.2 * wl_aper[i]/10.
    #         aper[i] = 1.8 * 4
    #     elif (wl_aper[i] >= 14) & (wl_aper[i] <40):
    #         # aper[i] = 7.2 * 2
    #         aper[i] = 5.1 * 4
    #     else:
    #         aper[i] = 24.5

    # dict_peel_sed = {}
    # for i in range(0, len(wl_aper)):
    #     aper_dum = aper[i]/2 * (1/3600.*np.pi/180.)*dstar*pc
    #     dict_peel_sed[str(name[i])] = m.add_peeled_images(image=False)
    #     # use the index of wavelength array used by the monochromatic radiative transfer
    #     if mono == False:
    #         # dict_peel_sed[str(name[i])].set_wavelength_range(1300, 2.0, 1300.0)
    #         dict_peel_sed[str(name[i])].set_wavelength_range(1000, 2.0, 1000.0)
    #     dict_peel_sed[str(name[i])].set_viewing_angles([dict_params['view_angle']], [0.0])
    #     # aperture should be given in cm
    #     dict_peel_sed[str(name[i])].set_aperture_range(1, aper_dum, aper_dum)
    #     dict_peel_sed[str(name[i])].set_uncertainties(True)
    #     dict_peel_sed[str(name[i])].set_output_bytes(8)

    dict_peel_sed = {}
    for i in range(0, len(aper_reduced)):
        aper_dum = aper_reduced[i] / 2 * (1 / 3600. * np.pi /
                                          180.) * dstar * pc
        dict_peel_sed[str(index_reduced[i])] = m.add_peeled_images(image=False)
        # use the index of wavelength array used by the monochromatic radiative transfer
        if mono == False:
            dict_peel_sed[str(index_reduced[i])].set_wavelength_range(
                1400, 2.0, 1400.0)
        dict_peel_sed[str(index_reduced[i])].set_viewing_angles(
            [dict_params['view_angle']], [0.0])
        # aperture should be given in cm and its the radius of the aperture
        dict_peel_sed[str(index_reduced[i])].set_aperture_range(
            1, aper_dum, aper_dum)
        dict_peel_sed[str(index_reduced[i])].set_uncertainties(True)
        dict_peel_sed[str(index_reduced[i])].set_output_bytes(8)

    # image setting
    syn_im = m.add_peeled_images(sed=False)
    # use the index of wavelength array used by the monochromatic radiative transfer
    if mono == False:
        syn_im.set_wavelength_range(1400, 2.0, 1400.0)
    # pixel number
    syn_im.set_image_size(300, 300)
    syn_im.set_image_limits(-R_env_max, R_env_max, -R_env_max, R_env_max)
    syn_im.set_viewing_angles([dict_params['view_angle']], [0.0])
    syn_im.set_uncertainties(True)
    # output as 64-bit
    syn_im.set_output_bytes(8)

    # Output setting
    # Density
    m.conf.output.output_density = 'last'

    # Density difference (shows where dust was destroyed)
    m.conf.output.output_density_diff = 'none'

    # Energy absorbed (using pathlengths)
    m.conf.output.output_specific_energy = 'last'

    # Number of unique photons that passed through the cell
    m.conf.output.output_n_photons = 'last'

    m.write(outdir + outname + '.rtin')

    if radmc == True:
        # RADMC-3D still use a pre-defined aperture with lazy for-loop
        aper = np.zeros([len(lam)])
        ind = 0
        for wl in lam:
            if wl < 5:
                aper[ind] = 8.4
            elif wl >= 5 and wl < 14:
                aper[ind] = 1.8 * 4
            elif wl >= 14 and wl < 40:
                aper[ind] = 5.1 * 4
            else:
                aper[ind] = 24.5
            ind += 1

        # Write the wavelength_micron.inp file
        #
        f_wave = open(outdir + 'wavelength_micron.inp', 'w')
        f_wave.write('%d \n' % int(nlam))
        for ilam in range(0, nlam):
            f_wave.write('%f \n' % lam[ilam])
        f_wave.close()

        # Write the camera_wavelength_micron.inp file
        #
        f_wave_cam = open(outdir + 'camera_wavelength_micron.inp', 'w')
        f_wave_cam.write('%d \n' % int(nlam))
        for ilam in range(0, nlam):
            f_wave_cam.write('%f \n' % lam[ilam])
        f_wave_cam.close()

        # Write the aperture_info.inp
        #
        f_aper = open(outdir + 'aperture_info.inp', 'w')
        f_aper.write('1 \n')
        f_aper.write('%d \n' % int(nlam))
        for iaper in range(0, len(aper)):
            f_aper.write('%f \t %f \n' % (lam[iaper], aper[iaper] / 2))
        f_aper.close()

        # Write the stars.inp file
        #
        f_star = open(outdir + 'stars.inp', 'w')
        f_star.write('2\n')
        f_star.write('1 \t %d \n' % int(nlam))
        f_star.write('\n')
        f_star.write('%e \t %e \t %e \t %e \t %e \n' %
                     (rstar * 0.9999, mstar, 0, 0, 0))
        f_star.write('\n')
        for ilam in range(0, nlam):
            f_star.write('%f \n' % lam[ilam])
        f_star.write('\n')
        f_star.write('%f \n' % -tstar)
        f_star.close()

        # Write the grid file
        #
        f_grid = open(outdir + 'amr_grid.inp', 'w')
        f_grid.write('1\n')  # iformat
        f_grid.write('0\n')  # AMR grid style  (0=regular grid, no AMR)
        f_grid.write(
            '150\n'
        )  # Coordinate system  coordsystem<100: Cartisian; 100<=coordsystem<200: Spherical; 200<=coordsystem<300: Cylindrical
        f_grid.write('0\n')  # gridinfo
        f_grid.write('1 \t 1 \t 1 \n')  # Include x,y,z coordinate
        f_grid.write('%d \t %d \t %d \n' %
                     (int(nx) - 1, int(ny), int(nz)))  # Size of the grid
        [f_grid.write('%e \n' % ri[ir]) for ir in range(1, len(ri))]
        [
            f_grid.write('%f \n' % thetai[itheta])
            for itheta in range(0, len(thetai))
        ]
        [f_grid.write('%f \n' % phii[iphi]) for iphi in range(0, len(phii))]
        f_grid.close()

        # Write the density file
        #
        f_dust = open(outdir + 'dust_density.inp', 'w')
        f_dust.write('1 \n')  # format number
        f_dust.write('%d \n' % int((nx - 1) * ny * nz))  # Nr of cells
        f_dust.write('1 \n')  # Nr of dust species
        for iphi in range(0, len(phic)):
            for itheta in range(0, len(thetac)):
                for ir in range(1, len(rc)):
                    f_dust.write('%e \n' % rho_dust[ir, itheta, iphi])
        f_dust.close()

        # Write the dust opacity table
        f_dustkappa = open(outdir + 'dustkappa_oh5_extended.inp', 'w')
        f_dustkappa.write('3 \n')  # format index for including g-factor
        f_dustkappa.write(
            '%d \n' %
            len(dust['nu']))  # number of wavlength/frequency in the table
        for i in range(len(dust['nu'])):
            f_dustkappa.write('%f \t %f \t %f \t %f \n' %
                              (c / dust['nu'][i] * 1e4, dust['chi'][i],
                               dust['chi'][i] * dust['albedo'][i] /
                               (1 - dust['albedo'][i]), dust['g'][i]))
        f_dustkappa.close()

        # Write the Dust opacity control file
        #
        f_opac = open(outdir + 'dustopac.inp', 'w')
        f_opac.write('2               Format number of this file\n')
        f_opac.write('1               Nr of dust species\n')
        f_opac.write(
            '============================================================================\n'
        )
        f_opac.write(
            '1               Way in which this dust species is read\n')
        f_opac.write('0               0=Thermal grain\n')
        # f_opac.write('klaus           Extension of name of dustkappa_***.inp file\n')
        f_opac.write(
            'oh5_extended    Extension of name of dustkappa_***.inp file\n')
        f_opac.write(
            '----------------------------------------------------------------------------\n'
        )
        f_opac.close()

        # In[112]:

        # Write the radmc3d.inp control file
        #
        f_control = open(outdir + 'radmc3d.inp', 'w')
        f_control.write('nphot = %d \n' % 100000)
        f_control.write('scattering_mode_max = 2\n')
        f_control.write('camera_min_drr = 0.1\n')
        f_control.write('camera_min_dangle = 0.1\n')
        f_control.write('camera_spher_cavity_relres = 0.1\n')
        f_control.write('istar_sphere = 1\n')
        f_control.write('modified_random_walk = 1\n')
        f_control.close()

    return m


# from input_reader import input_reader_table
# from pprint import pprint
# filename = '/Users/yaolun/programs/misc/hyperion/test_input.txt'
# params = input_reader_table(filename)
# pprint(params[0])
# indir = '/Users/yaolun/test/'
# outdir = '/Users/yaolun/test/'
# dust_file = '/Users/yaolun/programs/misc/oh5_hyperion.txt'
# # dust_file = '/Users/yaolun/Copy/dust_model/Ormel2011/hyperion/(ic-sil,gra)3opc.txt'
# # fix_params = {'R_min': 0.14}
# fix_params = {}
# setup_model(indir,outdir,'model_test',params[0],dust_file,plot=True,record=False,\
#     idl=False,radmc=False,fix_params=fix_params,ellipsoid=False)
예제 #23
0
def call_pro(pro_name, idl_path='idl', **pro_kwargs):
    idl = pidly.IDL(idl_path)
    idl.pro(pro_name, **pro_kwargs)
    idl.close()
예제 #24
0
def rotate_shift_align(xcen, ycen, angle, skysub_science_array, objname, sciheader, current_dir, imsize=1024):
    '''
    rotate_shift_align
    ----------
    Procedure to rotate reduced science images (if needed), shift them, and then combine into a final 
    reduced science frame. 
        
    Inputs
    ----------
    xcen                    : (array) array of x-centers for each image
    ycen                    : (array) array of y-centers for each image
    angle                   : (list) list of length n containing rotation angle of each image
    skysub_science_array    : (array) stacked (x by y by n) array of reduced, sky-subtracted science image data 
    objname                 : (string) name of object
    sciheader               : (FITS header) header from the first science image in the stack
    current_dir             : (string) path to current directory to update pIDLy
    imsize                  : image dimensions, default = 1024
    
    Returns
    ----------
    name                    : (FITS image) reduced, combined frame in form of objname + '_' + date + '_final.fits'
    
    Dependents
    ----------
    reduced_science_array   :  this should be the output from the sky_subtract function
    measure_star_centers    :  needed to provide the input x, y center positions
    '''
    date = sciheader['UTSTART']
    date = date[0:10]
    
    n = skysub_science_array.shape[2]

    #The position of the star in the first image
    #is used as the reference position

    corners = np.zeros([2,4,n])

    #xcen, ycen are the list of coordinates for the stars in each image
    old_xcen = np.copy(xcen)
    old_ycen = np.copy(ycen)

    for ii in range(0, n):
        corners[0,0,ii]= 0
        corners[0,1,ii]= 0
        corners[0,2,ii]= imsize
        corners[0,3,ii]= imsize

        corners[1,0,ii]= 0
        corners[1,1,ii]= imsize
        corners[1,2,ii]= 0
        corners[1,3,ii]= imsize

        if angle[ii] != 0:
    #If we need to rotate, do this now
    #update both star position, and corner positions
    #Rotation matrix
            new_x = (np.cos(angle[ii])*xcen[ii]) + (-(np.sin(angle[ii])*ycen[ii]))
            new_y = (np.sin(angle[ii])*xcen[ii]) + (np.cos(angle[ii])*ycen[ii]) 
            
            xcen[ii] = new_x
            ycen[ii] = new_y

            for jj in range(0,4):
                new_x = (np.cos(angle[ii])*corners[1,jj,ii]) + (-(np.sin(angle[ii])*corners[0,jj,ii]))
                new_y = (np.sin(angle[ii])*corners[1,jj,ii]) + (np.cos(angle[ii])*corners[0,jj,ii])   
                corners[:,jj,ii] = [new_y, new_x]

        # define reference image star position
        if ii == 0:
            star = [ycen[ii], xcen[ii]]
        else:
            # define offsets for each image
            dx = star[1] - xcen[ii]
            dy = star[0] - ycen[ii]
            corners[1,:,ii] += dx
            corners[0,:,ii] += dy

    # Set so that the image starts at 0,0
    dx = np.min(corners[1,:,:])
    star[1] -= dx
    corners[1,:,:] -= dx

    dy = np.min(corners[0,:,:])
    star[0] -= dy
    corners[0,:,:] -= dy

    # and find the maximum size
    xsize = int(np.ceil(np.max(corners[1,:,:])))
    ysize = int(np.ceil(np.max(corners[0,:,:])))
    print(xsize,ysize)

    # Restore your original list of star positions within the non-rotated/shifted images
    xcen = np.copy(old_xcen)
    ycen = np.copy(old_ycen)

    # now shift each of the science frames to match reference
    big_im = np.zeros([ysize,xsize,n])

    for ii in range(0, n):
        
        xarr = np.array([np.arange(xsize),]*ysize, dtype=np.float64)
        yarr = np.array([np.arange(ysize),]*xsize, dtype=np.float64).transpose()

        if angle[ii] != 0.0:
            new_x = (np.cos(angle[ii])*xcen[ii]) + (-(np.sin(angle[ii])*ycen[ii]))
            new_y = (np.sin(angle[ii])*xcen[ii]) + (np.cos(angle[ii])*ycen[ii]) 

            xcen[ii] = new_x
            ycen[ii] = new_y
        
            xshift = star[1] - xcen[ii]
            yshift = star[0] - ycen[ii]

            new_x = (np.cos(-angle[ii])*xshift) + (-(np.sin(-angle[ii])*yshift))
            new_y = (np.sin(-angle[ii])*xshift) + (np.cos(-angle[ii])*yshift) 
        
            xshift = new_x
            yshift = new_y      
            
            new_x = (np.cos(-angle[ii])*xarr) + (-(np.sin(-angle[ii])*yarr))
            new_y = (np.sin(-angle[ii])*xarr) + (np.cos(-angle[ii])*yarr)

            xarr = new_x
            yarr = new_y
            xarr -= xshift
            yarr -= yshift
        else:
            xshift = star[1] - xcen[ii]
            yshift = star[0] - ycen[ii]
            xarr -= xshift
            yarr -= yshift

        shifted_tmp = sp.ndimage.map_coordinates(skysub_science_array[:,:,ii], [yarr.reshape((1,xsize*ysize)), xarr.reshape((1,xsize*ysize))], mode='constant', cval=0.0, order=3)
        shifted_tmp = shifted_tmp.reshape((ysize,xsize))
        shifted_tmp[np.where(shifted_tmp == 0)] = np.nan

        big_im[:,:,ii] = shifted_tmp
        print(f"Shifting image {ii} of {n}...") 

        shiftname = objname + '-' + date + '-MMT-00' + str(ii) + '.fits'
        if ii >= 10:
            shiftname = objname + '-'+ date + '-MMT-0' + str(ii) + '.fits'
        if ii >= 100:
            shiftname = objname + '-' + date + '-MMT-' + str(ii) + '.fits'

        sciheader['CRPIX1A'] = (star[1],'primary star X-center')
        sciheader['CRPIX2A'] = (star[0],'primary star Y-center')
        sciheader['CRVAL1A'] = (0,'')
        sciheader['CRVAL2A'] = (0,'')
        sciheader['CTYPE1A'] = ('Xprime','')
        sciheader['CTYPE2A'] = ('Yprime','')
        sciheader['CD1_1A'] = (1,'')
        sciheader['CD1_2A'] = (0,'')
        sciheader['CD2_1A'] = (0,'')
        sciheader['CD2_2A'] = (1,'')
        sciheader['BZERO'] = (0,'')

        fits.writeto(shiftname, big_im[:,:,ii], sciheader, overwrite = True, output_verify = 'silentfix')


    # median combine the shifted science frames to produce final image!

    date = sciheader['UTSTART']
    date = date[0:10]

    name = objname + '_' + date + '_final.fits'

    sciheader['CRPIX1A'] = (star[1],'primary star X-center')
    sciheader['CRPIX2A'] = (star[0],'primary star Y-center')
    sciheader['CRVAL1A'] = (0,'')
    sciheader['CRVAL2A'] = (0,'')
    sciheader['CTYPE1A'] = ('Xprime','')
    sciheader['CTYPE2A'] = ('Yprime','')
    sciheader['CD1_1A'] = (1,'')
    sciheader['CD1_2A'] = (0,'')
    sciheader['CD2_1A'] = (0,'')
    sciheader['CD2_2A'] = (1,'')
    sciheader['BZERO'] = (0,'')

    fits.writeto('tmp.fits', big_im, sciheader, overwrite = True, output_verify='silentfix')

    del skysub_science_array
    del big_im
    del shifted_tmp
    
    idl = pidly.IDL('/Applications/exelis/idl/bin/idl')
    # ensure that idl thinks we're in the same place the console does
    idl_changedir = 'cd, ' + f'"{current_dir}"'
    idl(idl_changedir)

    idl('name = "'+ name +'"')
    idl('big_im = mrdfits("tmp.fits",0,header,/fscale,/silent)')
    idl('big_im = transpose(big_im,[1,2,0])')
    idl('mwrfits,big_im,"stack.fits",/create')
    idl('med_im = median(big_im,dimension=3)')
    idl('sxdelpar,header,"NAXIS3"')
    idl('mwrfits,med_im,name,header,/create')

    os.remove('tmp.fits')

    idl.close()

    return
예제 #25
0
파일: lnr.py 프로젝트: s0239057/lnr
def kelly(x1, x2, x1err=[], x2err=[], cerr=[], logify=True,
          miniter=5000, maxiter=1e5, metro=True, silent=True,
          output='percentiles', full_output=None):
    """
    Python wrapper for the linear regression MCMC of Kelly (2007).
    Requires pidly (http://astronomy.sussex.ac.uk/~anthonys/pidly/) and
    an IDL license.

    Parameters
    ----------
      x1        : array of floats
                  Independent variable, or observable
      x2        : array of floats
                  Dependent variable
      x1err     : array of floats (optional)
                  Uncertainties on the independent variable
      x2err     : array of floats (optional)
                  Uncertainties on the dependent variable
      cerr      : array of floats (optional)
                  Covariances of the uncertainties in the dependent and
                  independent variables
      output    : {'full', 'percentiles', 'std'}
                  whether to return the full posterior distributions,
                  the median and lower and upper uncertainties, or the
                  median and standard deviation. Default 'percentiles'.
      full_output : bool (optional)
                  For backward compatibility. `full_output=True` sets
                  `output='full'` and `full_output=False` sets
                  `output='std'`. If not specified, this parameter is
                  ignored. DEPRECATED.

    Returns
    -------
      a, b, s   : float arrays
                  normalization, slope and intrinsic scatter, depending
                  on the `output` parameter
    """
    assert output in ('full', 'percentiles', 'std'), \
        'Invalid value of argument output. See function help for details.'

    # import here so it's not required if any other function is called
    import pidly

    n = len(x1)
    assert len(x2) == n, 'x1 and x2 must have same length'
    if len(x1err) == 0:
        x1err = np.zeros(n)
    if len(x2err) == 0:
        x2err = np.zeros(n)
    if len(cerr) == 0:
        cerr = np.zeros(n)
    if logify:
        x1, x1errr = to_log(x1, x1err)
        x2, x1errr = to_log(x2, x2err)
    idl = pidly.IDL()
    idl('x1', x1)
    idl('x2', x2)
    cmd = 'linmix_err, x1, x2, fit'
    if len(x1err) == n:
        idl('x1err', x1err)
        cmd += ', xsig=x1err'
    if len(x2err) == n:
        idl('x2err', x2err)
        cmd += ', ysig=x2err'
    if len(cerr) == n:
        idl('cerr', cerr)
        cmd += ', xycov=cerr'
    cmd += ', miniter={0}, maxiter={1}'.format(miniter, maxiter)
    if metro:
        cmd += ', /metro'
    if silent:
        cmd += ', /silent'
    idl(cmd)
    alpha = idl.ev('fit.alpha')
    beta = idl.ev('fit.beta')
    sigma = np.sqrt(idl.ev('fit.sigsqr'))

    if full_output is not None:
        msg = 'argument full_output is deprecated. Please use the argument' \
              ' output instead.'
        warnings.warn(msg, DeprecationWarning)
        output = 'full' if full_output else 'std'

    if output == 'full':
        output = alpha, beta, sigma
    elif output == 'percentiles':
        out = np.array(
            [[np.median(i), np.percentile(i, 16), np.percentile(i, 84)]
             for i in (alpha, beta, sigma)])
        out[:,1:] = np.abs(out[:,1:] - out[:,0,np.newaxis])
    elif output == 'std':
        out = np.array(
            [[np.median(i), np.std(i)] for i in (alpha, beta, sigma)])
    return out
def gas_velo_at_particle_pos(varfiles='last4', sim=False, scheme='tsc', use_IDL=False, OVERWRITE=False):
  """This script calulates the gas velocity at the particle position and stores this together
  with particle position, containing grid cell idicies, particle velocities, and particle index
  in a gas_velo_at_particle_pos file.

  Args:
    varfiles:       specifiy varfiles for calculation, e.g. 'last', 'first',
                        'all', 'VAR###', 'last4', 'first3'
    scheme:         possible are:
                        - ngp: nearest grid point
                        - cic: cloud in cell
                        - tsc: triangular shaped cloud
    OVERWRITE:		set to True to overwrite already calculated results
  """

  import pencilnew as pcn
  from os.path import exists
  import numpy as np

  GAS_VELO_TAG = 'gas_velo_at_particle_pos'

  if sim == False:
      sim = pcn.get_sim()
      if sim == False:
          print('! ERROR: Specify simulation object!')
          return False
  SIM = sim

  if use_IDL:
      print('? WARNING: IDL VERSION OF THIS SCRIPT BY JOHANSEN, not recommended for 2D data')
      import pidly; print '## starting IDL engine..'; IDL = pidly.IDL(long_delay=0.05)		# start IDL engine

      ## skip if nothing is new
      if (not OVERWRITE) and (exists(join(SIM.pc_datadir, 'sigma.pkl'))) and (exists(join(SIM.pc_datadir, 'zeta.pkl'))):
          print('~ '+SIM.name+' is already calculated and up-to-date! -> skipping it!')

      else:
          ## start calculations
          print('~ Calculating gas_velo_at_particle_pos for "'+SIM.name+'" in "'+SIM.path+'"')
          IDL.pro('gas_velo_at_particle_pos', datadir=SIM.datadir, destination=GAS_VELO_TAG, doforthelastNvar=varfiles[4:])
          files = [i.split('_')[-1].split('.sav')[0] for i in listdir(join(SIM.pendatadir,GAS_VELO_TAG)) if i.startswith(GAS_VELO_TAG) and i.endswith('.sav') or i.endswith('.pkl')]
          if files == []: print('!! ERROR: No calc_gas_speed_at_particle_position-files found for '+SIM.name+'! Use idl script to produce them first!')

      IDL.close()
      return True

  else:
      print('~ Calculating gas_velo_at_particle_pos for "'+SIM.name+'" in "'+SIM.path+'"')
      save_destination = join(SIM.pc_datadir, GAS_VELO_TAG); mkdir(save_destination)
      varlist = SIM.get_varlist(pos=varfiles, particle=False); pvarlist = SIM.get_varlist(pos=varfiles, particle=True)

      for f, p in zip(varlist, pvarlist):
          save_filename = GAS_VELO_TAG+'_'+scheme+'_'+f[3:]
          if not OVERWRITE and exists(save_filename, folder=save_destination): continue

          print('## Reading '+f+' ...')
          ff = pcn.read.var(datadir=SIM.datadir, varfile=f, quiet=True, trimall=False)
          pp = pc.read.pvar(datadir=SIM.datadir, varfile=p)

          ## remove ghost zones from grid, call the reduced grid the "real grid"
          realgridx = ff.x[ff.l1:ff.l2]; realgridy = ff.y[ff.m1:ff.m2]; realgridz = ff.z[ff.n1:ff.n2]
          nx = ff.l2-ff.l1; ny = ff.m2-ff.m1; nz = ff.n2-ff.n1

          ## prepare list for all quantities
          l_ipars = pp.ipars                                # particle number   KNOWN
          l_px = pp.xp;  l_py = pp.yp;  l_pz = pp.zp        # particle absolut position KNOWN
          l_vx = pp.vpx; l_vy = pp.vpy; l_vz = pp.vpz       # particle velocity KNOWN
          l_rix = [];    l_riy = [];    l_riz = []          # particle untrimmed realgrid index (grid index = l/m/n + readgrid index ???)
          l_ix = [];     l_iy = [];     l_iz = []           # particle grid index (in untrimmed grid)
          l_ux = [];     l_uy = [];     l_uz = []           # underlying gas velocity at position of particle

          ## get index of realgrid cell for each particle
          for i in range(len(l_ipars)):
              l_rix.append(np.abs(realgridx-l_px[i]).argmin())
              l_riy.append(np.abs(realgridy-l_py[i]).argmin())
              l_riz.append(np.abs(realgridz-l_pz[i]).argmin())

          ## convert into untrimmed grid
          l_ix = np.array(l_rix)+ff.l1; l_iy = np.array(l_riy)+ff.m1; l_iz = np.array(l_riz)+ff.n1

          ## NGP
          if scheme == 'ngp' or scheme == 'NGP':
              print('## Calculating gas velocities via '+scheme)
              l_ux = ff.ux[l_iz, l_iy, l_ix]
              l_uy = ff.uy[l_iz, l_iy, l_ix]
              l_uz = ff.uz[l_iz, l_iy, l_ix]

          ## CIC
          if scheme == 'cic' or scheme == 'CIC':
              print('## Calculating gas velocities via '+scheme)
              for ix0, iy0, iz0, px, py, pz in zip(l_ix, l_iy, l_iz, l_px, l_py, l_pz):     # for each particle
                  if ff.x[ix0] > px: ix0 = ix0-1            # ix0 must be left to particle
                  if ff.y[iy0] > py: iy0 = iy0-1            # iy0 must be below the particle
                  if ff.z[iz0] > pz: iz0 = iz0-1            # iz0 must be under particle

                  ix1=ix0; iy1=iy0; iz1=iz0                 # if a dim. is zero, this is default, else:
                  if nx > 1: ix1 = ix0+1; dx_1 = 1./ff.dx   # if a dim is non-zero, ajust ix1 to right cell
                  if ny > 1: iy1 = iy0+1; dy_1 = 1./ff.dy   # if a dim is non-zero, ajust iy1 to above cell
                  if nz > 1: iz1 = iz0+1; dz_1 = 1./ff.dz   # if a dim is non-zero, ajust iz1 to above cell

                  ux = 0.; uy = 0.; uz = 0.
                  for ix in [ix0, ix1]:
                      for iy in [iy0, iy1]:
                          for iz in [iz0, iz1]:
                              weight = 1.
                              if nx > 1: weight = weight * ( 1. - abs(px-ff.x[ix])*dx_1)
                              if ny > 1: weight = weight * ( 1. - abs(py-ff.y[iy])*dy_1)
                              if nz > 1: weight = weight * ( 1. - abs(pz-ff.z[iz])*dz_1)

                              ux = ux + weight*ff.ux[iz, iy, ix]
                              uy = uy + weight*ff.uy[iz, iy, ix]
                              uz = uz + weight*ff.uz[iz, iy, ix]

                              if iz0 == iz1: break      # beware of degeneracy:
                          if iy0 == iy1: break      # beware of degeneracy:
                      if ix0 == ix1: break      # beware of degeneracy:

                  l_ux.append(ux); l_uy.append(uy); l_uz.append(uz)



          ## TSC
          if scheme == 'tsc' or scheme == 'TSC':
              for ix0, iy0, iz0, px, py, pz in zip(l_ix, l_iy, l_iz, l_px, l_py, l_pz):  # for each particle
                ixx0 = ix0; ixx1 = ix0      # beware of degeneracy
                iyy0 = iy0; iyy1 = iy0
                izz0 = iz0; izz1 = iz0

                if nx > 1: ixx0 = ix0-1; ixx1 = ix0+1; dx_1 = 1./ff.dx; dx_2 = 1./ff.dx**2
                if ny > 1: iyy0 = iy0-1; iyy1 = iy0+1; dy_1 = 1./ff.dy; dy_2 = 1./ff.dy**2
                if nz > 1: izz0 = iz0-1; izz1 = iz0+1; dz_1 = 1./ff.dz; dz_2 = 1./ff.dz**2

                ux = 0.; uy = 0.; uz = 0.
                for ix in [ix0, ixx0, ixx1]:
                    weight_x = 0.
                    if ix-ix0 == -1 or ix-ix0 == 1:
                        weight_x = 1.125 - 1.5*abs(px-ff.x[ix])*dx_1 + 0.5*abs(px-ff.x[ix])**2*dx_2
                    elif nx != 1:
                        weight_x = 0.75  - (px-ff.x[ix])**2*dx_2

                    for iy in [iy0, iyy0, iyy1]:
                        weight_y = 0.
                        if iy-iy0 == -1 or iy-iy0 == 1:
                            weight_y = 1.125 - 1.5*abs(py-ff.y[iy])*dy_1 + 0.5*abs(py-ff.y[iy])**2*dy_2
                        elif ny != 1:
                            weight_y = 0.75  - (py-ff.y[iy])**2*dy_2

                        for iz in [iz0, izz0, izz1]:
                            weight_z = 0.
                            if iz-iz0 == -1 or iz-iz0 == 1:
                                weight_z = 1.125 - 1.5*abs(pz-ff.z[iz])*dz_1 + 0.5*abs(pz-ff.z[iz])**2*dz_2
                            elif nz != 1:
                              weight_z = 0.75  - (pz-ff.z[iz])**2*dz_2

                            weight = 1.
                            if nx > 1: weight = weight * weight_x
                            if ny > 1: weight = weight * weight_y
                            if nz > 1: weight = weight * weight_z

                            ux = ux + weight*ff.ux[iz, iy, ix]
                            uy = uy + weight*ff.uy[iz, iy, ix]
                            uz = uz + weight*ff.uz[iz, iy, ix]

                            if izz0 == izz1: break      # beware of degeneracy:
                        if iyy0 == iyy1: break      # beware of degeneracy:
                    if ixx0 == ixx1: break      # beware of degeneracy:

                l_ux.append(ux); l_uy.append(uy); l_uz.append(uz)


          ## Convert all information into a single record array
          data_set = np.core.records.fromarrays(
                        [l_ipars.astype('int'),
                        l_px, l_py, l_pz,
                        l_vx, l_vy, l_vz,
                        l_rix, l_riy, l_riz,
                        l_ix, l_iy, l_iz,
                        l_ux, l_uy, l_uz],
                        names = 'ipar, ipx, ipy, ipz, vx, vy, vz, rix, riy, riz, ix, iy, iz, ux, uy, uz',
                        formats = 'int, float, float, float, float, float, float, int, int, int, int, int, int, float, float, float'
                        )
          gas_velo_at_particle_pos = np.sort(data_set, order=['ix', 'iy', 'iz'])

          Nix = int(gas_velo_at_particle_pos['rix'].max()+1)
          Niy = int(gas_velo_at_particle_pos['riy'].max()+1)
          Niz = int(gas_velo_at_particle_pos['riz'].max()+1)

          Npar_arr = np.array([gas_velo_at_particle_pos['rix'], gas_velo_at_particle_pos['riy'], gas_velo_at_particle_pos['riz']])
          #rgrid_edges = (grid.x[1:]-(grid.x[1:]-grid.x[:-1])/2)[2:-2]
          xrange=np.arange(0,float(gas_velo_at_particle_pos['rix'].max())+2); xrange=xrange-0.5
          yrange=np.arange(0,float(gas_velo_at_particle_pos['riy'].max())+2)
          zrange=np.arange(0,float(gas_velo_at_particle_pos['riz'].max())+2)

          Npar_hist, edges = np.histogramdd(Npar_arr.T, bins=(xrange, yrange, zrange))
          Npar_hist, edges = np.histogramdd(Npar_arr.T, bins=(Nix, Niy, Niz))


          gas_velo_at_particle_pos = {
                    'time': ff.t,
                    'par_pos': np.array([gas_velo_at_particle_pos['ipx'],
                                         gas_velo_at_particle_pos['ipy'],
                                         gas_velo_at_particle_pos['ipz']]),
                    'par_velo': np.array([gas_velo_at_particle_pos['vx'],
                                          gas_velo_at_particle_pos['vy'],
                                          gas_velo_at_particle_pos['vz']]),
                    'par_idx': np.array([gas_velo_at_particle_pos['rix'],
                                         gas_velo_at_particle_pos['riy'],
                                         gas_velo_at_particle_pos['riz']]),
                    'npar': np.array(Npar_hist[gas_velo_at_particle_pos['rix'],
                                               gas_velo_at_particle_pos['riy'],
                                               gas_velo_at_particle_pos['riz']]),
                    'gas_velo': np.array([gas_velo_at_particle_pos['ux'],
                                         gas_velo_at_particle_pos['uy'],
                                         gas_velo_at_particle_pos['uz']])
                    }


          print('## Saving dataset into '+save_destination+'...')
          pkl_save({'gas_velo_at_particle_pos': gas_velo_at_particle_pos, 't': ff.t}, save_filename, folder=save_destination)
      print('## Done!')
예제 #27
0
import numpy as np
import pandas as pd
import pidly
import glob
import json


if __name__ == "__main__":

    input_dir = "../data/ew_known/tame_inputs/"
    output_dir = "../data/ew_known/tame_outputs_windowsize/"

    spectra = glob.glob(input_dir + "*wavsoln.fits")
    parameter = 'SPACING'
    parameter_space = np.linspace(1.5, 5.5, 5)
    idl = pidly.IDL('/Applications/exelis/idl/bin/idl')

    for spectrum in spectra:

        spec_label = spectrum.split('/')[-1].split('_wavsoln')[0]
        print(spec_label)
        line_dict = {}
        for parameter_value in parameter_space:

            # Read in Parameter File
            df = pd.read_csv('tame.par', delim_whitespace=True, header=None)

            # Modify Parameter File (Sweep Parameter & Working File)
            df.at[df.index[df[0] == "LOWERCUT"].tolist()[0], 1] = '0.99'  # Obtained from extended_calibration.ipynb
            df.at[df.index[df[0] == "WORKNAME"].tolist()[0], 1] = input_dir + spec_label
            df.at[df.index[df[0] == "SPECTRUM"].tolist()[0], 1] = input_dir + spec_label+'.lpx'
예제 #28
0
def load_brightness(shot_num,
                    t_start=8.0,
                    t_end=28.0,
                    delta=0.1,
                    smooth=10.0,
                    exclude=[20, 59, 60],
                    adj=None,
                    cmd_str=''):
    """
    Function: st = load_brightness(shot_num, t_start, t_end, delta, smooth, exclude, adj, cmd_str)
    This version of load_brightness interfaces directly with the IDL implementation, via the pidly interface
        (see the signals README for instructions on setting this up).
    Inputs:
        - shot_num = [INT] The MST shot ID for the desired set of data
        - t_start = [FLOAT] The start time for the desired interval of SXR data.
        - t_end = [FLOAT] The end time for the desired interval of SXR data.
        - delta = [FLOAT] The desired sampling window for SXR data. Set to None to get the full signal. Note that
            sampling error will not be available in that case.
        - smooth = [FLOAT] The size of the smoothing window (10.0 is standard).
        - exclude = [[INT]] List of logicals which were excluded in the data file. By defaults excludes the NickAl2
            channels. For older data make sure to exclude 69
        - adj = [[FLOAT]] The time adjustment due to SXR trigger settings. Set to 0 for data past mid-2016
        - cmd_str = [STR] Additional string to append to the IDL command.
    Outputs:
        - st['key'] = [DICT] Nested dictionary containing the SXR tomography diagnostic data, indexed by camera label.
    """
    # Access (and initialize, if needed) the pidly object and assemble the command string
    idl = pidly.IDL()
    idl_str = "staus = sxr_mst_get_signals(St, /ms, shot=" + str(
        shot_num) + ", tst = " + str(t_start) + ", excl = " + str(exclude)
    idl_str += ", tend = " + str(t_end)

    # Optional keywods
    if delta is not None:
        idl_str += ", delta = " + str(delta)

    if smooth is not None:
        idl_str += ", sm = " + str(smooth)

    if len(cmd_str) == 0:
        idl_str += ")"
    else:
        idl_str += ", " + cmd_str + ")"

    # Create the structure in IDL and begin exporting the contents
    idl(idl_str)
    sxr_data = idl.ev('st.bright.data', use_cache=True)
    sxr_impact = idl.ev('st.bright.prel', use_cache=True)
    sxr_angles = idl.ev('st.bright.phi', use_cache=True)
    sxr_noise = idl.ev('st.bright.off_str.sxr_r_noise', use_cache=True)
    sxr_time = idl.ev('st.bright.time', use_cache=True)

    if delta is not None:
        sxr_error = idl.ev('st.bright.err', use_cache=True)

    # Organize the data by probe label and thick/thin convention. Now automated to account for excluded probes
    filt_list = [
        'A thick', 'B thick', 'C thick', 'D thick', 'A thin', 'B thin',
        'C thin', 'D thin'
    ]

    brightness = {}
    impact_p = {}
    impact_angle = {}
    sigma = {}
    off_noise = {}
    logicals_inc = {}

    # Manual index in order to allow exclusion of specified logicals
    index = 0

    for filt in filt_list:
        base_logical = filt_list.index(filt) * 10 + 1

        data = []
        error = []
        impact = []
        angles = []
        noise = []
        logs = []
        for logical in range(base_logical, base_logical + 10):
            if logical not in exclude:
                data.append(np.transpose(sxr_data[:, index]))
                impact.append(sxr_impact[index])
                angles.append(sxr_angles[index])
                noise.append(sxr_noise[index])
                logs.append(logical)

                if delta is not None:
                    error.append(np.transpose(sxr_error[:, index]))
                else:
                    error.append([])

                index += 1

        # Store into the dictionary
        brightness[filt] = np.array(data)
        sigma[filt] = np.array(error)
        impact_p[filt] = np.array(impact)
        impact_angle[filt] = np.array(angles)
        off_noise[filt] = np.array(noise)
        logicals_inc[filt] = logs

    # Also store same basic configuration info - logical indexing is fine
    config = {
        'filters': idl.ev('st.bright.FILTERBE_THICK', use_cache=True),
        'alpha': idl.ev('st.bright.alfa', use_cache=True),
        'gain': idl.ev('st.bright.gain', use_cache=True),
        'insertion': idl.ev('st.bright.insertion', use_cache=True)
    }

    # Assemble these into a single dictionary
    st = {
        'bright': brightness,
        'p': impact_p,
        'phi': impact_angle,
        'sigma': sigma,
        'noise': sigma,
        'logical': logicals_inc,
        'shot': shot_num,
        'time': sxr_time,
        'config': config
    }

    # Close the IDL instance to prevent runaway processes
    idl.close()

    return AttrDict(st)
예제 #29
0
    def get_data(self, trange, norm=0, atrange=[1.0, 1.1], res=0, verbose=1):
        if norm == 0:
            if verbose == 1: print('Data is not normalized')
        elif norm == 1:
            if verbose == 1: print('Data is normalized by trange average')
        elif norm == 2:
            if verbose == 1: print('Data is normalized by atrange average')

        self.trange = trange

        # open idl
        idl = pidly.IDL('/fusion/usc/opt/idl/idl84/bin/idl')

        # --- loop starts --- #
        clist_temp = self.clist.copy()
        for i, cname in enumerate(clist_temp):

            # set node
            if cname in VAR_NODE:
                node ='{:s}'.format(VAR_NODE[cname])
            else:
                node = cname

            # load data
            try:
                #idl.pro('gadat,time,data,/alldata',node,self.shot,XMIN=self.trange[0]*1000.0,XMAX=self.trange[1]*1000.0)
                idl.pro('gadat2,time,data,/alldata',node,self.shot,XMIN=self.trange[0]*1000.0,XMAX=self.trange[1]*1000.0)
                time, v = idl.time, idl.data
                if verbose == 1: print("Read {:d} - {:s} (number of data points = {:d})".format(self.shot, node, len(v)))
            except:
                self.clist.remove(cname)
                if verbose == 1: print("Failed   {:s}".format(node))
                continue

            # [ms] -> [s]
            time = time/1000.0

            # set data size
            idx = np.where((time >= trange[0])*(time <= trange[1]))
            idx1 = int(idx[0][0])
            idx2 = int(idx[0][-1]+1)
            time = time[idx1:idx2]
            v = v[idx1:idx2]

            if norm == 1:
                v = v/np.mean(v) - 1

            # expand dimension - concatenate
            v = np.expand_dims(v, axis=0)
            if i == 0:
                data = v
            else:
                data = np.concatenate((data, v), axis=0)
        # --- loop ends --- #

        self.time = time
        self.fs = round(1/(time[1] - time[0])/1000)*1000
        self.data = data

        # get channel position
        self.channel_position()

        # close idl
        idl.close()

        return time, data
예제 #30
0
def invert_brightness(shot_num,
                      t_start=8.0,
                      t_end=28.0,
                      delta=0.1,
                      smooth=10.0,
                      exclude=[20, 59, 60],
                      thick=False,
                      thin=False,
                      **kwargs):
    """
    Perform a tomographic inversion using the Cormack-Bessel technique. Makes use of Paolo's IDL library.
    Inputs:
        - shot_num = [INT] The MST shot ID for the desired set of data
    Optional:
        - t_start = [FLOAT] The start time for the desired interval of SXR data.
        - t_end = [FLOAT] The end time for the desired interval of SXR data.
        - delta = [FLOAT] The desired sampling window for SXR data.
        - smooth = [FLOAT] The size of the smoothing window (10.0 is standard).
        - exclude = [[INT]] List of logicals which were excluded in the data file. By default excludes the NickAl2
            channels. For older data make sure to still exclude 69.
        - thick = [BOOL] Include only thick filter data.
        - thin = [BOOL] Include only thick filter data.
        - kwargs = Additional keywords are used to change the inversion

    Inversion keywords: Other keyword arguments will be used to alter the inversion options array passed
        directly to the IDL routine. The allowed arguments, according to the IDL documentation, are:
        ka = $
        [ $
          'name=Cormack'          # inversion method
          'base=Bessel'           # radial function base
          'matname=matrix.dat'    # not important
          'mc=1'                  # n. of angular (poloidal) cos components
          'ms=1'                  # n. of angular (poloidal) sin components
          'ls=6'                  # n. of radial components
          'svd_tol=0.100'         # svd threshold
          'p_ref=[0.0,0,0,0.0]'   # coordinates of the origin of the axis
                                  # where the inversion will be performed
          'n_nch=5'               # n. of added edge lines of sight
          'mst'=1                 # specifies that we are working on Mst SXR data
        ]
        
        Note: The values of p_ref are [x0, y0, z0], signifying the location of the magnetic axis. These
            values are measured in meters, and z0 will typically be set to zero. The defaults arguments are
            p_ref = [0.06, 0.0, 0.0], signifying a 6cm Shafranov shift.
        Note: The value of svd_tol is the tolerance for stopping the iterative SVD inversion process. The
            default is 0.06, but can be increased (up to 0.1) as needed to smooth the reconstruction.
    """
    # Load the data into idl
    idl = pidly.IDL()
    idl_str = "staus = sxr_mst_get_signals(St, /ms, shot=" + str(
        shot_num) + ", tst = " + str(t_start)
    idl_str += ", excl = " + str(exclude) + ", tend = " + str(t_end)
    idl_str += ", delta = " + str(delta) + ", sm = " + str(smooth) + ')'
    idl(idl_str)

    # Format keywords - check for supplied arguments and change if necessary
    ka = {
        'name': 'Cormack',
        'base': 'bessel',
        'matname': 'matrix.dat',
        'mc': 1,
        'ms': 1,
        'ls': 6,
        'svd_tol': 0.06,
        'p_ref': [0.06, 0.00, 0.0]
    }

    if len(kwargs) > 0:
        for key, value in kwargs.items():
            ka[key] = value

    ka_str = 'ka = ' + str(
        ['{0:}={1:}'.format(key, value) for key, value in ka.items()])
    idl(ka_str)
    idl_str = "st_out = sxr_MST_get_emiss(st, st_emiss=st_emiss, status=status, ka=ka"
    if thick:
        idl_str += ', /thick'
    elif thin:
        idl_str += ', /thin'
    idl_str += ')'

    # Do the inversion
    idl(idl_str)

    # Import the data into python
    results = {
        'emiss': idl.ev('st_emiss.emiss', use_cache=True).T,
        'time': idl.ev('st_emiss.t', use_cache=True),
        'xs': idl.ev('st_emiss.x_emiss', use_cache=True),
        'ys': idl.ev('st_emiss.y_emiss', use_cache=True),
        'major': idl.ev('st_emiss.majr'),
        'radius': idl.ev('st_emiss.radius'),
        'kwargs': ka
    }

    # Close the IDL instance to prevent runaway processes
    idl.close()

    return AttrDict(results)