Example #1
0
    def __init__(self, mass, distance, age, Av, Rin=5):
        self.mass = mass  #Msun
        self.dist = distance  #pc
        self.age = age  #Myr
        self.Av = Av  #mag

        #derived variables
        #self.Teff = MtoTfunc(self.mass, self.age)
        #self.radius = MtoRfunc(self.mass, self.age)
        #1d interpolation method done
        #can't incorporate age errors this way
        self.Teff = a.mass_to_Teff(self.mass, self.age)
        self.radius = a.Teff_to_params(self.Teff, self.age)[1]
        self.SpTy = a.Teff_to_SpTy(self.Teff)
        self.Rin = Rin * self.radius

        #ideal mdot, Lacc
        self.ideal_mdot = a.empiricalMdot(self.mass)
        self.ideal_Lacc = a.Mdot_to_Lacc(self.ideal_mdot, self.mass,
                                         self.radius, self.Rin)

        self.mdot = self.ideal_mdot
Example #2
0
def build_figure(observed, df):

    fig = go.Figure()

    fig.add_trace(
        go.Scatter(
            x=df["Mass (M$_\odot$)"],
            y=df["Mdot (M$_\odot$)"],
            mode='markers',
            name="Simulated",
            opacity=0.7,
            marker=dict(color='salmon'),
        ))

    fig.add_trace(
        go.Scatter(
            x=observed["Object Mass M_Solar"],
            y=observed["Accretion Rate M_solar yr-1"],
            mode='markers',
            name='Observed',
            opacity=0.6,
            marker=dict(symbol='x', color='#44749D'),
        ))

    fig.add_trace(
        go.Scatter(
            x=observed["Object Mass M_Solar"],
            y=a.empiricalMdot(observed["Object Mass M_Solar"]),
            mode='lines',
            name='Empirical Relationship',
            opacity=0.9,
            marker=dict(color='gray'),
        ))

    fig.update_layout(
        width=1200,
        height=675,
        title={
            'text': "Accretion Monte Carlo Error Propagation",
            'y': 0.9,
            'x': 0.46,
            'xanchor': 'center',
            'yanchor': 'top',
        },
        xaxis_title="Mass (solar masses)",
        yaxis_title="Mass Accretion Rate (solar masses/yr)",
        legend_title=None,
        font=dict(),
        xaxis=dict(tickmode='array',
                   tickvals=[0, 0.01, 0.05, 0.1, 0.5, 1, 1.5, 2],
                   showgrid=False),
        yaxis=dict(
            showexponent='all',
            tickmode='array',
            tickvals=[1e-13, 1e-12, 1e-11, 1e-10, 1e-9, 1e-8, 1e-7, 1e-6],
            ticktext=[1e-13, 1e-12, 1e-11, 1e-10, 1e-9, 1e-8, 1e-7, 1e-6],
            showgrid=True),
    )
    fig.update_xaxes(type="log")
    fig.update_yaxes(type="log")

    return fig
Example #3
0
def build_residuals(observed, df):

    residual_fig = go.Figure()

    observed_difference = np.log10(
        observed['Accretion Rate M_solar yr-1']) - np.log10(
            a.empiricalMdot(observed['Object Mass M_Solar']))
    simulated_difference = np.log10(df['Mdot (M$_\\odot$)']) - np.log10(
        a.empiricalMdot(df['Mass (M$_\\odot$)']))

    residual_fig.add_trace(
        go.Scatter(
            x=df["Mass (M$_\odot$)"],
            y=simulated_difference,
            mode='markers',
            name="Simulated",
            opacity=0.7,
            marker=dict(color='salmon'),
        ))

    residual_fig.add_trace(
        go.Scatter(
            x=observed["Object Mass M_Solar"],
            y=observed_difference,
            mode='markers',
            name='Observed',
            opacity=0.6,
            marker=dict(symbol='x', color='#44749D'),
        ))

    residual_fig.add_trace(
        go.Scatter(
            x=observed["Object Mass M_Solar"],
            y=np.zeros(len(observed["Object Mass M_Solar"])),
            mode='lines',
            name='Empirical Relationship',
            opacity=0.9,
            marker=dict(color='gray'),
        ))

    residual_fig.update_layout(
        width=1200,
        height=575,
        title={
            'text': "Residuals",
            'y': 0.9,
            'x': 0.46,
            'xanchor': 'center',
            'yanchor': 'top',
        },
        xaxis_title="Mass (solar masses)",
        yaxis_title="Residual (log space)",
        legend_title=None,
        font=dict(),
        xaxis=dict(tickmode='array',
                   tickvals=[0, 0.01, 0.05, 0.1, 0.5, 1, 1.5, 2],
                   showgrid=False),
        yaxis=dict(showexponent='all',
                   tickmode='array',
                   tickvals=[-3, -2, -1, 0, 1, 2, 3],
                   showgrid=True),
    )
    residual_fig.update_xaxes(type="log")

    return residual_fig
