Beispiel #1
0
    def show_walkers(self, savefile=None, **kwargs):
        """
        Plot the fitted parameters walkers.
        Return the figure.
        
        Options
        -------
        savefile : [string or None]
            Give a directory to save the figure.
            Default is None (not saved).
        
        showpars : [list(string) or None]
            List of the parameters to show.
            If None, plot every fitted parameters (listed in 'self.theta_labels').
            Defaults is None.

        start : [int]
            Integer giving the iteration number from which to start plotting.
            Default is 0.

        chains : [np.array or slice]
            If results are from an ensemble sampler, setting 'chain' to an integer
            array of walker indices will cause only those walkers to be used in
            generating the plot.
            Useful for to keep the plot from getting too cluttered.
            Default is slice(None, None, None).
        
        truths : [list(float) or None]
            List of truth values for the chosen parameters to add them on the plot.
            Default is None.
    
        **plot_kwargs:
            Extra keywords are passed to the 'matplotlib.axes._subplots.AxesSubplot.plot()' method.
        
        Returns
        -------
        matplotlib.Figure
        """
        import prospect.io.read_results as reader
        _data = self._get_plot_data_()
        _fig = reader.traceplot(_data, **kwargs)
        if savefile is not None:
            _fig.savefig(savefile)
        return _fig
# also get the sps and model objects. This works if using a parameter file with
# `build_*` methods
sps = reader.get_sps(result)
model = reader.get_model(result)

# print the contents of the `results` dictionary
if verbose:
    print(result.keys())

# STEP 1: invetigate the parameter traces
if plots:
    if results_type == 'emcee':
        chosen = np.random.choice(result['run_params']['nwalkers'],
                                  size=10,
                                  replace=False)
        tracefig = reader.traceplot(result, figsize=(16, 9), chains=chosen)
    else:
        tracefig = reader.traceplot(result, figsize=(16, 9))

# STEP 2: create corner plots
imax = np.argmax(result['lnprobability'])

if results_type == 'emcee':
    i, j = np.unravel_index(imax, result['lnprobability'].shape)
    theta_max = result['chain'][i, j, :].copy()
    thin = 5
else:
    theta_max = result['chain'][imax, :]
    thin = 1

