예제 #1
0
 def test_parametric(self):
     profile = Profile()
     P0 = np.min(profile.pressures)
     T0 = 1300
     P1 = 1e-3
     alpha1 = 0.3
     alpha2 = 0.5
     P3 = 1e4
     T3 = 2000
     P2, T2 = profile.set_parametric(T0, P1, alpha1, alpha2, P3, T3)
     self.assertTrue(
         abs(P3 - P2 * np.exp(alpha2 * (T3 - T2)**0.5)) < 1e-3 * P3)
     T1 = np.log(P1 / P0)**2 / alpha1**2 + T0
     self.assertTrue(
         abs(P1 - P0 * np.exp(alpha1 * (T1 - T0)**0.5)) < 1e-3 * P1)
     self.assertTrue(
         abs(P1 - P2 * np.exp(-alpha2 * (T1 - T2)**0.5)) < 1e-3 * P1)
    def test_isothermal(self):
        Ts = 5700
        Tp = 1500
        p = Profile()
        p.set_isothermal(Tp)
        calc = EclipseDepthCalculator()
        wavelengths, depths, info_dict = calc.compute_depths(p,
                                                             R_sun,
                                                             M_jup,
                                                             R_jup,
                                                             Ts,
                                                             full_output=True)

        blackbody = np.pi * 2 * h * c**2 / wavelengths**5 / (
            np.exp(h * c / wavelengths / k_B / Tp) - 1)

        rel_diffs = (info_dict["planet_spectrum"] - blackbody) / blackbody

        plt.loglog(1e6 * wavelengths, 1e-3 * blackbody, label="Blackbody")
        plt.loglog(1e6 * wavelengths,
                   1e-3 * info_dict["planet_spectrum"],
                   label="PLATON")
        plt.xlabel("Wavelength (micron)", fontsize=12)
        plt.ylabel("Planet flux (erg/s/cm$^2$/micron)", fontsize=12)
        plt.legend()
        plt.tight_layout()
        plt.figure()
        plt.semilogx(1e6 * wavelengths, 100 * rel_diffs)
        plt.xlabel("Wavelength (micron)", fontsize=12)
        plt.ylabel("Relative difference (%)", fontsize=12)
        plt.tight_layout()
        plt.show()

        # Should be exact, but in practice isn't, due to our discretization
        self.assertLess(np.percentile(np.abs(rel_diffs), 50), 0.02)
        self.assertLess(np.percentile(np.abs(rel_diffs), 99), 0.05)
        self.assertLess(np.max(np.abs(rel_diffs)), 0.1)

        blackbody_star = np.pi * 2 * h * c**2 / wavelengths**5 / (
            np.exp(h * c / wavelengths / k_B / Ts) - 1)
        approximate_depths = blackbody / blackbody_star * (R_jup / R_sun)**2
        # Not expected to be very accurate because the star is not a blackbody
        self.assertLess(
            np.median(
                np.abs(approximate_depths - depths) / approximate_depths), 0.2)
    def test_ktables_unbinned(self):
        profile = Profile()
        profile.set_from_radiative_solution(5052, 0.75 * R_sun, 0.03142 * AU,
                                            1.129 * M_jup, 1.115 * R_jup,
                                            0.983, -1.77, -0.44, -0.56, 0.23)
        xsec_calc = EclipseDepthCalculator(method="xsec")
        ktab_calc = EclipseDepthCalculator(method="ktables")
        xsec_wavelengths, xsec_depths = xsec_calc.compute_depths(
            profile, 0.75 * R_sun, 1.129 * M_jup, 1.115 * R_jup, 5052)
        N = 10
        smoothed_xsec_wavelengths = uniform_filter(xsec_wavelengths, N)[::N]
        smoothed_xsec_depths = uniform_filter(xsec_depths, N)[::N]

        ktab_wavelengths, ktab_depths = ktab_calc.compute_depths(
            profile, 0.75 * R_sun, 1.129 * M_jup, 1.115 * R_jup, 5052)
        rel_diffs = np.abs(ktab_depths -
                           smoothed_xsec_depths[:-1]) / ktab_depths
        self.assertTrue(np.median(rel_diffs) < 0.05)