Example #4
0
    def UVExcessErrorProp(self,
                          SpTyUnc,
                          distUnc,
                          ageUnc,
                          AvUnc,
                          bc,
                          bcUnc,
                          UVExcessUnc,
                          numMC,
                          Rin=5,
                          RinUnc=0,
                          variability=0,
                          age_scatter=False):
        #propagate errors forward and obtain uncertainty distributions
        if age_scatter == True:
            #self.shifted_ideal_mdot = a.empiricalMdot(self.mass, intercept=-a.age_to_intercept_func(self.age))
            self.shifted_ideal_mdot = a.empiricalMdot(
                self.mass, intercept=-a.age_intercept_exponential(self.age))
            self.ideal_UVExcess = a.Mdot_to_UVExcess(self.shifted_ideal_mdot,
                                                     bc, self.dist, self.mass,
                                                     self.radius, self.Av,
                                                     self.Rin)
        else:
            self.ideal_UVExcess = a.Mdot_to_UVExcess(self.ideal_mdot, bc,
                                                     self.dist, self.mass,
                                                     self.radius, self.Av,
                                                     self.Rin)
        #add in uncertainties to observable itself
        if numMC == 1:
            self.UVExcessUncDist = np.random.normal(self.ideal_UVExcess,
                                                    UVExcessUnc *
                                                    self.ideal_UVExcess,
                                                    size=numMC)[0]
        else:
            self.UVExcessUncDist = np.random.normal(self.ideal_UVExcess,
                                                    UVExcessUnc *
                                                    self.ideal_UVExcess,
                                                    size=numMC)

        #add in uncertainties to variables specific to observable
        x = np.linspace(0, 20000, 100000)
        if bcUnc == 0:
            if numMC == 1:
                self.bcUncDist = bc
            else:
                self.bcUncDist = np.ones(numMC) * bc
        else:
            self.bcUncDist = a.uncdist(x, bc, bcUnc, numMC)

        #build uncertainty distributions
        if SpTyUnc == 0:
            if numMC == 1:
                self.SpTyUncDist = self.SpTy
            else:
                self.SpTyUncDist = np.ones(numMC) * self.SpTy
        else:
            self.SpTyUncDist = a.uncdist(x, self.SpTy, SpTyUnc, numMC)

        if distUnc == 0:
            if numMC == 1:
                self.distUncDist = self.dist
            else:
                self.distUncDist = np.ones(numMC) * self.dist
        else:
            self.distUncDist = a.uncdist(x, self.dist, distUnc, numMC)

        if ageUnc == 0:
            if numMC == 1:
                self.ageUncDist = self.age
            else:
                self.ageUncDist = np.ones(numMC) * self.age
        else:
            self.ageUncDist = a.uncdist(x, self.age, ageUnc, numMC)

        if AvUnc == 0:
            if numMC == 1:
                self.AvUncDist = self.Av
            else:
                self.AvUncDist = np.ones(numMC) * self.Av
        else:
            self.AvUncDist = a.uncdist(x, self.Av, AvUnc, numMC)

        if RinUnc == 0:
            if numMC == 1:
                self.RinUncDist = Rin
            else:
                self.RinUncDist = np.ones(numMC) * Rin
        else:
            self.RinUncDist = a.uncdist(x, Rin, RinUnc, numMC)

        self.TeffUncDist = a.SpTy_to_Teff(self.SpTyUncDist)
        self.massUncDist = a.Teff_to_params(self.TeffUncDist,
                                            (self.ageUncDist))[0]
        self.radiusUncDist = a.Teff_to_params(self.TeffUncDist,
                                              (self.ageUncDist))[1]
        self.RinUncDist = self.RinUncDist * self.radiusUncDist
        #self.RinUncDist = Rin*self.radiusUncDist

        #Generate synthetic Mdot distribution
        #Generate synthetic Lacc distribution
        self.mdot = a.UVExcess_to_Mdot(self.UVExcessUncDist, self.bcUncDist,
                                       self.distUncDist, self.massUncDist,
                                       self.radiusUncDist, self.AvUncDist,
                                       self.RinUncDist)
        if variability != 0:
            log_mdot = np.log10(self.mdot)
            if numMC == 1:
                draw = np.random.normal(log_mdot, variability, size=numMC)[0]
            else:
                draw = np.random.normal(log_mdot, variability, size=numMC)

            self.mdot = 10**draw
            '''
                #specify lower and upper bounds for the truncated gaussian
                lower, upper = 0,1
                mu, sigma = (self.mdot), (self.mdot*variability)
                variability_distribution = st.truncnorm(
                    (lower - mu) / sigma, (upper - mu) / sigma, loc=mu, scale=sigma)
                if numMC == 1: 
                    self.mdot = variability_distribution.rvs(numMC)[0]
                else:
                    self.mdot = variability_distribution.rvs(numMC)
                '''

        self.Lacc = a.Mdot_to_Lacc(self.mdot, self.massUncDist,
                                   self.radiusUncDist, self.RinUncDist)
