예제 #1
0
def plotspecabun(fnames,
                 base,
                 geo='eclipse',
                 xlims=(2.28905, 2.28945),
                 oname=False,
                 title=False):
    """
    The function produces a plot of the spectra produced in abundance.
    All spectra are plotted together to show the difference in line depth.

    Inputs
    ------
    fnames: list of strings. File names of the spectrum files.
                   [fname1, fname2, fname3, ...]
    base  : string. File name of the spectrum with the line moved.
    geo   : string. Geometry of the produced spectrum.
                   'transit' or 'eclipse'
    xlims : tuple. Minimum and maximum X-axis values to be plotted.
                   Default corresponds to the default line used in abundance.
                   (xmin, xmax)
    oname: string. If oname is False, the default plotting name is used. If 
                   it is a string, then that path/to/plotname is used.
    title : bool   If True, plots w/ title. If False, it does not.

    Outputs
    -------
    PNG file of the portion of the spectrum. Naming convention is i.e.
      abundance_emission_spectra.png
    """
    # Load and plot spectrum w/ line moved
    wl, fl = rt.readspectrum(base, 0)
    plt.plot(wl, fl, label='No line', color=(0, 0, 0))

    # Loop over list of files
    for fn in range(len(fnames)):
        # Load data
        wlength, flux = rt.readspectrum(fnames[fn], 0)
        col = float(fn) / float(len(fnames))
        # Plot it, with label and no repeat colors
        plt.plot(wlength, flux, label=fnames[fn].split('/')[-1].split('_')[1], \
                 color=(col, 0, 1-col))

    # Set axis limits for the plot
    plt.xlim(xlims[0], xlims[1])
    loc = np.where(fl - flux == np.amax(fl - flux))[0][0]
    plt.ylim(flux[loc] - 5, fl[loc] + 5)

    # Label rest of plot, save
    if title:
        plt.title('Varying Abundance of One Line, \n Optically Thin Regime')
    plt.ylabel("Flux  (erg s$^{-1}$ cm$^{-1}$)", fontsize=14)
    plt.xlabel(u"Wavelength  (\u00b5m)", fontsize=14)
    plt.legend(loc="best")
    if not oname:
        plt.savefig(base.split('/')[0] + '/' +
                    'abundance_emission_spectra.png',
                    bbox_inches='tight')
    else:
        plt.savefig(oname, bbox_inches='tight')
    plt.clf()
예제 #2
0
def energycons(spectra, outfile):
    """
    Integrates each spectrum, saves those values as well as if they all 
    match within a specified tolerance.

    Inputs
    ------
    spectra: list, strings. Path/to/file for each spectrum to be integrated.
    outfile: string.        Path/to/file to save the results.
    """
    # Array to hold integrated values
    integspec = np.zeros(len(spectra))

    # Load each spectrum, integrate it
    for i in range(len(spectra)):
        wnums, flux = rt.readspectrum(spectra[i])
        integspec[i] = np.trapz(flux, x=wnums)
        # Cubic spline returns roughly same value
        #integspec[i] = si.InterpolatedUnivariateSpline(wnums, flux,
        #                                 k=3).integral(wnums[0], wnums[-1])

    # Check if they match
    diff = integspec / integspec[0] - 1

    # Save out result
    hdr = "# Units are erg/s/cm2"
    ftr = "# % differences compared to the first spectrum: \n" + \
          "#   " + str(100*diff) + " %"
    np.savetxt(outfile, integspec, header=hdr, footer=ftr)
def plot_bestFit_Spectrum(filters,
                          kurucz,
                          tepfile,
                          solution,
                          output,
                          data,
                          uncert,
                          date_dir,
                          fs=15):
    '''
    Plot BART best-model spectrum

    Parameters
    ----------
    filters : list, strings. Paths to filter files corresponding to data.
    kurucz  : string. Path to Kurucz stellar model file.
    tepfile : string. Path to Transiting ExoPlanet (TEP) file.
    solution: string. Observing geometry. 'eclipse' or 'transit'.
    output  : string. Best-fit spectrum output file name.
    data    : 1D array. Eclipse or transit depths.
    uncert  : 1D array. Uncertainties for data values.
    date_dir: string. Path to directory where the plot will be saved.
    fs      : int.    Font size for plots.
    '''
    # get star data
    R_star, T_star, sma, gstar = get_starData(tepfile)

    # get surface gravity
    grav, Rp = mat.get_g(tepfile)

    # convert Rp to m
    Rp = Rp * 1000

    # ratio planet to star
    rprs = Rp / R_star

    # read kurucz file
    starfl, starwn, tmodel, gmodel = w.readkurucz(kurucz, T_star, gstar)

    # read best-fit spectrum output file, take wn and spectra values
    if solution == 'eclipse':
        specwn, bestspectrum = rt.readspectrum(date_dir + output, wn=True)
        # print on screen
        print("  Plotting BART best-fit eclipse spectrum figure.")
    elif solution == 'transit':
        specwn, bestspectrum = rt.readspectrum(date_dir + output, wn=True)
        # print on screen
        print("  Plotting BART best-fit modulation spectrum figure.")

    # convert wn to wl
    specwl = 1e4 / specwn

    # number of filters
    nfilters = len(filters)

    # read and resample the filters:
    nifilter = []  # Normalized interpolated filter
    istarfl = []  # interpolated stellar flux
    wnindices = []  # wavenumber indices used in interpolation
    meanwn = []  # Filter mean wavenumber
    for i in np.arange(nfilters):
        # read filter:
        filtwaven, filttransm = w.readfilter(filters[i])
        meanwn.append(np.sum(filtwaven * filttransm) / sum(filttransm))
        # resample filter and stellar spectrum:
        nifilt, strfl, wnind = w.resample(specwn, filtwaven, filttransm,
                                          starwn, starfl)
        nifilter.append(nifilt)
        istarfl.append(strfl)
        wnindices.append(wnind)

    # convert mean wn to mean wl
    meanwl = 1e4 / np.asarray(meanwn)

    # band-integrate the flux-ratio or modulation:
    bandflux = np.zeros(nfilters, dtype='d')
    bandmod = np.zeros(nfilters, dtype='d')
    for i in np.arange(nfilters):
        fluxrat = (bestspectrum[wnindices[i]] / istarfl[i]) * rprs * rprs
        bandflux[i] = w.bandintegrate(fluxrat, specwn, nifilter[i],
                                      wnindices[i])
        bandmod[i] = w.bandintegrate(bestspectrum[wnindices[i]], specwn,
                                     nifilter[i], wnindices[i])

    # stellar spectrum on specwn:
    sinterp = si.interp1d(starwn, starfl)
    sflux = sinterp(specwn)
    frat = bestspectrum / sflux * rprs * rprs

    # plot figure
    plt.rcParams["mathtext.default"] = 'rm'
    matplotlib.rcParams.update({'mathtext.default': 'rm'})
    matplotlib.rcParams.update({'font.size': fs - 2})
    plt.figure(3, (8.5, 6))
    plt.clf()

    # depending on solution plot eclipse or modulation spectrum
    if solution == 'eclipse':
        gfrat = gaussf(frat, 2)
        plt.semilogx(specwl, gfrat * 1e3, "b", lw=1.5, label="Best-fit")
        plt.errorbar(meanwl, data * 1e3, uncert * 1e3, fmt="or", label="data")
        plt.plot(meanwl, bandflux * 1e3, "ok", label="model", alpha=1.0)
        plt.ylabel(r"$F_p/F_s$ (10$^{-3}$)", fontsize=fs)

    elif solution == 'transit':
        gmodel = gaussf(bestspectrum, 2)
        plt.semilogx(specwl, gmodel, "b", lw=1.5, label="Best-fit")
        plt.errorbar(meanwl, data, uncert, fmt="or", label="data")
        plt.plot(meanwl, bandmod, "ok", label="model", alpha=0.5)
        plt.ylabel(r"$(R_p/R_s)^2$", fontsize=fs)

    leg = plt.legend(loc="best")
    leg.get_frame().set_alpha(0.5)
    ax = plt.subplot(111)
    ax.set_xscale('log')
    plt.xlabel("${\\rm Wavelength\ \ (\u03bcm)}$", fontsize=fs)
    #plt.xticks(size=fs)
    #plt.yticks(size=fs)
    formatter = matplotlib.ticker.FuncFormatter(
        lambda y, _: '{:.8g}'.format(y))
    ax.get_xaxis().set_major_formatter(formatter)
    ax.get_xaxis().set_minor_formatter(formatter)
    plt.xlim(min(specwl), max(specwl))
    plt.savefig(date_dir + "BART-bestFit-Spectrum.png")
    plt.close()
