def cf(date_dir, atmfile, filters): """ Call above functions to calculate cf and plot them """ # Read atmfile molecules, p, T, abundances = mat.readatm(atmfile) nlayers = len(p) # Read tau.dat file = date_dir + 'tau.dat' tau, wns = readTauDat(file, nlayers) # Calculate BB, reverse the order of p and T p = p[::-1] T = T[::-1] BB = Planck(T, wns) # Call cf_eq() to calculate cf cf = cf_eq(BB, p, tau, nlayers, wns) # Call filter_cf() to calculate cf filt_cf, filt_cf_norm = filter_cf(filters, nlayers, wns, cf) ############ Plotting ################ print(" Plotting contribution functions.\n") # Not normalized cf plt.figure(4) plt.clf() gs = gridspec.GridSpec(1, 2, width_ratios=[5, 1]) ax0 = plt.subplot(gs[0]) for i in np.arange(len(filt_cf)): (head, tail) = os.path.split(filters[i]) lbl = tail[:-4] ax0.semilogy(filt_cf[i], p, '-', linewidth = 1, label=lbl) ax0.legend(loc='center left', bbox_to_anchor=(1.0, 0.5), prop={'size':8}) ax0.set_ylim(max(p), min(p)) ax0.ticklabel_format(style='sci', axis='x', scilimits=(0,0)) ax0.set_xlabel('Contribution functions', fontsize=14) ax0.set_ylabel('Pressure [bar]' , fontsize=14) plt.savefig(date_dir + 'ContrFuncs.png') # Normalized cf plt.figure(5) plt.clf() gs = gridspec.GridSpec(1, 2, width_ratios=[5, 1]) ax0 = plt.subplot(gs[0]) for i in np.arange(len(filt_cf_norm)): (head, tail) = os.path.split(filters[i]) lbl = tail[:-4] ax0.semilogy(filt_cf_norm[i], p, '--', linewidth = 1, label=lbl) ax0.legend(loc='center left', bbox_to_anchor=(1,0.5), prop={'size':8}) ax0.set_ylim(max(p), min(p)) ax0.set_xlim(0, 1.0) ax0.ticklabel_format(style='sci', axis='x', scilimits=(0,0)) ax0.set_xlabel('Normalized contribution functions', fontsize=14) ax0.set_ylabel('Pressure [bar]' , fontsize=14) plt.savefig(date_dir + 'NormContrFuncs.png')
def cf(date_dir, atmfile, filters): """ Call above functions to calculate cf and plot them """ # Read atmfile molecules, p, T, abundances = mat.readatm(atmfile) nlayers = len(p) # Read tau.dat file = date_dir + 'tau.dat' tau, wns = readTauDat(file, nlayers) # Calculate BB, reverse the order of p and T p = p[::-1] T = T[::-1] BB = Planck(T, wns) # Call cf_eq() to calculate cf cf = cf_eq(BB, p, tau, nlayers, wns) # Call filter_cf() to calculate cf filt_cf, filt_cf_norm = filter_cf(filters, nlayers, wns, cf) ############ Plotting ################ print(" Plotting contribution functions.\n") # Not normalized cf plt.figure(4) plt.clf() gs = gridspec.GridSpec(1, 2, width_ratios=[5, 1]) ax0 = plt.subplot(gs[0]) for i in np.arange(len(filt_cf)): (head, tail) = os.path.split(filters[i]) lbl = tail[:-4] ax0.semilogy(filt_cf[i], p, '-', linewidth=1, label=lbl) ax0.legend(loc='center left', bbox_to_anchor=(1.0, 0.5), prop={'size': 8}) ax0.set_ylim(max(p), min(p)) ax0.ticklabel_format(style='sci', axis='x', scilimits=(0, 0)) ax0.set_xlabel('Contribution functions', fontsize=14) ax0.set_ylabel('Pressure [bar]', fontsize=14) plt.savefig(date_dir + 'ContrFuncs.png') # Normalized cf plt.figure(5) plt.clf() gs = gridspec.GridSpec(1, 2, width_ratios=[5, 1]) ax0 = plt.subplot(gs[0]) for i in np.arange(len(filt_cf_norm)): (head, tail) = os.path.split(filters[i]) lbl = tail[:-4] ax0.semilogy(filt_cf_norm[i], p, '--', linewidth=1, label=lbl) ax0.legend(loc='center left', bbox_to_anchor=(1, 0.5), prop={'size': 8}) ax0.set_ylim(max(p), min(p)) ax0.set_xlim(0, 1.0) ax0.ticklabel_format(style='sci', axis='x', scilimits=(0, 0)) ax0.set_xlabel('Normalized contribution functions', fontsize=14) ax0.set_ylabel('Pressure [bar]', fontsize=14) plt.savefig(date_dir + 'NormContrFuncs.png')
def transmittance(date_dir, atmfile, filters, fext='.png', plot=True): """ """ # Read atmfile molecules, p, T, abundances = mat.readatm(date_dir + atmfile) nlayers = len(p) p = p[::-1] # top to bottom of the atmosphere # Read tau.dat foo = date_dir + 'tau.dat' tau, wns = readTauDat(foo, nlayers) # Transmittance: transmit = np.exp(-tau) # Band intgrate it: filt_tr = filter_cf(filters, nlayers, wns, transmit) nfilters = len(filters) meanwl = np.zeros(nfilters) for i in np.arange(nfilters): filtwaven, filttransm = w.readfilter(filters[i]) meanwn = np.sum(filtwaven * filttransm) / np.sum(filttransm) meanwl[i] = 1e4 / meanwn maxmeanwl = np.max(meanwl) minmeanwl = np.min(meanwl) colors = (meanwl - minmeanwl) / (maxmeanwl - minmeanwl) if plot: print(" Plotting contribution functions.\n") # Not normalized cf plt.figure(4, figsize=(8, 6.5)) plt.clf() gs = gridspec.GridSpec(1, 2, width_ratios=[20, 1], wspace=0.05) ax0 = plt.subplot(gs[0]) ax1 = plt.subplot(gs[1]) for i in np.arange(nfilters): (head, tail) = os.path.split(filters[i]) lbl = tail[:-4] ax0.semilogy(filt_tr[i], p, '-', color=plt.cm.rainbow(colors[i]), linewidth=1, label=lbl) norm = matplotlib.colors.Normalize(vmin=minmeanwl, vmax=maxmeanwl) cbar = matplotlib.colorbar.ColorbarBase(ax1, cmap=plt.cm.rainbow, norm=norm, orientation='vertical') cbar.set_label("Mean Wavelength (\u00b5m)", fontsize=14) ax0.set_ylim(max(p), min(p)) ax0.ticklabel_format(style='sci', axis='x', scilimits=(0, 0)) ax0.set_xlabel('Transmittance', fontsize=14) ax0.set_ylabel('Pressure (bar)', fontsize=14) plt.savefig(date_dir + 'Transmittance' + fext, bbox_inches='tight') plt.close() return filt_tr[:, ::-1]
def plotabun(date_dir, atmfile, molfit, fext='.png', fs=15): ''' Plot abundance profiles from best fit run. Input ----- date_dir: string Path to BART output directory atmfile: string Name of best fit atmospheric file molfit: 1D string array Molecules to plot fext: string File extension for the plots to be saved. Options: .png, .pdf Default: .png fs: int Font size for plots. ''' # Import best fit atmosphere results species, pressure, temp, abundances = mat.readatm(date_dir + atmfile) # Create array of indices for species to plot molfitindex = np.zeros(len(molfit), dtype='int') k = 0 # Find the index of each species within the atmosphere file for i in range(len(species)): for j in range(len(molfit)): if species[i] == molfit[j]: molfitindex[k] = i k += 1 plt.clf() # Plot the abundance profile of each species for i in range(len(molfit)): plt.loglog(abundances[:,molfitindex[i]], pressure, label=species[molfitindex[i]], linewidth=4) plt.legend(loc='upper left') plt.xlabel('Molar Mixing Fraction', fontsize=fs) plt.ylabel('Pressure (bar)', fontsize=fs) plt.ylim(np.amin(pressure), np.amax(pressure)) plt.title('Best Fit Abundance Profiles') plt.gca().invert_yaxis() plt.savefig(date_dir + 'abun_profiles' + fext, bbox_inches='tight')
def transmittance(date_dir, atmfile, filters, plot=True): """ """ # Read atmfile molecules, p, T, abundances = mat.readatm(date_dir + atmfile) nlayers = len(p) p = p[::-1] # top to bottom of the atmosphere # Read tau.dat foo = date_dir + 'tau.dat' tau, wns = readTauDat(foo, nlayers) # Transmittance: transmit = np.exp(-tau) # Band intgrate it: filt_tr = filter_cf(filters, nlayers, wns, transmit) nfilters = len(filters) colors = plt.cm.rainbow(np.asarray(np.linspace(0, 255, nfilters), np.int)) if plot: print(" Plotting contribution functions.\n") # Not normalized cf plt.figure(4) plt.clf() gs = gridspec.GridSpec(1, 2, width_ratios=[5, 1]) ax0 = plt.subplot(gs[0]) colormap = plt.cm.rainbow(np.linspace(0, 1, len(filters))) ax0.set_prop_cycle(plt.cycler('color', colormap)) for i in np.arange(len(filt_tr)): (head, tail) = os.path.split(filters[i]) lbl = tail[:-4] ax0.semilogy(filt_tr[i], p, '-', linewidth=1.5, label=lbl, color=colors[i]) lgd = ax0.legend(loc='center left', bbox_to_anchor=(1.0, 0.5), ncol=nfilters // 30 + 1, prop={'size': 8}) ax0.set_ylim(max(p), min(p)) ax0.ticklabel_format(style='sci', axis='x', scilimits=(0, 0)) ax0.set_xlabel('Transmittance', fontsize=14) ax0.set_ylabel('Pressure (bar)', fontsize=14) plt.savefig(date_dir + 'Transmittance.png') return filt_tr[:, ::-1]
def plotabun(date_dir, atmfile, molfit): ''' Plot abundance profiles from best fit run. Input ----- date_dir: string Path to BART output directory atmfile: string Name of best fit atmospheric file molfit: 1D string array Molecules to plot ''' # Import best fit atmosphere results species, pressure, temp, abundances = mat.readatm(date_dir + atmfile) # Create array of indices for species to plot molfitindex = np.zeros(len(molfit), dtype='int') k = 0 # Find the index of each species within the atmosphere file for i in range(len(species)): for j in range(len(molfit)): if species[i] == molfit[j]: molfitindex[k] = i k += 1 plt.clf() # Plot the abundance profile of each species for i in range(len(molfit)): plt.loglog(abundances[:,molfitindex[i]], pressure, label=species[molfitindex[i]], linewidth=4) plt.legend(loc='upper left') plt.xlabel('Molar Mixing Fraction') plt.ylabel('Pressure (bars)') plt.title('Best Fit Abundance Profiles') plt.gca().invert_yaxis() plt.savefig(date_dir + 'abun_profiles.png')
def transmittance(date_dir, atmfile, filters, plot=True): """ """ # Read atmfile molecules, p, T, abundances = mat.readatm(date_dir + atmfile) nlayers = len(p) p = p[::-1] # top to bottom of the atmosphere # Read tau.dat foo = date_dir + 'tau.dat' tau, wns = readTauDat(foo, nlayers) # Transmittance: transmit = np.exp(-tau) # Band intgrate it: filt_tr = filter_cf(filters, nlayers, wns, transmit) nfilters = len(filters) colors = plt.cm.rainbow(np.asarray(np.linspace(0, 255, nfilters), np.int)) if plot: print(" Plotting contribution functions.\n") # Not normalized cf plt.figure(4) plt.clf() gs = gridspec.GridSpec(1, 2, width_ratios=[5, 1]) ax0 = plt.subplot(gs[0]) colormap = plt.cm.rainbow(np.linspace(0, 1, len(filters))) ax0.set_prop_cycle(plt.cycler('color', colormap)) for i in np.arange(len(filt_tr)): (head, tail) = os.path.split(filters[i]) lbl = tail[:-4] ax0.semilogy(filt_tr[i], p, '-', linewidth = 1.5, label=lbl, color=colors[i]) lgd = ax0.legend(loc='center left', bbox_to_anchor=(1.0, 0.5), ncol=nfilters//30 + 1, prop={'size':8}) ax0.set_ylim(max(p), min(p)) ax0.ticklabel_format(style='sci', axis='x', scilimits=(0,0)) ax0.set_xlabel('Transmittance', fontsize=14) ax0.set_ylabel('Pressure (bar)' , fontsize=14) plt.savefig(date_dir + 'Transmittance.png') return filt_tr[:,::-1]
def callTransit(atmfile, tepfile, MCfile, stepsize, molfit, tconfig, date_dir): # read atmfile molecules, pressure, temp, abundances = mat.readatm(atmfile) # get surface gravity grav, Rp = mat.get_g(tepfile) # get star data R_star, T_star, sma = get_starData(tepfile) # get best parameters bestP, uncer, SN, mean = read_MCMC_out(MCfile) # get all params params = get_params(bestP, stepsize) # get PTparams and abundances factors nparams = len(params) nmol = len(molfit) nPTparams = nparams - nmol PTparams = params[:nPTparams] AbunFact = params[nPTparams:] # HARDCODED !!!!!!!!!!!! T_int = 100 # K # call PT line profile to calculate temperature T_line = pt.PT_line(pressure, PTparams, R_star, T_star, T_int, sma, grav) # write best-fit atmospheric file write_atmfile(atmfile, molfit, T_line, params, date_dir) # bestFit atm file bestFit_atm = date_dir + 'bestFit.atm' # write new bestFit Transit config bestFit_tconfig(tconfig, date_dir)
def callTransit(atmfile, tepfile, MCfile, stepsize, molfit, solution, p0, tconfig, date_dir, params, burnin, abun_file): """ Call Transit to produce best-fit outputs. Plot MCMC posterior PT plot. Parameters: ----------- atmfile: String Atmospheric file. tepfile: String Transiting extra-solar planet file. MCfile: String File with MCMC log and best-fitting results. stepsize: 1D float ndarray FINDME molfit: 1D String ndarray List of molecule names to modify their abundances. solution: String Flag to indicate transit or eclipse geometry p0: Float Atmosphere's 'surface' pressure level. tconfig: String Transit configuration file. date_dir: String Directory where to store results. params: 1D float ndarray burnin: Integer abun_file: String Elemental abundances file. """ # read atmfile molecules, pressure, temp, abundances = mat.readatm(atmfile) # get surface gravity grav, Rp = mat.get_g(tepfile) # get star data R_star, T_star, sma, gstar = get_starData(tepfile) # get best parameters bestP, uncer, SN, mean = read_MCMC_out(MCfile) # get all params allParams = get_params(bestP, stepsize, params) # get PTparams and abundances factors nparams = len(allParams) nmol = len(molfit) nradfit = int(solution == 'transit') nPTparams = nparams - nmol - nradfit PTparams = allParams[:nPTparams] # FINDME: Hardcoded value: T_int = 100 # K # call PT line profile to calculate temperature best_T = pt.PT_line(pressure, PTparams, R_star, T_star, T_int, sma, grav*1e2) # Plot best PT profile plt.figure(1) plt.clf() plt.semilogy(best_T, pressure, '-', color = 'r') plt.xlim(0.9*min(best_T), 1.1*max(best_T)) plt.ylim(max(pressure), min(pressure)) plt.title('Best PT', fontsize=14) plt.xlabel('T [K]' , fontsize=14) plt.ylabel('logP [bar]', fontsize=14) # Save plot to current directory plt.savefig(date_dir + 'Best_PT.png') # Update R0, if needed: if nradfit: Rp = allParams[nPTparams] # Mean molecular mass: mu = mat.mean_molar_mass(abun_file, atmfile) # Re-calculate the layers' radii using the Hydrostatic-equilibrium calc: # (Has to be in reversed order since the interpolation requires the # pressure array in increasing order) rad = mat.radpress(pressure[::-1], best_T[::-1], mu[::-1], p0, Rp, grav) rad = rad[::-1] # write best-fit atmospheric file write_atmfile(atmfile, molfit, rad, best_T, allParams[nPTparams+nradfit:], date_dir) # bestFit atm file bestFit_atm = date_dir + 'bestFit.atm' # write new bestFit Transit config bestFit_tconfig(tconfig, date_dir) # ========== plot MCMC PT profiles ========== # get MCMC data: MCMCdata = date_dir + "/output.npy" data = np.load(MCMCdata) nchains, npars, niter = np.shape(data) # stuck chains: data_stack = data[0,:,burnin:] for c in np.arange(1, nchains): data_stack = np.hstack((data_stack, data[c, :, burnin:])) # create array of PT profiles PTprofiles = np.zeros((np.shape(data_stack)[1], len(pressure))) # current PT parameters for each chain, iteration curr_PTparams = PTparams # fill-in PT profiles array print(" Plotting MCMC PT profile figure.") for k in np.arange(0, np.shape(data_stack)[1]): j = 0 for i in np.arange(len(PTparams)): if stepsize[i] != 0.0: curr_PTparams[i] = data_stack[j,k] j +=1 else: pass PTprofiles[k] = pt.PT_line(pressure, curr_PTparams, R_star, T_star, T_int, sma, grav*1e2) # get percentiles (for 1,2-sigma boundaries): low1 = np.percentile(PTprofiles, 16.0, axis=0) hi1 = np.percentile(PTprofiles, 84.0, axis=0) low2 = np.percentile(PTprofiles, 2.5, axis=0) hi2 = np.percentile(PTprofiles, 97.5, axis=0) median = np.median(PTprofiles, axis=0) # plot figure plt.figure(2) plt.clf() ax=plt.subplot(111) ax.fill_betweenx(pressure, low2, hi2, facecolor="#62B1FF", edgecolor="0.5") ax.fill_betweenx(pressure, low1, hi1, facecolor="#1873CC", edgecolor="#1873CC") plt.semilogy(median, pressure, "-", lw=2, label='Median',color="k") plt.semilogy(best_T, pressure, "-", lw=2, label="Best fit", color="r") plt.ylim(pressure[0], pressure[-1]) plt.legend(loc="best") plt.xlabel("Temperature (K)", size=15) plt.ylabel("Pressure (bar)", size=15) # save figure savefile = date_dir + "MCMC_PTprofiles.png" plt.savefig(savefile)
def callTransit(atmfile, tepfile, MCfile, stepsize, molfit, solution, p0, tconfig, date_dir, params, burnin, abun_file): """ Call Transit to produce best-fit outputs. Plot MCMC posterior PT plot. Parameters: ----------- atmfile: String Atmospheric file. tepfile: String Transiting extra-solar planet file. MCfile: String File with MCMC log and best-fitting results. stepsize: 1D float ndarray FINDME molfit: 1D String ndarray List of molecule names to modify their abundances. solution: String Flag to indicate transit or eclipse geometry p0: Float Atmosphere's 'surface' pressure level. tconfig: String Transit configuration file. date_dir: String Directory where to store results. params: 1D float ndarray burnin: Integer abun_file: String Elemental abundances file. """ # read atmfile molecules, pressure, temp, abundances = mat.readatm(atmfile) # get surface gravity grav, Rp = mat.get_g(tepfile) # get star data R_star, T_star, sma, gstar = get_starData(tepfile) # Get best parameters bestP, uncer = read_MCMC_out(MCfile) # get all params #allParams = get_params(bestP, stepsize, params) allParams = bestP # get PTparams and abundances factors nparams = len(allParams) nmol = len(molfit) nradfit = int(solution == 'transit') nPTparams = nparams - nmol - nradfit PTparams = allParams[:nPTparams] # FINDME: Hardcoded value: T_int = 100 # K # call PT line profile to calculate temperature best_T = pt.PT_line(pressure, PTparams, R_star, T_star, T_int, sma, grav*1e2) # Plot best PT profile plt.figure(1) plt.clf() plt.semilogy(best_T, pressure, '-', color = 'r') plt.xlim(0.9*min(best_T), 1.1*max(best_T)) plt.ylim(max(pressure), min(pressure)) plt.title('Best PT', fontsize=14) plt.xlabel('T [K]' , fontsize=14) plt.ylabel('logP [bar]', fontsize=14) # Save plot to current directory plt.savefig(date_dir + 'Best_PT.png') # Update R0, if needed: if nradfit: Rp = allParams[nPTparams] # Mean molecular mass: mu = mat.mean_molar_mass(abun_file, atmfile) # Re-calculate the layers' radii using the Hydrostatic-equilibrium calc: # (Has to be in reversed order since the interpolation requires the # pressure array in increasing order) rad = mat.radpress(pressure[::-1], best_T[::-1], mu[::-1], p0, Rp, grav) rad = rad[::-1] # write best-fit atmospheric file write_atmfile(atmfile, molfit, rad, best_T, allParams[nPTparams+nradfit:], date_dir) # bestFit atm file bestFit_atm = date_dir + 'bestFit.atm' # write new bestFit Transit config bestFit_tconfig(tconfig, date_dir) # ========== plot MCMC PT profiles ========== # get MCMC data: MCMCdata = date_dir + "/output.npy" data = np.load(MCMCdata) nchains, npars, niter = np.shape(data) # stuck chains: data_stack = data[0,:,burnin:] for c in np.arange(1, nchains): data_stack = np.hstack((data_stack, data[c, :, burnin:])) # create array of PT profiles PTprofiles = np.zeros((np.shape(data_stack)[1], len(pressure))) # current PT parameters for each chain, iteration curr_PTparams = PTparams # fill-in PT profiles array print(" Plotting MCMC PT profile figure.") for k in np.arange(0, np.shape(data_stack)[1]): j = 0 for i in np.arange(len(PTparams)): if stepsize[i] != 0.0: curr_PTparams[i] = data_stack[j,k] j +=1 else: pass PTprofiles[k] = pt.PT_line(pressure, curr_PTparams, R_star, T_star, T_int, sma, grav*1e2) # get percentiles (for 1,2-sigma boundaries): low1 = np.percentile(PTprofiles, 16.0, axis=0) hi1 = np.percentile(PTprofiles, 84.0, axis=0) low2 = np.percentile(PTprofiles, 2.5, axis=0) hi2 = np.percentile(PTprofiles, 97.5, axis=0) median = np.median(PTprofiles, axis=0) # plot figure plt.figure(2) plt.clf() ax=plt.subplot(111) ax.fill_betweenx(pressure, low2, hi2, facecolor="#62B1FF", edgecolor="0.5") ax.fill_betweenx(pressure, low1, hi1, facecolor="#1873CC", edgecolor="#1873CC") plt.semilogy(median, pressure, "-", lw=2, label='Median',color="k") plt.semilogy(best_T, pressure, "-", lw=2, label="Best fit", color="r") plt.ylim(pressure[0], pressure[-1]) plt.legend(loc="best") plt.xlabel("Temperature (K)", size=15) plt.ylabel("Pressure (bar)", size=15) # save figure savefile = date_dir + "MCMC_PTprofiles.png" plt.savefig(savefile)
def cf(date_dir, atmfile, filters, plot=True, fs=15): """ Call above functions to calculate cf and plot them """ # Read atmfile molecules, p, T, abundances = mat.readatm(date_dir + atmfile) nlayers = len(p) # Read tau.dat foo = date_dir + 'tau.dat' tau, wns = readTauDat(foo, nlayers) # Calculate BB, reverse the order of p and T p = p[::-1] T = T[::-1] BB = Planck(T, wns) # Call cf_eq() to calculate cf cf = cf_eq(BB, p, tau, nlayers, wns) # Call filter_cf() to calculate cf filt_cf, filt_cf_norm = filter_cf(filters, nlayers, wns, cf, normalize=True) nfilters = len(filters) meanwl = np.zeros(nfilters) for i in np.arange(nfilters): filtwaven, filttransm = w.readfilter(filters[i]) meanwn = np.sum(filtwaven * filttransm) / np.sum(filttransm) meanwl[i] = 1e4 / meanwn maxmeanwl = np.max(meanwl) minmeanwl = np.min(meanwl) colors = (meanwl - minmeanwl) / (maxmeanwl - minmeanwl) if plot: print(" Plotting contribution functions.\n") # Not normalized cf plt.figure(4) plt.clf() gs = gridspec.GridSpec(1, 2, width_ratios=[20, 1], wspace=0.05) ax0 = plt.subplot(gs[0]) ax1 = plt.subplot(gs[1]) for i in np.arange(len(filt_cf)): (head, tail) = os.path.split(filters[i]) lbl = tail[:-4] ax0.semilogy(filt_cf[i], p, '-', color=plt.cm.rainbow(colors[i]), linewidth=1, label=lbl) norm = matplotlib.colors.Normalize(vmin=minmeanwl, vmax=maxmeanwl) cbar = matplotlib.colorbar.ColorbarBase(ax1, cmap=plt.cm.rainbow, norm=norm, orientation='vertical') cbar.set_label("Mean Wavelength (\u00b5m)", fontsize=fs) cbar.ax.tick_params(labelsize=fs - 4) ax0.set_ylim(max(p), min(p)) ax0.ticklabel_format(style='sci', axis='x', scilimits=(0, 0)) ax0.set_xlabel('Contribution Functions', fontsize=fs) ax0.set_ylabel('Pressure (bar)', fontsize=fs) plt.xticks(size=fs - 4) plt.yticks(size=fs - 4) plt.savefig(date_dir + 'ContrFuncs.png', bbox_inches='tight') # Normalized cf plt.figure(5, figsize=(8, 6.5)) plt.clf() gs = gridspec.GridSpec(1, 2, width_ratios=[20, 1], wspace=0.05) ax0 = plt.subplot(gs[0]) ax1 = plt.subplot(gs[1]) for i in np.arange(len(filt_cf_norm)): (head, tail) = os.path.split(filters[i]) lbl = tail[:-4] ax0.semilogy(filt_cf_norm[i], p, '--', color=plt.cm.rainbow(colors[i]), linewidth=1, label=lbl) norm = matplotlib.colors.Normalize(vmin=minmeanwl, vmax=maxmeanwl) cbar = matplotlib.colorbar.ColorbarBase(ax1, cmap=plt.cm.rainbow, norm=norm, orientation='vertical') cbar.set_label("Mean Wavelength (\u00b5m)", fontsize=fs) cbar.ax.tick_params(labelsize=fs - 4) ax0.set_ylim(max(p), min(p)) ax0.set_xlim(0, 1.0) ax0.ticklabel_format(style='sci', axis='x', scilimits=(0, 0)) ax0.set_xlabel('Normalized Contribution Functions', fontsize=fs) ax0.set_ylabel('Pressure (bar)', fontsize=fs) plt.xticks(size=fs - 4) plt.yticks(size=fs - 4) plt.savefig(date_dir + 'NormContrFuncs.png', bbox_inches='tight') return filt_cf[:, ::-1], filt_cf_norm[:, ::-1]
def cf(date_dir, atmfile, filters, plot=True): """ Call above functions to calculate cf and plot them """ # Read atmfile molecules, p, T, abundances = mat.readatm(date_dir + atmfile) nlayers = len(p) # Read tau.dat foo = date_dir + 'tau.dat' tau, wns = readTauDat(foo, nlayers) # Calculate BB, reverse the order of p and T p = p[::-1] T = T[::-1] BB = Planck(T, wns) # Call cf_eq() to calculate cf cf = cf_eq(BB, p, tau, nlayers, wns) # Call filter_cf() to calculate cf filt_cf, filt_cf_norm = filter_cf(filters, nlayers, wns, cf, normalize=True) if plot: print(" Plotting contribution functions.\n") # Not normalized cf plt.figure(4) plt.clf() gs = gridspec.GridSpec(1, 2, width_ratios=[5, 1]) ax0 = plt.subplot(gs[0]) colormap = plt.cm.rainbow(np.linspace(0, 1, len(filters))) ax0.set_prop_cycle(plt.cycler('color', colormap)) for i in np.arange(len(filt_cf)): (head, tail) = os.path.split(filters[i]) lbl = tail[:-4] ax0.semilogy(filt_cf[i], p, '-', linewidth = 1, label=lbl) lgd = ax0.legend(loc='center left', bbox_to_anchor=(1.0, 0.5), ncol=len(filt_cf)//30 + 1, prop={'size':8}) ax0.set_ylim(max(p), min(p)) ax0.ticklabel_format(style='sci', axis='x', scilimits=(0,0)) ax0.set_xlabel('Contribution Functions', fontsize=14) ax0.set_ylabel('Pressure (bar)' , fontsize=14) plt.savefig(date_dir + 'ContrFuncs.png', bbox_extra_artists=(lgd,), bbox_inches='tight') # Normalized cf plt.figure(5) plt.clf() gs = gridspec.GridSpec(1, 2, width_ratios=[5, 1]) ax0 = plt.subplot(gs[0]) colormap = plt.cm.rainbow(np.linspace(0, 1, len(filters))) ax0.set_prop_cycle(plt.cycler('color', colormap)) for i in np.arange(len(filt_cf_norm)): (head, tail) = os.path.split(filters[i]) lbl = tail[:-4] ax0.semilogy(filt_cf_norm[i], p, '--', linewidth = 1, label=lbl) lgd = ax0.legend(loc='center left', bbox_to_anchor=(1,0.5), ncol=len(filt_cf)//30 + 1, prop={'size':8}) ax0.set_ylim(max(p), min(p)) ax0.set_xlim(0, 1.0) ax0.ticklabel_format(style='sci', axis='x', scilimits=(0,0)) ax0.set_xlabel('Normalized Contribution Functions', fontsize=14) ax0.set_ylabel('Pressure (bar)' , fontsize=14) plt.savefig(date_dir + 'NormContrFuncs.png', bbox_extra_artists=(lgd,), bbox_inches='tight') return filt_cf[:,::-1], filt_cf_norm[:,::-1]
'xtick.labelsize': 14, 'ytick.labelsize': 14, }) # 4 mol uniform atmfile = './7species_7opac_uniform/bestFit.atm' params = np.array([ -0.6, -0.4, 0.0, 0.0, 1.09, -1.07, -1.168, 1.784, -1.749, -3.0, 3.0, -4.5 ]) logfile = './7species_7opac_uniform/MCMC.log' stepsize = np.array( [0.01, 0.01, 0.0, 0.0, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01]) MCMCdata = './7species_7opac_uniform/output.npy' # read atmfile molecules, pressure, temp, abundances = mat.readatm(atmfile) # get surface gravity grav, Rp = mat.get_g(tep_name) # convert gravity to cm/s^2 grav = grav * 1e2 # get star data R_star, T_star, sma, gstar = bf.get_starData(tep_name) # get best parameters bestP, uncer = bf.read_MCMC_out(logfile) # get all params allParams = bf.get_params(bestP, stepsize, params) # get PTparams and abundances factors nparams = len(allParams) nmol = len(molfit) nPTparams = nparams - nmol PTparams = allParams[:nPTparams]
def cf(date_dir, atmfile, filters, plot=True): """ Call above functions to calculate cf and plot them """ # Read atmfile molecules, p, T, abundances = mat.readatm(date_dir + atmfile) nlayers = len(p) # Read tau.dat foo = date_dir + 'tau.dat' tau, wns = readTauDat(foo, nlayers) # Calculate BB, reverse the order of p and T p = p[::-1] T = T[::-1] BB = Planck(T, wns) # Call cf_eq() to calculate cf cf = cf_eq(BB, p, tau, nlayers, wns) # Call filter_cf() to calculate cf filt_cf, filt_cf_norm = filter_cf(filters, nlayers, wns, cf, normalize=True) if plot: print(" Plotting contribution functions.\n") # Not normalized cf plt.figure(4) plt.clf() gs = gridspec.GridSpec(1, 2, width_ratios=[5, 1]) ax0 = plt.subplot(gs[0]) colormap = plt.cm.rainbow(np.linspace(0, 1, len(filters))) ax0.set_prop_cycle(plt.cycler('color', colormap)) for i in np.arange(len(filt_cf)): (head, tail) = os.path.split(filters[i]) lbl = tail[:-4] ax0.semilogy(filt_cf[i], p, '-', linewidth=1, label=lbl) lgd = ax0.legend(loc='center left', bbox_to_anchor=(1.0, 0.5), ncol=len(filt_cf) // 30 + 1, prop={'size': 8}) ax0.set_ylim(max(p), min(p)) ax0.ticklabel_format(style='sci', axis='x', scilimits=(0, 0)) ax0.set_xlabel('Contribution Functions', fontsize=14) ax0.set_ylabel('Pressure (bar)', fontsize=14) plt.savefig(date_dir + 'ContrFuncs.png', bbox_extra_artists=(lgd, ), bbox_inches='tight') # Normalized cf plt.figure(5) plt.clf() gs = gridspec.GridSpec(1, 2, width_ratios=[5, 1]) ax0 = plt.subplot(gs[0]) colormap = plt.cm.rainbow(np.linspace(0, 1, len(filters))) ax0.set_prop_cycle(plt.cycler('color', colormap)) for i in np.arange(len(filt_cf_norm)): (head, tail) = os.path.split(filters[i]) lbl = tail[:-4] ax0.semilogy(filt_cf_norm[i], p, '--', linewidth=1, label=lbl) lgd = ax0.legend(loc='center left', bbox_to_anchor=(1, 0.5), ncol=len(filt_cf) // 30 + 1, prop={'size': 8}) ax0.set_ylim(max(p), min(p)) ax0.set_xlim(0, 1.0) ax0.ticklabel_format(style='sci', axis='x', scilimits=(0, 0)) ax0.set_xlabel('Normalized Contribution Functions', fontsize=14) ax0.set_ylabel('Pressure (bar)', fontsize=14) plt.savefig(date_dir + 'NormContrFuncs.png', bbox_extra_artists=(lgd, ), bbox_inches='tight') return filt_cf[:, ::-1], filt_cf_norm[:, ::-1]
def get_widths(cfile): """ Calculate the max and min Lorentz and Doppler broadening HWHM for the given configuration file. Parameters: ----------- cfile: String A BART configuration file. """ # Read config: config = ConfigParser.SafeConfigParser() config.optionxform = str # This one enable Uppercase in arguments config.read([cfile]) defaults = dict(config.items("MCMC")) # Get min-max wavenumber: try: wnmin = 1.0/(float(defaults["wlhigh"])*float(defaults["wlfct"])) except: wnmin = float(defaults["wnlow"]) * float(defaults["wnfct"]) try: wnmax = 1.0/(float(defaults["wllow"])*float(defaults["wlfct"])) except: wnmax = float(defaults["wnhigh"]) * float(defaults["wnfct"]) # Read atmospheric file: molecs, pressure, temps, abun = ma.readatm(defaults["atmfile"]) # Get min-max temperatures: try: tmin = float(defaults["tlow"]) except: tmin = np.amin(temps) try: tmax = float(defaults["thigh"]) except: tmax = np.amax(temps) # Get min-max pressures: pmin = np.amin(pressure) * 1e6 pmax = np.amax(pressure) * 1e6 # Get masses: molfile = scriptsdir + "/../modules/transit/inputs/molecules.dat" ID, mol, mass, diam = readmol(molfile) # Keep only molecules from the atmospheric file: mask = np.zeros(len(mol), int) for i in np.arange(len(mol)): mask[i] = mol[i] in molecs mol = mol [np.where(mask)] mass = mass[np.where(mask)] * sc.u * 1e3 # grams diam = diam[np.where(mask)] * sc.angstrom * 100 # cm # Sort molecules according to the order in the atmospheric file: isort = np.zeros(len(mol), int) for i in np.arange(len(mol)): isort[i] = np.where(np.asarray(mol) == molecs[i])[0][0] mol = mol [isort] mass = mass[isort] diam = diam[isort] # Calculate minimum and maximum Doppler widths: dmin = Doppler(wnmin, tmin, np.amin(mass)) dmax = Doppler(wnmax, tmax, np.amax(mass)) iH2 = np.where(mol == 'H2')[0] iHe = np.where(mol == 'He')[0] # Calculate minimum and maximum Lorentz widths: lmin = Lorentz(pmin, tmax, mass, iH2, iHe, abun[-1], diam, True) lmax = Lorentz(pmax, tmin, mass, iH2, iHe, abun[ 0], diam, False) print("Doppler minimum and maximum HWHM (cm-1): {:.3e}, {:.3e}\n" "Lorentz minimum and maximum HWHM (cm-1): {:.3e}, {:.3e}". format(dmin, dmax, lmin, lmax))
def main(comm): """ This is a hacked version of MC3's func.py. This function directly call's the modeling function for the BART project. Modification History: --------------------- 2014-04-19 patricio Initial implementation. [email protected] 2014-06-25 patricio Added support for inner-MPI loop. """ # Parse arguments: cparser = argparse.ArgumentParser(description=__doc__, add_help=False, formatter_class=argparse.RawDescriptionHelpFormatter) # Add config file option: cparser.add_argument("-c", "--config_file", help="Configuration file", metavar="FILE") # Remaining_argv contains all other command-line-arguments: args, remaining_argv = cparser.parse_known_args() # Get parameters from configuration file: cfile = args.config_file if cfile: config = ConfigParser.SafeConfigParser() config.optionxform = str config.read([cfile]) defaults = dict(config.items("MCMC")) else: defaults = {} parser = argparse.ArgumentParser(parents=[cparser]) parser.add_argument("--func", dest="func", type=mu.parray, action="store", default=None) parser.add_argument("--indparams", dest="indparams", type=mu.parray, action="store", default=[]) parser.add_argument("--params", dest="params", type=mu.parray, action="store", default=None, help="Model-fitting parameters [default: %(default)s]") parser.add_argument("--molfit", dest="molfit", type=mu.parray, action="store", default=None, help="Molecules fit [default: %(default)s]") parser.add_argument("--Tmin", dest="Tmin", type=float, action="store", default=400.0, help="Lower Temperature boundary [default: %(default)s]") parser.add_argument("--Tmax", dest="Tmax", type=float, action="store", default=3000.0, help="Higher Temperature boundary [default: %(default)s]") parser.add_argument("--quiet", action="store_true", help="Set verbosity level to minimum", dest="quiet") # Input-Converter Options: group = parser.add_argument_group("Input Converter Options") group.add_argument("--atmospheric_file", action="store", help="Atmospheric file [default: %(default)s]", dest="atmfile", type=str, default=None) group.add_argument("--PTtype", action="store", help="PT profile type.", dest="PTtype", type=str, default="none") #choices=('line', 'madhu')) group.add_argument("--tint", action="store", help="Internal temperature of the planet [default: " "%(default)s].", dest="tint", type=float, default=100.0) # transit Options: group = parser.add_argument_group("transit Options") group.add_argument("--config", action="store", help="transit configuration file [default: %(default)s]", dest="config", type=str, default=None) # Output-Converter Options: group = parser.add_argument_group("Output Converter Options") group.add_argument("--filter", action="store", help="Waveband filter name [default: %(default)s]", dest="filter", type=mu.parray, default=None) group.add_argument("--tep_name", action="store", help="A TEP file [default: %(default)s]", dest="tep_name", type=str, default=None) group.add_argument("--kurucz_file", action="store", help="Stellar Kurucz file [default: %(default)s]", dest="kurucz", type=str, default=None) group.add_argument("--solution", action="store", help="Solution geometry [default: %(default)s]", dest="solution", type=str, default="None", choices=('transit', 'eclipse')) parser.set_defaults(**defaults) args2, unknown = parser.parse_known_args(remaining_argv) # Quiet all threads except rank 0: rank = comm.Get_rank() verb = rank == 0 # Get (Broadcast) the number of parameters and iterations from MPI: array1 = np.zeros(2, np.int) mu.comm_bcast(comm, array1) npars, niter = array1 # ::::::: Initialize the Input converter :::::::::::::::::::::::::: atmfile = args2.atmfile molfit = args2.molfit PTtype = args2.PTtype params = args2.params tepfile = args2.tep_name tint = args2.tint Tmin = args2.Tmin Tmax = args2.Tmax solution = args2.solution # Solution type # Extract necessary values from the TEP file: tep = rd.File(tepfile) # Stellar temperature in K: tstar = float(tep.getvalue('Ts')[0]) # Stellar radius (in meters): rstar = float(tep.getvalue('Rs')[0]) * c.Rsun # Semi-major axis (in meters): sma = float(tep.getvalue( 'a')[0]) * sc.au # Planetary radius (in meters): rplanet = float(tep.getvalue('Rp')[0]) * c.Rjup # Planetary mass (in kg): mplanet = float(tep.getvalue('Mp')[0]) * c.Mjup # Number of fitting parameters: nfree = len(params) # Total number of free parameters nmolfit = len(molfit) # Number of molecular free parameters nradfit = int(solution == 'transit') # 1 for transit, 0 for eclipse nPT = nfree - nmolfit - nradfit # Number of PT free parameters # Read atmospheric file to get data arrays: species, pressure, temp, abundances = mat.readatm(atmfile) # Reverse pressure order (for PT to work): pressure = pressure[::-1] nlayers = len(pressure) # Number of atmospheric layers nspecies = len(species) # Number of species in the atmosphere mu.msg(verb, "There are {:d} layers and {:d} species.".format(nlayers, nspecies)) # Find index for Hydrogen and Helium: species = np.asarray(species) iH2 = np.where(species=="H2")[0] iHe = np.where(species=="He")[0] # Get H2/He abundance ratio: ratio = (abundances[:,iH2] / abundances[:,iHe]).squeeze() # Find indices for the metals: imetals = np.where((species != "He") & (species != "H2"))[0] # Index of molecular abundances being modified: imol = np.zeros(nmolfit, dtype='i') for i in np.arange(nmolfit): imol[i] = np.where(np.asarray(species) == molfit[i])[0] # Pressure-Temperature profile: PTargs = [PTtype] if PTtype == "line": # Planetary surface gravity (in cm s-2): gplanet = 100.0 * sc.G * mplanet / rplanet**2 # Additional PT arguments: PTargs += [rstar, tstar, tint, sma, gplanet] # Allocate arrays for receiving and sending data to master: freepars = np.zeros(nfree, dtype='d') profiles = np.zeros((nspecies+1, nlayers), dtype='d') # This are sub-sections of profiles, containing just the temperature and # the abundance profiles, respectively: tprofile = profiles[0, :] aprofiles = profiles[1:,:] # Store abundance profiles: for i in np.arange(nspecies): aprofiles[i] = abundances[:, i] # ::::::: Spawn transit code ::::::::::::::::::::::::::::::::::::: # # transit configuration file: transitcfile = args2.tconfig # FINDME: Find a way to set verb to the transit subprocesses. # Silence all threads except rank 0: # if verb == 0: # rargs = ["--quiet"] # else: # rargs = [] # Initialize the transit python module: transit_args = ["transit", "-c", transitcfile] trm.transit_init(len(transit_args), transit_args) # Get wavenumber array from transit: nwave = trm.get_no_samples() specwn = trm.get_waveno_arr(nwave) # ::::::: Output Converter ::::::::::::::::::::::::::::::::::::::: ffile = args2.filter # Filter files kurucz = args2.kurucz # Kurucz file # Log10(stellar gravity) gstar = float(tep.getvalue('loggstar')[0]) # Planet-to-star radius ratio: rprs = rplanet / rstar mu.msg(verb, "OCON FLAG 10: {}, {}, {}".format(tstar, gstar, rprs)) nfilters = len(ffile) # Number of filters: # FINDME: Separate filter/stellar interpolation? # Get stellar model: starfl, starwn, tmodel, gmodel = w.readkurucz(kurucz, tstar, gstar) # Read and resample the filters: nifilter = [] # Normalized interpolated filter istarfl = [] # interpolated stellar flux wnindices = [] # wavenumber indices used in interpolation for i in np.arange(nfilters): # Read filter: filtwaven, filttransm = w.readfilter(ffile[i]) # Check that filter boundaries lie within the spectrum wn range: if filtwaven[0] < specwn[0] or filtwaven[-1] > specwn[-1]: mu.exit(message="Wavenumber array ({:.2f} - {:.2f} cm-1) does not " "cover the filter[{:d}] wavenumber range ({:.2f} - {:.2f} " "cm-1).".format(specwn[0], specwn[-1], i, filtwaven[0], filtwaven[-1])) # Resample filter and stellar spectrum: nifilt, strfl, wnind = w.resample(specwn, filtwaven, filttransm, starwn, starfl) mu.msg(verb, "OCON FLAG 67: mean star flux: %.3e"%np.mean(strfl)) nifilter.append(nifilt) istarfl.append(strfl) wnindices.append(wnind) # Allocate arrays for receiving and sending data to master: spectrum = np.zeros(nwave, dtype='d') bandflux = np.zeros(nfilters, dtype='d') # Allocate array to receive parameters from MPI: params = np.zeros(npars, np.double) # :::::: Main MCMC Loop :::::::::::::::::::::::::::::::::::::::::: # :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: while niter >= 0: niter -= 1 # Receive parameters from MCMC: mu.comm_scatter(comm, params) #mu.msg(verb, "ICON FLAG 71: incon pars: {:s}". # format(str(params).replace("\n", ""))) # Input converter calculate the profiles: try: tprofile[:] = pt.PT_generator(pressure, params[0:nPT], PTargs)[::-1] except ValueError: mu.msg(verb, 'Input parameters give non-physical profile.') # FINDME: what to do here? # If the temperature goes out of bounds: if np.any(tprofile < Tmin) or np.any(tprofile > Tmax): print("Out of bounds") mu.comm_gather(comm, -np.ones(nfilters), MPI.DOUBLE) continue #mu.msg(verb, "T pars: \n{}\n".format(PTargs)) mu.msg(verb-20, "Temperature profile: {}".format(tprofile)) # Scale abundance profiles: for i in np.arange(nmolfit): m = imol[i] # Use variable as the log10: aprofiles[m] = abundances[:, m] * 10.0**params[nPT+nradfit+i] # Update H2, He abundances so sum(abundances) = 1.0 in each layer: q = 1.0 - np.sum(aprofiles[imetals], axis=0) aprofiles[iH2] = ratio * q / (1.0 + ratio) aprofiles[iHe] = q / (1.0 + ratio) # print("qH2O: {}, Qmetals: {}, QH2: {} p: {}".format(params[nPT], # q[50], profiles[iH2+1,50], profiles[:,50])) # Set the 'surface' level: if solution == "transit": trm.set_radius(params[nPT]) if rank == 1: print("Iteration: {:05}".format(niter)) # Let transit calculate the model spectrum: spectrum = trm.run_transit(profiles.flatten(), nwave) # Output converter band-integrate the spectrum: # Calculate the band-integrated intensity per filter: for i in np.arange(nfilters): if solution == "eclipse": fluxrat = (spectrum[wnindices[i]]/istarfl[i]) * rprs*rprs bandflux[i] = w.bandintegrate(fluxrat, specwn, nifilter[i], wnindices[i]) elif solution == "transit": bandflux[i] = w.bandintegrate(spectrum[wnindices[i]], specwn, nifilter[i], wnindices[i]) # Send resutls back to MCMC: #mu.msg(verb, "OCON FLAG 95: Flux band integrated ({})".format(bandflux)) #mu.msg(verb, "{}".format(params[nPT:])) mu.comm_gather(comm, bandflux, MPI.DOUBLE) #mu.msg(verb, "OCON FLAG 97: Sent results back to MCMC") # :::::: End main Loop ::::::::::::::::::::::::::::::::::::::::::: # :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # Close communications and disconnect: mu.comm_disconnect(comm) mu.msg(verb, "FUNC FLAG 99: func out") # Close the transit communicators: trm.free_memory() mu.msg(verb, "FUNC FLAG OUT ~~ 100 ~~")
def callTransit(atmfile, tepfile, MCfile, stepsize, molfit, solution, p0, tconfig, date_dir, burnin, abun_file, PTtype, PTfunc, filters, ctf=None): """ Call Transit to produce best-fit outputs. Plot MCMC posterior PT plot. Parameters: ----------- atmfile: String Atmospheric file. tepfile: String Transiting extra-solar planet file. MCfile: String File with MCMC log and best-fitting results. stepsize: 1D float ndarray Specified step sizes for each parameter. molfit: 1D String ndarray List of molecule names to modify their abundances. solution: String Flag to indicate transit or eclipse geometry p0: Float Atmosphere's 'surface' pressure level. tconfig: String Transit configuration file. date_dir: String Directory where to store results. burnin: Integer abun_file: String Elemental abundances file. PTtype: String Pressure-temperature profile type ('line' for Line et al. 2013, 'madhu_noinv' or 'madhu_inv' for Madhusudhan & Seager 2009, 'iso' for isothermal) PTfunc: pointer to function Determines the method of evaluating the PT profile's temperature filters: list, strings. Filter files associated with the eclipse/transit depths ctf: 2D array. Contribution or transmittance functions corresponding to `filters` """ # make sure burnin is an integer burnin = int(burnin) # read atmfile molecules, pressure, temp, abundances = mat.readatm(atmfile) # get surface gravity grav, Rp = mat.get_g(tepfile) # get star data if needed if PTtype == 'line': R_star, T_star, sma, gstar = get_starData(tepfile) # FINDME: Hardcoded value: T_int = 100 # K PTargs = [R_star, T_star, T_int, sma, grav*1e2] else: PTargs = None # For non-Line profiles # Get best parameters bestP, uncer = read_MCMC_out(MCfile) allParams = bestP # get PTparams and abundances factors nparams = len(allParams) nmol = len(molfit) nradfit = int(solution == 'transit') nPTparams = nparams - nmol - nradfit PTparams = allParams[:nPTparams] # call PT profile generator to calculate temperature best_T = pt.PT_generator(pressure, PTparams, PTfunc, PTargs) # Plot best PT profile plt.figure(1) plt.clf() plt.semilogy(best_T, pressure, '-', color = 'r') plt.xlim(0.9*min(best_T), 1.1*max(best_T)) plt.ylim(max(pressure), min(pressure)) plt.title('Best PT', fontsize=14) plt.xlabel('T (K)' , fontsize=14) plt.ylabel('logP (bar)', fontsize=14) # Save plot to current directory plt.savefig(date_dir + 'Best_PT.png') # Update R0, if needed: if nradfit: Rp = allParams[nPTparams] # write best-fit atmospheric file write_atmfile(atmfile, abun_file, molfit, best_T, allParams[nPTparams+nradfit:], date_dir, p0, Rp, grav) # write new bestFit Transit config if solution == 'transit': bestFit_tconfig(tconfig, date_dir, allParams[nPTparams]) else: bestFit_tconfig(tconfig, date_dir) # Call Transit with the best-fit tconfig Transitdir = os.path.dirname(os.path.realpath(__file__)) + \ "/../modules/transit/" bf_tconfig = date_dir + 'bestFit_tconfig.cfg' Tcall = Transitdir + "/transit/transit" subprocess.call(["{:s} -c {:s}".format(Tcall, bf_tconfig)], shell=True, cwd=date_dir) # ========== plot MCMC PT profiles ========== # get MCMC data: MCMCdata = date_dir + "/output.npy" data = np.load(MCMCdata) nchains, npars, niter = np.shape(data) # stuck chains: data_stack = data[0,:,burnin:] for c in np.arange(1, nchains): data_stack = np.hstack((data_stack, data[c, :, burnin:])) # create array of PT profiles PTprofiles = np.zeros((np.shape(data_stack)[1], len(pressure))) # current PT parameters for each chain, iteration curr_PTparams = PTparams # fill-in PT profiles array if ctf is None: print(" Plotting MCMC PT profile figure.") for k in np.arange(0, np.shape(data_stack)[1]): j = 0 for i in np.arange(len(PTparams)): if stepsize[i] != 0.0: curr_PTparams[i] = data_stack[j,k] j +=1 else: pass PTprofiles[k] = pt.PT_generator(pressure, curr_PTparams, PTfunc, PTargs) # get percentiles (for 1,2-sigma boundaries): low1 = np.percentile(PTprofiles, 16.0, axis=0) hi1 = np.percentile(PTprofiles, 84.0, axis=0) low2 = np.percentile(PTprofiles, 2.5, axis=0) hi2 = np.percentile(PTprofiles, 97.5, axis=0) median = np.median( PTprofiles, axis=0) # plot figure plt.figure(2, dpi=300) plt.clf() if ctf is not None: plt.subplots_adjust(wspace=0.15) ax1=plt.subplot(121) else: ax1=plt.subplot(111) ax1.fill_betweenx(pressure, low2, hi2, facecolor="#62B1FF", edgecolor="0.5") ax1.fill_betweenx(pressure, low1, hi1, facecolor="#1873CC", edgecolor="#1873CC") plt.semilogy(median, pressure, "-", lw=2, label='Median',color="k") plt.semilogy(best_T, pressure, "-", lw=2, label="Best fit", color="r") plt.ylim(pressure[0], pressure[-1]) plt.legend(loc="best") plt.xlabel("Temperature (K)", size=15) plt.ylabel("Pressure (bar)", size=15) if ctf is not None: # Add contribution or transmittance functions ax2=plt.subplot(122, sharey=ax1) colormap = plt.cm.rainbow(np.linspace(0, 1, len(filters))) ax2.set_prop_cycle(plt.cycler('color', colormap)) # Plot with filter labels for i in np.arange(len(filters)): (head, tail) = os.path.split(filters[i]) lbl = tail[:-4] ax2.semilogy(ctf[i], pressure, '--', linewidth = 1, label=lbl) # Hide y axis tick labels plt.setp(ax2.get_yticklabels(), visible=False) # Place legend off figure in case there are many filters lgd = ax2.legend(loc='center left', bbox_to_anchor=(1,0.5), ncol=len(filters)//30 + 1, prop={'size':8}) if solution == 'eclipse': ax2.set_xlabel('Normalized Contribution\nFunctions', fontsize=15) else: ax2.set_xlabel('Transmittance', fontsize=15) # save figure if ctf is not None: savefile = date_dir + "MCMC_PTprofiles_cf.png" plt.savefig(savefile, bbox_extra_artists=(lgd,), bbox_inches='tight') else: savefile = date_dir + "MCMC_PTprofiles.png" plt.savefig(savefile)