Example #5
0
def residuals(observed, simulated):
    #load in data
    logmass = np.log10(simulated['Mass (M$_\\odot$)'])
    logMdot = np.log10(simulated['Mdot (M$_\\odot$)'])
    logaccepted_relation = np.log10(simulated['"true" Mdot (M$_\\odot$)'])
    observed_mass = np.log10(observed['Object Mass M_Solar'])
    observed_mdot = np.log10(observed['Accretion Rate M_solar yr-1'])

    #Figure Dimensions
    left, width = 0.1, 0.4
    bottom, height = 0.1, 0.7
    spacing = 0.0075

    #create figure
    fig = plt.figure(figsize=(16, 12))

    #Residual Plot
    rect_frame2 = [left, bottom, width, height]
    rect_ax2_hist = [left + width + spacing, bottom, 0.3, height]

    #create axes
    frame2 = fig.add_axes(rect_frame2)
    ax2_hist = fig.add_axes(rect_ax2_hist)
    ax = plt.gca()

    #Calculate Residuals
    observed_difference = np.log10(
        observed['Accretion Rate M_solar yr-1']) - np.log10(
            a.empiricalMdot(observed['Object Mass M_Solar']))
    simulated_difference = np.log10(simulated['Mdot (M$_\\odot$)']) - np.log10(
        a.empiricalMdot(simulated['Mass (M$_\\odot$)']))

    #Residual Marginal Distribution
    #remove ticks
    ax2_hist.tick_params(axis="y", labelleft=False)

    #bins by hand
    residualbinwidth = 0.25
    residualmax = np.max(np.abs(observed_difference))
    residuallim = (int(residualmax / residualbinwidth) + 1) * residualbinwidth
    residualbins = np.arange(-residuallim, residuallim + residualbinwidth,
                             residualbinwidth)

    #plot
    ax2_hist.hist(observed_difference,
                  bins=residualbins,
                  orientation='horizontal',
                  color='black',
                  density=True,
                  alpha=0.225,
                  label='Observed')
    ax2_hist.hist(simulated_difference,
                  bins=residualbins,
                  orientation='horizontal',
                  color='darkseagreen',
                  density=True,
                  alpha=0.3,
                  label='Simulated')
    ax2_hist.set_ylim(-3.3, 3.2)
    ax2_hist.axhline(0, color='tomato', label='Empirical Relationship')
    ax2_hist.legend()

    #Residual Plot
    frame2.axhline(0, color='tomato', label='Empirical Relationship')
    frame2.set_xlabel('log(Mass) (M$_\odot$)', size=16)
    frame2.set_ylabel('Residual (log space)', size=16)
    frame2.set_ylim(-3.3, 3.2)
    frame2.scatter(np.log10(observed['Object Mass M_Solar']),
                   observed_difference,
                   color='black',
                   marker='x',
                   alpha=0.4,
                   label='Observed Residuals')
    frame2.scatter(np.log10(simulated['Mass (M$_\\odot$)']),
                   simulated_difference,
                   color='darkseagreen',
                   alpha=0.4,
                   label='Simulated Residuals')
    frame2.legend(frameon=True)

    return fig