if verbose:
Beispiel #3
0
def viewer(file_name):
    import time, sys, os
    import h5py
    import numpy as np
    import scipy
    from matplotlib.pyplot import *
    import matplotlib.pyplot as plt
    import fsps
    import sedpy
    import prospect
    import emcee
    import astropy
    import math
    from func import *
    import prospect.io.read_results as reader
    results_type = "emcee"  # | "dynesty"
    # grab results (dictionary), the obs dictionary, and our corresponding models
    # When using parameter files set `dangerous=True`
    tem_name = file_name[:-8] + '{}.h5'
    #result, obs, _ = reader.results_from(tem_name.format(results_type), dangerous=False)
    result, obs, _ = reader.results_from(file_name, dangerous=False)

    #The following commented lines reconstruct the model and sps object,
    # if a parameter file continaing the `build_*` methods was saved along with the results
    #model = reader.get_model(result)
    #sps = reader.get_sps(result)

    # let's look at what's stored in the `result` dictionary
    print(result.keys())

    if results_type == "emcee":
        chosen = np.random.choice(result["run_params"]["nwalkers"],
                                  size=10,
                                  replace=False)
        tracefig = reader.traceplot(result, figsize=(20, 10), chains=chosen)
    else:
        tracefig = reader.traceplot(result, figsize=(20, 10))

    # maximum a posteriori (of the locations visited by the MCMC sampler)
    imax = np.argmax(result['lnprobability'])
    if results_type == "emcee":
        i, j = np.unravel_index(imax, result['lnprobability'].shape)
        theta_max = result['chain'][i, j, :].copy()
        thin = 5
    else:
        theta_max = result["chain"][imax, :]
        thin = 1

    print('MAP value: {}'.format(theta_max))
    cornerfig = reader.subcorner(result,
                                 start=0,
                                 thin=thin,
                                 fig=subplots(15, 15, figsize=(27, 27))[0])

    # --- Draw final fitting curve ---

    run_params = result['run_params']
    print(run_params)
    model = build_model(**run_params)
    print(model)
    sps = build_sps(**run_params)

    a = 1.0 + model.params.get('zred', 0.0)  # cosmological redshifting
    # photometric effective wavelengths
    wphot = obs["phot_wave"]
    # spectroscopic wavelengths
    if obs["wavelength"] is None:
        # *restframe* spectral wavelengths, since obs["wavelength"] is None
        wspec = sps.wavelengths
        wspec *= a  #redshift them
    else:
        wspec = obs["wavelength"]

    # Get enssential data to calculate sfr
    z_fraction = theta_max[5:10]
    total_mass = theta_max[0]
    agebins = model.params['agebins']
    x = np.zeros(6)
    for i in range(6):
        if i == 5:
            x[i] = (agebins[i][0] + agebins[i][1]) / 2
        else:
            x[i] = (agebins[i][0] + agebins[i + 1][0]) / 2

    sfr = prospect.models.transforms.zfrac_to_sfr(total_mass, z_fraction,
                                                  agebins)

    # Calculate the 16% and 84% value from emcee results
    z_fraction1 = []
    z_fraction2 = []
    z_fraction3 = []
    z_fraction4 = []
    z_fraction5 = []
    for i in range(30):
        for j in range(3000):
            z_fraction1.append(result['chain'][i][j][5])
            z_fraction2.append(result['chain'][i][j][6])
            z_fraction3.append(result['chain'][i][j][7])
            z_fraction4.append(result['chain'][i][j][8])
            z_fraction5.append(result['chain'][i][j][9])

    zerr_1 = [np.percentile(z_fraction1, 16), np.percentile(z_fraction1, 84)]
    zerr_2 = [np.percentile(z_fraction2, 16), np.percentile(z_fraction2, 84)]
    zerr_3 = [np.percentile(z_fraction3, 16), np.percentile(z_fraction3, 84)]
    zerr_4 = [np.percentile(z_fraction4, 16), np.percentile(z_fraction4, 84)]
    zerr_5 = [np.percentile(z_fraction5, 16), np.percentile(z_fraction5, 84)]
    # Build upper and lower z_fraction array
    z_max = np.zeros(5)
    z_min = np.zeros(5)
    for i in range(5):
        z_min[i] = eval('zerr_{}[0]'.format(i + 1))
        z_max[i] = eval('zerr_{}[1]'.format(i + 1))
    #print(z_min)
    #print(z_max)

    # Build new sfr
    sfr_max = prospect.models.transforms.zfrac_to_sfr(total_mass, z_max,
                                                      agebins)
    sfr_min = prospect.models.transforms.zfrac_to_sfr(total_mass, z_min,
                                                      agebins)

    # randomly chosen parameters from chain
    randint = np.random.randint
    if results_type == "emcee":
        nwalkers, niter = run_params['nwalkers'], run_params['niter']
        # Draw 100 random plots from mcmc
        figure(figsize=(16, 16))
        ax = plt.subplot(211)
        for i in range(100):
            # Get data from any random chain
            theta = result['chain'][randint(nwalkers), randint(niter)]
            mspec_t, mphot_t, mextra = model.mean_model(theta, obs, sps=sps)

            # unit conversion to erg/cm^2/s
            mspec = (mspec_t * 1e-23) * 3e18 / wspec
            mphot = (mphot_t * 1e-23) * 3e18 / wphot

            # plot them out
            loglog(wspec, mspec, lw=0.7, color='grey', alpha=0.3)
    else:
        theta = result["chain"][randint(len(result["chain"]))]

    # now do it again for best fit model
    # sps = reader.get_sps(result)  # this works if using parameter files
    mspec_map_t, mphot_map_t, _ = model.mean_model(theta_max, obs, sps=sps)
    # units conversion to erg/cm^2/s
    mspec_map = (mspec_map_t * 1e-23) * 3e18 / wspec
    mphot_map = (mphot_map_t * 1e-23) * 3e18 / wphot
    ob = (obs['maggies'] * 1e-23) * 3e18 / wphot
    ob_unc = (obs['maggies_unc'] * 1e-23) * 3e18 / wphot

    # calculate reduced chi^2
    chi = np.float128(0)
    for i in range(len(wphot)):
        var = ob_unc[i]
        chi += np.float128((mphot_map[i] - ob[i])**2) / var**2

    # Make plot of best fit model
    loglog(wspec,
           mspec_map,
           label='Model spectrum (MAP)',
           lw=0.7,
           color='green',
           alpha=0.7)
    errorbar(wphot,
             mphot_map,
             label='Model photometry (MAP)',
             marker='s',
             markersize=10,
             alpha=0.8,
             ls='',
             lw=3,
             markerfacecolor='none',
             markeredgecolor='green',
             markeredgewidth=3)
    errorbar(wphot,
             ob,
             yerr=ob_unc,
             label='Observed photometry',
             ecolor='red',
             marker='o',
             markersize=10,
             ls='',
             lw=3,
             alpha=0.8,
             markerfacecolor='none',
             markeredgecolor='red',
             markeredgewidth=3)
    text(0,
         1,
         'Chi-squared/N-phot =' + str(chi / len(wphot)),
         horizontalalignment='center',
         verticalalignment='center',
         transform=ax.transAxes)
    # Setup bound
    xmin, xmax = np.min(wphot) * 0.6, np.max(wphot) / 0.8
    temp = np.interp(np.linspace(xmin, xmax, 10000), wphot, mphot_map)
    ymin, ymax = temp.min() * 0.8, temp.max() * 10
    xlabel('Wavelength [A]', fontsize=20)
    ylabel('Flux Density [erg/cm^2/s]', fontsize=20)
    xlim([xmin, xmax])
    ylim([ymin, ymax])
    legend(loc='lower right', fontsize=15)
    tight_layout()
    #  plt.show()

    # plot sfr on the same canvas
    from mpl_toolkits.axes_grid.inset_locator import inset_axes
    in_axes = inset_axes(
        ax,
        width="25%",  # width = 30% of parent_bbox
        height=2,  # height : 1 inch
        loc='upper center')
    in_axes.scatter(10**(x - 9), sfr)
    #plt.fill_between(10**(x-9), sfr_min, sfr_max)
    xlabel('Age [Gyr]', fontsize=10)
    ylabel('SFR [M_sun/yr]', fontsize=10)
    #plt.xscale('log')
    plt.yscale('log')

    # plot residue as subplot
    figure(figsize=(16, 8))
    plt.subplot(212, sharex=ax)
    import pylab
    residue = abs(mphot_map - ob)
    scatter(wphot, abs(mphot_map - ob), label='Residue', lw=2, alpha=0.8)
    plt.xscale('log')
    plt.yscale('log')
    xmin, xmax = np.min(wphot) * 0.8, np.max(wphot) / 0.8
    temp = np.interp(np.linspace(xmin, xmax, 10000), wphot, residue)
    ymin, ymax = temp.min() * 0.1, temp.max() / 0.8
    xlabel('Wavelength [A]', fontsize=20)
    ylabel('Flux Change [erg/cm^2/s]', fontsize=20)
    xlim([xmin, xmax])
    ylim([ymin, ymax])
    legend(loc='best', fontsize=15)
    tight_layout()
    return