예제 #4
0
def comparison(transit, rhd, geo, atm, outdir=None, titles=False):
    """
    This function produces a plot of Transit and RHD (or other RT code) spectra 
    for the comparison tests (c##).

    Inputs
    ------
    transit: string. path/to/file for transit spectrum data.
    rhd    : string. path/to/file for RHD (or other RT code) spectrum data.
    geo    : string. Viewing geometry. 'eclipse' or 'transit'
    atm    : string. Atmosphere's PT profile. 'iso', 'inv', or 'noi'
    outdir : string. path/to/output. Default is execution directory
    titles : bool.   Determines whether to include titles on plots or not.

    Revisions
    ---------
    2017-10-16  mhimes          Initial implementation.
    2018-02-03  raechel         Improved plotting, added residuals subplot.
    2019-04-01  mhimes          Merged into BARTTest.
    """
    # Load transit data
    wlength, flux = rt.readspectrum(transit, 0)

    # Load RHD data
    data = open(rhd, "r")
    lines = data.readlines()

    if geo == 'eclipse':
        lines = lines[3:]

        wlengthb = np.zeros(len(lines), dtype=float)
        fluxb = np.zeros(len(lines), dtype=float)

        for i in range(len(lines)):
            line = lines[i].split()
            wlengthb[i] = float(line[1])
            fluxb[i] = float(line[2]) * 2.998e10
    elif geo == 'transit':
        lines = lines[3:]

        wlengthb = np.zeros(len(lines), dtype=float)
        fluxb = np.zeros(len(lines), dtype=float)

        for i in range(len(lines)):
            line = lines[i].split()
            wlengthb[i] = float(line[1])
            fluxb[i] = float(line[2]) / 100

    # Resample code1 to code2's sampling
    # Use a linear interpolation! Splines can cause values smaller/bigger than
    # the known mix and max values
    rep = si.interp1d(wlength, flux)
    resamp = rep(wlengthb)
    # Set plot title and file output name
    if geo == 'transit':
        if atm == 'inv':
            titlenm = "inverted Transmission"
            filenm = "inverted_transmission_comp.png"
        elif atm == 'iso':
            titlenm = "Isothermal Transmission"
            filenm = "Isothermal_transmission_comp.png"
        elif atm == 'noi':
            titlenm = "Non-inverted Transmission"
            filenm = "noninverted_transmission_comp.png"
        else:
            print("Wrong `atm` specification. Use 'inv', 'iso', or 'noi'.\n")
    elif geo == 'eclipse':
        if atm == 'inv':
            titlenm = "inverted Emission"
            filenm = "inverted_emission_comp.png"
        elif atm == 'iso':
            titlenm = "Isothermal Emission"
            filenm = "Isothermal_emission_comp.png"
        elif atm == 'noi':
            titlenm = "Non-inverted Emission"
            filenm = "noninverted_emission_comp.png"
        else:
            print("Wrong `atm` specification. Use 'inv', 'iso', or 'noi'.\n")
    else:
        print("Wrong `geo` specification. Use 'transit' or 'eclipse'.\n")
        sys.exit()
    # Add code names to `filenm`
    cname1 = transit.split('/')
    cname1 = cname1[cname1.index('code-output') + 1][2:]
    cname2 = rhd.split('/')
    cname2 = cname2[cname2.index('code-output') + 1][2:]
    filenm = cname1 + '_' + cname2 + '_' + filenm

    # Plot it
    fig0 = plt.figure(0, (8, 5))
    plt.clf()
    frame1 = fig0.add_axes((.14, .3, .8, .65))
    if titles == True:
        plt.title(titlenm)

    if geo == 'transit':
        flux = 100 * flux  # convert to %
        fluxb = 100 * fluxb
        resamp = 100 * resamp
    if geo == 'eclipse':
        if atm == 'iso':
            plt.plot(wlength,
                     flux,
                     "lightblue",
                     label=cname1 + ' - high resolution',
                     linewidth=10.0)
            plt.plot(wlengthb,
                     resamp,
                     "royalblue",
                     label=cname1 + ' - resampled to ' + cname2)
            plt.plot(wlengthb, fluxb, "firebrick", label=cname2)
        else:
            plt.plot(wlength,
                     flux,
                     "lightblue",
                     label=cname1 + ' - high resolution')
            plt.plot(wlengthb,
                     resamp,
                     "royalblue",
                     label=cname1 + ' - resampled to ' + cname2)
            plt.plot(wlengthb, fluxb, "firebrick", label=cname2)
    else:
        plt.plot(wlength,
                 flux,
                 "lightblue",
                 label=cname1 + ' - high resolution')
        plt.plot(wlengthb,
                 resamp,
                 "royalblue",
                 label=cname1 + ' - resampled to ' + cname2)
        plt.plot(wlengthb, fluxb, "firebrick", label=cname2)

    plt.xlabel(u"Wavelength  (\u03bcm)")
    if geo == 'transit':
        plt.ylabel("Modulation  (%)")
    else:
        plt.ylabel("Flux (erg s$^{-1}$ cm$^{-1}$)")

    #plot black body curves
    h = 6.62607004e-27  # erg*s
    c = 2.9979245800e10  # cm/s
    k = 1.38064852e-16  # erg/K

    # Set min and max temperatures for plotting
    if atm == 'inv':
        T1 = 968.60  # K
        T2 = 1243.05  # K
    elif atm == 'iso':
        T1 = 1100.0
        T2 = 1100.0
    elif atm == 'noi':
        T1 = 882.93
        T2 = 1408.70

    w = np.linspace(10000. / 11.0, 10000. / 1.000, 10000)  # cm^-1

    # Blackbody associated with min/max temperature
    a = np.pi * 2 * h * (c**2) * (w**3)
    b1 = (h * c * w) / (k * T1)
    Bb1 = a / (np.exp(b1) - 1.0)

    b2 = (h * c * w) / (k * T2)
    Bb2 = a / (np.exp(b2) - 1.0)

    l = 10000. / w

    T1s = str(T1) + ' K'
    T2s = str(T2) + ' K'

    if geo == 'eclipse':
        frame1.set_ylim(0, max(Bb2) + 5000)
        if T1 != T2:
            plt.plot(l,
                     Bb1,
                     "r",
                     linestyle=':',
                     label="Blackbody at " + T1s,
                     linewidth=2.0)
            plt.plot(l,
                     Bb2,
                     "b",
                     linestyle=':',
                     label="Blackbody at " + T2s,
                     linewidth=2.0)
        else:
            plt.plot(l,
                     Bb1,
                     "k",
                     linestyle=':',
                     label="Blackbody at " + T2s,
                     linewidth=2.0)
        plt.legend(loc='upper left', prop={'size': 8})
    elif geo == 'transit':
        plt.legend(loc='lower right', prop={'size': 8})

    frame1.set_xscale('log')
    frame1.set_xlim(1, 11.0)
    frame1.set_xticklabels([])
    frame1.yaxis.set_label_coords(-0.1, 0.5)
    # Set y axis limits
    if geo == 'transit':
        frame1.set_ylim(np.amin(flux) * 0.99, np.amax(flux) * 1.01)
        frame1.yaxis.set_major_locator(MaxNLocator(nbins='6', prune='lower'))
    else:
        frame1.set_ylim(np.amin(Bb1) * 0.9, np.amax(Bb2) * 1.1)

    frame2 = fig0.add_axes((.14, .1, .8, .2))

    #residual plots
    resid = np.zeros(len(lines), dtype=float)
    # Residuals, in units of %
    resid = (resamp - fluxb) / np.max(np.concatenate((resamp, fluxb))) * 100

    plt.plot(wlengthb, resid, "k", linestyle=":")
    plt.ylabel('Residuals (%)')
    plt.xlabel(u"Wavelength  (\u00b5m)")

    frame2.set_xscale('log')
    frame2.set_xlim(0, 11.0)

    frame2.set_ylim(
        np.amin(resid) - 0.2 * np.abs(np.amin(resid)),
        np.amax(resid) + 0.2 * np.abs(np.amax(resid)))

    frame2.set_xticklabels([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
    frame2.yaxis.set_major_locator(MaxNLocator(nbins='5', prune='upper'))
    if (geo == 'eclipse') and (atm == 'iso'):
        frame2.yaxis.get_major_ticks()[-1].label1.set_visible(False)
    frame2.xaxis.set_major_locator(plt.MultipleLocator(1))

    frame2.yaxis.set_label_coords(-0.1, 0.5)

    if (geo == 'eclipse') and (atm == 'iso'):
        frame3 = fig0.add_axes((.57, .38, .25, .25))
        frame3.set_ylim(23000, 24000)
        frame3.set_xscale('log')
        frame3.set_xlim(3.5, 6.5)
        frame3.set_xticklabels([4, 4.5, 5, 5.5, 6])
        frame3.xaxis.set_major_locator(plt.MultipleLocator(1))
        plt.plot(wlength, flux, "lightblue", linewidth=10.0)
        plt.plot(wlengthb, resamp, "royalblue", linewidth=2.0)
        plt.plot(wlengthb, fluxb, "firebrick", linewidth=2.0)
        plt.plot(l, Bb1, "k", linestyle=':', linewidth=4.0)

    if outdir != None:
        plt.savefig(outdir + filenm)
    else:
        plt.savefig(filenm)
    plt.close()
예제 #5
0
def compspec(fspec1,
             fspec2,
             outname,
             outdir='../results/plots/',
             geo='eclipse'):
    """
    This function produces a plot comparing two spectra for the forward 
    tests (f##).

    Inputs
    ------
    fspec1 : string. Path to specturm text file.
    fspec2 : string. Path to spectrum text file.
    outname: string. Savename of plot. The code names for `fspec1` and `fspec2` 
                     will be added to the beginning of this.
    """
    # Load spectra
    wlength1, flux1 = rt.readspectrum(fspec1, 0)
    wlength2, flux2 = rt.readspectrum(fspec2, 0)

    # Add code names to `outname`
    cname1 = fspec1.split('/')
    cname1 = cname1[cname1.index('code-output') + 1][2:]
    cname2 = fspec2.split('/')
    cname2 = cname2[cname2.index('code-output') + 1][2:]
    outname = cname1 + '_' + cname2 + '_' + outname

    # Make plot
    fig0 = plt.figure(0, (8, 5))
    plt.clf()
    frame1 = fig0.add_axes((.14, .3, .8, .65))

    plt.xlabel(u"Wavelength  (\u03bcm)")
    if geo == 'transit':
        plt.ylabel("Modulation  (%)")
    else:
        plt.ylabel("Flux (erg s$^{-1}$ cm$^{-1}$)")

    frame1.set_xticklabels([])
    frame1.yaxis.set_label_coords(-0.1, 0.5)
    plt.plot(wlength1, flux1, label=cname1)
    plt.plot(wlength2, flux2, label=cname2)
    yticks = frame1.yaxis.get_major_ticks()
    yticks[0].label1.set_visible(False)
    plt.legend(loc='best')

    frame2 = fig0.add_axes((.14, .1, .8, .2))

    # Residuals, in units of %
    if np.all(wlength1 != wlength2):
        print("Wavelength arrays do not match.")
        print("Interpolating " + fspec2 + " to the grid of " + fspec1)
        fint = si.interp1d(wlength2, flux2, bounds_error=False, fill_value=0)
        flux2 = fint(wlength1)
    resid = (flux1 - flux2) / np.max(np.concatenate((flux1, flux2))) * 100

    plt.plot(wlength1, resid, "k", linestyle=":")
    plt.ylabel('Residuals (%)')
    plt.xlabel(u"Wavelength  (\u00b5m)")
    frame2.yaxis.set_major_locator(MaxNLocator(nbins='5', prune='upper'))

    plt.savefig(outdir + outname)
    plt.close()
예제 #6
0
파일: bestFit.py 프로젝트: sperezhoyos/BART
def plot_bestFit_Spectrum(filters, kurucz, tepfile, solution, output, data,
                                                          uncert, date_dir):
    '''
    Plot BART best-model spectrum
    '''
    # get star data
    R_star, T_star, sma, gstar = get_starData(tepfile)

    # get surface gravity
    grav, Rp = mat.get_g(tepfile)

    # convert Rp to m
    Rp = Rp * 1000

    # ratio planet to star
    rprs = Rp/R_star
  
    # read kurucz file
    starfl, starwn, tmodel, gmodel = w.readkurucz(kurucz, T_star, gstar)

    # read best-fit spectrum output file, take wn and spectra values
    if solution == 'eclipse':
        specwn, bestspectrum = rt.readspectrum(date_dir + output, wn=True)
        # print on screen
        print("  Plotting BART best-fit eclipse spectrum figure.")
    elif solution == 'transit':
        specwn, bestspectrum = rt.readspectrum(date_dir + output, wn=True)
        # print on screen
        print("  Plotting BART best-fit modulation spectrum figure.")

    # convert wn to wl
    specwl = 1e4/specwn

    # number of filters
    nfilters = len(filters)

    # read and resample the filters:
    nifilter  = [] # Normalized interpolated filter
    istarfl   = [] # interpolated stellar flux
    wnindices = [] # wavenumber indices used in interpolation
    meanwn    = [] # Filter mean wavenumber
    for i in np.arange(nfilters):
        # read filter:
        filtwaven, filttransm = w.readfilter(filters[i])
        meanwn.append(np.sum(filtwaven*filttransm)/sum(filttransm))
        # resample filter and stellar spectrum:
        nifilt, strfl, wnind = w.resample(specwn, filtwaven, filttransm,
                                            starwn,    starfl)
        nifilter.append(nifilt)
        istarfl.append(strfl)
        wnindices.append(wnind)

    # convert mean wn to mean wl
    meanwl = 1e4/np.asarray(meanwn)

    # band-integrate the flux-ratio or modulation:
    bandflux = np.zeros(nfilters, dtype='d')
    bandmod  = np.zeros(nfilters, dtype='d')
    for i in np.arange(nfilters):
        fluxrat = (bestspectrum[wnindices[i]]/istarfl[i]) * rprs*rprs
        bandflux[i] = w.bandintegrate(fluxrat, specwn, nifilter[i],
                                                                 wnindices[i])
        bandmod[i]  = w.bandintegrate(bestspectrum[wnindices[i]],
                                            specwn, nifilter[i], wnindices[i])

    # stellar spectrum on specwn:
    sinterp = si.interp1d(starwn, starfl)
    sflux = sinterp(specwn)
    frat = bestspectrum/sflux * rprs * rprs

    # plot figure
    plt.rcParams["mathtext.default"] = 'rm'
    matplotlib.rcParams.update({'mathtext.default':'rm'})
    matplotlib.rcParams.update({'font.size':10})
    plt.figure(3, (8.5, 5))
    plt.clf()

    # depending on solution plot eclipse or modulation spectrum
    if solution == 'eclipse':
        gfrat = gaussf(frat, 2)
        plt.semilogx(specwl, gfrat*1e3, "b", lw=1.5, label="Best-fit")
        plt.errorbar(meanwl, data*1e3, uncert*1e3, fmt="or", label="data")
        plt.plot(meanwl, bandflux*1e3, "ok", label="model", alpha=1.0)
        plt.ylabel(r"$F_p/F_s$ (10$^{3}$)", fontsize=12)

    elif solution == 'transit':
        gmodel = gaussf(bestspectrum, 2)
        plt.semilogx(specwl, gmodel, "b", lw=1.5, label="Best-fit")
        # Check units!
        plt.errorbar(meanwl, data, uncert, fmt="or", label="data")
        plt.plot(meanwl, bandmod, "ok", label="model", alpha=0.5)
        plt.ylabel(r"$(R_p/R_s)^2$", fontsize=12)

    leg = plt.legend(loc="lower right")
    leg.get_frame().set_alpha(0.5)
    ax = plt.subplot(111)
    ax.set_xscale('log')
    plt.xlabel(r"${\rm Wavelength\ \ (um)}$", fontsize=12)  
    ax.get_xaxis().set_major_formatter(matplotlib.ticker.ScalarFormatter())
    ax.set_xticks(np.arange(min(specwl),max(specwl),1))
    plt.xlim(min(specwl),max(specwl))
    plt.savefig(date_dir + "BART-bestFit-Spectrum.png")
예제 #7
0
파일: quickguide.py 프로젝트: zhpfu/BART
# Atmospheric species:
species = "He    H2    CO    CO2   CH4   H2O   NH3    C2H2   C2H4"
# Abundances (mole mixing ratio):
abundances = "0.15  0.85  1e-4  1e-4  1e-4  1e-4  1e-10  1e-10  1e-10"

# [Run script ( 2) to make a temperature profile]

# Make the atmospheric file:
ma.uniform(atmfile, pfile, elemabun, tep, species, abundances, temp)

# ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# ( 3) Read and plot a transit spectrum:
import readtransit as rt

wl, spectrum = rt.readspectrum("eclipse_out.dat.-Flux", 0)

plt.figure(1)
plt.clf()
plt.semilogx(wl, spectrum, "b", label="Planet spectrum")
plt.xlim(wl[-1], wl[0])
plt.legend(loc="best")

# ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# ( 4) Calculate the minimum and maximum line-profile widths:

# TBD

# ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# ( 5) Plot the posterior TP profiles:
def noiseup(kuruczfile, planetfile, filters, geometry, outdir, outpre, 
            mass=0.806, radius=0.756, temp=5000., planetrad=1.138, 
            distance=19.3, diameter=650., ecltime=1.827, seed=0):
    """
    This function takes an input star and planet spectrum and computes 
    transit/eclipse depths with photon noise, as observed by a 
    JWST-like telescope. 

    Inputs
    ------
    kuruczfile: string. Path/to/file of the Kurucz stellar model.
    planetfile: string. Path/to/file of the planet's spectrum.
    filters   : list, strings. Paths/to/filter files.
    geometry  : string. Viewing geometry. 'eclipse' or 'transit'
    outdir    : string. Path/to/directory/ where the outputs will be saved.
    outpre    : string. Prefix to use for all saved out files.
    mass      : float.  Mass   of the host star [M_sun]
    radius    : float.  Radius of the host star [R_sun]
    temp      : float.  Temperature of the host star [K]
    planetrad : float.  Radius of the planet [R_jup]
    distance  : float.  Distance to planetary system [pc]
    diameter  : float.  Telescope diameter [cm]
    ecltime   : float.  Duration of the secondary eclipse [hours]
    seed      : int.    Seed for random number generation.

    Outputs
    -------
    Four files are produced:
    - 
    - 
    - 
    - 

    Notes
    -----
    The default values are based on the HD 189733 system.
    The default `ecltime` value comes from 
    https://academic.oup.com/mnras/article/395/1/335/1746726/Secondary-radio-eclipse-of-the-transiting-planet

    Revisions
    ---------
    2017-11-15  Ryan        Original implementation
    2018-04-18  Michael     Added transit calculations
    2019-06-06  Michael     Reworked into function, incorporated into BARTTest
    """
    # Set the random seed for reproducibility
    np.random.seed(seed=seed)

    # Make sure `outdir` has trailing slash:
    if outdir[-1] != '/':
        outdir = outdir + '/'

    # Constants in CGS units
    G     = const.G.cgs.value
    h     = const.h.cgs.value
    c     = const.c.cgs.value
    Msun  = const.M_sun.cgs.value
    Rsun  = const.R_sun.cgs.value
    pc2cm = const.pc.cgs.value
    Rjup  = const.R_jup.cgs.value

    # Convert system parameters
    mass      *= Msun
    radius    *= Rsun
    planetrad *= Rjup
    distance  *= pc2cm
    ecltime   *= 3600 #hours --> seconds

    # Temperature and log(g) of star
    logg = np.log10(G * mass / radius**2) #log g (cm/s2)

    # Read and interpolate Kurucz grid, planet spectrum
    starfl, starwn, tmodel, gmodel = wine.readkurucz(kuruczfile, temp, logg)
    planetwn, planetfl             = rt.readspectrum(planetfile)

    nifilter  = []
    wnindices = []

    # Multiply by 4pi steradians, surface area
    # Planetary spectrum is already integrated over steradians
    sPower =   starfl * (4 * np.pi * radius**2)
    pPower = planetfl * (4 * np.pi * planetrad**2)

    # Multiply by eclipse duration
    sEnergy = sPower * ecltime
    pEnergy = pPower * ecltime

    # Spread out over distance
    sEdensity = sEnergy / (4 * np.pi * distance**2)
    pEdensity = pEnergy / (4 * np.pi * distance**2)

    # Multiply by telescope area (total energy received)
    sSED = sEdensity * np.pi * (diameter/2.)**2.
    pSED = pEdensity * np.pi * (diameter/2.)**2.

    # Interpolate stellar SED
    sSEDinterp = si.interp1d(starwn, sSED)
    isSED      = sSEDinterp(planetwn)

    if geometry == 'transit':
        # Interpolate stellar flux
        starflinterp = si.interp1d(starwn, starfl)
        istarfl      = starflinterp(planetwn)

    # Initialize arrays for band-integrated energy and mean wavelength
    bandintegratedstar   = np.zeros(len(filters))
    bandintegratedplanet = np.zeros(len(filters))
    meanwn               = np.zeros(len(filters))

    # Read filters. Resample to planetwn
    for i in np.arange(len(filters)):
        filtwn, filttransm   = wine.readfilter(filters[i])
        meanwn[i]            = np.mean(filtwn)
        nifilt, rsSED, wnind = wine.resample(planetwn, filtwn, filttransm, 
                                             starwn, sSED)
        nifilter.append(nifilt)
        wnindices.append(wnind)

    # Loop over each filter file, read the file, interpolate to the
    # wavelength array, and integrate over the bandpass, weighted by the
    # filter. 
    for i in np.arange(len(filters)):
        # integrate over the bandpass
        bandintegratedstar[i]       = wine.bandintegrate(
                                           isSED[wnindices[i][0]], planetwn, 
                                           nifilter[i], wnindices[i])
        if   geometry == 'eclipse':
            bandintegratedplanet[i] = wine.bandintegrate(
                                           pSED[wnindices[i][0]], 
                                           planetwn, nifilter[i], wnindices[i])
        elif geometry == 'transit':
            bandintegratedplanet[i] = wine.bandintegrate(
                                           planetfl[wnindices[i][0]], 
                                           planetwn, nifilter[i], wnindices[i])
        else:
            print("Invalid `geometry` specification.\n")
            sys.exit()

    # Divide by photon energy to get number of photons (counts)
    # Find total photon signal
    sphotons = bandintegratedstar   / (h * meanwn * c)
    if geometry == 'eclipse':
        pphotons = bandintegratedplanet / (h * meanwn * c)
        phot_tot = sphotons + pphotons
    else:
        phot_tot = sphotons #planet flux is negligible in transit geometry
        # Multiply by 1 minus the transit depth = signal during transit
        phot_tot_rat = phot_tot * (1. - bandintegratedplanet)

    # Noise it up
    poisson_tot = phot_tot**(.5)
    poisson_s   = sphotons**(.5)
    if geometry == 'eclipse':
        poisson_p = pphotons**(.5)
        noise     = np.random.normal(0, poisson_tot)
        # Add noise to the band-integrated photon counts
        noisedpts    = phot_tot + noise
        noisedplanet = pphotons + noise
        noisedstar   = sphotons + noise
        # Calculate eclipse depths
        depths = noisedplanet / phot_tot
        # Calculate eclipse depth uncertainty
        unc    = phot_tot/sphotons * ((poisson_tot/phot_tot)**2 + \
                                      (poisson_s  /sphotons)**2)**(.5)
    else:
        poisson_tot_rat = (phot_tot_rat)**(.5)
        # Propagate error
        unc    =      phot_tot_rat / phot_tot * \
                 ((poisson_tot_rat / phot_tot_rat)**2 + \
                  (poisson_tot     / phot_tot    )**2)**(.5)
        noise  = np.random.normal(0, poisson_tot_rat) / phot_tot_rat
        depths = bandintegratedplanet + noise

    # Save out files
    # Save filter file paths for BART
    with open(outdir+outpre+'filters.txt', 'w') as f:
        for i in range(len(filters)):
            f.write('../00inputs/filters/' + \
                    os.path.basename(filters[i]) + '\n')
    if geometry == 'eclipse':
        # Save depths to a file
        with open(outdir+outpre+'ecldepths.txt', 'w') as f:
            for i in range(len(depths)):
                f.write(str(depths[i]) + '\n')
        # Save uncertainties to a file
        with open(outdir+outpre+'ecluncs.txt', 'w') as f:
            for i in range(len(unc)):
                f.write(str(unc[i]) + '\n')
        # Save noiseless depths
        with open(outdir+outpre+'ecl_noiseless.txt', 'w') as f:
            for i in range(len(filters)):
                f.write(str(pphotons[i]/phot_tot[i]) + '\n')
    else:
        # Save depths to a file
        with open(outdir+outpre+'tradepths.txt', 'w') as f:
            for i in range(len(depths)):
                f.write(str(depths[i]) + '\n')
        # Save uncertainties to a file
        with open(outdir+outpre+'trauncs.txt', 'w') as f:
            for i in range(len(unc)):
                f.write(str(unc[i]) + '\n')
        # Save noiseless depths
        with open(outdir+outpre+'tra_noiseless.txt', 'w') as f:
            for i in range(len(filters)):
                f.write(str(bandintegratedplanet[i]) + '\n')
plt.rcParams["mathtext.default"] = 'rm'
matplotlib.rcParams.update({'mathtext.default':'rm'})
matplotlib.rcParams.update({'axes.labelsize': 16,
                                'xtick.labelsize': 14,
                                'ytick.labelsize': 14,})

fig= plt.figure(figsize=(8.5, 5))
plt.ylabel(r"$F_p/F_s$ (10$^{-3}$)", fontsize=14)
plt.xlabel(r"${\rm Wavelength\ \ (um)}$", fontsize=14)

######################################### for each spectrum separately

outflux = './4species_4opac_uniform/4species_4opac_uniform-flux.dat'

# read best-fit spectrum output file, take wn and spectra values
specwn, bestspectrum = rt.readspectrum(outflux, wn=True)
# convert wn to wl
specwl = 1e4/specwn
# number of filters
nfilters = len(filters)
# read and resample the filters:
nifilter  = [] # Normalized interpolated filter
istarfl   = [] # interpolated stellar flux
wnindices = [] # wavenumber indices used in interpolation
meanwn    = [] # Filter mean wavenumber
for i in np.arange(nfilters):
    # read filter:
    filtwaven, filttransm = w.readfilter(filters[i])
    meanwn.append(np.sum(filtwaven*filttransm)/sum(filttransm))
    # resample filter and stellar spectrum:
    nifilt, strfl, wnind = w.resample(specwn, filtwaven, filttransm,
예제 #10
0
def plot_bestFit_Spectrum(low, high, xtic, xlab, spec, clr, specs, atmfile,
                          filters, kurucz, tepfile, outflux, data, uncert,
                          direct):
    '''
    Plot Transit spectrum
    '''
    # get star data
    R_star, T_star, sma, gstar = bf.get_starData(tepfile)

    # get surface gravity
    grav, Rp = mat.get_g(tepfile)

    # convert Rp to m
    Rp = Rp * 1000

    # ratio planet to star
    rprs = Rp / R_star

    # read kurucz file
    starfl, starwn, tmodel, gmodel = w.readkurucz(kurucz, T_star, gstar)

    # read best-fit spectrum output file, take wn and spectra values
    (head, tail) = os.path.split(outflux)
    specwn, bestspectrum = rt.readspectrum(direct + '/' + tail, wn=True)

    # convert wn to wl
    specwl = 1e4 / specwn

    # number of filters
    nfilters = len(filters)

    # read and resample the filters:
    nifilter = []  # Normalized interpolated filter
    istarfl = []  # interpolated stellar flux
    wnindices = []  # wavenumber indices used in interpolation
    meanwn = []  # Filter mean wavenumber
    for i in np.arange(nfilters):
        # read filter:
        filtwaven, filttransm = w.readfilter(filters[i])
        meanwn.append(np.sum(filtwaven * filttransm) / sum(filttransm))
        # resample filter and stellar spectrum:
        nifilt, strfl, wnind = w.resample(specwn, filtwaven, filttransm,
                                          starwn, starfl)
        nifilter.append(nifilt)
        istarfl.append(strfl)
        wnindices.append(wnind)

    # convert mean wn to mean wl
    meanwl = 1e4 / np.asarray(meanwn)

    # band-integrate the flux-ratio or modulation:
    bandflux = np.zeros(nfilters, dtype='d')
    bandmod = np.zeros(nfilters, dtype='d')
    for i in np.arange(nfilters):
        fluxrat = (bestspectrum[wnindices[i]] / istarfl[i]) * rprs * rprs
        bandflux[i] = w.bandintegrate(fluxrat, specwn, nifilter[i],
                                      wnindices[i])
        bandmod[i] = w.bandintegrate(bestspectrum[wnindices[i]], specwn,
                                     nifilter[i], wnindices[i])

    # stellar spectrum on specwn:
    sinterp = si.interp1d(starwn, starfl)
    sflux = sinterp(specwn)
    frat = bestspectrum / sflux * rprs * rprs

    ###################### plot figure #############################

    plt.rcParams["mathtext.default"] = 'rm'
    matplotlib.rcParams.update({'mathtext.default': 'rm'})
    matplotlib.rcParams.update({
        'axes.labelsize': 16,
        'xtick.labelsize': 20,
        'ytick.labelsize': 20,
    })

    plt.figure(2, (8.5, 5))
    plt.clf()

    # smooth the spectrum a fit
    gfrat = gaussf(frat, 2)

    # plot eclipse spectrum
    plt.semilogx(specwl,
                 gfrat * 1e3,
                 clr,
                 lw=1.5,
                 label="Spectrum",
                 linewidth=4)
    plt.errorbar(meanwl,
                 data * 1e3,
                 uncert * 1e3,
                 fmt="ko",
                 label="Data",
                 alpha=0.7)
    plt.ylabel(r"$F_p/F_s$ (10$^{-3}$)", fontsize=24)

    leg = plt.legend(loc="upper left")
    leg.get_frame().set_alpha(0.5)
    ax = plt.subplot(111)
    ax.set_xscale('log')
    plt.xlabel(r"${\rm Wavelength\ \ (um)}$", fontsize=24)
    ax.get_xaxis().set_major_formatter(matplotlib.ticker.ScalarFormatter())
    plt.gca().xaxis.set_minor_formatter(matplotlib.ticker.NullFormatter())
    ax.set_xticks([0.7, 0.8, 0.9, 1.0, 2.0, 3.0, 4.0, 5.0])
    ax.set_xticklabels(["0.7", "", "", "1.0", "2.0", "3.0", "4.0", "5.0"])
    plt.xlim(min(specwl), max(specwl))

    nfilters = len(filters)
    # plot filter bandpasses
    for i in np.arange(nfilters - 15):
        (head, tail) = os.path.split(filters[i])
        lbl = tail[:-4]
        # read filter:
        wn, respons = w.readfilter(filters[i])
        respons = respons / 3 - 0.4
        wl = 10000.0 / wn
        #plt.plot(wl, respons, color='crimson', linewidth =1)
        if lbl == 'spitzer_irac1_sa' or lbl == 'spitzer_irac2_sa':
            respons = respons * 2 + 0.4
            plt.plot(wl, respons, color='grey', linewidth=1, alpha=0.5)
            #plt.plot(wl, respons*2, color='orangered', linewidth =1)
        elif lbl == 'Wang-Hband' or lbl == 'Wang-Kband':
            plt.plot(wl, respons, 'grey', linewidth=1, alpha=0.5)
        elif lbl == 'VLT_1190' or lbl == 'VLT_2090':
            plt.plot(wl, respons, color='grey', linewidth=2, alpha=0.5)
            #plt.plot(wl, respons, color='firebrick', linewidth =2)
        elif lbl == 'GROND_K_JB' or lbl == 'GROND_i_JB':
            plt.plot(wl, respons, 'grey', linewidth=1, alpha=0.5)
        elif lbl == 'Zhou_Ks':
            plt.plot(wl, respons, 'grey', linewidth=1, alpha=0.5)

    plt.ylim(-0.4, 7)
    plt.text(1.9, 3, specs, color=clr, fontsize=26)

    plt.subplots_adjust(bottom=0.20)

    plt.savefig(spec + "_BestFit-transSpec.png")
    plt.savefig(spec + "_BestFit-transSpec.ps")
예제 #11
0
# Atmospheric species:
species    = "He    H2    CO    CO2   CH4   H2O   NH3    C2H2   C2H4"
# Abundances (mole mixing ratio):
abundances = "0.15  0.85  1e-4  1e-4  1e-4  1e-4  1e-10  1e-10  1e-10"

# [Run script ( 2) to make a temperature profile]

# Make the atmospheric file:
ma.uniform(atmfile, pfile, elemabun, tep, species, abundances, temp)


# ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# ( 3) Read and plot a transit spectrum:
import readtransit as rt

wl, spectrum = rt.readspectrum("eclipse_out.dat.-Flux", 0)

plt.figure(1)
plt.clf()
plt.semilogx(wl, spectrum, "b", label="Planet spectrum")
plt.xlim(wl[-1], wl[0])
plt.legend(loc="best")


# ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# ( 4) Calculate the minimum and maximum line-profile widths:

# TBD

# ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# ( 5) Plot the posterior TP profiles:
예제 #12
0
def noiseup(snr,
            planetfile,
            filters,
            geometry,
            outdir,
            outpre,
            kuruczfile,
            mass=0.806,
            radius=0.756,
            temp=5000.,
            planetrad=1.138,
            seed=0):
    """
    This function takes an input star and planet spectrum and computes 
    transit/eclipse depths with photon noise, as observed by a 
    JWST-like telescope. 

    Inputs
    ------
    snr       : float.  Desired SNR value.
    planetfile: string. Path/to/file of the planet's spectrum.
    filters   : list, strings. Paths/to/filter files.
    geometry  : string. Viewing geometry. 'eclipse' or 'transit'
    outdir    : string. Path/to/directory/ where the outputs will be saved.
    outpre    : string. Prefix to use for all saved out files.
    kuruczfile: string. Path/to/file of the Kurucz stellar model.
    mass      : float.  Mass   of the host star [M_sun]
    radius    : float.  Radius of the host star [R_sun]
    temp      : float.  Temperature of the host star [K]
    planetrad : float.  Radius of the planet [R_jup]
    seed      : int.    Seed for random number generation.

    Outputs
    -------
    Four text files are produced:
    - list of filers
    - noiseless spectrum
    - noised spectrum
    - uncertainties on noised spectrum

    Notes
    -----
    The default values are based on the HD 189733 system.
    The default `ecltime` value comes from 
    https://academic.oup.com/mnras/article/395/1/335/1746726/Secondary-radio-eclipse-of-the-transiting-planet

    Revisions
    ---------
    2017-11-15  Ryan        Original implementation
    2018-04-18  Michael     Added transit calculations
    2019-06-06  Michael     Reworked into function, incorporated into BARTTest
    2020-08-08  Michael     Simplified computation
    """
    # Set the random seed for reproducibility
    np.random.seed(seed=seed)

    # Make sure `outdir` has trailing slash:
    if outdir[-1] != '/':
        outdir = outdir + '/'

    # Constants in CGS units
    G = const.G.cgs.value
    h = const.h.cgs.value
    c = const.c.cgs.value
    Msun = const.M_sun.cgs.value
    Rsun = const.R_sun.cgs.value
    pc2cm = const.pc.cgs.value
    Rjup = const.R_jup.cgs.value

    # Convert system parameters
    mass *= Msun
    radius *= Rsun
    planetrad *= Rjup

    rprs = planetrad / radius  #ratio of planet/star radii

    # Temperature and log(g) of star
    logg = np.log10(G * mass / radius**2)  #log g (cm/s2)

    # Read and interpolate Kurucz grid, planet spectrum
    starfl, starwn, tmodel, gmodel = wine.readkurucz(kuruczfile, temp, logg)
    planetwn, planetfl = rt.readspectrum(planetfile)

    # Initialize arrays for band-integrated spectrum and mean wavelength
    bandflux = np.zeros(len(filters))
    meanwn = np.zeros(len(filters))
    nifilter = []
    wnindices = []
    istarfl = []  # interpolated stellar flux
    # Read filters. Resample to planetwn
    for i in np.arange(len(filters)):
        filtwn, filttransm = wine.readfilter(filters[i])
        meanwn[i] = np.mean(filtwn)
        nifilt, strfl, wnind = wine.resample(planetwn, filtwn, filttransm,
                                             starwn, starfl)
        nifilter.append(nifilt)
        wnindices.append(wnind)
        istarfl.append(strfl)

    # Loop over each filter file, read the file, interpolate to the
    # wavelength array, and integrate over the bandpass, weighted by the
    # filter.
    for i in np.arange(len(filters)):
        # integrate over the bandpass
        if geometry == "eclipse":
            fluxrat = (planetfl[wnindices[i]] / istarfl[i]) * rprs * rprs
            bandflux[i] = wine.bandintegrate(fluxrat, planetwn, nifilter[i],
                                             wnindices[i])
        elif geometry == "transit":
            bandflux[i] = wine.bandintegrate(planetfl[wnindices[i]], planetwn,
                                             nifilter[i], wnindices[i])

    # Uncertainty
    unc = bandflux / snr

    # Save out files
    # Save filter file paths for BART
    with open(outdir + outpre + 'filters.txt', 'w') as f:
        for i in range(len(filters)):
            f.write('../00inputs/filters/' + \
                    os.path.basename(filters[i]) + '\n')
    if geometry == 'eclipse':
        strname = 'ecl'
    elif geometry == 'transit':
        strname = 'tra'
    # Save noised depths to a file
    with open(outdir + outpre + strname + 'depths.txt', 'w') as f:
        for i in range(len(depths)):
            f.write(str(bandflux[i]) + '\n')
    # Save uncertainties to a file
    with open(outdir + outpre + strname + 'uncs.txt', 'w') as f:
        for i in range(len(unc)):
            f.write(str(unc[i]) + '\n')
예제 #13
0
def plotspectrum(fname, geo, wl=True, oname=False, title=False):
    """
    This function produces a plot of the spectrum produced by Transit.
    
    Inputs
    ------
    fname: string. File name of the spectrum file, with directory relative to 
                   /BARTTest/.
    geo  : string. Geometry of the produced spectrum.
                   'transit' or 'eclipse'
    wl   : bool.   True plots over wavelength, False plots over wavenumber.
    oname: string. If oname is False, the default plotting name is used when 
                   saving the file. If it is a string, then that 
                   path/to/plotname is used.
    title: bool.   True produces a plot with a title. False does not.
    
    Outputs
    -------
    PNG file of the spectrum. Default naming convention is i.e.
      oneline_emission_spectrum.png
      fewline_transmission_spectrum.png
    
    Example
    -------
    >>> plotspectrum('fewline/fewline_emission_spectrum.dat', 'eclipse')
    """
    # Load the data
    try:
        if wl==True:
            wlength, flux = rt.readspectrum(fname, 0)
        else:
            wlength, flux = rt.readspectrum(fname)
    except:
        return

    # Get test name
    testname = fname.split('/')[-1].split('_')[0]

    # Plot the data
    plt.figure(0, (8,5))
    plt.clf()
    plt.plot(wlength, flux, "b")
    
    # Set title and plot filename based on the geometry
    if geo=='eclipse':
        if title==True:
            plt.title(testname + " Emission Spectrum")
        plt.ylabel("Flux  (erg s$^{-1}$ cm$^{-1}$)")
        plotname = testname + '_emission_spectrum.png'
    else:
        if title==True:
            plt.title(testname + " Transmission Spectrum")
        plt.ylabel("Modulation  ($(R_p/R_s)^2$)")
        plotname = testname + '_transmission_spectrum.png'
    
    # Set X axis label to that specified
    if wl==True:
        plt.xlabel(u"Wavelength  (\u00b5m)")
    else:
        plt.xlabel("Wavenumber  (cm$^{-1}$)")

    # Set x limits
    plt.xlim(np.amin(wlength), np.amax(wlength))
    
    # Save the plot
    if oname==False:
        plt.savefig(fname.split('/')[0] + '/' + plotname)
    else:
        plt.savefig(oname)
    plt.clf()
예제 #14
0
def plotspeciso(fname, atm, geo, wl=True, oname=False, title=False):
    """
    This function produces a plot of the isothermal spectrum produced by 
    the isothermal test with the Planck function overplotted.
    
    Inputs
    ------
    fname: string. File name of the spectrum file, with directory relative to 
                   /BARTTest/.
    atm  : string. File name of the atmospheric file used, with directory.
    geo  : string. Geometry of the produced spectrum.
                   'transit' or 'eclipse'
    wl   : bool.   True plots over wavelength, False plots over wavenumber.
    oname: string. If oname is False, the default plotting name is used when 
                   saving the file. If it is a string, then that 
                   path/to/plotname is used.
    title: bool.   If True, plots w/ title. If False, it does not.
    
    Outputs
    -------
    PNG file of the spectrum. Default naming convention is i.e.
      isothermal_emission_spectrum.png
      isothermal_transmission_spectrum.png
    
    Example
    -------
    >>> plotspeciso('isothermal/isothermal_emission_spectrum.dat', \
                    'isothermal/isothermal.atm', 'eclipse')

    Notes
    -----
    For this plot to be produced correctly, an isothermal atmospheric file must 
    be supplied. There is a check for this in the function. A message will be 
    printed to the screen, and the code will continue to run. The resulting plot
    will however not contain the overplotted Planck function.

    """
    # Get the temperatures from the atm file
    foo = open(atm, 'r')
    lines = foo.readlines()
    lines = lines[13:] # trim the first 12 lines as they are headers

    # Array to hold temps
    temparr = np.zeros(len(lines), dtype=float)

    # Read in all the temps
    for i in range(len(lines)):
        temparr[i] = lines[i].split()[2]

    # Check that they are all the same--if not, yell at the user
    if len(np.unique(temparr)) != 1:
        print("The atmospheric file supplied is non-isothermal! " + \
              "Please supply an isothermal atmospheric file.\n")
        bgtemp = None
    else:
        bgtemp = np.unique(temparr)

    # Load the data
    try:
        if wl:
            wlength, flux = rt.readspectrum(fname, 0)
        else:
            wlength, flux = rt.readspectrum(fname)
    except:
        print("\nIsothermal plot: invalid specification for the data file name.")
        print("Problematic file:", fname, '\n')
        return

    # Get test name
    testname = fname.split('/')[-1].split('_')[0]

    # Plot the data
    plt.clf()
    fig1   = plt.figure(1)
    frame1 = fig1.add_axes((.1, .3, .8, .6))
    plt.plot(wlength, flux, color="k", lw=2, label='Transit')
    
    # Set title and plot filename based on the geometry
    if geo=='eclipse':
        if title:
            plt.title(testname + " Emission Spectrum")
        plt.ylabel("Flux  (erg s$^{-1}$ cm$^{-1}$)", fontsize=14)
        plotname = testname + '_emission_spectrum.png'
    else:
        if title:
            plt.title(testname + " Transmission Spectrum")
        plt.ylabel("Modulation  ($(R_p/R_s)^2$)", fontsize=14)
        plotname = testname + '_transmission_spectrum.png'
    
    # Plot the Planck function
    if wl:
        # Convert to wavenumber
        wavenum = 10000./wlength
        # Calculate the Planck function
        planck = 2. * const.h*1e7 * (wavenum**3) * (const.c*100)**2 /   \
                 (np.exp(const.h*1e7 * wavenum * const.c*100 /          \
                 (const.k*1e7) / bgtemp) - 1)
        # Plot it. Multiply Planck by pi because of how Transit calcs flux
        # Reverse Planck to match wlength
        plt.plot(wlength, np.pi*planck, color='goldenrod', lw=2, ls="--", 
                 label='Planck')
    else:
        planck = 2. * const.h*1e7 * (wlength**3) * (const.c*100)**2 /   \
                 (np.exp(const.h*1e7 * wlength * const.c*100 /          \
                 (const.k*1e7) / bgtemp) - 1)
        plt.plot(wlength, np.pi*planck, color='#ffff00', lw=2, ls="--", 
                 label='Planck')
    plt.legend(loc='upper right')

    frame1.set_xticklabels([])

    # Residuals
    frame2 = fig1.add_axes((.1, .1, .8, .2))
    plt.plot(wlength, 100*(flux - (np.pi*planck)) / (np.pi*planck))
    plt.ylabel('Residuals (%)', fontsize=14)
    yticks = frame2.yaxis.get_major_ticks()
    yticks[-1].label1.set_visible(False)

    # Set X axis label to that specified
    if wl:
        plt.xlabel(u"Wavelength  (\u00b5m)", fontsize=14)
    else:
        plt.xlabel("Wavenumber  (cm$^{-1}$)", fontsize=14)
    
    
    # Save the plot
    if not oname:
        plt.savefig(fname.split('/')[0] + '/' + plotname, bbox_inches='tight')
    else:
        plt.savefig(oname, bbox_inches='tight')
    plt.clf()
예제 #15
0
def plotspeczoom(fname, geo, loc, wl=True, xlims=False, oname=False, 
                 title=True):
    """
    This function produces a plot of a portion of the spectrum produced by 
    Transit.
    
    Inputs
    ------
    fname: string. File name of the spectrum file.
    geo  : string. Geometry of the produced spectrum.
                   'transit' or 'eclipse'
    loc  : float.  Location in microns (if wl=True) or inverse centimeters 
                   (if wl=False) to zoom in on.
    wl   : bool.   True plots over wavelength, False plots over wavenumber.
    xlims: tuple.  (xmin, xmax) Minimum and maximum X-axis values for the plot. 
                   Only use this if user desires a different range for the 
                   X axis than the default.
    oname: string. If oname is False, the default plotting name is used. If 
                   it is a string, then that path/to/plotname is used.
    title: bool.   True plots w/ title. False does not.
        
    Outputs
    -------
    PNG file of the portion of the spectrum. Naming convention is i.e.
      fewline_emission_spectrum_zoom2500nm.png

    Example
    -------
    >>> plotspeczoom('fewline/fewline_emission_spectrum.dat', 'eclipse', 2.5)
    """
    # Load the data
    try:
        if wl==True:
            wlength, flux = rt.readspectrum(fname, 0)
            # File is ordered by decreasing wavelength--reverse it
            wlength = wlength[::-1]
            flux    = flux   [::-1]
        else:
            wlength, flux = rt.readspectrum(fname)
    except:
        return

    # Get test name
    testname = fname.split('/')[-1].split('_')[0]
    
    # Find where to zoom in, trim data to this region
    hi       = wlength[wlength < loc]
    wlentrim = wlength[len(hi) - 33 : len(hi) + 33] # This is why reverse wl
    fluxtrim = flux   [len(hi) - 33 : len(hi) + 33] # above
    
    # Plot the data
    plt.figure(0, (8,5))
    plt.clf()
    plt.plot(wlentrim, fluxtrim, "b")
    
    # Set title and plot filename based on the geometry
    if geo=='eclipse':
        if title==True:
            plt.title(testname + " Emission Spectrum")
        plt.ylabel("Flux  (erg s$^{-1}$ cm$^{-1}$)")
        plotname = testname + '_emission_spectrum_zoom'
    else:
        if title==True:
            plt.title(testname + " Transmission Spectrum")
        plt.ylabel("Modulation  ($(R_p/R_s)^2$)")
        plotname = testname + '_transmission_spectrum_zoom'
    
    # Set X axis label to that specified
    if wl==True:
        plt.xlabel(u"Wavelength  (\u00b5m)")
        plotname += str(1000*loc)[:4] + 'nm'
    else:
        plt.xlabel("Wavenumber  (cm$^{-1}$)")
        plotname += str(loc) + 'cm-1'
    
    # Set the X axis limits for the plot
    plt.xlim(wlentrim[0], wlentrim[-1])
    
    # Save the plot
    if oname==False:
        plt.savefig(fname.split('/')[0] + '/' + plotname + '.png')
    else:
        plt.savefig(oname)
    plt.clf()
예제 #16
0
def compspec(specs, codes, geo, atm, outdir=None, titles=False, fext='.pdf'):
    """
    This function produces a plot of supplied spectra.  If multiple are given, 
    it computes the residuals for each spectrum with respect to the average 
    of all supplied spectra.

    Inputs
    ------
    specs  : list, string. path/to/file for spectrum data.
    codes  : list, string. Code names corresponding to `specs`.
    geo    : string. Viewing geometry. 'eclipse' or 'transit'
    atm    : string. Atmosphere's PT profile. 'iso', 'inv', or 'noi'
    outdir : string. path/to/output. Default is execution directory
    titles : bool.   Determines whether to include titles on plots or not.
    fext   : str.    Plot file extension. .pdf or .png

    Revisions
    ---------
    2017-10-16  mhimes          Initial implementation.
    2018-02-03  raechel         Improved plotting, added residuals subplot.
    2019-04-01  mhimes          Merged into BARTTest.
    2021-01-08  mhimes          Refactor to allow more codes to be easily added.
    """
    # Set plot title and file output name
    if geo == 'transit':
        if atm == 'inv':
            titlenm = "Inverted Transmission"
            filenm = "Inverted_transmission_comp"
        elif atm == 'iso':
            titlenm = "Isothermal Transmission"
            filenm = "isothermal_transmission_comp"
        elif atm == 'noi':
            titlenm = "Non-inverted Transmission"
            filenm = "noninverted_transmission_comp"
        else:
            print("Wrong `atm` specification. Use 'inv', 'iso', or 'noi'.\n")
    elif geo == 'eclipse':
        if atm == 'inv':
            titlenm = "Inverted Emission"
            filenm = "Inverted_emission_comp"
        elif atm == 'iso':
            titlenm = "Isothermal Emission"
            filenm = "isothermal_emission_comp"
        elif atm == 'noi':
            titlenm = "Non-inverted Emission"
            filenm = "noninverted_emission_comp"
        else:
            print("Wrong `atm` specification. Use 'inv', 'iso', or 'noi'.\n")
    else:
        raise ValueError(
            "Wrong `geo` specification. Use 'transit' or 'eclipse'.\n")

    # Plot it
    fig0 = plt.figure(0, (8, 5))
    plt.clf()
    frame1 = fig0.add_axes((.14, .3, .8, .65))
    if titles:
        plt.title(titlenm)

    avgspec = 0  #average spectrum, for residuals
    for i in range(len(specs)):
        wlength, flux = rt.readspectrum(specs[i], 0)
        if geo == 'transit':
            flux *= 100  # convert to %
        avgspec += flux
        plt.plot(wlength, flux, label=codes[i])
    avgspec /= len(specs)

    plt.xlabel(u"Wavelength  (\u03bcm)")
    if geo == 'transit':
        plt.ylabel("Modulation  (%)")
    else:
        plt.ylabel("Flux (erg s$^{-1}$ cm$^{-1}$)")

    #plot black body curves
    h = 6.62607004e-27  # erg*s
    c = 2.9979245800e10  # cm/s
    k = 1.38064852e-16  # erg/K

    # Set min and max temperatures for plotting
    if atm == 'inv':
        T1 = 911.14  # K
        T2 = 1012.68  # K
    elif atm == 'iso':
        T1 = 1100.0
        T2 = 1100.0
    elif atm == 'noi':
        T1 = 882.93
        T2 = 1408.70

    w = np.linspace(10000. / 11.0, 10000. / 1.000, 10000)  # cm^-1

    # Blackbody associated with min/max temperature
    a = np.pi * 2 * h * (c**2) * (w**3)
    b1 = (h * c * w) / (k * T1)
    Bb1 = a / (np.exp(b1) - 1.0)

    b2 = (h * c * w) / (k * T2)
    Bb2 = a / (np.exp(b2) - 1.0)

    l = 10000. / w

    T1s = str(T1) + ' K'
    T2s = str(T2) + ' K'

    if geo == 'eclipse':
        frame1.set_ylim(0, max(Bb2) + 5000)
        if T1 != T2:
            plt.plot(l,
                     Bb1,
                     "r",
                     linestyle=':',
                     label="Blackbody at " + T1s,
                     linewidth=2.0)
            plt.plot(l,
                     Bb2,
                     "b",
                     linestyle=':',
                     label="Blackbody at " + T2s,
                     linewidth=2.0)
        else:
            plt.plot(l,
                     Bb1,
                     "k",
                     linestyle=':',
                     label="Blackbody at " + T2s,
                     linewidth=2.0)
    plt.legend(loc='center left', bbox_to_anchor=(1.0, 0.5))

    frame1.set_xscale('log')
    frame1.set_xlim(1, 11.0)

    frame1.yaxis.set_label_coords(-0.1, 0.5)

    # For the x-axis to be integers, rather than C * 10^n
    formatter = mpl.ticker.FuncFormatter(lambda y, _: '{:.8g}'.format(y))

    if len(specs) > 1:
        frame1.set_xticklabels([])
        fig0.canvas.draw()
        if frame1.get_yticklabels()[0].get_position()[-1] == 0.0:
            plt.setp(frame1.get_yticklabels()[0], visible=False)
        #residual plots
        frame2 = fig0.add_axes((.14, .1, .8, .2))
        for i in range(len(specs)):
            wlength, flux = rt.readspectrum(specs[i], 0)
            if geo == 'transit':
                flux *= 100  # convert to %
            plt.plot(wlength, flux - avgspec)
        plt.ylabel('Residuals\nw.r.t. average')
        plt.xlabel(u"Wavelength  (\u00b5m)")
        frame2.set_xscale('log')
        frame2.set_xlim(1, 11.0)
        frame2.get_xaxis().set_major_formatter(formatter)
        frame2.get_xaxis().set_minor_formatter(formatter)
        frame2.yaxis.set_label_coords(-0.1, 0.5)
    else:
        frame1.get_xaxis().set_major_formatter(formatter)
        frame1.get_xaxis().set_minor_formatter(formatter)

    if (geo == 'eclipse') and (atm == 'iso'):
        frame3 = fig0.add_axes((.57, .38, .25, .25))
        frame3.set_ylim(23000, 24000)
        frame3.set_xscale('log')
        frame3.set_xlim(3.5, 6.5)
        frame3.get_xaxis().set_major_formatter(formatter)
        frame3.get_xaxis().set_minor_formatter(formatter)
        for i in range(len(specs)):
            wlength, flux = rt.readspectrum(specs[i], 0)
            plt.plot(wlength, flux)
        plt.plot(l, Bb1, "k", linestyle=':', linewidth=4.0)

    if outdir is not None:
        plt.savefig(outdir + filenm + "_" + "_".join(codes) + fext,
                    bbox_inches='tight')
    else:
        plt.savefig(filenm + "_" + "_".join(codes) + fext, bbox_inches='tight')
    plt.close()
def plot_bestFit_Spectrum(spec, clr, specs, atmfile, filters, kurucz, tepfile,
                          outflux, data, uncert, direct):
    '''
    Plot Transit spectrum
    '''
    # get star data
    R_star, T_star, sma, gstar = bf.get_starData(tepfile)

    # get surface gravity
    grav, Rp = mat.get_g(tepfile)

    # convert Rp to m
    Rp = Rp * 1000

    # ratio planet to star
    rprs = Rp / R_star

    # read kurucz file
    starfl, starwn, tmodel, gmodel = w.readkurucz(kurucz, T_star, gstar)

    # read best-fit spectrum output file, take wn and spectra values
    (head, tail) = os.path.split(outflux)
    specwn, bestspectrum = rt.readspectrum(direct + '/' + tail, wn=True)

    # convert wn to wl
    specwl = 1e4 / specwn

    # number of filters
    nfilters = len(filters)

    # read and resample the filters:
    nifilter = []  # Normalized interpolated filter
    istarfl = []  # interpolated stellar flux
    wnindices = []  # wavenumber indices used in interpolation
    meanwn = []  # Filter mean wavenumber
    for i in np.arange(nfilters):
        # read filter:
        filtwaven, filttransm = w.readfilter(filters[i])
        meanwn.append(np.sum(filtwaven * filttransm) / sum(filttransm))
        # resample filter and stellar spectrum:
        nifilt, strfl, wnind = w.resample(specwn, filtwaven, filttransm,
                                          starwn, starfl)
        nifilter.append(nifilt)
        istarfl.append(strfl)
        wnindices.append(wnind)

    # convert mean wn to mean wl
    meanwl = 1e4 / np.asarray(meanwn)

    # band-integrate the flux-ratio or modulation:
    bandflux = np.zeros(nfilters, dtype='d')
    bandmod = np.zeros(nfilters, dtype='d')
    for i in np.arange(nfilters):
        fluxrat = (bestspectrum[wnindices[i]] / istarfl[i]) * rprs * rprs
        bandflux[i] = w.bandintegrate(fluxrat, specwn, nifilter[i],
                                      wnindices[i])
        bandmod[i] = w.bandintegrate(bestspectrum[wnindices[i]], specwn,
                                     nifilter[i], wnindices[i])

    # stellar spectrum on specwn:
    sinterp = si.interp1d(starwn, starfl)
    sflux = sinterp(specwn)
    frat = bestspectrum / sflux * rprs * rprs

    ###################### plot figure #############################

    plt.rcParams["mathtext.default"] = 'rm'
    matplotlib.rcParams.update({'mathtext.default': 'rm'})
    #matplotlib.rcParams.update({'fontsize': 10,})
    matplotlib.rcParams.update({
        'axes.labelsize': 16,
        #'text.fontsize':   10,
        'legend.fontsize': 14,
        'xtick.labelsize': 20,
        'ytick.labelsize': 20,
    })

    plt.figure(2, (8.5, 5))
    plt.clf()
    #plt.xlim(0.60, 5.5)

    #plt.xlim(min(specwl),max(specwl))

    # plot eclipse spectrum
    #gfrat = gaussf(frat, 0)
    plt.semilogx(specwl,
                 frat * 1e3,
                 clr,
                 lw=1.5,
                 label="Spectrum",
                 linewidth=4)
    #cornflowerblue, lightskyblue
    #plt.errorbar(meanwl, data*1e3, uncert*1e3, fmt="ko", label="Data", alpha=0.7)
    plt.errorbar(meanwl,
                 data * 1e3,
                 uncert * 1e3,
                 fmt=".",
                 color='k',
                 zorder=100,
                 capsize=2,
                 capthick=1,
                 label="Data",
                 alpha=0.7)
    #plt.plot(meanwl, bandflux*1e3, "ko", label="model")
    plt.ylabel(r"$F_p/F_s$ (10$^{-3}$)", fontsize=24)

    leg = plt.legend(loc="upper left")
    #leg.draw_frame(False)
    leg.get_frame().set_alpha(0.5)

    ax = plt.subplot(111)
    ax.set_xscale('log')

    ax.get_xaxis().set_major_formatter(matplotlib.ticker.ScalarFormatter())
    ax.set_xticks([0.7, 0.8, 0.9, 1.0, 2.0, 3.0, 4.0, 5.0])
    ax.set_xticklabels(["0.7", "", "", "1.0", "2.0", "3.0", "4.0", "5.0"])

    plt.xlabel(r"${\rm Wavelength\ \ (um)}$", fontsize=24)

    nfilters = len(filters)
    # plot filter bandpasses
    for i in np.arange(nfilters - 15):
        (head, tail) = os.path.split(filters[i])
        lbl = tail[:-4]
        # read filter:
        wn, respons = w.readfilter(filters[i])
        respons = respons / 3 - 0.4
        wl = 10000.0 / wn
        #plt.plot(wl, respons, color='crimson', linewidth =1)
        if lbl == 'spitzer_irac1_sa' or lbl == 'spitzer_irac2_sa':
            respons = respons * 2 + 0.4
            plt.plot(wl, respons, color='grey', linewidth=1, alpha=0.5)
            #plt.plot(wl, respons*2, color='orangered', linewidth =1)
        elif lbl == 'Wang-Hband' or lbl == 'Wang-Kband':
            plt.plot(wl, respons, 'grey', linewidth=1, alpha=0.5)
        elif lbl == 'VLT_1190' or lbl == 'VLT_2090':
            plt.plot(wl, respons, color='grey', linewidth=2, alpha=0.5)
            #plt.plot(wl, respons, color='firebrick', linewidth =2)
        elif lbl == 'GROND_K_JB' or lbl == 'GROND_i_JB':
            plt.plot(wl, respons, 'grey', linewidth=1, alpha=0.5)
        elif lbl == 'Zhou_Ks':
            plt.plot(wl, respons, 'grey', linewidth=1, alpha=0.5)

    plt.ylim(-0.4, 7)

    plt.text(1.9, 3, specs, color=clr, fontsize=26)

    ###################### INSET PT and ABUN FIGURE ####################
    b = plt.axes([.21, .45, .14, .24])

    # read atmfile
    molecules, pres, temp, abundances = mat.readatm(atmfile)

    plt.semilogy(temp, pres, color='r', linewidth=3)
    plt.xlim(1000, 2200)
    plt.ylim(max(pres), min(pres))
    b.minorticks_off()
    yticks = [1e2, 1e1, 1, 1e-1, 1e-2, 1e-3, 1e-4, 1e-5]
    ylabels = [
        "10$^{2}$", "", "10$^{0}$", "", "10$^{-2}$", "", "10$^{-4}$", ""
    ]
    plt.yticks(yticks, ylabels, fontsize=8)
    xticks = [1000, 1200, 1400, 1600, 1800, 2000, 2200]
    xlabels = ["", "1200", "", "", "1800", ""]
    plt.xticks(xticks, xlabels, fontsize=12)
    plt.xlabel('T (K)', fontsize=12)
    plt.ylabel('P (bar)', fontsize=12)

    # ############################## SECOND INSET ABUN
    c = plt.axes([.35, .45, .14, .24])

    # Sets the second argument given as the species names
    species = spec

    # Open the atmospheric file and read
    f = open(atmfile, 'r')
    lines = np.asarray(f.readlines())
    f.close()

    # Get molecules names
    imol = np.where(lines == "#SPECIES\n")[0][0] + 1
    molecules = lines[imol].split()
    nmol = len(molecules)
    for m in np.arange(nmol):
        molecules[m] = molecules[m].partition('_')[0]

    nspec = 1

    # Populate column numbers for requested species and
    #          update list of species if order is not appropriate
    columns = []
    spec = []
    for i in np.arange(nmol):
        if molecules[i] == species:
            columns.append(i + 3)  # defines p, T +2 or rad, p, T +3
            spec.append(species)

    # Convert spec to tuple
    spec = tuple(spec)

    # Concatenate spec with pressure for data and columns
    data = tuple(np.concatenate((['p'], spec)))
    usecols = tuple(np.concatenate(
        ([1], columns)))  # defines p as 0 columns, or p as 1 columns

    # Load all data for all interested species
    data = np.loadtxt(atmfile, dtype=float, comments='#', delimiter=None,    \
                converters=None, skiprows=13, usecols=usecols, unpack=True)

    plt.loglog(data[1], data[0], '-', color=clr, \
                                    linewidth=3)

    plt.ylim(max(pres), min(pres))
    c.minorticks_off()
    yticks = [1e2, 1e1, 1, 1e-1, 1e-2, 1e-3, 1e-4, 1e-5]
    ylabels = []
    plt.yticks(yticks, ylabels)
    plt.xlim(1e-12, 1e-2)
    xticks = [1e-11, 1e-9, 1e-7, 1e-5, 1e-3]
    xlabels = ["10$^{-11}$", "", "10$^{-5}$", "", "10$^{-3}$"]
    plt.xticks(xticks, xlabels, fontsize=12)
    plt.xlabel('Mix. fraction', fontsize=12)

    plt.subplots_adjust(bottom=0.16)

    spec = spec[0]
    print(spec)

    plt.savefig(spec + "_transSpec_new.png")
    plt.savefig(spec + "_transSpec_new.ps")
예제 #18
0
파일: bestFit.py 프로젝트: walterwsmf/BART
def plot_bestFit_Spectrum(filters, kurucz, tepfile, solution, output, data,
                                                          uncert, date_dir):
    '''
    Plot BART best-model spectrum
    '''
    # get star data
    R_star, T_star, sma, gstar = get_starData(tepfile)

    # get surface gravity
    grav, Rp = mat.get_g(tepfile)

    # convert Rp to m
    Rp = Rp * 1000

    # ratio planet to star
    rprs = Rp/R_star
  
    # read kurucz file
    starfl, starwn, tmodel, gmodel = w.readkurucz(kurucz, T_star, gstar)

    # read best-fit spectrum output file, take wn and spectra values
    if solution == 'eclipse':
        specwn, bestspectrum = rt.readspectrum(date_dir + output, wn=True)
        # print on screen
        print("  Plotting BART best-fit eclipse spectrum figure.")
    elif solution == 'transit':
        specwn, bestspectrum = rt.readspectrum(date_dir + output, wn=True)
        # print on screen
        print("  Plotting BART best-fit modulation spectrum figure.")

    # convert wn to wl
    specwl = 1e4/specwn

    # number of filters
    nfilters = len(filters)

    # read and resample the filters:
    nifilter  = [] # Normalized interpolated filter
    istarfl   = [] # interpolated stellar flux
    wnindices = [] # wavenumber indices used in interpolation
    meanwn    = [] # Filter mean wavenumber
    for i in np.arange(nfilters):
        # read filter:
        filtwaven, filttransm = w.readfilter(filters[i])
        meanwn.append(np.sum(filtwaven*filttransm)/sum(filttransm))
        # resample filter and stellar spectrum:
        nifilt, strfl, wnind = w.resample(specwn, filtwaven, filttransm,
                                            starwn,    starfl)
        nifilter.append(nifilt)
        istarfl.append(strfl)
        wnindices.append(wnind)

    # convert mean wn to mean wl
    meanwl = 1e4/np.asarray(meanwn)

    # band-integrate the flux-ratio or modulation:
    bandflux = np.zeros(nfilters, dtype='d')
    bandmod  = np.zeros(nfilters, dtype='d')
    for i in np.arange(nfilters):
        fluxrat = (bestspectrum[wnindices[i]]/istarfl[i]) * rprs*rprs
        bandflux[i] = w.bandintegrate(fluxrat, specwn, nifilter[i],
                                                                 wnindices[i])
        bandmod[i]  = w.bandintegrate(bestspectrum[wnindices[i]],
                                            specwn, nifilter[i], wnindices[i])

    # stellar spectrum on specwn:
    sinterp = si.interp1d(starwn, starfl)
    sflux = sinterp(specwn)
    frat = bestspectrum/sflux * rprs * rprs

    # plot figure
    plt.rcParams["mathtext.default"] = 'rm'
    matplotlib.rcParams.update({'mathtext.default':'rm'})
    matplotlib.rcParams.update({'font.size':10})
    plt.figure(3, (8.5, 5))
    plt.clf()

    # depending on solution plot eclipse or modulation spectrum
    if solution == 'eclipse':
        gfrat = gaussf(frat, 2)
        plt.semilogx(specwl, gfrat*1e3, "b", lw=1.5, label="Best-fit")
        plt.errorbar(meanwl, data*1e3, uncert*1e3, fmt="or", label="data")
        plt.plot(meanwl, bandflux*1e3, "ok", label="model", alpha=1.0)
        plt.ylabel(r"$F_p/F_s$ (10$^{3}$)", fontsize=12)

    elif solution == 'transit':
        gmodel = gaussf(bestspectrum, 2)
        plt.semilogx(specwl, gmodel, "b", lw=1.5, label="Best-fit")
        # Check units!
        plt.errorbar(meanwl, data, uncert, fmt="or", label="data")
        plt.plot(meanwl, bandmod, "ok", label="model", alpha=0.5)
        plt.ylabel(r"$(R_p/R_s)^2$", fontsize=12)

    leg = plt.legend(loc="lower right")
    leg.get_frame().set_alpha(0.5)
    ax = plt.subplot(111)
    ax.set_xscale('log')
    plt.xlabel(r"${\rm Wavelength\ \ (um)}$", fontsize=12)  
    ax.get_xaxis().set_major_formatter(matplotlib.ticker.ScalarFormatter())
    ax.set_xticks(np.arange(round(min(specwl)),max(specwl),1))
    plt.xlim(min(specwl),max(specwl))
    plt.savefig(date_dir + "BART-bestFit-Spectrum.png")