Example #6
0
def MarginalDistribution(observed, simulated):
    #load in data
    logmass = np.log10(simulated['Mass (M$_\\odot$)'])
    logMdot = np.log10(simulated['Mdot (M$_\\odot$)'])
    logaccepted_relation = np.log10(simulated['"true" Mdot (M$_\\odot$)'])
    observed_mass = np.log10(observed['Object Mass M_Solar'])
    observed_mdot = np.log10(observed['Accretion Rate M_solar yr-1'])

    #Figure Dimensions
    left, width = 0.1, 0.7
    bottom, height = 0.3, 0.55
    spacing = 0.0075

    #create figure
    fig = plt.figure(figsize=(16, 12))

    #Mass vs Mdot
    rect_frame1 = [left, bottom, width, height]

    #Marginal Distributions
    rect_histx = [left, bottom + height + spacing, width, 0.1]
    rect_histy = [left + width + spacing, bottom, 0.1, height]

    #create axes
    frame1 = fig.add_axes(rect_frame1)
    ax_histx = fig.add_axes(rect_histx, sharex=frame1)
    ax_histy = fig.add_axes(rect_histy, sharey=frame1)
    ax = plt.gca()

    #Marginal Distributions
    # no labels
    ax_histx.tick_params(axis="x", labelbottom=False)
    ax_histy.tick_params(axis="y", labelleft=False)

    # determine nice limits by hand:
    binwidth = 0.25
    xymax = max(np.max(np.abs(observed_mass)), np.max(np.abs(observed_mdot)))
    lim = (int(xymax / binwidth) + 1) * binwidth
    bins = np.arange(-lim, lim + binwidth, binwidth)

    #Plot histograms
    ax_histx.hist(observed_mass,
                  bins=bins,
                  color='black',
                  density=True,
                  alpha=0.225,
                  label='Observed')
    ax_histy.hist(observed_mdot,
                  bins=bins,
                  orientation='horizontal',
                  color='black',
                  density=True,
                  alpha=0.225,
                  label='Observed')
    ax_histx.hist(logmass,
                  bins=bins,
                  color='darkseagreen',
                  density=True,
                  alpha=0.3,
                  label='Simulated')
    ax_histy.hist(logMdot,
                  bins=bins,
                  orientation='horizontal',
                  color='darkseagreen',
                  density=True,
                  alpha=0.3,
                  label='Simulated')
    ax_histx.legend()
    ax_histy.legend()

    #Mass vs Mdot
    frame1.scatter(logmass,
                   logMdot,
                   color='darkseagreen',
                   s=130,
                   alpha=0.4,
                   label='Simulated')
    frame1.scatter(observed_mass,
                   observed_mdot,
                   color='black',
                   s=50,
                   marker='x',
                   alpha=0.4,
                   label='Observed')
    frame1.plot(logmass,
                logaccepted_relation,
                color='tomato',
                label='Empirical Relationship')
    frame1.axvline(x=np.log10(0.012),
                   color='black',
                   linestyle='-.',
                   label='Deuterium Burning Limit')
    frame1.axvline(x=np.log10(0.1),
                   color='black',
                   linestyle=':',
                   label='Hydrogen Burning Limit')
    frame1.set_xlim(-2.6, 0.6)
    frame1.set_ylim(-14, -5.75)
    frame1.set_xlabel('log(Mass) (M$_\odot$)', size=16)
    frame1.set_ylabel('log(Mass Accretion Rate) (M$_\odot$/yr)', size=16)
    frame1.text(-2.3, -6.6, 'Planets', size=15, fontstyle='italic')
    frame1.text(-1.64, -6.6, 'Brown Dwarfs', size=15, fontstyle='italic')
    frame1.text(-0.29, -6.6, 'Stars', size=15, fontstyle='italic')
    ax_histx.set_title('Monte Carlo Error Propagation',
                       size=20,
                       fontweight='heavy')
    frame1.legend(loc='lower right',
                  prop={
                      'family': 'sans-serif',
                      'style': 'normal',
                      'size': 16
                  },
                  frameon=False,
                  shadow=True)

    #Residual Plot
    rect_frame2 = [left, bottom - 0.2, width, bottom - 0.1 - spacing]
    rect_ax2_hist = [
        left + width + spacing, bottom - 0.2, 0.1, bottom - 0.1 - spacing
    ]

    #create axes
    frame2 = fig.add_axes(rect_frame2)
    ax2_hist = fig.add_axes(rect_ax2_hist)
    ax = plt.gca()

    #Calculate Residuals
    observed_difference = np.log10(
        observed['Accretion Rate M_solar yr-1']) - np.log10(
            a.empiricalMdot(observed['Object Mass M_Solar']))
    simulated_difference = np.log10(simulated['Mdot (M$_\\odot$)']) - np.log10(
        a.empiricalMdot(simulated['Mass (M$_\\odot$)']))

    #Residual Marginal Distribution
    #remove ticks
    ax2_hist.tick_params(axis="y", labelleft=False)

    #bins by hand
    residualbinwidth = 0.25
    residualmax = np.max(np.abs(observed_difference))
    residuallim = (int(residualmax / residualbinwidth) + 1) * residualbinwidth
    residualbins = np.arange(-residuallim, residuallim + residualbinwidth,
                             residualbinwidth)

    #plot
    ax2_hist.hist(observed_difference,
                  bins=residualbins,
                  orientation='horizontal',
                  color='black',
                  density=True,
                  alpha=0.225,
                  label='Observed')
    ax2_hist.hist(simulated_difference,
                  bins=residualbins,
                  orientation='horizontal',
                  color='darkseagreen',
                  density=True,
                  alpha=0.3,
                  label='Simulated')
    ax2_hist.set_ylim(-3.3, 3.2)
    ax2_hist.axhline(0, color='tomato')
    ax2_hist.legend()

    #Residual Plot
    frame2.axhline(0, color='tomato')
    frame2.set_xlabel('log(Mass) (M$_\odot$)', size=16)
    frame2.set_ylabel('Residual (log space)', size=16)
    frame2.set_ylim(-3.3, 3.2)
    frame2.scatter(np.log10(observed['Object Mass M_Solar']),
                   observed_difference,
                   color='black',
                   marker='x',
                   alpha=0.4,
                   label='Observed Residuals')
    frame2.scatter(np.log10(simulated['Mass (M$_\\odot$)']),
                   simulated_difference,
                   color='darkseagreen',
                   alpha=0.4,
                   label='Simulated Residuals')
    frame2.legend(frameon=True)

    return fig