Beispiel #4
0
def main():

    vers = (np.__version__, scipy.__version__, h5py.__version__,
            fsps.__version__, prospect.__version__)
    print(
        "Numpy: {}\nScipy: {}\nH5PY: {}\nFSPS: {}\nProspect: {}".format(*vers))

    # And we will store some meta-parameters that control the input arguments to this method:
    run_params = {}
    run_params["snr"] = 10.0
    run_params["ldist"] = 10.0

    # Build the obs dictionary using the meta-parameters
    obs = build_obs(**run_params)

    # Look at the contents of the obs dictionary
    print("Obs Dictionary Keys:\n\n{}\n".format(obs.keys()))
    print("--------\nFilter objects:\n")
    print(obs["filters"])

    # --- Plot the Data ----
    """
    # This is why we stored these...
    wphot = obs["phot_wave"]

    # establish bounds
    xmin, xmax = np.min(wphot)*0.8, np.max(wphot)/0.8
    ymin, ymax = obs["maggies"].min()*0.8, obs["maggies"].max()/0.4

    fig = plt.figure(figsize=(10,5))
    ax = fig.add_subplot(111)

    # plot all the data
    ax.plot(wphot, obs['maggies'],
         label='All observed photometry',
         marker='o', markersize=12, alpha=0.8, ls='', lw=3,
         color='slateblue')

    # overplot only the data we intend to fit
    mask = obs["phot_mask"]
    ax.errorbar(wphot[mask], obs['maggies'][mask], 
             yerr=obs['maggies_unc'][mask], 
             label='Photometry to fit',
             marker='o', markersize=8, alpha=0.8, ls='', lw=3,
             ecolor='tomato', markerfacecolor='none', markeredgecolor='tomato', 
             markeredgewidth=3)

    # plot Filters
    for f in obs['filters']:
        w, t = f.wavelength.copy(), f.transmission.copy()
        t = t / t.max()
        t = 10**(0.2*(np.log10(ymax/ymin)))*t * ymin
        ax.loglog(w, t, lw=3, color='gray', alpha=0.7)

    # prettify
    ax.set_xlabel('Wavelength [A]')
    ax.set_ylabel('Flux Density [maggies]')
    ax.set_xlim([xmin, xmax])
    ax.set_ylim([ymin, ymax])
    ax.set_xscale("log")
    ax.set_yscale("log")
    ax.legend(loc='best', fontsize=20)
    fig.tight_layout()

    plt.show()
    """
    # ----------------------------

    from prospect.models import priors
    mass_param = {
        "name": "mass",
        # The mass parameter here is a scalar, so it has N=1
        "N": 1,
        # We will be fitting for the mass, so it is a free parameter
        "isfree": True,
        # This is the initial value. For fixed parameters this is the
        # value that will always be used.
        "init": 1e8,
        # This sets the prior probability for the parameter
        "prior": priors.LogUniform(mini=1e6, maxi=1e12),
        # this sets the initial dispersion to use when generating
        # clouds of emcee "walkers".  It is not required, but can be very helpful.
        "init_disp": 1e6,
        # this sets the minimum dispersion to use when generating
        #clouds of emcee "walkers".  It is not required, but can be useful if
        # burn-in rounds leave the walker distribution too narrow for some reason.
        "disp_floor": 1e6,
        # This is not required, but can be helpful
        "units": "solar masses formed",
    }

    from prospect.models.templates import TemplateLibrary

    # Look at all the prepackaged parameter sets
    TemplateLibrary.show_contents()

    # Check a specific model.
    # This shows the defaults and params for the model.
    # parametric_sfh in this case (delayed-tau)
    # This is the one we will use
    TemplateLibrary.describe("parametric_sfh")

    run_params["object_redshift"] = 0.0
    run_params["fixed_metallicity"] = None
    run_params["add_duste"] = True

    model = build_model(**run_params)
    print(model)
    print("\nInitial free parameter vector theta:\n  {}\n".format(model.theta))
    print("Initial parameter dictionary:\n{}".format(model.params))

    run_params["zcontinuous"] = 1

    sps = build_sps(**run_params)

    # Generate the model SED at the initial value of theta
    theta = model.theta.copy()
    initial_spec, initial_phot, initial_mfrac = model.sed(theta,
                                                          obs=obs,
                                                          sps=sps)

    #title_text = ','.join(["{}={}".format(p, model.params[p][0])
    #                       for p in model.free_params])

    a = 1.0 + model.params.get('zred', 0.0)  # cosmological redshifting
    # photometric effective wavelengths
    wphot = obs["phot_wave"]
    # spectroscopic wavelengths
    if obs["wavelength"] is None:
        # *restframe* spectral wavelengths, since obs["wavelength"] is None
        wspec = sps.wavelengths
        wspec *= a  #redshift them
    else:
        wspec = obs["wavelength"]

    # establish bounds
    xmin, xmax = np.min(wphot) * 0.8, np.max(wphot) / 0.8
    temp = np.interp(np.linspace(xmin, xmax, 10000), wspec, initial_spec)
    ymin, ymax = temp.min() * 0.8, temp.max() / 0.4
    """
    fig = plt.figure(figsize=(10,5))
    ax = fig.add_subplot(111)

    # plot model + data
    ax.loglog(wspec, initial_spec, label='Model spectrum', 
           lw=0.7, color='navy', alpha=0.7)
    ax.errorbar(wphot, initial_phot, label='Model photometry', 
             marker='s',markersize=10, alpha=0.8, ls='', lw=3,
             markerfacecolor='none', markeredgecolor='blue', 
             markeredgewidth=3)
    ax.errorbar(wphot, obs['maggies'], yerr=obs['maggies_unc'], 
             label='Observed photometry',
             marker='o', markersize=10, alpha=0.8, ls='', lw=3,
             ecolor='red', markerfacecolor='none', markeredgecolor='red', 
             markeredgewidth=3)
    ax.set_title(title_text)

    # plot Filters
    for f in obs['filters']:
        w, t = f.wavelength.copy(), f.transmission.copy()
        t = t / t.max()
        t = 10**(0.2*(np.log10(ymax/ymin)))*t * ymin
        ax.loglog(w, t, lw=3, color='gray', alpha=0.7)

    # prettify
    ax.set_xlabel('Wavelength [A]')
    ax.set_ylabel('Flux Density [maggies]')
    ax.set_xlim([xmin, xmax])
    ax.set_ylim([ymin, ymax])
    ax.legend(loc='best', fontsize=20)
    fig.tight_layout()

    plt.show()
    """

    verbose = True
    run_params["verbose"] = verbose

    # Here we will run all our building functions
    obs = build_obs(**run_params)
    sps = build_sps(**run_params)
    model = build_model(**run_params)

    # For fsps based sources it is useful to
    # know which stellar isochrone and spectral library
    # we are using
    print(sps.ssp.libraries)

    # --- start minimization ----
    run_params["dynesty"] = False
    run_params["emcee"] = False
    run_params["optimize"] = True
    run_params["min_method"] = 'lm'
    # We'll start minimization from "nmin" separate places,
    # the first based on the current values of each parameter and the
    # rest drawn from the prior.  Starting from these extra draws
    # can guard against local minima, or problems caused by
    # starting at the edge of a prior (e.g. dust2=0.0)
    run_params["nmin"] = 2

    output = fit_model(obs, model, sps, lnprobfn=lnprobfn, **run_params)

    print("Done optmization in {}s".format(output["optimization"][1]))

    print(model.theta)
    (results, topt) = output["optimization"]
    # Find which of the minimizations gave the best result,
    # and use the parameter vector for that minimization
    ind_best = np.argmin([r.cost for r in results])
    print(ind_best)
    theta_best = results[ind_best].x.copy()
    print(theta_best)

    # generate model
    prediction = model.mean_model(theta_best, obs=obs, sps=sps)
    pspec, pphot, pfrac = prediction
    """
    fig = plt.figure(figsize=(10,5))
    ax = fig.add_subplot(111)
    
    # plot Data, best fit model, and old models
    ax.loglog(wspec, initial_spec, label='Old model spectrum',
           lw=0.7, color='gray', alpha=0.5)
    ax.errorbar(wphot, initial_phot, label='Old model Photometry', 
             marker='s', markersize=10, alpha=0.6, ls='', lw=3, 
             markerfacecolor='none', markeredgecolor='gray', 
             markeredgewidth=3)
    ax.loglog(wspec, pspec, label='Model spectrum', 
           lw=0.7, color='slateblue', alpha=0.7)
    ax.errorbar(wphot, pphot, label='Model photometry', 
             marker='s', markersize=10, alpha=0.8, ls='', lw=3,
             markerfacecolor='none', markeredgecolor='slateblue', 
             markeredgewidth=3)
    ax.errorbar(wphot, obs['maggies'], yerr=obs['maggies_unc'],
             label='Observed photometry', 
             marker='o', markersize=10, alpha=0.8, ls='', lw=3, 
             ecolor='tomato', markerfacecolor='none', markeredgecolor='tomato', 
             markeredgewidth=3)

    # plot filter transmission curves
    for f in obs['filters']:
        w, t = f.wavelength.copy(), f.transmission.copy()
        t = t / t.max()
        t = 10**(0.2*(np.log10(ymax/ymin)))*t * ymin
        ax.loglog(w, t, lw=3, color='gray', alpha=0.7)

    # Prettify
    ax.set_xlabel('Wavelength [A]')
    ax.set_ylabel('Flux Density [maggies]')
    ax.set_xlim([xmin, xmax])
    ax.set_ylim([ymin, ymax])
    ax.legend(loc='best', fontsize=20)
    fig.tight_layout()

    plt.show()
    """

    # Set this to False if you don't want to do another optimization
    # before emcee sampling (but note that the "optimization" entry
    # in the output dictionary will be (None, 0.) in this case)
    # If set to true then another round of optmization will be performed
    # before sampling begins and the "optmization" entry of the output
    # will be populated.
    run_params["optimize"] = False
    run_params["emcee"] = True
    run_params["dynesty"] = False
    # Number of emcee walkers
    run_params["nwalkers"] = 128
    # Number of iterations of the MCMC sampling
    run_params["niter"] = 512
    # Number of iterations in each round of burn-in
    # After each round, the walkers are reinitialized based on the
    # locations of the highest probablity half of the walkers.
    run_params["nburn"] = [16, 32, 64]

    print("Now running with Emcee.")

    output = fit_model(obs, model, sps, lnprobfn=lnprobfn, **run_params)
    print('done emcee in {0}s'.format(output["sampling"][1]))

    hfile = "demo_emcee_mcmc.h5"
    writer.write_hdf5(hfile,
                      run_params,
                      model,
                      obs,
                      output["sampling"][0],
                      output["optimization"][0],
                      tsample=output["sampling"][1],
                      toptimize=output["optimization"][1])

    print('Finished')

    # -------------------
    print("Now running with Dynesty.")

    run_params["dynesty"] = True
    run_params["optmization"] = False
    run_params["emcee"] = False
    run_params["nested_method"] = "rwalk"
    run_params["nlive_init"] = 400
    run_params["nlive_batch"] = 200
    run_params["nested_dlogz_init"] = 0.05
    run_params["nested_posterior_thresh"] = 0.05
    run_params["nested_maxcall"] = int(1e7)

    output = fit_model(obs, model, sps, lnprobfn=lnprobfn, **run_params)
    print('done dynesty in {0}s'.format(output["sampling"][1]))

    hfile = "demo_dynesty_mcmc.h5"
    writer.write_hdf5(hfile,
                      run_params,
                      model,
                      obs,
                      output["sampling"][0],
                      output["optimization"][0],
                      tsample=output["sampling"][1],
                      toptimize=output["optimization"][1])

    print('Finished')

    # -------------------------
    # Visualizing results

    results_type = "dynesty"  # "emcee" | "dynesty"
    # grab results (dictionary), the obs dictionary, and our corresponding models
    # When using parameter files set `dangerous=True`
    result, obs, _ = reader.results_from(
        "demo_{}_mcmc.h5".format(results_type), dangerous=False)

    #The following commented lines reconstruct the model and sps object,
    # if a parameter file continaing the `build_*` methods was saved along with the results
    #model = reader.get_model(result)
    #sps = reader.get_sps(result)

    # let's look at what's stored in the `result` dictionary
    print(result.keys())

    if results_type == "emcee":
        chosen = np.random.choice(result["run_params"]["nwalkers"],
                                  size=10,
                                  replace=False)
        tracefig = reader.traceplot(result, figsize=(20, 10), chains=chosen)
    else:
        tracefig = reader.traceplot(result, figsize=(20, 10))

    # maximum a posteriori (of the locations visited by the MCMC sampler)
    imax = np.argmax(result['lnprobability'])
    if results_type == "emcee":
        i, j = np.unravel_index(imax, result['lnprobability'].shape)
        theta_max = result['chain'][i, j, :].copy()
        thin = 5
    else:
        theta_max = result["chain"][imax, :]
        thin = 1

    print('Optimization value: {}'.format(theta_best))
    print('MAP value: {}'.format(theta_max))
    cornerfig = reader.subcorner(result,
                                 start=0,
                                 thin=thin,
                                 truths=theta_best,
                                 fig=plt.subplots(5, 5, figsize=(8, 8))[0])

    plt.show()

    return None