예제 #4
0
    def test_radiative_solution(self):
        p = Profile()

        # Parameters from Table 1 of http://iopscience.iop.org/article/10.1088/0004-637X/775/2/137/pdf
        p.set_from_radiative_solution(5040, 0.756 * R_sun,
                                      0.031 * AU, 0.885 * M_jup, R_jup, 1,
                                      np.log10(3e-3), np.log10(1.58e-1),
                                      np.log10(1.58e-1), 0.5, 100)

        # Compare to Figure 2 of aforementioned paper
        is_upper_atm = np.logical_and(p.pressures > 0.1, p.pressures < 1e3)
        self.assertTrue(np.all(p.temperatures[is_upper_atm] > 1000))
        self.assertTrue(np.all(p.temperatures[is_upper_atm] < 1100))

        is_lower_atm = np.logical_and(p.pressures > 1e5, p.pressures < 3e6)
        self.assertTrue(np.all(p.temperatures[is_lower_atm] > 1600))
        self.assertTrue(np.all(p.temperatures[is_lower_atm] < 1700))

        self.assertTrue(np.all(np.diff(p.temperatures) > 0))
    def test_ktables_binned(self):
        wavelengths = np.exp(np.arange(np.log(0.31e-6), np.log(29e-6),
                                       1. / 20))
        wavelengths = np.append(wavelengths[0:20], wavelengths[50:90])
        wavelength_bins = np.array([wavelengths[0:-1], wavelengths[1:]]).T

        profile = Profile()
        profile.set_from_radiative_solution(5052, 0.75 * R_sun, 0.03142 * AU,
                                            1.129 * M_jup, 1.115 * R_jup,
                                            0.983, -1.77, -0.44, -0.56, 0.23)
        xsec_calc = EclipseDepthCalculator(method="xsec")
        xsec_calc.change_wavelength_bins(wavelength_bins)
        ktab_calc = EclipseDepthCalculator(method="ktables")
        ktab_calc.change_wavelength_bins(wavelength_bins)
        xsec_wavelengths, xsec_depths = xsec_calc.compute_depths(
            profile, 0.75 * R_sun, 1.129 * M_jup, 1.115 * R_jup, 5052)
        ktab_wavelengths, ktab_depths = ktab_calc.compute_depths(
            profile, 0.75 * R_sun, 1.129 * M_jup, 1.115 * R_jup, 5052)
        rel_diffs = np.abs(ktab_depths - xsec_depths) / ktab_depths
        self.assertTrue(np.median(rel_diffs) < 0.03)
        self.assertTrue(np.percentile(rel_diffs, 95) < 0.15)
        self.assertTrue(np.max(rel_diffs) < 0.2)
        '''print(np.median(rel_diffs), np.percentile(rel_diffs, 95), np.max(rel_diffs))
예제 #6
0
    def test_set_opacity(self):
        # Can't easily test whether this is "right", but at least make sure it
        # runs
        p = Profile()
        p.set_isothermal(1200)

        calc = EclipseDepthCalculator()
        wavelengths, depths, info_dict = calc.compute_depths(p,
                                                             R_sun,
                                                             M_jup,
                                                             R_jup,
                                                             5700,
                                                             full_output=True)
        p.set_from_opacity(1700, info_dict)
        self.assertTrue(np.all(p.temperatures > 0))
        self.assertTrue(np.all(~np.isnan(p.temperatures)))
예제 #7
0
import matplotlib.pyplot as plt
import numpy as np

from platon.constants import h, c, k_B, R_jup, M_jup, R_sun
from platon.eclipse_depth_calculator import EclipseDepthCalculator
from platon.TP_profile import Profile

edges = np.linspace(1.1e-6, 1.7e-6, 30)
bins = np.array([edges[0:-1], edges[1:]]).T

p = Profile()
p.set_parametric(1200, 500, 0.5, 0.6, 1e6, 1900)
#p.set_isothermal(1500)
calc = EclipseDepthCalculator()
#calc.change_wavelength_bins(bins)

wavelengths, depths, info_dict = calc.compute_depths(p,
                                                     R_sun,
                                                     M_jup,
                                                     R_jup,
                                                     5700,
                                                     full_output=True)
plt.semilogy(p.temperatures, p.pressures)
plt.xlabel("Temperature (K)")
plt.ylabel("Pressure (Pa)")
plt.figure()

plt.loglog(1e6 * wavelengths, 1e6 * depths)
plt.xlabel("Wavelength ($\mu m$)")
plt.ylabel("Eclipse depth (ppm)")
plt.show()
    def _ln_like(self,
                 params,
                 transit_calc,
                 eclipse_calc,
                 fit_info,
                 measured_transit_depths,
                 measured_transit_errors,
                 measured_eclipse_depths,
                 measured_eclipse_errors,
                 plot=False):

        if not fit_info._within_limits(params):
            return -np.inf

        params_dict = fit_info._interpret_param_array(params)

        Rp = params_dict["Rp"]
        T = params_dict["T"]
        logZ = params_dict["logZ"]
        CO_ratio = params_dict["CO_ratio"]
        scatt_factor = 10.0**params_dict["log_scatt_factor"]
        scatt_slope = params_dict["scatt_slope"]
        cloudtop_P = 10.0**params_dict["log_cloudtop_P"]
        error_multiple = params_dict["error_multiple"]
        Rs = params_dict["Rs"]
        Mp = params_dict["Mp"]
        T_star = params_dict["T_star"]
        T_spot = params_dict["T_spot"]
        spot_cov_frac = params_dict["spot_cov_frac"]
        frac_scale_height = params_dict["frac_scale_height"]
        number_density = 10.0**params_dict["log_number_density"]
        part_size = 10.0**params_dict["log_part_size"]
        ri = params_dict["ri"]
        """
        adding cloud fraction
        """
        cloud_fraction = params_dict["cloud_fraction"]
        if cloud_fraction < 0. or cloud_fraction > 1.:
            return -np.inf
        """ Add offset """

        offset = params_dict["offset"]
        offset2 = params_dict["offset2"]
        #offset3=params_dict["offset3"]

        #measured_transit_depths[46:75]+=offset
        """
        Done
        """
        if Rs <= 0 or Mp <= 0:
            return -np.inf

        ln_likelihood = 0
        try:
            if measured_transit_depths is not None:
                if T is None:
                    raise ValueError("Must fit for T if using transit depths")
                transit_wavelengths, calculated_transit_depths, info_dict = transit_calc.compute_depths(
                    Rs,
                    Mp,
                    Rp,
                    T,
                    logZ,
                    CO_ratio,
                    scattering_factor=scatt_factor,
                    scattering_slope=scatt_slope,
                    cloudtop_pressure=cloudtop_P,
                    T_star=T_star,
                    T_spot=T_spot,
                    spot_cov_frac=spot_cov_frac,
                    frac_scale_height=frac_scale_height,
                    number_density=number_density,
                    part_size=part_size,
                    ri=ri,
                    full_output=True)
                """
                computing clear depth
                """
                if cloud_fraction != 1:
                    xxx, clear_calculated_transit_depths, clear_info_dict = transit_calc.compute_depths(
                        Rs,
                        Mp,
                        Rp,
                        T,
                        logZ,
                        CO_ratio,
                        scattering_factor=scatt_factor,
                        scattering_slope=scatt_slope,
                        cloudtop_pressure=10**8,
                        T_star=T_star,
                        T_spot=T_spot,
                        spot_cov_frac=spot_cov_frac,
                        frac_scale_height=frac_scale_height,
                        number_density=number_density,
                        part_size=part_size,
                        ri=ri,
                        full_output=True)

                    calculated_transit_depths = cloud_fraction * calculated_transit_depths + (
                        1. - cloud_fraction) * clear_calculated_transit_depths
                    info_dict['unbinned_depths'] = cloud_fraction * info_dict[
                        'unbinned_depths'] + (
                            1. - cloud_fraction
                        ) * clear_info_dict['unbinned_depths']

                #calculated_transit_depths[46:75]+=offset*1.0e-5
                #calculated_transit_depths[:29]+=offset2*1.0e-5
                #calculated_transit_depths[29:46]+=offset3*1.0e-5

                wfc3_range = np.where((transit_wavelengths > 1.12e-6)
                                      & (transit_wavelengths < 1.66e-6))
                stis_range = np.where(transit_wavelengths < 9.3e-7)
                #stis_range1=np.where(transit_wavelengths<5.69e-7)
                #stis_range2=np.where((transit_wavelengths>5.69e-7) & (transit_wavelengths<9.3e-7))

                calculated_transit_depths[wfc3_range] += offset * 1.0e-5
                calculated_transit_depths[stis_range] += offset2 * 1.0e-5
                #calculated_transit_depths[stis_range1]+=offset2*1.0e-5
                #calculated_transit_depths[stis_range2]+=offset3*1.0e-5

                wfc3_range = np.where(
                    (info_dict['unbinned_wavelengths'] > 1.12e-6)
                    & (info_dict['unbinned_wavelengths'] < 1.66e-6))
                stis_range = np.where(
                    info_dict['unbinned_wavelengths'] < 9.3e-7)
                #stis_range1=np.where(info_dict['unbinned_wavelengths']<5.69e-7)
                #stis_range2=np.where((info_dict['unbinned_wavelengths']>5.69e-7) & (info_dict['unbinned_wavelengths']<9.3e-7))

                info_dict['unbinned_depths'][wfc3_range] += offset * 1.0e-5
                info_dict['unbinned_depths'][stis_range] += offset2 * 1.0e-5
                #info_dict['unbinned_depths'][stis_range1]+=offset2*1.0e-5
                #info_dict['unbinned_depths'][stis_range2]+=offset3*1.0e-5

                residuals = calculated_transit_depths - measured_transit_depths
                scaled_errors = error_multiple * measured_transit_errors
                ln_likelihood += -0.5 * np.sum(
                    residuals**2 / scaled_errors**2 +
                    np.log(2 * np.pi * scaled_errors**2))

                if plot:
                    plt.figure(1)
                    plt.plot(METRES_TO_UM * info_dict["unbinned_wavelengths"],
                             info_dict["unbinned_depths"],
                             alpha=0.2,
                             color='b',
                             label="Calculated (unbinned)")
                    plt.errorbar(METRES_TO_UM * transit_wavelengths,
                                 measured_transit_depths,
                                 yerr=measured_transit_errors,
                                 fmt='.',
                                 color='k',
                                 label="Observed")
                    plt.scatter(METRES_TO_UM * transit_wavelengths,
                                calculated_transit_depths,
                                color='r',
                                label="Calculated (binned)")
                    plt.xlabel("Wavelength ($\mu m$)")
                    plt.ylabel("Transit depth")
                    plt.xscale('log')
                    plt.tight_layout()
                    plt.legend()

            if measured_eclipse_depths is not None:
                t_p_profile = Profile()
                t_p_profile.set_from_params_dict(params_dict["profile_type"],
                                                 params_dict)

                if np.any(np.isnan(t_p_profile.temperatures)):
                    raise AtmosphereError("Invalid T/P profile")

                eclipse_wavelengths, calculated_eclipse_depths, info_dict = eclipse_calc.compute_depths(
                    t_p_profile,
                    Rs,
                    Mp,
                    Rp,
                    T_star,
                    logZ,
                    CO_ratio,
                    scattering_factor=scatt_factor,
                    scattering_slope=scatt_slope,
                    cloudtop_pressure=cloudtop_P,
                    T_spot=T_spot,
                    spot_cov_frac=spot_cov_frac,
                    frac_scale_height=frac_scale_height,
                    number_density=number_density,
                    part_size=part_size,
                    ri=ri,
                    full_output=True)
                residuals = calculated_eclipse_depths - measured_eclipse_depths
                scaled_errors = error_multiple * measured_eclipse_errors
                ln_likelihood += -0.5 * np.sum(
                    residuals**2 / scaled_errors**2 +
                    np.log(2 * np.pi * scaled_errors**2))

                if plot:
                    plt.figure(2)
                    plt.plot(METRES_TO_UM * info_dict["unbinned_wavelengths"],
                             info_dict["unbinned_eclipse_depths"],
                             alpha=0.2,
                             color='b',
                             label="Calculated (unbinned)")
                    plt.errorbar(METRES_TO_UM * eclipse_wavelengths,
                                 measured_eclipse_depths,
                                 yerr=measured_eclipse_errors,
                                 fmt='.',
                                 color='k',
                                 label="Observed")
                    plt.scatter(METRES_TO_UM * eclipse_wavelengths,
                                calculated_eclipse_depths,
                                color='r',
                                label="Calculated (binned)")
                    plt.legend()
                    plt.xlabel("Wavelength ($\mu m$)")
                    plt.ylabel("Eclipse depth")
                    plt.xscale('log')
                    plt.tight_layout()
                    plt.legend()

        except AtmosphereError as e:
            print(e)
            return -np.inf

        self.last_params = params
        self.last_lnprob = fit_info._ln_prior(params) + ln_likelihood
        return ln_likelihood
예제 #9
0
 def test_isothermal(self):
     profile = Profile(num_profile_heights=130)
     profile.set_isothermal(1300)
     self.assertEqual(len(profile.pressures), 130)
     self.assertEqual(len(profile.temperatures), 130)
     self.assertTrue(np.all(profile.temperatures == 1300))