Example #7
0
def MoneyPlot(observed, simulated):
    logmass = np.log10(simulated['Mass (M$_\\odot$)'])
    logMdot = np.log10(simulated['Mdot (M$_\\odot$)'])
    logaccepted_relation = np.log10(simulated['"true" Mdot (M$_\\odot$)'])
    observed_mass = np.log10(observed['Object Mass M_Solar'])
    observed_mdot = np.log10(observed['Accretion Rate M_solar yr-1'])

    fig = plt.figure(figsize=(16, 12))
    frame1 = fig.add_axes((.1, .3, .8, .6))
    ax = plt.gca()
    ax.scatter(logmass,
               logMdot,
               color='darkseagreen',
               s=130,
               alpha=0.4,
               label='Simulated')
    ax.scatter(observed_mass,
               observed_mdot,
               color='black',
               s=50,
               marker='x',
               alpha=0.4,
               label='Observed')
    ax.plot(logmass,
            logaccepted_relation,
            color='tomato',
            label='Empirical Relationship')
    ax.axvline(x=np.log10(0.012),
               color='black',
               linestyle='-.',
               label='Deuterium Burning Limit')
    ax.axvline(x=np.log10(0.1),
               color='black',
               linestyle=':',
               label='Hydrogen Burning Limit')
    ax.set_xlim(-2.6, 0.6)
    ax.set_xlabel('log(Mass) (M$_\odot$)', size=16)
    ax.set_ylabel('log(Mass Accretion Rate) (M$_\odot$/yr)', size=16)
    ax.text(-2.3, -6.6, 'Planets', size=15, fontstyle='italic')
    ax.text(-1.64, -6.6, 'Brown Dwarfs', size=15, fontstyle='italic')
    ax.text(-0.29, -6.6, 'Stars', size=15, fontstyle='italic')
    ax.set_title('Monte Carlo Error Propagation', size=20, fontweight='heavy')
    ax.legend(loc='lower right',
              prop={
                  'family': 'sans-serif',
                  'style': 'normal',
                  'size': 16
              },
              frameon=False,
              shadow=True)

    frame2 = fig.add_axes((.1, .1, .8, .2))
    ax = plt.gca()
    observed_difference = np.log10(
        observed['Accretion Rate M_solar yr-1']) - np.log10(
            a.empiricalMdot(observed['Object Mass M_Solar']))
    simulated_difference = np.log10(simulated['Mdot (M$_\\odot$)']) - np.log10(
        a.empiricalMdot(simulated['Mass (M$_\\odot$)']))
    ax.axhline(0, color='tomato')
    ax.set_xlabel('log(Mass) (M$_\odot$)', size=16)
    ax.set_ylabel('Residual (log space)', size=16)
    ax.scatter(np.log10(observed['Object Mass M_Solar']),
               observed_difference,
               color='black',
               marker='x',
               alpha=0.4,
               label='Observed Residuals')
    ax.scatter(np.log10(simulated['Mass (M$_\\odot$)']),
               simulated_difference,
               color='darkseagreen',
               alpha=0.4,
               label='Simulated Residuals')
    ax.legend(frameon=True)

    return fig