Beispiel #5
0
# let's look at what's stored in the `res` dictionary
print('-------')
print('Stored info:')
print(res.keys())
print('')
if 'mock' in outroot:
    theta_input = np.squeeze(
        np.array([obs["mock_params"][p] for p in res['theta_labels']]))
    print(theta_input)
    #Parameter Traces
    chosen = np.random.choice(run_params["nwalkers"], size=10, replace=False)
else:
    theta_input = None
    chosen = np.random.choice(run_params["nwalkers"], size=10, replace=False)
tracefig = traceplot(res, figsize=(20, 10), chains=chosen)
savefig(outroot + '_parameter_traces.png')

# Conerplot

# Maximum Likelihood (of the locations visited by the MCMC sampler)
imax = np.argmax(res['lnprobability'])
i, j = np.unravel_index(imax, res['lnprobability'].shape)
theta_max = res['chain'][i, j, :].copy()
n_param = len(theta_max)
size = int(n_param * n_param) + 2

print('Max Likelihood value: {}'.format(theta_max))
cornerfig = subcorner(res,
                      start=0,
                      thin=5,
Beispiel #6
0
def run_prospector(name_z):
    import time, sys, os
    import h5py
    import numpy as np
    import scipy
    from matplotlib.pyplot import *
    #%matplotlib inline
    import fsps
    import sedpy
    import prospect
    import emcee
    import astropy
    import math
    from prospect.fitting import fit_model
    from prospect.fitting import lnprobfn
    from func import *
    import matplotlib.pyplot as plt

    # --- Output files ---
    name = name_z[0]
    z = name_z[1]
    path_input = '/home/kk/work/data/red_magic/' + name
    path = '/home/kk/work/result/red_magic/' + name[:-4]
    '''try:
        os.mkdir(path)
    except:
        pass

    fe = open(path+'/para.txt','w')'''

    # --- Set up the essential parameter ---
    data_list = [
        'sdss_u', 'sdss_g', 'sdss_r', 'sdss_i', 'galex_fuv', 'galex_nuv',
        'pan-starrs_ps1_i', 'pan-starrs_ps1_r', 'pan-starrs_ps1_g',
        'pan-starrs_ps1_y', 'pan-starrs_ps1_z', 'sdss_z', 'ukidss_j',
        'ukidss_h', 'ukidss_k', 'wise_w1', 'spitzer_irac_3.6', '_=3.6um',
        'spitzer_irac_4.5', '_=4.5um', 'wise_w2', 'spitzer_irac_5.8',
        'spitzer_irac_8.0', 'wise_w3', 'wise_w4', 'spitzer_mips_24', '2mass_h',
        '2mass_ks', '2mass_j', 'gaia_gaia2_gbp', 'gaia_gaia2_g',
        'gaia_gaia2_grp', 'gaia_g', 'ukidss_y', 'vista_j', 'vista_h',
        'vista_ks'
    ]
    run_params = {}
    run_params["snr"] = 10.0
    run_params["object_redshift"] = z
    run_params["fixed_metallicity"] = None
    run_params["add_duste"] = True

    # --- Start build up the model ---
    fit_data = load_data(path_input, data_list)
    obs = build_obs(fit_data, **run_params)
    sps = build_sps(**run_params)
    model = build_model(**run_params)

    #fe.write(str(obs))
    #print(fit_data)
    # --- Draw initial data plot ---

    wphot = obs["phot_wave"]

    # establish bounds
    xmin, xmax = np.min(wphot) * 0.8, np.max(wphot) / 0.8
    ymin, ymax = obs["maggies"].min() * 0.8, obs["maggies"].max() / 0.4
    figure(figsize=(16, 8))

    # plot all the data
    plot(wphot,
         obs['maggies'],
         label='All observed photometry',
         marker='o',
         markersize=12,
         alpha=0.8,
         ls='',
         lw=3,
         color='slateblue')

    # overplot only the data we intend to fit
    mask = obs["phot_mask"]
    errorbar(wphot[mask],
             obs['maggies'][mask],
             yerr=obs['maggies_unc'][mask],
             label='Photometry to fit',
             marker='o',
             markersize=8,
             alpha=0.8,
             ls='',
             lw=3,
             ecolor='tomato',
             markerfacecolor='none',
             markeredgecolor='tomato',
             markeredgewidth=3)

    # prettify
    xlabel('Wavelength [A]')
    ylabel('Flux Density [maggies]')
    xlim([xmin, xmax])
    ylim([ymin, ymax])
    xscale("log")
    yscale("log")
    legend(loc='best', fontsize=20)
    #tight_layout()
    #plt.savefig(path+'/input.png')

    # run minimization and emcee with error handling
    condition = False
    while condition is False:
        try:
            # --- start minimization ----
            run_params["dynesty"] = False
            run_params["emcee"] = False
            run_params["optimize"] = True
            run_params["min_method"] = 'lm'
            run_params["nmin"] = 5
            output = fit_model(obs,
                               model,
                               sps,
                               lnprobfn=lnprobfn,
                               **run_params)
            print("Done optmization in {}s".format(output["optimization"][1]))

            # save theta_best for later use
            (results, topt) = output["optimization"]
            ind_best = np.argmin([r.cost for r in results])
            theta_best = results[ind_best].x.copy()

            # --- start emcee ---
            run_params["optimize"] = False
            run_params["emcee"] = True
            run_params["dynesty"] = False
            run_params["nwalkers"] = 30
            run_params["niter"] = 8000
            run_params["nburn"] = [300, 800, 1600]
            output = fit_model(obs,
                               model,
                               sps,
                               lnprobfn=lnprobfn,
                               **run_params)
            print('done emcee in {0}s'.format(output["sampling"][1]))
            condition = True

        # sort out different errors and apply method to proceed
        except AssertionError as e:
            # error: sfr cannot be negative
            if str(e) == 'sfr cannot be negative.':
                obs = build_obs(fit_data, **run_params)
                sps = build_sps(**run_params)
                model = build_model(**run_params)
            # error: number of residules are less than variables
        except ValueError as e:
            if str(
                    e
            ) == "Method 'lm' doesn't work when the number of residuals is less than the number of variables.":
                print(name)
                return
            # error: residule are not finite in the initial point
            elif str(e) == "Residuals are not finite in the initial point.":
                print(name)
                return

    # write final results to file
    from prospect.io import write_results as writer
    hfile = path + '_emcee.h5'
    print(hfile)
    writer.write_hdf5(hfile,
                      run_params,
                      model,
                      obs,
                      output["sampling"][0],
                      output["optimization"][0],
                      tsample=output["sampling"][1],
                      toptimize=output["optimization"][1])
    #fe.write(str(obs))
    print('Finished')

    ##############################################################################

    import prospect.io.read_results as reader
    results_type = "emcee"  # | "dynesty"
    # grab results (dictionary), the obs dictionary, and our corresponding models
    # When using parameter files set `dangerous=True`
    #tem_name = hfile[:-8]+'{}.h5'
    #result, obs, _ = reader.results_from(tem_name.format(results_type), dangerous=False)
    result, obs, _ = reader.results_from(hfile, dangerous=False)
    #The following commented lines reconstruct the model and sps object,                            # if a parameter file continaing the `build_*` methods was saved along with the results
    #model = reader.get_model(result)
    #sps = reader.get_sps(result)
    # let's look at what's stored in the `result` dictionary
    #print(result.keys())

    # Make plot of data and model

    if results_type == "emcee":
        chosen = np.random.choice(result["run_params"]["nwalkers"],
                                  size=10,
                                  replace=False)
        tracefig = reader.traceplot(result, figsize=(20, 10), chains=chosen)
    else:
        tracefig = reader.traceplot(result, figsize=(20, 10))
    #plt.savefig(path+'/trace.png')
    # maximum a posteriori (of the locations visited by the MCMC sampler)
    imax = np.argmax(result['lnprobability'])
    if results_type == "emcee":
        i, j = np.unravel_index(imax, result['lnprobability'].shape)
        theta_max = result['chain'][i, j, :].copy()
        thin = 5
    else:
        theta_max = result["chain"][imax, :]
        thin = 1

    #f.Write('Optimization value: {}'.format(theta_best))
    #fe.write(str('MAP value: {}'.format(theta_max)))
    #fe.close()

    cornerfig = reader.subcorner(result,
                                 start=0,
                                 thin=thin,
                                 truths=theta_best,
                                 fig=subplots(15, 15, figsize=(27, 27))[0])
    #plt.savefig(path+'/corner.png')
    # --- Draw final fitting curve ---

    a = 1.0 + model.params.get('zred', 0.0)  # cosmological redshifting
    # photometric effective wavelengths
    wphot = obs["phot_wave"]
    # spectroscopic wavelengths
    if obs["wavelength"] is None:
        # *restframe* spectral wavelengths, since obs["wavelength"] is None
        wspec = sps.wavelengths
        wspec *= a  #redshift them
    else:
        wspec = obs["wavelength"]

    # Get enssential data to calculate sfr
    z_fraction = theta_max[5:10]
    total_mass = theta_max[0]
    agebins = model.params['agebins']
    x = np.zeros(6)
    for i in range(6):
        if i == 5:
            x[i] = (agebins[i][0] + agebins[i][1]) / 2
        else:
            x[i] = (agebins[i][0] + agebins[i + 1][0]) / 2

    sfr = prospect.models.transforms.zfrac_to_sfr(total_mass, z_fraction,
                                                  agebins)

    # Calculate the 16% and 84% value from emcee results
    z_fraction1 = []
    z_fraction2 = []
    z_fraction3 = []
    z_fraction4 = []
    z_fraction5 = []
    for i in range(30):
        for j in range(3000):
            z_fraction1.append(result['chain'][i][j][5])
            z_fraction2.append(result['chain'][i][j][6])
            z_fraction3.append(result['chain'][i][j][7])
            z_fraction4.append(result['chain'][i][j][8])
            z_fraction5.append(result['chain'][i][j][9])

    zerr_1 = [np.percentile(z_fraction1, 16), np.percentile(z_fraction1, 84)]
    zerr_2 = [np.percentile(z_fraction2, 16), np.percentile(z_fraction2, 84)]
    zerr_3 = [np.percentile(z_fraction3, 16), np.percentile(z_fraction3, 84)]
    zerr_4 = [np.percentile(z_fraction4, 16), np.percentile(z_fraction4, 84)]
    zerr_5 = [np.percentile(z_fraction5, 16), np.percentile(z_fraction5, 84)]
    # Build upper and lower z_fraction array
    z_max = np.zeros(5)
    z_min = np.zeros(5)
    for i in range(5):
        z_min[i] = eval('zerr_{}[0]'.format(i + 1))
        z_max[i] = eval('zerr_{}[1]'.format(i + 1))
    #print(z_min)
    #print(z_max)

    # Build new sfr
    sfr_max = prospect.models.transforms.zfrac_to_sfr(total_mass, z_max,
                                                      agebins)
    sfr_min = prospect.models.transforms.zfrac_to_sfr(total_mass, z_min,
                                                      agebins)

    # randomly chosen parameters from chain
    randint = np.random.randint
    if results_type == "emcee":
        nwalkers, niter = run_params['nwalkers'], run_params['niter']
        # Draw 100 random plots from mcmc
        figure(figsize=(16, 16))
        ax = plt.subplot(211)
        for i in range(100):
            # Get data from any random chain
            theta = result['chain'][randint(nwalkers), randint(niter)]
            mspec_t, mphot_t, mextra = model.mean_model(theta, obs, sps=sps)

            # unit conversion to erg/cm^2/s
            mspec = (mspec_t * 1e-23) * 3e18 / wspec
            mphot = (mphot_t * 1e-23) * 3e18 / wphot

            # plot them out
            loglog(wspec, mspec, lw=0.7, color='grey', alpha=0.3)
    else:
        theta = result["chain"][randint(len(result["chain"]))]

    # now do it again for best fit model
    # sps = reader.get_sps(result)  # this works if using parameter files
    mspec_map_t, mphot_map_t, _ = model.mean_model(theta_max, obs, sps=sps)
    # units conversion to erg/cm^2/s
    mspec_map = (mspec_map_t * 1e-23) * 3e18 / wspec
    mphot_map = (mphot_map_t * 1e-23) * 3e18 / wphot
    ob = (obs['maggies'] * 1e-23) * 3e18 / wphot
    ob_unc = (obs['maggies_unc'] * 1e-23) * 3e18 / wphot

    # calculate reduced chi^2
    chi = 0
    for i in range(len(wphot)):
        var = ob_unc[i]
        chi += (mphot_map[i] - ob[i])**2 / var**2

    # Make plot of best fit model
    loglog(wspec,
           mspec_map,
           label='Model spectrum (MAP)',
           lw=0.7,
           color='green',
           alpha=0.7)
    errorbar(wphot,
             mphot_map,
             label='Model photometry (MAP)',
             marker='s',
             markersize=10,
             alpha=0.8,
             ls='',
             lw=3,
             markerfacecolor='none',
             markeredgecolor='green',
             markeredgewidth=3)
    errorbar(wphot,
             ob,
             yerr=ob_unc,
             label='Observed photometry',
             ecolor='red',
             marker='o',
             markersize=10,
             ls='',
             lw=3,
             alpha=0.8,
             markerfacecolor='none',
             markeredgecolor='red',
             markeredgewidth=3)
    text(0,
         1,
         'Chi-squared/Nphot =' + str(chi / len(wphot)),
         horizontalalignment='center',
         verticalalignment='center',
         transform=ax.transAxes)
    # Setup bound
    xmin, xmax = np.min(wphot) * 0.6, np.max(wphot) / 0.8
    temp = np.interp(np.linspace(xmin, xmax, 10000), wphot, mphot_map)
    ymin, ymax = temp.min() * 0.8, temp.max() * 10
    xlabel('Wavelength [A]', fontsize=20)
    ylabel('Flux Density [erg/cm^2/s]', fontsize=20)
    xlim([xmin, xmax])
    ylim([ymin, ymax])
    legend(loc='lower right', fontsize=15)
    tight_layout()
    #  plt.show()

    # plot sfr on the same canvas
    from mpl_toolkits.axes_grid.inset_locator import inset_axes
    in_axes = inset_axes(
        ax,
        width="25%",  # width = 30% of parent_bbox                            
        height=2,  # height : 1 inch                                          
        loc='upper center')
    in_axes.scatter(10**(x - 9), sfr)
    #plt.fill_between(10**(x-9), sfr_min, sfr_max)
    xlabel('Age [Gyr]', fontsize=10)
    ylabel('SFR [M_sun/yr]', fontsize=10)
    #plt.xscale('log')
    plt.yscale('log')
    plt.savefig(path + '_fitting.png')
    # plot residue as subplot

    figure(figsize=(16, 8))
    plt.subplot(212, sharex=ax)
    import pylab
    residue = abs(mphot_map - ob)
    scatter(wphot, abs(mphot_map - ob), label='Residue', lw=2, alpha=0.8)
    plt.xscale('log')
    plt.yscale('log')
    xmin, xmax = np.min(wphot) * 0.8, np.max(wphot) / 0.8
    temp = np.interp(np.linspace(xmin, xmax, 10000), wphot, residue)
    ymin, ymax = temp.min() * 0.1, temp.max() / 0.8
    xlabel('Wavelength [A]', fontsize=20)
    ylabel('Flux Change [erg/cm^2/s]', fontsize=20)
    xlim([xmin, xmax])
    ylim([ymin, ymax])
    legend(loc='best', fontsize=15)
    tight_layout()