{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Can formation scenarios and mass be determined with age and thermal spectroscopy\n", "\n", "What you will learn\n", "\n", "1. If we only know the age of a young exoplanet, can we infer both the mass and the birth mechanism (hot vs. cold) just from its spectrum?\n", "\n", "What you should already know:\n", "\n", "1. What do formation models predict for the effective temperatures of young planets across different masses?\n", "2. Given identical mass and age, what might two different formation scenarios lead the spectra to look like?\n", "3. How do we dissect spectroscopy of planet atmospheres in order to infer atmospheric physical properties such as abundance and climate profiles?\n", "\n", "\n", "**Questions?** [Submit an Issue to PICASO Github](https://github.com/natashabatalha/picaso/issues) with any issues you are experiencing. Don't be shy! Others are likely experiencing similar problems" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import warnings\n", "warnings.filterwarnings(action='ignore')\n", "import os\n", "import pandas as pd\n", "import numpy as np\n", "\n", "import picaso.justdoit as jdi\n", "import picaso.justplotit as jpi\n", "jpi.output_notebook()\n", "\n", "#point to your sonora profile grid that you untared (see above cell #2)\n", "sonora_profile_db = '/data/sonora_profile/'" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Planet Evolution Tracks in the Context of Planet Discoveries\n", "\n", "How do these stack up against real data. Bolometric luminosities and ages of nearly all young planets and brown dwarfs were compiled from [Zhang et al. 2020](#References) (Tables 3-4) and [Zhang et al. 2021](#References) (Tables 4-5). The remaining 2 objects, beta Pic c & YSES-1c, are from [Nowak et al. 2020](#References) & [Bohn et al. 2020](#References), respectively. Lastly, there is one brand new object, COCONUTS-2b from [Zhang et al. 2021](#References)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#load curves again \n", "evo = jdi.evolution_track(mass='all',age='all')\n", "\n", "#load table from ZJ Zhang\n", "data = jdi.young_planets()\n", "data.head()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The data are in luminosity. So we need to change our evolution tracks. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "data.keys()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fig = jpi.plot_evolution(evo, y = 'logL',\n", " y_range=[26.5,30],x_range=[1e6,1e9],\n", " plot_height=400, plot_width=500,\n", " title='Thermal Evolution Against Data')\n", "\n", "jpi.plot_multierror(data['age_Gyr']*1e9, data['log_lbol'] + np.log10(3.839e33),\n", " fig, \n", " dx_low = 1e9*data['age_Gyr_low_err'], \n", " dx_up = 1e9*data['age_Gyr_upp_err'], \n", " dy_low = data['log_lbol_low_err'], \n", " dy_up = data['log_lbol_upp_err'],\n", " error_kwargs={'line_width':1.5,'color':'black'},\n", " point_kwargs={'line_color':'red','color':'white','size':6})\n", "\n", "fig.legend.location='bottom_left'\n", "jpi.show(fig)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "1. Which of these planets/brown dwarfs would have to be hot start?\n", "2. Which of these planets/brown dwarfs would have to be cold start? \n", "3. Which could be either? " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Analyze the spectra of two planets with same age and luminosity\n", "\n", "Let's pick an ambiguous location along these cold/hot start cases. For example, the 10 Mj cold start curve crosses the 4 Mj hot start curve at an age of ~3.2e7 years. Let's take a look to see if we can differentiate these scenarios. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "cold = jdi.evolution_track(mass=10,age=3.2e7)['cold'] #cold start, higher mass\n", "hot = jdi.evolution_track(mass=4,age=3.2e7)['hot'] #hot start, lower mass" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "hot,cold" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "wave_range = [0.8,14] \n", "opa = jdi.opannection(wave_range=wave_range)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The only difference in the code blocks below is the gravity and the effective temperature, which we can pull from the planet evolution tracks. For now, we will focus on absolute flux from the planet (as opposed to contrast, the ratio of planet to stellar flux). Therefore, we are relatively agnostic to the stellar spectrum.\n", "\n", "A quick refresher in running the `jdi.inputs` function: \n", "\n", "1. First define an empty class by running `jdi.inputs`\n", "2. Set the stellar parameters : `star(opacityclass, Teff, M/H, logg, radius, radius_unit)` \n", "3. Set the `gravity` of the planet. In this case we have this information from evolution models. \n", "4. Set the chemistry and pressure-temperature using the `sonora` grid 1D models that you downloaded. \n", "5. Finally, compute the spectrum with calculation set to `thermal` for thermal emission (other options include `reflected` and `transmission`). " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#HOT START\n", "yph = jdi.inputs()\n", "yph.star(opa, 5000,0,4.0,radius=1, radius_unit=jdi.u.Unit('R_sun'))\n", "yph.gravity(gravity=hot['grav_cgs'] , gravity_unit=jdi.u.Unit('cm/s**2'))\n", "yph.sonora(sonora_profile_db, hot['Teff'])\n", "hot_case = yph.spectrum(opa,calculation='thermal', full_output=True)\n", "\n", "#COLD START\n", "ypc = jdi.inputs()\n", "ypc.star(opa, 5000,0,4.0,radius=1, radius_unit=jdi.u.Unit('R_sun'))\n", "ypc.gravity(gravity=cold['grav_cgs'] , gravity_unit=jdi.u.Unit('cm/s**2'))\n", "ypc.sonora(sonora_profile_db, cold['Teff'])\n", "cold_case = ypc.spectrum(opa,calculation='thermal', full_output=True)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we can use our first `PICASO` plotting function: `jpi.spectrum`. More plotting functions will follow" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "wno,spec=[],[]\n", "for i in [cold_case, hot_case]:\n", " x,y = jdi.mean_regrid(i['wavenumber'],i['thermal'], R=100)\n", " wno+=[x]\n", " spec+=[y]\n", "jpi.show(jpi.spectrum(wno,spec,legend=['Cold','Hot'], y_axis_type='log',\n", " plot_width=500))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As you can immediately see, it is a lot more complicated to differentiate these!! Let's see if we can pick apart any differences" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Application of Spectroscopy Analysis Skills\n", "\n", "In the previous exercise we went through these steps to analyze a spectrum: \n", "\n", "1. Assess chemistry, pressure-temperature input\n", "2. Assess contribution function of opacity \n", "3. Assess \"flux at top\" in comparison with black body functions or brightness temperature\n", "\n", "We will focus on #2 in this demo." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "cold_cont = jdi.get_contribution(ypc, opa, at_tau=1)\n", "hot_cont = jdi.get_contribution(yph, opa, at_tau=1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As a reminder, this output consists of three important items: \n", "`taus_per_layer`\n", "- Each dictionary entry is a nlayer x nwave that represents the per layer optical depth for that molecule. \n", "\n", "`cumsum_taus`\n", "- Each dictionary entry is a nlevel x nwave that represents the cumulative summed opacity for that molecule. \n", "\n", "`tau_p_surface` \n", "- Each dictionary entry is a nwave array that represents the pressure level where the cumulative opacity reaches the value specified by the user through `at_tau`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#explore the output\n", "hot_cont['tau_p_surface'].keys()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's take a look at the last one, optical depth ~ 1 surface, as it will give us the best global view of what is going on" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "figs=[]\n", "for i,it in zip([cold_cont['tau_p_surface'], hot_cont['tau_p_surface']],['Cold Start','Hot Start']):\n", " wno=[]\n", " spec=[]\n", " labels=[]\n", " for j in i.keys(): \n", " x,y = jdi.mean_regrid(opa.wno, i[j],R=100)\n", " if np.min(y)<5:\n", " wno+=[x]\n", " spec+=[y]\n", " labels +=[j]\n", " fig = jpi.spectrum(wno,spec,plot_width=600,plot_height=350,y_axis_label='Tau~1 Pressure (bars)',\n", " y_axis_type='log',x_range=[1,6],\n", " y_range=[1e2,1e-4],legend=labels)\n", " fig.title.text=it\n", " figs+=[fig]\n", "jpi.show(jpi.column(figs))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Though these two cases look nearly identical, what is the main difference that is ultimately visible in the spectra?\n", "\n", "Any other insight we can glean form the the flux plot?" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "figs =[]\n", "for title,data in zip(['Cold Start','Hot Start'],[cold_case, hot_case]):\n", " fig = jpi.flux_at_top(data, pressures=[10,1,0.1],R=100,title=title)\n", " fig.legend.location='bottom_right'\n", " figs+=[fig]\n", "jpi.show(jpi.row(figs))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Revisit questions concerning observables. Would any of your answers change?\n", "\n", "1. What do each of the spectroscopic bands provide you? J, H and K? What do the JWST modes get you? You can use [the PandExo graphic for guidance](https://exoctk.stsci.edu/pandexo/calculation/new)\n", "2. If you were limited to differential photometry (e.g. J-H, J-K, H-K) what two bands might you pick to maximize information from this system? Does photometry help at all?\n", "3. In addition to the two photometric bands you've chosen, what third 1 micron in width spectroscopic band might you choose in this wavelength region? Assume there are no observational constraints across this 1-14 micron region. \n", "\n", "Then move to discuss: \n", "\n", "1. If photometry is not suitable for this problem, what spectroscopic bands are most suitable for differentiating formation scenarios? \n", "\n", "Final discussion: \n", "\n", "1. If we only know the age of a young exoplanet, can we infer both the mass and the birth mechanism (hot vs. cold) just from its spectrum? What aspects have we not considered? What could help? What could complicate things further? " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## References \n", "\n", "[Bohn, Alexander J., et al. \"Two Directly Imaged, Wide-orbit Giant Planets around the Young, Solar Analog TYC 8998-760-1.\" The Astrophysical Journal Letters 898.1 (2020): L16.](https://ui.adsabs.harvard.edu/abs/2020ApJ...898L..16B/abstract)\n", "\n", "[Nowak, Mathias, et al. \"Direct confirmation of the radial-velocity planet β Pictoris c.\" Astronomy & Astrophysics 642 (2020): L2.](https://ui.adsabs.harvard.edu/abs/2020A%26A...642L...2N/abstract)\n", "\n", "[Zhang, Zhoujian, et al. \"COol Companions ON Ultrawide orbiTS (COCONUTS). I. A High-gravity T4 Benchmark around an Old White Dwarf and a Re-examination of the Surface-gravity Dependence of the L/T Transition.\" The Astrophysical Journal 891.2 (2020): 171.](https://ui.adsabs.harvard.edu/abs/2020ApJ...891..171Z/abstract)\n", "\n", "[Zhang, Zhoujian, et al. \"The Hawaii Infrared Parallax Program. V. New T-dwarf Members and Candidate Members of Nearby Young Moving Groups.\" The Astrophysical Journal 911.1 (2021): 7.](https://ui.adsabs.harvard.edu/abs/2021ApJ...911....7Z/abstract)\n", "\n", "[Zhang, Zhoujian, et al. \"The Second Discovery from the COol Companions ON Ultrawide orbiTS (COCONUTS) Program: A Cold Wide-Orbit Exoplanet around a Young Field M Dwarf at 10.9 pc.\" arXiv preprint arXiv:2107.02805 (2021).](https://ui.adsabs.harvard.edu/abs/2021arXiv210702805Z/abstract)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.5" }, "toc": { "base_numbering": 1, "nav_menu": {}, "number_sections": true, "sideBar": true, "skip_h1_title": false, "title_cell": "Table of Contents", "title_sidebar": "Contents", "toc_cell": true, "toc_position": {}, "toc_section_display": true, "toc_window_display": false }, "varInspector": { "cols": { "lenName": 16, "lenType": 16, "lenVar": 40 }, "kernels_config": { "python": { "delete_cmd_postfix": "", "delete_cmd_prefix": "del ", "library": "var_list.py", "varRefreshCmd": "print(var_dic_list())" }, "r": { "delete_cmd_postfix": ") ", "delete_cmd_prefix": "rm(", "library": "var_list.r", "varRefreshCmd": "cat(var_dic_list()) " } }, "types_to_exclude": [ "module", "function", "builtin_function_or_method", "instance", "_Feature" ], "window_display": false } }, "nbformat": 4, "nbformat_minor": 4 }