Example #8
0
    def linefluxErrorProp(self,
                          SpTyUnc,
                          distUnc,
                          ageUnc,
                          AvUnc,
                          linefluxUnc,
                          numMC,
                          Rin=5,
                          RinUnc=0,
                          line=None,
                          A=None,
                          AUnc=None,
                          B=None,
                          BUnc=None,
                          variability=0,
                          age_scatter=False):
        #propagate errors forward and obtain uncertainty distributions
        if line == None:
            A = A
            aUnc = AUnc
            B = B
            bUnc = BUnc
        elif line == 'Ha':
            A = 1.13  #+/- 0.05
            aUnc = 0.05
            B = 1.74  #+/- 0.19
            bUnc = 0.19
        elif line == 'Pab':
            A = 1.06  #+/- 0.07
            aUnc = 0.07
            B = 2.76  #+/- 0.34
            bUnc = 0.34
        elif line == 'Brg':
            A = 1.19  #+/- 0.10
            aUnc = 0.10
            B = 4.02  #+/- 0.51
            bUnc = 0.51
        else:
            print('Line not found.')
            return

        if age_scatter == True:
            #self.shifted_ideal_mdot = a.empiricalMdot(self.mass, intercept=-a.age_to_intercept_func(self.age))
            self.shifted_ideal_mdot = a.empiricalMdot(
                self.mass, intercept=-a.age_intercept_exponential(self.age))
            self.ideal_lineflux = a.Mdot_to_lineflux(self.shifted_ideal_mdot,
                                                     self.dist,
                                                     self.mass,
                                                     self.radius,
                                                     self.Av,
                                                     Rin=self.Rin,
                                                     line=line,
                                                     A=A,
                                                     B=B)
        else:
            self.ideal_lineflux = a.Mdot_to_lineflux(self.ideal_mdot,
                                                     self.dist,
                                                     self.mass,
                                                     self.radius,
                                                     self.Av,
                                                     Rin=self.Rin,
                                                     line=line,
                                                     A=A,
                                                     B=B)

        #add in uncertainties to observable itself
        if numMC == 1:
            self.linefluxUncDist = np.random.normal(self.ideal_lineflux,
                                                    linefluxUnc *
                                                    self.ideal_lineflux,
                                                    size=numMC)[0]
        else:
            self.linefluxUncDist = np.random.normal(self.ideal_lineflux,
                                                    linefluxUnc *
                                                    self.ideal_lineflux,
                                                    size=numMC)

        x = np.linspace(0, 1000, 100000)

        #add in uncertainties to variables specific to observable
        #self.AUncDist = a.uncdist(x, A, aUnc, numMC) #A
        #self.BUncDist = a.uncdist(x, B, bUnc, numMC) #B
        #Ignore uncertainties of the empirical fit
        self.AUncDist = A  #A
        self.BUncDist = B  #B

        #build uncertainty distributions
        if SpTyUnc == 0:
            if numMC == 1:
                self.SpTyUncDist = self.SpTy
            else:
                self.SpTyUncDist = np.ones(numMC) * self.SpTy
        else:
            self.SpTyUncDist = a.uncdist(x, self.SpTy, SpTyUnc, numMC)

        if distUnc == 0:
            if numMC == 1:
                self.distUncDist = self.dist
            else:
                self.distUncDist = np.ones(numMC) * self.dist
        else:
            self.distUncDist = a.uncdist(x, self.dist, distUnc, numMC)

        if ageUnc == 0:
            if numMC == 1:
                self.ageUncDist = self.age
            else:
                self.ageUncDist = np.ones(numMC) * self.age
        else:
            self.ageUncDist = a.uncdist(x, self.age, ageUnc, numMC)

        if AvUnc == 0:
            if numMC == 1:
                self.AvUncDist = self.Av
            else:
                self.AvUncDist = np.ones(numMC) * self.Av
        else:
            self.AvUncDist = a.uncdist(x, self.Av, AvUnc, numMC)

        if RinUnc == 0:
            if numMC == 1:
                self.RinUncDist = Rin
            else:
                self.RinUncDist = np.ones(numMC) * Rin
        else:
            self.RinUncDist = a.uncdist(x, Rin, RinUnc, numMC)

        self.TeffUncDist = a.SpTy_to_Teff(self.SpTyUncDist)
        self.massUncDist = a.Teff_to_params(self.TeffUncDist,
                                            (self.ageUncDist))[0]
        self.radiusUncDist = a.Teff_to_params(self.TeffUncDist,
                                              (self.ageUncDist))[1]
        self.RinUncDist = self.RinUncDist * self.radiusUncDist

        #Generate synthetic Mdot distribution
        #Generate synthetic Lacc distribution
        self.mdot = a.lineflux_to_Mdot(self.linefluxUncDist,
                                       self.distUncDist,
                                       self.massUncDist,
                                       self.radiusUncDist,
                                       self.AvUncDist,
                                       Rin=self.RinUncDist,
                                       A=self.AUncDist,
                                       B=self.BUncDist)
        if variability != 0:
            #specify lower and upper bounds for the truncated gaussian
            lower, upper = 0, 1
            mu, sigma = (self.mdot), (self.mdot * variability)
            variability_distribution = st.truncnorm((lower - mu) / sigma,
                                                    (upper - mu) / sigma,
                                                    loc=mu,
                                                    scale=sigma)
            if numMC == 1:
                self.mdot = variability_distribution.rvs(numMC)[0]
            else:
                self.mdot = variability_distribution.rvs(numMC)

        self.Lacc = a.Mdot_to_Lacc(self.mdot, self.massUncDist,
                                   self.radiusUncDist, self.RinUncDist)
Example #9
0
def MoneyPlot(observed, simulated, numMC=1):
    mass = []
    for r in range(len(simulated)):
        for i in range(numMC):
            mass.append(simulated['Mass (M$_\\odot$)'][r])
    mass = np.array(mass)

    mdot = []
    for r in range(len(simulated)):
        for i in range(numMC):
            if numMC == 1:
                mdot.append(simulated['Mdot (M$_\\odot$)'][r])
            else:
                mdot.append(simulated['Mdot (M$_\\odot$)'][r][i])
    mdot = np.array(mdot)

    true_mdot = []
    for r in range(len(simulated)):
        for i in range(numMC):
            true_mdot.append(simulated['"true" Mdot (M$_\\odot$)'][r])
    true_mdot = np.array(true_mdot)

    logmass = np.log10(mass)
    logMdot = np.log10(mdot)
    logaccepted_relation = np.log10(true_mdot)
    observed_mass = np.log10(observed['Object Mass M_Solar'])
    observed_mdot = np.log10(observed['Accretion Rate M_solar yr-1'])

    fig = plt.figure(figsize=(16, 12))
    frame1 = fig.add_axes((.1, .3, .8, .6))
    frame1.scatter(logmass,
                   logMdot,
                   facecolor='lightsteelblue',
                   edgecolor='steelblue',
                   s=130,
                   alpha=0.4,
                   label='Simulated')
    frame1.scatter(observed_mass,
                   observed_mdot,
                   edgecolor='black',
                   facecolor='black',
                   s=50,
                   marker='x',
                   alpha=0.4,
                   label='Observed')
    frame1.plot(logmass,
                logaccepted_relation,
                color='tomato',
                label='Empirical Relationship')
    frame1.axvline(x=np.log10(0.012),
                   color='black',
                   linestyle='-.',
                   label='Deuterium Burning Limit')
    frame1.axvline(x=np.log10(0.1),
                   color='black',
                   linestyle=':',
                   label='Hydrogen Burning Limit')
    frame1.set_xlim(-2.6, 0.6)
    frame1.set_ylim(-14, -5.75)
    frame1.set_xlabel('log(Mass) (M$_\odot$)', size=16)
    frame1.set_ylabel('log(Mass Accretion Rate) (M$_\odot$/yr)', size=16)
    frame1.text(-2.3, -6.6, 'Planets', size=15, fontstyle='italic')
    frame1.text(-1.64, -6.6, 'Brown Dwarfs', size=15, fontstyle='italic')
    frame1.text(-0.29, -6.6, 'Stars', size=15, fontstyle='italic')
    frame1.set_title('Monte Carlo Error Propagation',
                     size=20,
                     fontweight='heavy')
    frame1.legend(loc='lower right',
                  prop={
                      'family': 'sans-serif',
                      'style': 'normal',
                      'size': 16
                  },
                  frameon=False,
                  shadow=True)

    frame2 = fig.add_axes((.1, .1, .8, .2))
    observed_difference = np.log10(
        observed['Accretion Rate M_solar yr-1']) - np.log10(
            a.empiricalMdot(observed['Object Mass M_Solar']))
    simulated_difference = logMdot - np.log10(a.empiricalMdot(10**logmass))
    frame2.axhline(0, color='tomato')
    frame2.set_xlabel('log(Mass) (M$_\odot$)', size=16)
    frame2.set_ylabel('Residual (log space)', size=16)
    frame2.set_ylim(-3.3, 3.2)
    frame2.scatter(logmass,
                   simulated_difference,
                   facecolor='lightsteelblue',
                   edgecolor='steelblue',
                   alpha=0.4,
                   label='Simulated Residuals')
    frame2.scatter(np.log10(observed['Object Mass M_Solar']),
                   observed_difference,
                   facecolor='black',
                   edgecolor='black',
                   marker='x',
                   alpha=0.4,
                   label='Observed Residuals')
    frame2.legend(frameon=True)

    return fig
Example #10
0
def residuals(observed, simulated, numMC=1):
    #load in data
    mass = []
    for r in range(len(simulated)):
        for i in range(numMC):
            mass.append(simulated['Mass (M$_\\odot$)'][r])
    mass = np.array(mass)

    mdot = []
    for r in range(len(simulated)):
        for i in range(numMC):
            if numMC == 1:
                mdot.append(simulated['Mdot (M$_\\odot$)'][r])
            else:
                mdot.append(simulated['Mdot (M$_\\odot$)'][r][i])
    mdot = np.array(mdot)

    true_mdot = []
    for r in range(len(simulated)):
        for i in range(numMC):
            true_mdot.append(simulated['"true" Mdot (M$_\\odot$)'][r])
    true_mdot = np.array(true_mdot)

    logmass = np.log10(mass)
    logMdot = np.log10(mdot)
    logaccepted_relation = np.log10(true_mdot)
    observed_mass = np.log10(observed['Object Mass M_Solar'])
    observed_mdot = np.log10(observed['Accretion Rate M_solar yr-1'])

    #Figure Dimensions
    left, width = 0.1, 0.4
    bottom, height = 0.1, 0.7
    spacing = 0.0075

    #create figure
    fig = plt.figure(figsize=(16, 12))

    #Residual Plot
    rect_frame2 = [left, bottom, width, height]
    rect_ax2_hist = [left + width + spacing, bottom, 0.3, height]

    #create axes
    frame2 = fig.add_axes(rect_frame2)
    ax2_hist = fig.add_axes(rect_ax2_hist)
    ax = plt.gca()

    #Calculate Residuals
    observed_difference = np.log10(
        observed['Accretion Rate M_solar yr-1']) - np.log10(
            a.empiricalMdot(observed['Object Mass M_Solar']))
    simulated_difference = logMdot - np.log10(a.empiricalMdot(10**logmass))

    #Residual Marginal Distribution
    #remove ticks
    ax2_hist.tick_params(axis="y", labelleft=False)

    #bins by hand
    residualbinwidth = 0.25
    residualmax = np.max(np.abs(observed_difference))
    residuallim = (int(residualmax / residualbinwidth) + 1) * residualbinwidth
    residualbins = np.arange(-residuallim, residuallim + residualbinwidth,
                             residualbinwidth)

    #plot
    ax2_hist.hist(observed_difference,
                  bins=residualbins,
                  orientation='horizontal',
                  histtype='stepfilled',
                  facecolor='gray',
                  edgecolor='black',
                  density=True,
                  alpha=0.4,
                  label='Observed')
    ax2_hist.hist(simulated_difference,
                  bins=residualbins,
                  orientation='horizontal',
                  histtype='stepfilled',
                  facecolor='lightsteelblue',
                  edgecolor='royalblue',
                  density=True,
                  alpha=0.3,
                  label='Simulated')
    ax2_hist.set_ylim(-3.3, 3.2)
    ax2_hist.axhline(0, color='tomato', label='Empirical Relationship')
    ax2_hist.tick_params(labelsize=13.5)

    #Residual Plot
    frame2.axhline(0, color='tomato', label='Empirical Relationship')
    frame2.set_xlabel('log(Mass) (M$_\odot$)', size=16)
    frame2.set_ylabel('Residual (log space)', size=16)
    frame2.set_ylim(-3.3, 3.2)
    frame2.scatter(logmass,
                   simulated_difference,
                   facecolor='lightsteelblue',
                   edgecolor='steelblue',
                   alpha=0.4,
                   label='Simulated Residuals')
    frame2.scatter(np.log10(observed['Object Mass M_Solar']),
                   observed_difference,
                   color='black',
                   marker='x',
                   alpha=0.4,
                   label='Observed Residuals')
    frame2.tick_params(labelsize=13.5)
    frame2.legend(frameon=True, fontsize=15)

    return fig