From dc45dc3c604c998e8b9ce32ae40b89e57c8eaf01 Mon Sep 17 00:00:00 2001 From: nsabrams Date: Tue, 27 Jan 2026 14:18:58 -0800 Subject: [PATCH 01/28] initial commit for adding COSMIC into SPISEA --- docs/Cluster_w_COSMIC.ipynb | 494 +++++++++++++++++++++++++++++ spisea/atmospheres.py | 565 +++++++++++++++++++++++++++++++-- spisea/evolution.py | 169 ++++++++++ spisea/synthetic.py | 615 ++++++++++++++++++++++++++++++++---- 4 files changed, 1763 insertions(+), 80 deletions(-) create mode 100755 docs/Cluster_w_COSMIC.ipynb diff --git a/docs/Cluster_w_COSMIC.ipynb b/docs/Cluster_w_COSMIC.ipynb new file mode 100755 index 00000000..2bcc6532 --- /dev/null +++ b/docs/Cluster_w_COSMIC.ipynb @@ -0,0 +1,494 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "ff023bf0-605f-4d7c-ae4a-63ed04bfe5c1", + "metadata": {}, + "source": [ + "# SPISEA with COSMIC" + ] + }, + { + "cell_type": "markdown", + "id": "a003cd65-1a0a-48b6-9b24-f427f48bc651", + "metadata": {}, + "source": [ + "This is a quick tutorial to use SPISEA with COSMIC. COSMIC is a rapid binary synthesis code. We use it to evolve singles and binaries generated in a SPISEA cluster. In order to use this functionality, the user must install COSMIC. Info about installation and COSMIC usage can be found here: https://cosmic-popsynth.github.io/COSMIC/index.html\n", + "\n", + "Tutorial by Natasha Abrams 1-27-26" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "12bb2ed0-5349-485d-9bbf-eb3b2749743e", + "metadata": {}, + "outputs": [], + "source": [ + "%load_ext autoreload\n", + "%autoreload 2" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "78a29e15-e5ca-4c8b-90b3-c72ba02ec8a0", + "metadata": {}, + "outputs": [], + "source": [ + "from spisea import synthetic, evolution, atmospheres, reddening, ifmr, filters\n", + "from spisea.imf import imf, multiplicity\n", + "import os\n", + "import matplotlib.pyplot as plt\n", + "from astropy.table import Table\n", + "import numpy as np" + ] + }, + { + "cell_type": "markdown", + "id": "26f38db3-4c0e-4e4e-8154-d34c10a4d099", + "metadata": {}, + "source": [ + "You can start by instantiating a SPISEA isochrone object as usual, with a few key differences:\n", + "- Evolution object is COSMIC. This takes the dictionary specifying the binary evolution parameters. For detailed instructions on changing the parameters in this dictionary see the [COSMIC docs](https://github.com/COSMIC-PopSynth/COSMIC/blob/v3.6.1/examples/Params.ini).\n", + "- You can also specify if you'd like to keep disrupted companions which will be added to the primary table or if you would like them to be dropped. We recommend keeping them and this is the default.\n", + "- We use the IsochronePhotExternalEvolution() object as the ischrone object. We name it this way for convention, but COSMIC does not use an Isochrone grid like the other evolution models in SPISEA. Instead it uses prescriptions from Hurley et al. 2002.\n", + "- Since no isochrones are used, we interpolate over every point in Teff, logg, and metallicity for the atmospehre grids. This takes longer than the typical generation of isocrhones in SPISEA, but will have to be done less frequently.\n", + "- We suggest having a separate directory than your typical isochrone directory where the atmosphere grids will be stored.\n", + "- We recommend using get_merged_atmsophere_w_bb_supplement since some objects generated by COSMIC are outside of supported SPISEA atmospheres. You can specify your own ranges to have black bodies defined or use our default ones." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "90c33d5c-7c52-4dd1-9545-25b00db26032", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "# Fetch isochrone\n", + "logAge = 10 # Age in log(years)\n", + "AKs = 0 # Ks filter extinction in mags\n", + "dist = 4000 # distance in parsecs\n", + "metallicity = 0 # metallicity in [M/H]\n", + "atm_func = atmospheres.get_merged_atmosphere_w_bb_supplement\n", + "evo_merged = evolution.COSMIC(keep_COSMIC_tables=True)\n", + "redlaw = reddening.RedLawCardelli(3.1) # Rv = 3.1\n", + "filt_list = ['ubv,U', 'ubv,V', 'ubv,R']\n", + "\n", + "iso_dir = 'iso_cosmic/'\n", + "\n", + "if not os.path.exists(iso_dir):\n", + " os.mkdir(iso_dir)\n", + "\n", + "iso = synthetic.IsochronePhotExternalEvolution(logAge, AKs, dist, metallicity=metallicity,\n", + " evo_model=evo_merged, atm_func=atm_func,\n", + " filters=filt_list, red_law=redlaw,\n", + " atm_grid_dir=iso_dir, mass_sampling=3, recomp=False)" + ] + }, + { + "cell_type": "markdown", + "id": "40243f4b-5559-4a30-8a5b-cd000eea3fa0", + "metadata": {}, + "source": [ + "Next we can make the cluster. You must specify a resolved multiplicity object (i.e. with orbital parameters defined) and with a CSF_max = 1 and companion_max = True. This ensures there are only binaries and no higher order systems since COSMIC does not support them." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "4c12140e-88d8-48ba-98e2-0ba55e87d9e6", + "metadata": {}, + "outputs": [], + "source": [ + "# Now we can make the cluster. \n", + "clust_mtot = 10**4.\n", + "clust_multiplicity = multiplicity.MultiplicityResolvedDK(CSF_max = 1, companion_max = True)\n", + "\n", + "# Multiplicity is defined in the IMF object\n", + "clust_imf_Mult = imf.Kroupa_2001(multiplicity=clust_multiplicity)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "17d315a9-ec84-4289-a810-855443628e67", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/mambaforge3/envs/astro_cosmic/lib/python3.11/site-packages/cosmic/utils.py:1687: UserWarning: At least one of your initial binaries is starting in Roche Lobe Overflow:\n", + " kstar_1 kstar_2 mass_1 mass_2 porb ecc \\\n", + "582 1.0 1.0 116.027861 92.484134 0.862282 0.840790 \n", + "917 1.0 1.0 93.249056 4.880100 0.984959 0.126383 \n", + "2054 1.0 1.0 122.595315 67.697527 0.029709 0.860986 \n", + "2936 1.0 0.0 28.512173 0.644606 0.185955 0.828483 \n", + "3949 1.0 1.0 36.708844 5.099184 0.068500 0.415908 \n", + "4473 1.0 1.0 11.901563 1.191013 0.500548 0.947242 \n", + "4898 1.0 1.0 27.121218 16.036259 0.185669 0.730699 \n", + "4981 1.0 1.0 7.524916 4.762153 0.113632 0.507614 \n", + "7111 1.0 0.0 2.294603 0.462178 0.382382 0.728774 \n", + "12445 1.0 1.0 13.812780 8.529573 0.096521 0.905398 \n", + "13443 1.0 1.0 33.070690 8.437323 0.108757 0.621895 \n", + "13980 1.0 1.0 15.780719 3.480080 0.256120 0.610062 \n", + "14152 1.0 1.0 4.358243 0.946180 0.482530 0.901946 \n", + "15194 1.0 1.0 73.235018 7.167147 0.178010 0.827868 \n", + "18758 1.0 1.0 9.565150 1.324515 0.499803 0.669640 \n", + "18848 1.0 1.0 28.602152 13.059879 0.506179 0.314764 \n", + "\n", + " metallicity tphysf mass0_1 mass0_2 ... tacc_1 tacc_2 \\\n", + "582 0.014 10000.0 116.027861 92.484134 ... 0.0 0.0 \n", + "917 0.014 10000.0 93.249056 4.880100 ... 0.0 0.0 \n", + "2054 0.014 10000.0 122.595315 67.697527 ... 0.0 0.0 \n", + "2936 0.014 10000.0 28.512173 0.644606 ... 0.0 0.0 \n", + "3949 0.014 10000.0 36.708844 5.099184 ... 0.0 0.0 \n", + "4473 0.014 10000.0 11.901563 1.191013 ... 0.0 0.0 \n", + "4898 0.014 10000.0 27.121218 16.036259 ... 0.0 0.0 \n", + "4981 0.014 10000.0 7.524916 4.762153 ... 0.0 0.0 \n", + "7111 0.014 10000.0 2.294603 0.462178 ... 0.0 0.0 \n", + "12445 0.014 10000.0 13.812780 8.529573 ... 0.0 0.0 \n", + "13443 0.014 10000.0 33.070690 8.437323 ... 0.0 0.0 \n", + "13980 0.014 10000.0 15.780719 3.480080 ... 0.0 0.0 \n", + "14152 0.014 10000.0 4.358243 0.946180 ... 0.0 0.0 \n", + "15194 0.014 10000.0 73.235018 7.167147 ... 0.0 0.0 \n", + "18758 0.014 10000.0 9.565150 1.324515 ... 0.0 0.0 \n", + "18848 0.014 10000.0 28.602152 13.059879 ... 0.0 0.0 \n", + "\n", + " epoch_1 epoch_2 tms_1 tms_2 bhspin_1 bhspin_2 tphys binfrac \n", + "582 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "917 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "2054 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "2936 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "3949 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "4473 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "4898 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "4981 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "7111 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "12445 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "13443 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "13980 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "14152 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "15194 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "18758 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "18848 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "\n", + "[16 rows x 38 columns]\n", + " warnings.warn(\n", + "/u/nsabrams/code/multiplicity/PyPopStar/spisea/evolution.py:1368: RuntimeWarning: divide by zero encountered in log10\n", + " return np.log10(((np.array(c.G.to('Rsun^3/(Msun*s^2)').value*masses/((radii)**2))*u.Rsun/u.s**2).to('cm/s^2')).value)\n", + "/u/nsabrams/code/multiplicity/PyPopStar/spisea/evolution.py:1368: RuntimeWarning: divide by zero encountered in log10\n", + " return np.log10(((np.array(c.G.to('Rsun^3/(Msun*s^2)').value*masses/((radii)**2))*u.Rsun/u.s**2).to('cm/s^2')).value)\n", + "/opt/mambaforge3/envs/astro_cosmic/lib/python3.11/site-packages/pandas/core/arraylike.py:402: RuntimeWarning: divide by zero encountered in log10\n", + " result = getattr(ufunc, method)(*inputs, **kwargs)\n", + "/opt/mambaforge3/envs/astro_cosmic/lib/python3.11/site-packages/pandas/core/arraylike.py:402: RuntimeWarning: invalid value encountered in log10\n", + " result = getattr(ufunc, method)(*inputs, **kwargs)\n" + ] + } + ], + "source": [ + "# Make cluster\n", + "clust_cosmic = synthetic.ResolvedCluster(iso, clust_imf_Mult, clust_mtot)" + ] + }, + { + "cell_type": "markdown", + "id": "43d8c754-54ff-49c8-a360-ffa5fbc86bd8", + "metadata": {}, + "source": [ + "If you specified `keep_COSMIC_tables=True`, then you can access the COSMIC tables as described here: https://cosmic-popsynth.github.io/COSMIC/pages/output_info.html#output-info" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "467f1672-1f16-4c43-8add-47d0953fcd05", + "metadata": {}, + "outputs": [], + "source": [ + "bcm_table = clust_cosmic.iso.evo_model.bcm\n", + "bpp_table = clust_cosmic.iso.evo_model.bpp" + ] + }, + { + "cell_type": "markdown", + "id": "10db81b9-2a29-41f3-af72-a02b941b6dad", + "metadata": {}, + "source": [ + "# Example analysis plots" + ] + }, + { + "cell_type": "markdown", + "id": "1e79d887-cb09-458c-a237-e1d76709f9d9", + "metadata": {}, + "source": [ + "CMD" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "45ac7b14-e09b-4840-b11d-647e2c5609e4", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Text(0, 0.5, 'm_ubv_R')" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjMAAAGxCAYAAACXwjeMAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAABWqElEQVR4nO3de1xU5do38N8aFASFEQRhVE5hhsbBY4YpnvKA1NZ0lzuttMxOarvX5ynFnU+2dwnabr8dNF+zMntKpbanylPuPKDiAQ8olpoSCOmgojAojKCw3j9opjkzM8zMmhl+38+H54k1a625HN2si/u+7usWRFEUQUREROShZFIHQERERNQcTGaIiIjIozGZISIiIo/GZIaIiIg8GpMZIiIi8mhMZoiIiMijMZkhIiIij8ZkhoiIiDxaK6kDcLaGhgZcunQJgYGBEARB6nCIiIjICqIo4saNG+jUqRNkMstjL16fzFy6dAmRkZFSh0FERER2KC0tRZcuXSye4/XJTGBgIIDGDyMoKEjiaIiIiMgaVVVViIyM1D7HLfH6ZEYztRQUFMRkhoiIyMNYUyLCAmAiIiLyaExmiIiIyKMxmSEiIiKPxmSGiIiIPBqTGSIiIvJoTGaIiIjIozGZISIiIo/GZIaIiIg8GpMZIiIi8mhMZoiIiMijMZkhIiIij8ZkhuymVKmRW1gOpUotdShERNSCef1Gk+Qc2XklyFhfgAYRkAlA5vhETOwXJXVYRETUAnFkhmymVKm1iQwANIjAvPWnOEJDRESSYDJDFpmaSioqr9YmMhr1ooji8hqL1xERETkDp5nILHNTSbGhbSEToJfQ+AgCYkIDLF5HRETkDByZIZMsTSUp5P7IHJ8IH0EA0JjILByfAIXcn1NQRETkchyZIZNW7isyO5WkkPtjYr8opHYLQ3F5DWJCA6CQ+wOwPAWlOYeIiMiRmMyQEaVKjRV7i4yOywRop5IAQCH3N0pQmpqCIiIicjROM5GRovJqiCaOPzvwriZHVyxNQRERETkDR2bIiKnRFRmApwfGWHW9uSkoIiIiZ+DIDBkxNbqSOSHRpqREIfdHSlwHJjJEROR0HJkhkzi6QkREnoLJDJllqsCXiIjI3XCaiezCDr9EROQuODJDNmOHXyIiciccmSGbsMMvERG5GyYzZBNrNpkkIiJyJSYzZBNNDxpd7PBLRERSYjJDNmlqk0kWBRMRkauxAJhsZqoHzfKcQmRtOQMRLAomIiLXYjJDdtHdJfvLgxewdFeh9rUGEZi7vgCp3cLYp4aIiJyOyQzZRXd5timiCBy7UIH0JCYzRETkXKyZIZsZLs82R2zidSIiIkdgMkM2M7U825AAoE9MsEviISKilo3JDNnM1PJsQ1k27rJNRERkL9bMUJOUKjWKyqsRG9pWu/lk5vhEzFt/CvWiCB9BwGuj70Hn9v4QBKB3dDATGSIichkmM2SRuX2YTC3PJiIikgKnmcgspUqNuev092Gau75A2xRPIfdHSlwHJjJERCQpJjNk1tELFTCs89UsuSYiInIXTGbIrP/8XGby+PXqOhdHQkREZB6TGTJJqVJjY77S5GtCEyuZiIiIXEnSZCYnJwcPP/wwOnXqBEEQsHHjRr3Xp06dCkEQ9L7uv/9+aYJtYYrKq82+1t7f14WREBERWSZpMlNdXY3k5GQsWbLE7DmjR4+GUqnUfm3ZssWFEbZc5nrJsBkeERG5G0mXZqelpSEtLc3iOX5+foiIiHBRRKTrL/0iseZwqV4RMJvhERGRu3H7PjO7d+9Gx44d0b59ewwePBhvv/02OnbsKHVYXi07rwRz1xXoJTGT7ovCrOFdmcgQEZHbcesC4LS0NHz11VfYuXMn3n33XeTl5WHYsGGora01e01tbS2qqqr0vsh6mt4yhkuy1xwukSQeIiKiprj1yMzEiRO1/52QkIC+ffsiOjoamzdvxvjx401ek5mZiTfffNNVIXqdovJqo0QGAEQ09pdJT+LIDBERuRe3HpkxpFAoEB0djXPnzpk9JyMjAyqVSvtVWlrqwgg9X2xoW7OviU3slE1ERCQFj0pmrl27htLSUigUCrPn+Pn5ISgoSO+LrKeQ+yMjLd7oOFcxERGRu5J0munmzZs4f/689vuioiLk5+cjJCQEISEhWLBgASZMmACFQoHi4mLMmzcPoaGheOSRRySMumXiKiYiInJXkiYzR44cwdChQ7Xfz549GwAwZcoULFu2DAUFBfjiiy9QWVkJhUKBoUOHIjs7G4GBgVKF7PWW5xQic+sZo+Op3cIkiIaIiKhpkiYzQ4YMgWihEGP79u0ujIaUKjUytxgnMgBwtLgCDyVzZIaIiNyPR9XMkHNZ2sKA+zEREZG7YjJDWpZWMnUJ5qgMERG5JyYzpKWQ++PujqYTmpq6BhdHQ0REZB0mM6R1orQC564YTzXJBCAmNECCiIiIiJrGZMaLKVVq5BaWQ6lSW3X+4eLrJo+PSVBwWTYREbktt97OgOyXnVeCjPUFaBAbR1YyxydiYr8oi9fcFxNi8vj01FhnhEhEROQQHJnxQkqVWpvIAECDCMxbf0pvhMbWURsiIiJ3xZEZL1RUXq1NZDTqRRHF5TVQyP3NjtqYm2Y6UlyB5EhuZUBERO6JIzNeKDa0LWQGfWF8BAExoQEWR23a+7c2eb8gf+a8RETkvpjMeCGF3B+Z4xPh83unOx9BwMLxCVDI/S2O2rz7wy8m7/fbdU5FERGR++Kv3F5IqVIjMiQAHz/VGydKKxEW1Ea7t5Jm1EY3ofERBPxWUY2yqlqT9wsL8nNF2ERERHZhMuNldOthdP3Pxp+QNaGxNiZzfCLmrT+FelHUjtrkni83e8/h3cOdHDUREZH9mMx4EcN6GF0igDnrClB09SZq7zRgRPcwFF2rQUSQLw7+eg27z141ec/7Y4PZY4aIiNwakxkvYqoextD/yynS+/7sZcvn3xfboZlRERERORcLgL2IqVVMzRUZwlEZIiJyb0xmvIhmFZMjVanvOPR+REREjsZkxsv8dr3GoffrG8NmeURE5N6YzHgRpUqN/7er0GH3m9C7Mzv/EhGR22MBsJfQLslu4rxXR3VD+Y06VNbU4mLlLYQEtEbbNq0QHxGE81dv4kJ5NaJD22LSfVFMZIiIyCMwmfEClpZkGxrfuwuXWhMRkVfhNJMXsGZJtkZxuWNraoiIiKTGZMYL2LIke9sppXODISIicjEmM17AliXZqw5cwPI9jisSJiIikhqTGS8xsV+U1edmbT0DpYo7YRMRkXdgMtMCiWDtDBEReQ8mM17k/pj2Vp8b4Mu/eiIi8g58onmRoT0irD533NJc/HP7GSdGQ0RE5BpMZryEUqXGoq3WJycigCW7CvH0ysPOC4qIiMgFmMx4CVt6zejadfYq3th0yvEBERERuQiTGS9hS68ZQ6sOXMDyHC7XJiIiz8Rkxktoes34CPZlNJlbuFybiIg8E5MZLzKxXxT2zR2KID8fu65/Zc1xB0dERETkfExmvIxC7o/tswfbde2h4gp8uPMXjtAQEZFHYTLjhRRyf7Sxcz/0d384hwGZO5GdV+LYoIiIiJyEyYyX2vXqMLuvFQHMWVfAERoiIvIITGa8lELujwRFULPucexChYOiISIich4mM17s+78Oatb1+89fc1AkREREzsNkxsttmjHA7mvXHC7hVBMREbk9JjNeLjkyGJ3b+9l1rQjgre9PM6EhIiK3xmSmBdg/90G7r91coOTqJiIicmtMZlqIAxnNW900b/0pjtAQEZFbYjLTQijk/pg6INru6+tFEccuVCC3sJxJDRERuRVBFEU79lr2HFVVVZDL5VCpVAgKat5SZW/Qc8F2VN66Y/N1ggBAbBylkQnAi0Pi4CMTENrOFyN6REAh93d4rERE1HLZ8vxmMtMCxczd7PB7LpqQiIn9ohx+XyIiaplseX5zmqkFKs5Kd/g92TGYiIikwmSmhXJGQnO0mB2DiYjI9ZjMtGCOTmgEwaG3IyIisgqTmRbOkQnNir2/cqqJiIhcjskMOSyhyS9VISVzJ5bvKXTI/YiIiKzBZIYAOHaEJnPrGSzPYUJDRESuwWSGtByZ0GRtOYMvDhRx2omIiJyOyQzpKc5KxwN3hTT7PiKA/9n0M/d1IiIip2MyQ0a+ei4FiyYkOuReIoAM9qAhIiInYjJDJk3sF9WszSl1NQAoLq9xyL2IiIgMMZkhsxRyf4fV0dTU3XbIfYiIiAwxmaEmOSKh2X/uGnfcJiIip+BGk2Q1R2xQKROAzPHclJKIiCzjRpPkFMVZ6WjujgUNIjBv/SmO0BARkcNImsxkZmaiX79+CAwMRMeOHTFu3DicPXtW7xxRFLFgwQJ06tQJ/v7+GDJkCH766SeJIqairHREB7dp1j3qRZEFwURE5DCSJjN79uzBjBkzcPDgQezYsQN37tzByJEjUV1drT1n8eLF+Ne//oUlS5YgLy8PERERGDFiBG7cuCFh5C3bnjnD0aZV8+4R4MtBQSIicgy3qpm5evUqOnbsiD179iA1NRWiKKJTp0545ZVXMGfOHABAbW0twsPDsWjRIjz//PNN3pM1M87TnBqaNdPvR0pcBwdGQ0RE3sRja2ZUKhUAICSksQNtUVERysrKMHLkSO05fn5+GDx4MHJzcyWJkf7QnFVOJ3+rdFwgRETUorlNMiOKImbPno2BAwciISEBAFBWVgYACA8P1zs3PDxc+5qh2tpaVFVV6X2R8xRnpeOx3p1tvi5z6xmcKK1wQkRERNTSuE0yM3PmTJw8eRJr1qwxek0Q9NfQiKJodEwjMzMTcrlc+xUZGemUeOkPix/raVdR8Niludy3iYiIms0tkplZs2bh22+/xa5du9ClSxft8YiICAAwGoW5cuWK0WiNRkZGBlQqlfartLTUeYGT1p45w+26bg73bSIiomaSNJkRRREzZ87E+vXrsXPnTsTGxuq9Hhsbi4iICOzYsUN7rK6uDnv27MGAAQNM3tPPzw9BQUF6X+QacaEBdl03598nHRwJERG1JJImMzNmzMCXX36J1atXIzAwEGVlZSgrK4Na3fibuiAIeOWVV7Bw4UJs2LABp06dwtSpUxEQEIBJkyZJGTqZ8ON/D7Xrupxz5ayfISIiu0mazCxbtgwqlQpDhgyBQqHQfmVnZ2vPee211/DKK6/gpZdeQt++fXHx4kX88MMPCAwMlDByMsfenbZ3nrni4EiIiKilcKs+M87APjOutzynEJlbzth0Ta8ucmyYOdBJERERkafx2D4z5B2eT41DRlq8Tdcc/03FQmAiIrILkxlyiucHx+GRngqbruF+TUREZA8mM+Q0r6V1t+n8f263bWqKiIgIYDJDTqSQ+9t0/tGSSq5qIiIimzGZIaeydXXT4m1nnRQJERF5KyYz5FQKuT98faw/f3/hNRYCExGRTZjMkNN984Lpbs3msBCYiIhswWSGnC45MhgTbNhZ+9TFSucFQ0REXofJDLnEu4/1tPrcHT9fdl4gRETkdZjMkMu0aWXdedera50bCBEReRUmM+QyZ95Kt+q881dZM0NERNZjMkNuif1miIjIWkxmyKWsnGnCJzm/OjUOIiLyHkxmyKW+mN7fqvOOl1Y6NxAiIvIaTGbIpdpa2UGvuu6OkyMhIiJvwWSGXKq6rt6q827XNzg5EiIi8hZMZsilYkPbWnXezVomM0REZB0mM+RSCrk/Fk1ItOrcFTmFTo6GiIi8AZMZcrmJ/aKsOu/z3GLnBkJERF6ByQxJwteKf3mXK285PxAiIvJ4TGbI5bLzSnBHbPq8OwCUKrXT4yEiIs/GZIZcSqlSI2N9ARqsSGYAYP2x35wbEBEReTwmM+RSReXVVicyAPDjGe6gTUREljGZIZeKDW0LmWD9+aXXOM1ERESWMZkhl1LI/ZE5PtHqhKayps65ARERkcdjMkMuN7FfFN7/S0+rzr3N3nlERNQEJjMkib4xIVKHQEREXoLJDElCIfdHRlq8Vef+eLrMydEQEZEnYzJDkmkf0Nqq8+Zv/MnJkRARkSdjMkOSUKrUmLuuwKpzL6lusXkeERGZxWSGJHH0QgVsaDeDYxcqnBYLERF5NocmM7du3cI///lPR96SvNSOn22rg7lezSXaRERkms3JTHl5OTZv3owffvgB9fX1AIDbt2/j/fffR0xMDLKyshweJHkXpUqNb/OVNl2z/1y5k6IhIiJP18qWk3Nzc5Geng6VSgVBENC3b1+sXLkS48aNQ0NDA15//XU888wzzoqVvERRebVNU0wAsPfcVafEQkREns+mkZn58+dj1KhROHnyJP76178iLy8PDz30EF5//XWcO3cOM2fOREBAgLNiJS9h65YGAFB9u4FFwEREZJJNycyJEycwf/58JCQk4K233oIgCFi0aBGeeuopCIKNTydqsTRbGvjY+G/mx9PcdJKIiIzZNM10/fp1hIWFAQACAgIQEBCAXr16OSUw8nxKlRpF5dWIDW0Lhdxf77WJ/aKQ2i0MxeU1CPCVYezS3Cbv9/rGn9DaR4aJ/aKcFTIREXkgm5IZQRBw48YNtGnTBqIoQhAE1NTUoKqqSu+8oKAghwZJnic7rwQZ6wvQIAIyAcgcn2iUhCjk/lDI/ZFbaH1x79x1BUjtFmaUHBERUctl0zSTKIro1q0bgoODERISgps3b6JXr14IDg5GcHAw2rdvj+DgYGfFSh5CqVJrExkAaBCBeetPmax5UarUmLTikNX3FgGs3FfsmECJiMgr2DQys2vXLmfFQV6kqLxam8ho1Isiistr9EZUNKM3tvp47694emAMR2eIiAiAjcnM4MGDbbp5VlYWXnjhBbRv396m68izaVYr6SY0PoKAmNA/VroZjt7Y6sfTl/HE/THNC5SIiLyCU7czWLhwIa5fv+7MtyA3ZLhayUcQsHB8gnYkRalS4/uTl+xOZADgalWtI0IlIiIvYNPIjK1EsRlPK/JouquVYkIDtImMbmFwcwzr3tEBURIRkTdwajJDLZtmtZJGc6eWdB0suo7kSBabExERd80mFzJVGGyvzC1n2BGYiIgAMJlpFqVKjdzCcj5UrWTPNgaWLNp6xnE3IyIij8Vkxk7ZeSUYkLkTk1YcwoDMncjOK5E6JJdoTgJn7zYG5mzMv8REkoiInFszM2jQIPj7e18vEKVKjbnrCrQ7P4toGZ1prenq2xRNYfDR4grMWnscza0RP3ahAulJ3vuZExFR0+wamRk6dCg+/fRTqFQqi+dt2bIFCoXCrsDc2ZHi6zB8BosAjhZXSBGOS9jS1bcpCrk/HkruhCyD5duLJiTafK8Zq4+3mFExIiIyza5kJjExEa+//joiIiIwYcIEbNy4EXV1dY6OzW2Z2yHcmzcOt9TV114T+0Vh/UspeD29O9a/lIKJ/aJQnJWOpE627e01d10Bp5uIiFowu5KZDz74ABcvXsSmTZsQGBiIKVOmICIiAs899xz27Nnj6BjdTp/oYBjmLYIA9I723qXCpop3Dbv62io7rwSPfJSLtzafxiMf5SI7r6RxCi+9O2JD2lh9H28fFSMiIsvsLgCWyWQYOXIkPv/8c1y+fBnLly/H4cOHMWzYMEfG55YUcn9kTUjUPtxlAvDswFinv6+Uq6ea6uprK1PTVnPXF2iLqouu37LpfrbsvE1ERN5FEJvZpresrAxr167Fl19+iWPHjqFfv344dMj6XZCdraqqCnK5HCqVCkFBtk1fNEWpUmPl/iKsyCmCCPuLYq3hiOJbR1Cq1EZdfe2RW1hu027ZTREA5GYM8+oCbCKilsSW57ddIzNVVVVYuXIlRowYgcjISCxbtgwPP/wwfvnlF7dKZFzhk71F2mLg5hTFWuLI4tvmUsj9kRLXodlJg6N7zohAs+p3iIjIc9m1NDs8PBzBwcF47LHHsHDhQvTr18/RcXkES0WxjhwhaKr4tqi8GrGhbZv9nkqV2mH3aopm2mre+lOoF0XIBEAUYbRKzBY1dbcdFh8REXkOu5KZTZs24cEHH4RM1rJ77mlGFwwTjZO/VSIlroNT38dHEHDyYiUmf3LQIVNPUkxjGW5GmfPLVW1yY49nVx1F1gRppt+IiEg6zaqZuXLlCs6ePQtBENCtWzd07Oh+Oxk7s2YGAJbnFCJzi35bfQHAxhkDHLoRYnZeifZB7yMIeG30PVi07YxRgrNv7lCbR1WUKjUeyNrpkHs1l6Ym5/EVB+26Xqq4iYjIsVxSM/Pkk0+ic+fOGDx4MFJTU9G5c2c88cQTTTbS8zaJneVGx0QAY5fmOrSZ28R+Udg3dyjWTL8f++YORWIXucP6vjijh4y9NDU5q6f3t+t6qeImIiLp2JXMPPvsszh06BC+//57VFZWQqVS4fvvv8eRI0cwffp0q++TmZmJfv36ITAwEB07dsS4ceNw9uxZvXOmTp0KQRD0vu6//357wnaK2NC2Rj1nNBzdzE23+NaRfV+c0UOmuZpTIBzg27KnP4mIWhq7fupv3rwZn332GUaNGoWgoCAEBgZi1KhRWLFiBTZv3mz1ffbs2YMZM2bg4MGD2LFjB+7cuYORI0eiurpa77zRo0dDqVRqv7Zs2WJP2E6hkPtj+iDTPWZEACv3FQMATpRWYMXeQpwodUxzN0f2fXF0DxlH0MRkT1dlR4+KERGRe7OrALhDhw6Qy42nV+RyOYKDra8T2bZtm973K1euRMeOHXH06FGkpqZqj/v5+SEiIsKeUF3i6YGx+HhvkcnXVuz9FaUVNdh6qkx7bELvznj3sZ7Nfl/DAtrmJB8T+0UhPiIQecUV6BcT7NB6n+bElNotDIu3ncGG45dsunbuugLERwSiuq7eJauziIhIOnaNzLz++uuYPXs2lEql9lhZWRleffVVzJ8/3+5gNPU2ISEhesd3796Njh07olu3bpg+fTquXLli9h61tbWoqqrS+3I2hdwf6Ymmky0R0EtkAGDdsYsOHaFxRN8XU1sLOJo9HYwVcn9MHRBj83uJAMZ9lItJKw7hgaydHKkhIvJiVq9m6tWrl94Gi+fOnUNtbS2iohqXwZaUlMDPzw933303jh07ZnMgoihi7NixqKiowN69e7XHs7Oz0a5dO0RHR6OoqAjz58/HnTt3cPToUfj5+RndZ8GCBXjzzTeNjjtrNZPGidIKjF2aa/X589O7Y9qgu5wWjy1csZrJ1qXfSpUaKZk7HfLeAFc5ERF5GltWM1k9zTRu3LjmxmXRzJkzcfLkSezbt0/v+MSJE7X/nZCQgL59+yI6OhqbN2/G+PHjje6TkZGB2bNna7+vqqpCZGSk8wL/XXJkMFLvDkXOOev2COob49xpHFsa4Dm7+Z9SpcbcdQVGnZJTu4WZvH92XgnmrCto9vvqckYzQyIicg9WJzNvvPGG04KYNWsWvv32W+Tk5KBLly4Wz1UoFIiOjsa5c+dMvu7n52dyxMYVFv05yarRhE7yNqiuq4dSpXbKw9XWURBzTfkctZrps31FRp19zSUXSpXa4YkMIP3qLCIich5J17CKooiZM2di/fr12LlzJ2Jjm955+tq1aygtLYVCoXBBhLZRyP3xnJmVTbouqW5h0opDGJDp+FoOe/ZxcuZqJqVKjU/3GRdHywCTyUVRebXRMUd4cchdHJUhIvJSdq1mkslkevUzhurr6626z4wZM7B69Wps2rQJgYGBKCtrLJSVy+Xw9/fHzZs3sWDBAkyYMAEKhQLFxcWYN28eQkND8cgjj9gTutM9PTAWn+wrMpq2MUVE46obc9Mt5liaQrJ3yshRK6MMYzMVDwA8mxpr8j1iQ9va9b5NWbKrELV3GvDMQNPvS0REnsuuZGbDhg1639++fRvHjx/HqlWrTBbfmrNs2TIAwJAhQ/SOr1y5ElOnToWPjw8KCgrwxRdfoLKyEgqFAkOHDkV2djYCAwPtCd3pDDdQbIoI4NlVR7DwkQSrlkM3NYXUnCkjhdy/WQ96U7GldgszikcmAE8/YHoEy5mJxoq9RVixtwjPDYrF00xqiIi8RrP2ZjK0evVqZGdnY9OmTY66ZbM5e28mczR7DAX4yvDuD79YVRjcVP+ZplYdaUZFCi6qsHjrWe0+TgvHJzh980VLseluIGlNPDFzrW+8aC9BAOaOjkdiFzn70BARuSGnrGayRv/+/W3azsCb6Y5yfDGtP06UVmDn6St4f+d5s9esO3YRT6VEo2NQG5PTSJamkHJ+uao3KjJndDySurRvdjM9a1mKzdYprOKsdKcnNKIIZG5t3CBUJgBz0uKR2JmJDRGRJ3JYMqNWq/Hhhx82uRqppUqObOyqG9CmldEu27o+2HkOO09fhQjjaSRzU0gBvjKjot/F2866tK9KU9Nbtk5hLZqQ6JRVTaY0iND+nViz+ouIiNyLXauZgoODERISov0KDg5GYGAgPvvsM7zzzjuOjtGrPJ8ahxlD48y+/uPviQzQ+JDNWFeAE6UV2imkOWnxRquOquvqJd/12pErojQrsqRgzeovIiJyL3aNzLz33nt638tkMoSFhaF///427c3UUr06Kh5BbVprpzksaUDjxokCoB2tMZxCUqrUTu0TYy1HrYgytwLKVdhgj4jIszi0ANjQSy+9hL///e8IDQ111ls0SaoCYGsoVWr85+fLKL9Zi9BAP8zf+JNV18kAbJgxQG/1U3ZeiU1Ftu7MVDGxq2WkxeP5wXE2dVImIiLHseX57dRkJigoCPn5+bjrLun2IHLnZEaXrQ9wQQCyDGo7NCuoXFX060yGyZk1y9wdSQAwY2gcPtpdaLTUvKi8Gm19fbgjNxGRE7lNMhMYGIgTJ04wmbGS7gPcGt6+eaJhcuaKJduWaNpE6v7tsGCYiMg5bHl+S7qdAemb2C8K++YOxVvj7rXqfFcX+bqaQu6PlLgO2mSttfmm0y4hAkZ7TLFgmIhIekxm3IxC7o8n7o/B0HvCrDq/JW2eeC4zXeoQTPL2pJKIyN0xmXFTK5++DwPuCmnyvLe++9kF0biP4qx0SDxAY4Q7chMRSYvJjBtb/VwKZgwx35MGADafKsN/Z+e7JiA3UZSVjgMZwxAa0FrqUCAAeG30Pdol8rmF5ZxyIiJyMbsLgG/duoWTJ0/iypUraGho0HvtT3/6EwDgxRdfxD/+8Q8uzW6mH0+XYdqqoxbPCWnbGiun9rNqs0pvolSpsf7Ybzj1mwo7T19GbUPT1ziaTAAe6dUZG45f/GM7CW6PQETULE5fzbRt2zY89dRTKC833jxREATU19fbekun8fRkRncnamuMSYzAR5P7ODcoN/fNkRK8+m9pOggbMlzSzeSGiMg6Tk9munbtilGjRuF//ud/EB4ebnegruDJyYy9zePSEyKw9AnbEhpvbA43beVh7PnlKu5I2HwPaJyKEn7v0Myl3ERE1nF6MhMUFITjx48jLs5yPYc78ORkJrewHJNWHLLr2oROQfj+5UFWnas7+uPND9vJHx/A/l+vSx0GZALw/l96om9MiNckjkREjub0ZOaZZ57BAw88gGnTptkdpKt4cjLT3Lb+vaLkmDm0K4Z3jzA78mLqPXwEAetfSvHqDreDF/2ICxW3JI1BQOO04HOpd7W4WicioqY4PZmpqanBo48+irCwMCQmJqJ1a/1VJS+//LKtt3QaT05mAP2uwDI0bjxpq9C2vrheU/dHceroeCR2aSxOLSqvNjn6o7uxpbeO1Gj0+8cPuFp92yH3GtdTgY35Sr1jms/SkjEJEfjIxqlBIiJv5vRk5pNPPsELL7wAf39/dOjQAYLwR+cPQRDw66+/2h61k3h6MgP80dY/wFeGRz7K1RtFseZBaY5m1c2irWcsjv54+7YJjyzdh+OlKqfdX/j9/zT1v7QZQ+Pw6qh4p8VBRORJnL6dweuvv46///3vUKlUKC4uRlFRkfbLnRIZb6Fp658cGYzM8Ynw+T15lAnAs4NikZFm3wOwQQQWbz2LOaPj9e5pyNs73I5JVDj1/iIaE5mmtqlYuquQPWqIiOxg18hMSEgI8vLyWAAsEaVKjZX7i7Aip0g7FTQnLR6l16vx5cFSm++3Zvr9iAkNMDv64+0jMwDQ+x8/4LqDpprMkbdphapbdyyOpE3qH4mFjyQ5NQ4iIk/g9JGZKVOmIDs7267gyDE+2VukfShqRlhmDL3b6j2dNDSt+M2N/vgIAhaOTzBKZLyt2+2c0c6f3lE1kcgAwJpDpV7zmRIRuUorey6qr6/H4sWLsX37diQlJRkVAP/rX/9ySHBkWlF5tVGNi2YqaOXT9+Hpzw9j15mrVt3ryZQoo0RlYr8opHYLQ3F5jTbR0WW4lHvawFg8MzDWY0dulCo1Mta7R5M9EdBO6Xlb3x8iImexK5kpKChAr169AACnTp3Se023GJicIza0LWS/N2HT0N3scOXU+/C/B4oxf9NPTd7r89wL2H32CtY8l6L30FTI/U0+RDUPfs17N4jAir1F+GRvEbImeOaqJ1PJoZT+92Axtp0qQ4PY2Gxvblo8nk91/yldIiKp2JXM7Nq1y9FxkA0Ucn9kjk/ULtk2NRX0YI9wvPHtT1Y9pIuvqZGSuRNTU6IxMiHC4miAuQe/CGDuugL8VlGDB7uHe1TfFFPJoZS2FJRp/1sUgcwtZwAReH5wY0Ljjd2aiYiaw+6NJj2FNxYAa2iWbJuaCgL0e9TYQgBMjrIoVWocKb6Ov67Nb/LBP+juUCz+c5LHPGx1PysfQbD5M3M2GYD9GcOQ88vVFtGtmYjI6X1mPIk3JzPW0CQ8XxwoxtZTZU1foOP51FgkdJajb0yI3kNUM5HY1D8cAcDcMZ4zRaKbHKa/l4Pr6jtSh6Rn6aRemLXmeItbaUZELZMtz2+7ppnIc2hqX1LiOuBEaQVeXnMMF65b18Z/eU6R9r91m/NZm/2KMJ4icWe6dULH3hiFmLmbXR6DTABGJ0ToTTUBjZ9/gyiaLPzefFKJ9CQFExoiarHsWppNnik5Mhh7XhuOTTMGoHtEO5uubc7wXdbWMzhRWtGMO0ijOCsdAa1dV9AuANjw0gAkd2lv8sWokACYiuatzafxQNZOZOeVAPC+ZfNERE3hNFMLpVSp8cqa4zhU7Jokw1wdjicwVZv0zZESvPpvxy/nDmrjg6pb9SZfey41Vtso0RQfQcBrafdot6dgTQ0ReTLWzOhgMmNMt0+MIABtW/vgZp3pB6gj2VLf4QkrdgZk/ohLKtfsvC37fW+nJuuUDPaAYk0NEXkqp3cAJs9l2CdGFIGauno8nxqLezs5N9mzdo+n7LwSPJC1E5NWHNKbPnE3uRnD8Wjvzi55r7/cF9VkIiOD8WaW3r6vFhERwGSmxTHVJ6YBjcW+p5VVyBgTj3+MvRdxvzfgs5VMACb3Nz2tIQAI8LX8T85UU75560+5bf1H39gQl7xPXtE1i6/7CAJGJUSYPB5j5d8la22IyFMxmWlhNA3iTNHs8fRgj3D8+N9DsWnGAMRHBNp0/zmj45GeZHoXahHA2KW5eGfbGbPXW9qqwd0oVWrMddE2COeuVJt97e6O7bD+pRRs/8l46f1rafdYNcXkKaNhRESmMJlpYTTdg33MbDuhmzgkRwZj2yupmDnU+mXVmVvPYOPR30yuutFYursQz6w8bHIUwFSyZcvogisVlVcbTetI4dyVm9haoDTZyDCpc/smr/e00TAiIkNMZlqYE6UVqLp1Gx8/1Rv/GHuvUdJhmDgoVWoM6BqKTTMGYNS94Va9x9fHLjZZ37Hz7FVMWnEIAzL1RwEMky1zu3a7g9jQtnCXrcj+n05PIA1rk0BPGg0jIjKFTfNczFmrdKy57399nY91xy6avYdMAJ4ZGKP9Xm/VE4Dpg2KxacYAfLSzENtPX3ZI3Jo9nVK7hWnjbmrXbnda6fTswFis2GucSLiD5Eg5isobp6csfU5NbVxKROTuuDTbhXSTA00PkNRuYc1+MJu678R+UXoP/StVtzB2aa7Ze+h2+JUJwJy0eG2/EsPz5o6Jx/2xIRbvZ6slj/fCQ8mdmjzP3J/VGo5MggwTvbE9OyGkrS8uVdbg3OWbqG9oQEXNbajM9IxxtVE9wrFg7L1QyP1Nfg6Ge1MtHJ9g8nN1p0SSiLwb+8zocJdkRqlS44GsnXrJgfB7BiHC/gZnpu7rIwh4cchdWLq7EOLvD/20hAhsLrB+b6amdpGeMSQOUR0CMHddQbO6A2ssndQL6UmWkxlzf1Zr+qg0JwmyNw6lSo0BmTuNPp+/jYnHaWUVauru4NTFKty6XY+EzkGorqtHXnGlXTHZwzDxPVJ8HTJBQO/oYLMbl3KTSyJyFe7N5IZM1SXoppGaokvd6RZ771sviliyq1Dv3oZ7/TSlqV2xl+4uRMaYeORmDMMznx3G6cs3bbq/od7RwU2eY6m2w9JnZq7A1dbP2tY4isqrTSZ6CZ3bY7qJzTfTP8ixOZbmaBCBOesKcFpZhS8OXLCYpDj6MyQiciQWALuIpSXRGvYUXRZcVFl1nggg9e5QvWOacGQCjAqBralrXbT1DP7x3c/NTmQAYOLyA02eY+9KJ0cXuFobh63xlrmom7Chz3Mv6CUpc9YVYNrnh7X7aSlVanx/8pLZz5D9aYhIahyZcRHNKh1NXYKp9vS2Fl2eKK1A1lbzPVt0yQRg0Z+TcKXqFo4UV6BvTDA6BrXRFtnm/HJVr2bisX5dsOZwqcV7NojAllO2jfiYU3JdjW+OlODRvn+MCBjWZxh+htaudLK3wNVcfYi1cdgab3xEIPYXXrcYk6v8eOYqfjxzFZ3bt8GlylsmR5h8BAEnf6vE5E8OcuqJiCTFmhkX09200DCBMCy6tFRsmZ1XYrZeRbeYVyNjTDyeNzG1YS42ACbrPZp6n+aQAfg1Kx2A5foMUxs/NsXaAlfd85uqD7E2DmvPO1Fa4dCiamcSADzePwprDpUYJeTcC4qIHIEFwDrcLZkxZO5B19TD3LAAVUMmNHbhXbztbOMIEBpXJj0/2PrGd7oxmEuYZALw4pA4LNWpzXGEd/6ciIF3h9ld6GuJNUmFUqXG0QsVmLX6uCQP6aaWz3sCa1emERFZwgJgD6KZPgH+GIlp6+tjsdjSVA2IRoMItA9ojX1zhxo9uG1dVqvp97JyfxE+ySlCAxpHT55NjcXTD8QCgMOTmW/zL6FzcIBdhb5N0f2sTdFNIA054v2t8e5jPfFUSjSOFFcgJjQAr6w9gRu1d8ye7+jRMUeYteY4quvucLqJiFyGyYwbUKrU+HDnOaw+ZL5GpV4UcexCBYLbVmP/+XKL95u7rgBvju2BET0i9PqI6PZFmTE0DpPvj8Z/fr6MKzdu4cHu4UiONF5RpJD74+kHYpHUpT0gAn1i/li2m1toOQ57hLbzlaSJm+FqHUOubCKXHBms/bsoeDMCK3IKsWTXOajUjT1rfH2AbuGB+D8jumF49wicKK3AkeIKBPm3Qul1Nb45WgqlqtYlsZoiAsj4vREiAPalISKn4zSTxCxN5TSXACBrQmNjPnPTUrr6xwbjyZQY9NHpM2KYBP3lvki8PPxubfM1a+5ri+HxYfh06n0217g0V25hOSatOGT29Qm9O+Pdx3o67f0d7cfTZfjmyG9o3UqAvE1rnL9yExU1t3HWASvPrPVcaiw+2VvE4mAisgtrZnS4czLjjGTAkAzAB5N6Yebq41Zfo+ny+6fkThiQtdPkZoqLJjQ+mHSTDhmAbhHtcKbM/gdmz8ggbJwxCIB9hb72aurvwtMLW839+XxkQH2Da2Lw9M+QiFzLluc3+8w4iTW9NyzVvjhKAwCI1vWN0RABZG45g8c/Pmh2V+g56wqQueVnBPj6YP1LKXhu0F2AgGYlMgCQ0FmO709ewncnGotgU+I64ErVLazYW6jtewJY9/maY+paW3YT90Tm/q25KpEBPP8zJCL3xZoZJ7C27bup2hBTTPWk0fARBIzr1Qkbjl80vboJjXUuM4bG6XUFtkbxNcsPnuUmdmpurq8OluLLg421QwKAXlHtcaykUvt66t2heKBrKBZtO2PX9IWlvxtNwfPR4gq8vPa4V228GBvaVvJiYc1nyP2diMjROM3kYLbuH5SdV4K56wuMRkB8BAGvjb4HSV3am+xJ81raPUjq3F47BaNUqbFyfxE+1kkwNDUzmof1i18exVYHNbmzxqCuHdChXWtszHfue1o7fWHL342ra3ZcYeHmn/GxhDt8Z6TFo31Aa22NmOG/TyIiXayZ0eHqZMbcA2PN9PuREtfB5DVKlRrHLlRAFIHIEH/U1DWYrBOxtk+K5l66K480TpRWYMXeX7H5ZJlLfkvvHt7OIdsdNMXS56thrsjX3LWurNlxBXMbXzpSaNvWKK++bfX5AoDcjGFe8fkSkWOxz4xElCo1VphIZGQCLE5RKOT+SE9q+od5U31SrLlXcmQwlkzqg7+lNz6oA3xlqKlrQICvDNl5v2HN4caOrj6CgORIud4Ujz1ckchYOwVk65Jvaz5vT6KQ+yNrQiLmrCtw2nvYksgAjdNeR4sr8FBy06NqnJoiInOYzDiQuV2Snx14l9v9ADb1oE6ODMas4V31RiNOlFZg5+kruHC9Bt+eMN5s0B2M69XYbTa3sNziw87evZ28iaYuaPHWM9hy8hJqXVgAbM53Jy5Z7BhsbQ0aEbVcnGZyIFM1GTIA+71kGF0z7VJTdxsnf1PBt5UMFytuaUdznM1cAasAQPh9xMWah523TR/ZwxVTTrYYkxCB+Q/3MBp9sbUGjYi8B6eZJOLtv/nrjuYM7x6hPT5reFccLa5ApboOO36+jD2/OL4zsCAAG18agLziCry1+bTeayKgLaBuEIGM9QXarR+a+nO0VOZGEaWy5VSZdgf2xk0sI6GQt8GvV42XlLtqawki8hxMZhxMM4zfkn7zV8j9tTUPT9wfg4c+2ItTl6oc+h6iCNTUNSA9SYGFW05bnO5qEIGV+4swb0wPh8bgTaxtCyAFEbC4tYcMQIBvY4ss1tIQEcBpJofgD1RjP54uw5vf/oySCtub2gHGU0q6UwuGXYdFGE8/edP0nrPofo4CgAi5n9GeTlL3pjFHJgCP9Oqs7a/EWhoi78Ol2Tqcnczo7q3EvhnG3tl2Bkt3276zdsaYeCzeetZsnxfdupfX/n0Se88ZT21Zs1y7pTOsH9JsWhkTGoAA39Yov3kLs9bkSx2mVVhLQ+RdPGY7g2XLliEpKQlBQUEICgpCSkoKtm7dqn1dFEUsWLAAnTp1gr+/P4YMGYKffvpJwoj1KVVqvU0iRTTuWG1Pi31v9eroeBzIGIYeikCbrrt2ow775g7Fmun3Y9/coUYJokLur01UTO0iLoPl5fDUSPM5ahKA5MhgTBt0F4Z3j0BKXAf0jQmBzJa9MCTE7RKIWi5Jk5kuXbogKysLR44cwZEjRzBs2DCMHTtWm7AsXrwY//rXv7BkyRLk5eUhIiICI0aMwI0bN6QMW+tI8XWjIXhN3wz6g0Lujy1/TcWnU/pYfc0n+34FAL0HrSnm9hx6NjWWv6E7QFN7VrkTT99ygojsJ2ky8/DDD2PMmDHo1q0bunXrhrfffhvt2rXDwYMHIYoi3nvvPfztb3/D+PHjkZCQgFWrVqGmpgarV6+WMmwtwcwPeA/4uS+J4d0jsGhColXnNoiw6rdsTSGrLpkAPP1ArD0hkgkT+0VpR8nc9Z+2pZWDzdmUlIg8g9vsml1fX4+1a9eiuroaKSkpKCoqQllZGUaOHKk9x8/PD4MHD0Zubq7Z+9TW1qKqqkrvy1n6RAcb/XAXBKB3dLDT3tPTTewXhQMZw/BIL/NN0jSs+S3bcOTARxCQOT6RozIOppmOKspKx0MJEXqvBfpJ+2Nk1L3hyJqQgJO/VeLH0/r7gGXnleCBrJ2YtOIQHsjaiey8EomiJCJnknxpdkFBAVJSUnDr1i20a9cOGzZsQI8ePbQJS3h4uN754eHhuHDhgtn7ZWZm4s0333RqzBqa9vCG3Un5ILVMIffH1AEx2HD8kkPu1xKXw0tpyRN9sMTg2PiP9jd76wt7bf/pMrb/dBkA8NWhUvSOao/1Lz0ApUqt/d8m0DjaN2/9KYs9iIjIM0mezNxzzz3Iz89HZWUl1q1bhylTpmDPnj3a1w2nckRRNDu9AwAZGRmYPXu29vuqqipERkY6PvDf8UFqn+TIYEzo3Rnrjl00e44tjdHYCE9a6196AD+eLkPmltM4f1XaItxjJY0jNP6+rdhwj6iFkDyZ8fX1RdeuXQEAffv2RV5eHt5//33MmTMHAFBWVgaFQqE9/8qVK0ajNbr8/Pzg5+fn3KAN8EFqn3cf64meke0xf5PxCjWuRvI8w7tHoEcnOVIyd0odCnafvYqXhnY1u7GoYW8ozfdtfX1QXVfPnlFEHkbyZMaQKIqora1FbGwsIiIisGPHDvTq1QsAUFdXhz179mDRokUSR0mO8mCPcLzx7U9Gv0HPSYvnw8QDKeT+WOTknbmtMeSeMG09Vca6AjSgMUFeOD4B3+ZfQtbWM9reUAPvDsW+c+V6KxNlAjBtYCyeGchVcUSeQNLKvXnz5mHv3r0oLi5GQUEB/va3v2H37t2YPHkyBEHAK6+8goULF2LDhg04deoUpk6dioCAAEyaNEnKsMmBDAt4ZUJjw7znB8dJHBnZS1PkPbpHR0neP7FzkN7eYZoqfRHA9lNlyPw9kdEc22uQyACNozkr9hZhQCaLhok8gaQdgKdNm4Yff/wRSqUScrkcSUlJmDNnDkaMGAGgcZTmzTffxPLly1FRUYH+/ftj6dKlSEhIsPo9XLlrNtmPO1l7rxU5hXh7yxmXvFdcWADa+bbCteo6jOgejlUHLzR7/yl2FiaSBrcz0OHMZIZ7MhFZb/LHB7D/1+tSh2EXbo1B5Hq2PL/drmbGU2TnlRgtyeaeTI7BJNE7ffVcCgDg3e1n8P1JJSCKKLruGY3sTl6sZDJD5MY4MmMHpUqNB7J2Gq2S4FB08zFJbFmUKjVe+vIITl2swu0GqaMxTyYA++dyF3YiV/KYjSY9lan9gLjJXfOZa3LGNvTeSyH3x4YZg3BuYToOZAxD/9gQqUMyqUEEPtx5jtsiELkpJjN2MLUfEDe5az4miS2bQu6P7OdTMGOIe65kW32oVG9bBO75ROQ+WDNjB81y4nnrT6FeFC1uckfW0ySJppqcUcvx6uh4PJESjWdXHsZPZTelDsdIgwjMXV8AiI1Lu031pGHdF5FrsWamGbic2PGy80qMkkTWzBAAzPzqKL4vKGv6RAllpMWjfUBr7XSpIABz0+Lxp+ROOFJ8HYIgoE90MH9eEFmBS7N1sM+M52GSSKacKK3A2KW5UofRbAKArAksbCdqCguAyaMp5P5IievARIb0aDYnlZpM0DYVtosIIGN9AWttiByINTNEbog1F6a9+1hPPJUSjSPFFSi5XoNVBy647L2npERjdIICMaEByPnlqt7KO1s1iLbtCk9EljGZIXIz7LVjWXJkMJIjgwEAndr7I3Ora7ZKWHXgAq7eqMVHT/TBxH5RSO0Whg9/PIfVh0ttvpdMsG1XeCa3RJaxZobIjbAho+2UKjXGL90PZVWtS97vwfgwRIYEYFyvzugY1AYLNv2E7T9ftvp6QQCybEhQnZ3cMlEid8XtDIg8lKVeO3zQmKaQ++PAvAf1jsXM3ey09/vPmasAgJW5tk9xvTysKx7vH2X136W5RpKp3cIcsgyco4DkLVgATORG2JDRMYqz0tG+jY8k7/3plD5YOqmXUZGwDEC3iECb7tVUI8nsvBI8kLVTr5mftaztuM3mgOQJmMwQuRFNQ0YfofFRyIaM9stfMBrFWemYNTQOfi78Sfdxzq/oHR2M6YNi9Y43AJi5+jhSMndi+Z5Cq+5lKbk1lYxkrC/AidIKq+5tTcdte5IlJj8kBdbMELkh9tpxjriMzah3k59443p2wsPJCvxaXo37YkLQMaiNyekic40kcwvLMWnFIaP7WtvHpqn6LHvqtzhtRY7Epnk6mMwQka7Xvs7H18cuSh2GWaaSAFPJralkQ8PaonFLHbfNJUtrpt+PlLgORsdZvE6OxgJgIrJKS1zJsvixnlj8WE9MW3kYP569KnU4RhpEIGNdAeJ/r685XHwd98WEICWuA5QqNb47cRGCICAy2B/TBsbik31FMPyV1Nqicc0Sc1OjgLbulcbidZISkxmiFsrclEBLSXA+ffo+ve+/OVKCN749hZo66QerGwCjrRt6R7XH8ZJKGEZnrhvxyd8qTY6gGFLI/U3+Pdu6oS43iiUpcZqJqAUyNyXwWto9WLT1TIuveXDm0m5XsTTFY0vCakv9FjeKJUdizYwOJjNExswWjwrQm7Jo6TUPvd/cjuvqO1KHYTdT9S2GI3JzRscjsYvcYSNxthavt5SRQLIda2aIyCJTUwIygDUPBo69Mcrk8adXHsYuN6y3MfT9yYs4f/UG1h8pxZnLN9DOrxWu3rytfb1BhHY7CEeNxGn+rRSVV+NK1S1U19WbTVScnVhRy8GRGaIWSndKQAbgL/dFYs3hUr2ajJY+MmOJUqXG0l3ncKJEhTPKKtz2kp+k/aKDAYgYeW8EyqtrcexCJdq2lqH4eg0aGkQ8mRKD6alxZq/XTVA0TNVktfX1wSMf5ZpcjdWSpzjpD5xm0sFkhqiRqeF8pUqNlfuK8cm+X9Eg/lFMKgI21zy09OmCH0+XYffZqxhyTxiGd4/AMysPY6cHjN7Yw1cGTE6JQd2dehReuQkAUMjbQH27Adt+Mr1PlY8g4LXR92DRtjPaf2uWHj6CAGx8aYDFkR3ybkxmdDCZIbK8csmwEFgmAB/8pRf6xARb/QBhszTTlCo1fjx9Gb9ercaaw6VQ366XOiSPJACYmxaPP/XspB3VYZLj/ZjM6GAyQy2dpWZmReXVNjVGs/X+fNDo++ZICf657Swu36wDAIS1bY28+SMBACtyCvH5/iJcUdXitqWbeJmmRmgsndvcxLmljya6OxYAE5GWpWZmjugNwmZp1nu0bxQe7Wv6wTs9Nc5kLcqJ0gq8s/0M8ksqUV3XYPWD31PY8ucxPNdwF3HD5MRSssLRRO/CZIbIy1lKWCw1RrP2t1Y2S3Ou5MhgfPlsivZ7pUqN/7PmOA4WW95QMjbUH1EhbbHnl3Kj1yKD2+DWnQZcvVHn8HhdrV4U8d6OX3D1Zi12nb0K8ffk5JFenbHh+EWTyYq5HcM1SZEtOLrjHjjNRNQCNNXMzLA3iK2/tbJZmuvd+z/bUF1nugYnPMgPh+Y9COCPv9sAXxlq6hqM9nf6z8+XUVReDd9WAipu3sbFyhrU1TdgRI8IXKuuxdHfVzPl/nodde6yS6edPp3SB8O7R9i875Q5hiu3Jt0XiVnD7wYAkwkOEx/bsGZGB5MZokbWNjOzpgbG3Moo7vTtWu9uP4MVOb/ilk6S0Tu6Pda/+IBT3u/H02XYUqBEm9Y+8Gvlg51nLqP4mtop7+UscWFtcf9dIfjqUKnRawcyhln9b1epUmNA5k6T02Sa2h5BaCxcfj41rsVvH2IPJjM6mMwQ2aap31pN/VBO7RbGH8gSOlFagSPFFegbE4zkyGBJ3jvIvxX+98AFnLxY5dL3d6SokDa4u2M77D9fjlt3AB8ZMKFnZyx+rKfRuW9v/hkr9hZZdd9xPRX49oTSePsQnaXqpqbCWvrKLSYzOpjMENnG0sgMAKPXhN9/DRXBQkpq/Pdz7EIFisqrcbu+AXfqRXy0p9BoZ29P07a1DL6tZOgVHYzJ/aMw/YujJhv+2cLU6qwNLw3AmbIbFhsPthRMZnQwmSGynbkaGHOjNrq4LJsMaRKcHT+XYWO+Uupw3IJh0bwuc8vVfQQB619KaTEjNUxmdDCZIbKPqRoYU6M2pix5vBceSu7kgijJ0yhVaqw/9hv+8/NllN+sRZtWMgzvEY68ogocLanUnicAyJqQCABGoxSezkcQ8OKQu7B0t+0jVprNYFvCSA2TGR1MZogcS29Pp99/sBr+EGkJP2jJ8U6UVmDn6SsIC/LD8O7h+ttu7C/CJzlFaEBjMjCuVydsPH4J9aIIAUBi5yCT9TpRwW1QUnHLtX8QM2QAPpzUC79VqLW1Ms3h7aOgTGZ0MJkhcjzdUZucX64iY10BGgzO8fYftOR6hqOFploKmJoeVarUWLLzPFYfKpG06eCjfTpj9sh7mhzdFNA4AmO0q72Jc19P7470JIVX/u+MyYwOJjNEzvf9yUuYufq40XFb+3YQNZelFgGGIzwCGv+PK5+Cfj5ArYUtujSjmpU1t5G19Yx2ifdLQ+KwbHdhi9plnMmMDiYzRM7H/ZnIk+gmPAD0Rhl1R3bG9+6Eny6qUHy9GjV1rnlULnm8cZNXU/97ei3tHizeehb1Jh7bMgAbZgxw+dJ8Z+LeTETkUpa2RSByNwq5v96/Tc1/T+wXhdRuYSZHdpQqNVblFuHHn6/gWk0d7tQ3oOqWY3dB9xEE9IkJNrvfWVLn9tg3dyjWHLqAD3YW6r3eAGDc0lxkTWh6hKa5jfrcsdEfkxkicghLDwIiT2GY6Ogen5vWA3PTeugdf+3rfHxfcAm3bosma1ps0dbPB/vOXcXAu8PM7neW88tVo0RGQwQwZ10B4iMCTS7fVqrU+GxfET7dV2T3Bpu6TTMF/N7heLDxBqmuxmkmIiIiB9D00/ku/yK2/XzF7vu08/NBUhc5DhRehwhoRzpTu4WZ3ULBFN1kJTuvBHPXFRhda2k6WKlS4+iFCoiiiKiQAOScu4p3fzhndF7GmMYtGxyN00xEREQuppD7Iz3JH+lJjT2WVuQU4u0tZ2y+z83aeuQWXgcAJHUJwj/GJiA5Mhi5heU2rcbS7AYeHxGIjPXGiQzQOH1VXF5jlMwszylEppWxZ245gz8ld5J0NFYm2TsTERF5sempcSjOSsesoXGNK6fscPK3Koxdmou3N/+Mtr4+Nt+nXhSRV1xhdim4TIC2EFrjnW1nrE5kNB76YJ+NkTkWkxkiIiIn+q9R8SjKSsc7f060+x4r9hZh7NJcjO/d2abrZAD6xQRDZiYLEkUg55er2u+X5xRi6W7TNTmWXKuuwzdHSmy+zlGYzBAREbnAo32jtCM19lp37CIAYEi3Dnh5WFdsmjEAGWPizSYrc9LicabshtmRGRGNU1FKlRpKlRpZW22fFtP44afLdl/bXExmiIiIXOi/RsWjOCsdw+LD7L7H7l+u4YOd57Hx2EU8nxqH/XOH4bnUWO1DXSY0Fub+qWcnzFlXYPFemrqZovLqZjUQHHlvuP0XNxMLgImIiCTw2dT7oFSp8fAH+1BeXWfXPVYeuICVBy5g1tA4zBvTA08/EKvXHuG7ExebvIeAP+pmBDs7IocH+eHRvtJ1IObIDBERkUQUcn8cmT8Cm2YMQHAb+8cXPtxViJi5m7Hu6G96fZ4EoemSYRHAS18exdgP99mdFDw36C47r3QM9pkhIiJyIw9k/gcXVbXNukdcWFv867FkdAxqY1NvGnttcsJWCtybSQeTGSIi8kTvbj+DD3fZvrJIl18r4PH7ovHFgQsWd+puruKsdIff05bnN6eZiIiI3JCmUHjTjAFI7mzfL+O1d4DPcy/Ax6uHLZjMEBERubXkyGBsmjUIxVnpGH6PfSugbjs4JkMxczc7+R0s42omIiIiD/Hp0/cBaNwq4d0fzuDWHYkDchMcmSEiIvIw01PjcOatdAyIC5E6FC0pR2eYzBAREXmo1dNTEBXcxmn31yzslgnAogn2b8fgbFzNRERE5OEe/mAvCi5VNeseM4bEoZVMgG9rGaJD2qJPTONSa90mfHfN3YyGJu7jqJVNtjy/WTNDRETk4b57eRCGv7sLhVdr7Lr+nT8nmuzgO/yfu1BYbt89XYkjM0RERF7gRGkFxi7NlToMAI4ZnWGfGSIiohYmOTIYiRb60bT24ie+pH+0ZcuWISkpCUFBQQgKCkJKSgq2bt2qfX3q1KkQBEHv6/7775cwYiIiIvf11rgEs6/dbqrYxYNJWjPTpUsXZGVloWvXrgCAVatWYezYsTh+/DjuvfdeAMDo0aOxcuVK7TW+vr6SxEpEROTukiOD0TuqPY6VVEoWgzO2NmiKpCMzDz/8MMaMGYNu3bqhW7duePvtt9GuXTscPHhQe46fnx8iIiK0XyEh7rOmnoiIyN2sf+kBhLWT5hd/KRIZwI1WM9XX1+Obb75BdXU1UlJStMd3796Njh07on379hg8eDDefvttdOzY0ex9amtrUVv7x26jVVXNW6pGRETkafJeH+GyJnZSJTC6JE9mCgoKkJKSglu3bqFdu3bYsGEDevToAQBIS0vDo48+iujoaBQVFWH+/PkYNmwYjh49Cj8/P5P3y8zMxJtvvunKPwIREZHXc4ekxRzJl2bX1dWhpKQElZWVWLduHT755BPs2bNHm9DoUiqViI6Oxtq1azF+/HiT9zM1MhMZGcml2URE1OLYOzrTSgDOZ0qbvHjU0mxfX1907doVffv2RWZmJpKTk/H++++bPFehUCA6Ohrnzp0zez8/Pz/t6ijNFxERUUtk72jKHRFQqtQOjsZ5JE9mDImiqDeyouvatWsoLS2FQqFwcVRERESeyd6EptgDOv9qSFozM2/ePKSlpSEyMhI3btzA2rVrsXv3bmzbtg03b97EggULMGHCBCgUChQXF2PevHkIDQ3FI488ImXYREREHkWT0Ngy7RQTGuCscBxO0mTm8uXLePLJJ6FUKiGXy5GUlIRt27ZhxIgRUKvVKCgowBdffIHKykooFAoMHToU2dnZCAwMlDJsIiIij6RJat7cdApfHylB9W3TZbOLJiRCIfd3ZWjNInkBsLNxbyYiIiLzJn98APt/va79/kDGMLdIZLhrNhEREVnlq+dSmj7JzbldATARERGRLZjMEBERkUdjMkNEREQejckMEREReTQmM0REROTRmMwQERGRR2MyQ0RERB6NyQwRERF5NCYzRERE5NGYzBAREZFHYzJDREREHo3JDBEREXk0JjNERETk0ZjMEBERkUdjMkNEREQejckMEREReTQmM0REROTRmMwQERF5EaVKjdzCcihVaqlDcZlWUgdAREREjpGdV4KM9QVoEAGZAGSOT8TEflFSh+V0HJkhIiLyAkqVWpvIAECDCMxbf6pFjNAwmSEiIvICReXV2kRGo14UUVxeI01ALsRkhoiIyAvEhraFTNA/5iMIiAkNkCYgF2IyQ0RE5AUUcn9k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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.plot(clust_cosmic.star_systems['m_ubv_V'] - clust_cosmic.star_systems['m_ubv_R'], clust_cosmic.star_systems['m_ubv_R'], marker = '.', linestyle = 'None')\n", + "plt.gca().invert_yaxis()\n", + "plt.xlabel('m_ubv_V - m_ubv_R')\n", + "plt.ylabel('m_ubv_R')" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "77389803-b5ab-408d-a825-68c2ac30c131", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Text(0.5, 1.0, 'Singles Only')" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.plot(clust_cosmic.star_systems['m_ubv_V'][clust_cosmic.star_systems['isMultiple'] == 0] - clust_cosmic.star_systems['m_ubv_R'][clust_cosmic.star_systems['isMultiple'] == 0], clust_cosmic.star_systems['m_ubv_R'][clust_cosmic.star_systems['isMultiple'] == 0], marker = '.', linestyle = 'None')\n", + "plt.gca().invert_yaxis()\n", + "plt.xlabel('m_ubv_V - m_ubv_R')\n", + "plt.ylabel('m_ubv_R')\n", + "plt.title('Singles Only')" + ] + }, + { + "cell_type": "markdown", + "id": "6f9f47e3-eb3c-4855-9d7e-a5e645c5229a", + "metadata": {}, + "source": [ + "Semimajor axis distribution. Note this goes down to lower semimajor axes than when we evolve each star individual since binary interaction is now taken into account." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "594beb18-cdee-4cc4-8d4b-64848ce4700e", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Text(0.5, 0, 'log(a) [AU]')" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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c+zYMT3zzDOBSz+nurzz/fff64svvtBVV10VUu0rV67UoUOH9OGHHyoiIiLQ/tlnn+nOO+/U/v37lZCQoC5duuiVV17R999/HzTKs3nzZrVv3z5QLwB7MYICIKBTp0669dZbdf/992vDhg366KOPdNddd+miiy7SrbfeKknKycnRypUrNWPGDO3cuVMvvfSS3nnnnaBRlauuukrt27fX+++/H2i79NJLdezYMc2aNUtffvml5s+frxdffLFeDZs2bZLT6VTPnj1Dqn3OnDkaMGCAunXrprS0tMAybNgwtW/fXgsWLJAk3XnnnYqMjNTdd9+tkpISffHFF1qwYIHy8/P10EMPnctpAxAGBBQAQQoKCpSenq6BAweqZ8+esixLK1euVKtWrSRJv/3tb/Xiiy9qxowZ6tatm9599139+c9/DhqNiIiI0H333aeFCxcG2n79619rxowZevrpp5WWlqaFCxcqPz+/3vFfeeUV3XnnnYqOjj7rmr/55hutWLFCw4YNq7fN4XBo6NChgcs8LpdL69evl2VZGjx4sLp166bp06friSee0IQJE876mADCy2Gd7qIzAJyl+++/X5999lnQrcHffPONrrjiCpWWliolJeWs9vPtt9+qS5cuKikpUWpq6mn7jRo1SgcPHgzbY+7tOhaAkxhBARCyv/3tb/roo4/0+eefa9asWZo7d65GjhwZ1MftdmvOnDnavXv3We93165deuGFF84YTn709ttvq23btnr77bdDrv9srF+/Xm3btg0aBQLQeBhBARCy4cOHa926dTp06JB+8YtfKCcnR2PGjGm041dVVammpkaSlJSUpJiYmAY/Rm1trb7++mtJUtu2beXxeBr8GABOj4ACAACMwyUeAABgHAIKAAAwDgEFAAAYh4ACAACMQ0ABAADGIaAAAADjEFAAAIBxCCgAAMA4/w+5L2052I6OXQAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.hist(clust_cosmic.companions['log_a'], bins = 40)\n", + "plt.xlabel('log(a) [AU]')" + ] + }, + { + "cell_type": "markdown", + "id": "bf893097-e5f5-43c7-90a4-941deca662be", + "metadata": {}, + "source": [ + "Kick distribution. We add the kicks from COSMIC which come from supernovae prescriptions and account for if the objects are disrupted or not." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "cf7ede5c-417f-4342-8e6a-3b9efae1e43e", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Text(0, 0.5, 'N objects')" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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bt00depU3XvvvYqPj5fE/LqTu+ayZcuWOnnyZJHx//Wvf1XpfBN03Kx27dqKiIhQUlKSS3tSUpIGDhzooaqqB2OM7r77br311lvatm2b2rdv77K/ffv2atmypcvc5ufna8eOHc65jYiIUK1atVz6ZGVl6dChQz4//yNGjNDBgweVmprq/PTp00dTpkxRamqqrrrqKua3Aq699toij0P45ptvFBoaKok/vxV14cIF1ajh+k+Wn5+f8/Zy5td93DWXAwYMUE5Ojvbs2ePss3v3buXk5FTtfFfZsmcfcvn28pdeesmkpaWZmJgYU79+ffPdd995ujSvdtddd5nAwEDz8ccfm6ysLOfnwoULzj5PPvmkCQwMNG+99ZY5ePCgmTx5crG3PLZp08Z89NFHZv/+/ea6667zydtHS+PXd10Zw/xWxJ49e0zNmjXNE088YY4cOWJee+01U69ePfPqq686+zC/5Td9+nTTunVr5+3lb731lmnWrJlZtGiRsw/zW3p5eXnmwIED5sCBA0aSeeaZZ8yBAwecj0Fx11yOGTPGdO/e3Xz22Wfms88+M926deP2clskJCSY0NBQU7t2bdO7d2/nLdIomaRiP2vXrnX2KSwsNEuWLDEtW7Y0/v7+ZsiQIebgwYMu4/z000/m7rvvNk2aNDF169Y1N9xwg8nIyKjib1M9/GfQYX4r5t133zXh4eHG39/fXHPNNWb16tUu+5nf8svNzTULFiwwbdu2NXXq1DFXXXWViYuLMxcvXnT2YX5Lb/v27cX+/3b69OnGGPfN5enTp82UKVNMQECACQgIMFOmTDFnzpypom/5bw5jjKm680cAAABVhzU6AADAWgQdAABgLYIOAACwFkEHAABYi6ADAACsRdABAADWIugAAABrEXQAAIC1CDpANTJs2DDFxMSUuH/GjBmaMGFCqcb67rvv5HA4lJqa6pbavEG7du20fPnyShn7t+a+tLZt26ZrrrnG+Y6mxx57TD179qzwuBWRnZ2t5s2b69ixYx6tA6gMBB3AIs8995zWrVvn6TI8Zu/evbrjjjuc2w6HQ5s2bfJcQcVYtGiR4uLiirygsrIMGzZML7744hX7tGjRQlOnTtWSJUuqpCagKhF0AIsEBgaqUaNGni7DY5o3b6569ep5uowSJScn68iRI7rllluq5Hg//vijkpOTNW7cuN/sO3PmTL322ms6c+ZMFVQGVB2CDlCNffDBBwoMDNT69eslFb10VVhYqD/96U/q0KGD/P391bZtWz3xxBPFjlVYWKg5c+aoU6dO+v7774vtc3n8P/7xjwoKClKjRo30+OOP69KlS1q4cKGaNGmiNm3a6H/+539cfu6BBx5Qp06dVK9ePV111VV65JFH9Msvv7j0WbZsmVq0aKGAgADNnj1bDz74oMslncvH/stf/qJWrVqpadOmio6Odhnn15eu2rVrJ0n63e9+J4fD4dwu7vJeTEyMhg0b5tw+f/68pk2bpgYNGqhVq1Z6+umni8xFfn6+Fi1apNatW6t+/frq37+/Pv7442Ln7bLExERFRkaqTp06JfZJT09Xhw4ddNddd6mwsFDr1q1To0aNtHnzZnXu3Fn16tXTzTffrPPnz+vll19Wu3bt1LhxY82fP18FBQUuY7333nvq0aOHWrdurTNnzmjKlClq3ry56tatq44dO2rt2rXOvt26dVPLli21cePGK34HoLqp6ekCAJRPYmKi7rjjDr3yyiu68cYbi+2zePFirVmzRs8++6wGDRqkrKwsHT58uEi//Px83Xbbbfr222/1ySefqEWLFiUed9u2bWrTpo127typTz/9VLNmzdJnn32mIUOGaPfu3dqwYYPmzp2rUaNGKSQkRJIUEBCgdevWKTg4WAcPHtScOXMUEBCgRYsWSZJee+01PfHEE1q5cqWuvfZaJSYm6umnn1b79u1djr19+3a1atVK27dv19GjRzVp0iT17NlTc+bMKVLn3r171aJFC61du1ZjxoyRn59fqed24cKF2r59uzZu3KiWLVvqoYceUkpKikvwmjlzpr777jslJiYqODhYGzdu1JgxY3Tw4EF17Nix2HF37typyZMnl3jcQ4cOKTIyUtOnT1d8fLyz/cKFC3r++eeVmJiovLw8TZw4URMnTlSjRo20ZcsW/fOf/9RNN92kQYMGadKkSc6fe+edd5x/Nh555BGlpaXp/fffV7NmzXT06FH99NNPLsfv16+fdu3apT/84Q+lnivA61Xpu9IBVMjQoUPNggULTEJCggkMDDTbtm1z2T99+nRz4403GmOMyc3NNf7+/mbNmjXFjpWenm4kmV27dpmRI0eaa6+91pw9e/aKx58+fboJDQ01BQUFzrbOnTubwYMHO7cvXbpk6tevb15//fUSx/nzn/9sIiIinNv9+/c30dHRLn2uvfZa06NHjyLHvnTpkrPtlltuMZMmTXJuh4aGmmeffda5Lcls3LixyHe4PEeXLViwwAwdOtQYY0xeXp6pXbu2SUxMdO4/ffq0qVu3rlmwYIExxpijR48ah8Nhjh075jLOiBEjzOLFi0v83oGBgWb9+vUubUuWLDE9evQwycnJpkmTJuapp55y2b927VojyRw9etTZduedd5p69eqZvLw8Z9vo0aPNnXfe6dz++eefTUBAgPnyyy+NMcaMGzfOzJw5s8TajDHm3nvvNcOGDbtiH6C64YwOUM28+eabOnnypD755BP169evxH7/+Mc/dPHiRY0YMeKK402ePFlt2rTR1q1bS7W+pWvXri4LaYOCghQeHu7c9vPzU9OmTZWdne1s+/vf/67ly5fr6NGjOnfunC5duqSGDRs693/99deaN2+ey3H69eunbdu2FTn2r8/MtGrVSgcPHvzNmsvi22+/VX5+vgYMGOBsa9KkiTp37uzc3r9/v4wx6tSpk8vPXrx4UU2bNi1x7J9++qnYy1YZGRkaOXKkli1bpnvvvbfI/nr16unqq692bgcFBaldu3Zq0KCBS9uv53zbtm1q2rSpunXrJkm66667dNNNN2n//v2KjIzUhAkTNHDgQJfj1K1bVxcuXCixfqA6Yo0OUM307NlTzZs319q1a2WMKbFf3bp1SzXe2LFj9eWXX+rzzz8vVf9atWq5bDscjmLbLt8+/fnnn+vWW29VVFSUNm/erAMHDiguLk75+flFfubXivtuVzpOadWoUaPI2L9e53OlOb2ssLBQfn5+SklJUWpqqvPzj3/8Q88991yJP9esWbNiF/s2b95c/fr1U2JionJzc4vsL+ucS66XrSQpKipK33//vWJiYnT8+HGNGDFC999/v8sYP/74o5o3b37lLw9UMwQdoJq5+uqrtX37dr399tuaP39+if06duyounXrauvWrVcc76677tKTTz6p8ePHa8eOHe4uV59++qlCQ0MVFxenPn36qGPHjkUWO3fu3Fl79uxxadu3b1+Fj12rVq0iC3SbN2+urKwsl7ZfP0uoQ4cOqlWrlkvwO3PmjL755hvndq9evVRQUKDs7Gx16NDB5dOyZcsS6+nVq5fS0tKKtNetW1ebN29WnTp1NHr0aOXl5ZX1q7owxujdd9/V+PHjXdqbN2+uGTNm6NVXX9Xy5cu1evVql/2HDh1Sr169KnRswNsQdIBqqFOnTtq+fbvefPPNEh9iV6dOHT3wwANatGiR1q9fr2+//Vaff/65XnrppSJ958+fr2XLlumGG27QJ5984tZaO3TooIyMDCUmJurbb7/V888/X+TOnvnz5+ull17Syy+/rCNHjmjZsmX68ssvi5zlKat27dpp69atOnHihPNMynXXXad9+/Zp/fr1OnLkiJYsWaJDhw45f6ZBgwaaNWuWFi5cqK1bt+rQoUOaMWOGy+W6Tp06acqUKZo2bZreeustpaena+/evfrTn/6kLVu2lFjP6NGjS5zf+vXr67333lPNmjUVFRWlc+fOlft7p6Sk6Pz58xoyZIiz7dFHH9Xbb7+to0eP6quvvtLmzZvVpUsX5/4LFy4oJSVFkZGR5T4u4I0IOkA11blzZ23btk2vv/667rvvvmL7PPLII7rvvvv06KOPqkuXLpo0aZLLOo5fi4mJ0eOPP66xY8cqOTnZbXXeeOONuvfee3X33XerZ8+eSk5O1iOPPOLSZ8qUKVq8eLHuv/9+9e7dW+np6ZoxY8YVb8MujaefflpJSUkKCQlxnqkYPXq0HnnkES1atEh9+/ZVXl6epk2b5vJzTz31lIYMGaLx48dr5MiRGjRokCIiIlz6rF27VtOmTdN9992nzp07a/z48dq9e7fzTrPi3H777UpLS9PXX39d7P4GDRro/ffflzFGY8eO1fnz58v1vd9++21df/31qlnz/5Zh1q5dW4sXL1b37t01ZMgQ+fn5KTEx0eVn2rZtq8GDB5frmIC3cpjSXJAGgCo2atQotWzZUq+88oqnS3GrRYsWKScnR//93/9dacfo3r27Hn74Yf3+978v9c/069dPMTExuu222yqtLsATuOsKgMdduHBBL774okaPHi0/Pz+9/vrr+uijj5SUlOTp0twuLi5OCQkJKigoKNOzfUorPz9fN910k6Kiokr9M9nZ2br55puv+IwfoLrijA4Aj/vpp580btw47d+/XxcvXlTnzp318MMPa+LEiZ4uDUA1R9ABAADWYjEyAACwFkEHAABYi6ADAACsRdABAADWIugAAABrEXQAAIC1CDoAAMBaBB0AAGCt/w923aKexJluVgAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.hist(clust_cosmic.star_systems['kick'], bins = 50)\n", + "plt.xlabel('kick magnitude (km/s)')\n", + "plt.yscale('log')\n", + "plt.ylabel('N objects')" + ] + }, + { + "cell_type": "markdown", + "id": "516ccebd-2ad7-4dfe-8b24-919707a168e0", + "metadata": {}, + "source": [ + "# Check interpolation over atmosphere grid" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "ce24f553-6020-4000-be02-13feb6c7ba39", + "metadata": {}, + "outputs": [], + "source": [ + "from scipy.interpolate import LinearNDInterpolator" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "a9b3f917-bf60-4c99-bb57-4270541733f9", + "metadata": {}, + "outputs": [], + "source": [ + "interp = LinearNDInterpolator((clust_cosmic.iso.points['Teff'], clust_cosmic.iso.points['logg']), clust_cosmic.iso.points['m_ubv_R'],\n", + " fill_value=np.nan)" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "dade2fb6-ae07-4597-9db7-5bfee462599d", + "metadata": {}, + "outputs": [], + "source": [ + "Teff_grid = 10**np.linspace(np.log10(clust_cosmic.iso.points['Teff'].min()), np.log10(clust_cosmic.iso.points['Teff'].max()), 50)\n", + "logg_grid = np.linspace(clust_cosmic.iso.points['logg'].min(), clust_cosmic.iso.points['logg'].max(), 50)\n", + "Z_grid = np.zeros(50)\n", + "\n", + "TT, GG = np.meshgrid(Teff_grid, logg_grid, indexing='ij')\n", + "\n", + "# Evaluate interpolator\n", + "values = interp(TT, GG)" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "13d68eb1-b495-4051-a150-4c63ddeefc2a", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjcAAAHFCAYAAAAOmtghAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAABLXklEQVR4nO3de3wU1f3/8fckkAQkSQ1KEiAiKpciIFSQqwgqQSgVRJQqcrGtaLkIolVBENBCQCsiYLFYBfpVLr8WIygXiZUEKaCAcvGGWFGiTUy9JYASkt35/UFZXZOdyWZ2M8nm9Xw85vFw58w5c3ZcNp89V8M0TVMAAAARIsrtCgAAAIQSwQ0AAIgoBDcAACCiENwAAICIQnADAAAiCsENAACIKAQ3AAAgohDcAACAiEJwAwAAIgrBDeCCOXPm6MUXX3RUhmEYmjlzpu91dna2DMNQdna279zMmTNlGEbQZY8ePVrnn3++37lQ1LkqrF69Wh06dFBcXJwaN26sSZMm6fjx425XC0AVIrgBXFBVgcLvfvc77dy5M+h806dPV2Zmpt+5mhDcPP/887rpppvUuXNnbdq0STNmzNDy5cs1ZMgQt6sGoArVcbsCAMKnadOmatq0adD5LrzwwjDUJrw8Ho/+8Ic/KD09XU8//bQkqU+fPoqPj9fw4cO1adMm9e/f3+VaAqgKtNwA/3OmC+fAgQO64YYblJiYqKSkJE2ePFmlpaU6dOiQrrnmGsXHx+v888/XI488UqaMoqIi3XPPPWrevLliYmLUpEkTTZo0SSdOnPBdYxiGTpw4oRUrVsgwDBmGod69e0uS/vvf/2rs2LFq06aNGjRooEaNGunKK6/U66+/7ug9/dTKlSvVrVs3NWjQQA0aNFCHDh30zDPP+NJ/2i0VqM6ffPKJ6tSpo4yMjDL32LZtmwzD0N///vdK1T1Yu3btUl5enm699Va/8zfccIMaNGhQpiUKQOSi5Qb4iRtvvFG33HKLbr/9dmVlZemRRx5RSUmJXn31VY0dO1b33HOPVq5cqfvuu08XXXSRr8vju+++0xVXXKHPPvtMU6dOVfv27fXuu+/qwQcf1MGDB/Xqq6/KMAzt3LlTV155pfr06aPp06dLkhISEiRJX3/9tSRpxowZSklJ0fHjx5WZmanevXvrn//8py8IcuLBBx/Uww8/rCFDhujuu+9WYmKi3nnnHX366acB8wSq8/nnn69rr71WTz31lO69915FR0f78ixevFiNGzfWddddZ1mf0tLSCtU7OjracvzQO++8I0lq37693/m6deuqdevWvnQAtYAJwDRN05wxY4YpyXzsscf8znfo0MGUZL7wwgu+cyUlJea5555rDhkyxHcuIyPDjIqKMnfv3u2X/x//+Icpydy4caPv3FlnnWWOGjXKtk6lpaVmSUmJedVVV5nXXXedX5okc8aMGb7XW7duNSWZW7duLfOezvj444/N6Ohoc/jw4Zb3HTVqlNmsWTO/c4HqfOa+mZmZvnOff/65WadOHXPWrFm271FShY5ly5ZZljN79mxTkpmXl1cmLT093WzZsqVtXQBEBlpugJ8YOHCg3+uf//zn2r9/v994jTp16uiiiy7ya+14+eWX1bZtW3Xo0MGvNaJfv36+WUwVGfPx1FNPaenSpXrvvfdUXFzsO9+6dWsnb0uSlJWVJY/Ho3Hjxjku64zevXvrkksu0ZNPPqnBgwdLOv0eDMPQmDFjbPPv3r27Qvdp3rx5ha4L1LpTmVljAGomghvgJ5KSkvxex8TEqH79+oqLiytzvqioyPf6iy++0EcffaS6deuWW+6XX35pe+/58+fr7rvv1h133KGHH35Y55xzjqKjozV9+nS9//77lXg3/v773/9KUqUGGVu588479bvf/U6HDh3SBRdcoKefflpDhw5VSkqKbd4OHTpU6B4/7vIqT8OGDSVJX331lZKTk/3Svv766zL/XwFELoIbIETOOecc1atXT88++2zAdDvPPfecevfurSVLlvidP3bsWEjqeO6550qSPvvsM6WlpYWkTEm6+eabdd999+nJJ59U165dlZ+fX+HWoUDB4E8tW7ZMo0ePDpjerl07SdLBgwfVpk0b3/nS0lJ98MEHuummmyp0HwA1H8ENECIDBw7UnDlz1LBhQ9sulNjYWH3//fdlzhuGodjYWL9zBw4c0M6dO0MSjKSnpys6OlpLlixRt27dgsobqM6SFBcXpzFjxmjx4sXasWOHOnTooB49elSo3FB1S3Xp0kWpqalavny5hg0b5jv/j3/8Q8ePH2etG6AWIbgBQmTSpElau3atevXqpbvuukvt27eX1+vV0aNHtWXLFt19993q0qWLpNOtDNnZ2XrppZeUmpqq+Ph4tWrVSgMHDtTDDz+sGTNm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XVd5eXnOawcAQKSiWypol19+uerVq2d7XdDdUq1bt9bcuXN16tQp37mSkhLNnTtXrVu3liR9/vnnSk5ODrbocn3++ee65ZZb1LBhQ9WvX18dOnTQ3r17Q1I2AABwX58+ffTMM8+osLDQ8rqNGzcqNTXVtrygW26efPJJXXvttWratKnat28vwzB04MABeTwevfzyy5Kkjz/+WGPHjg226DK++eYb9ejRQ3369NGmTZvUqFEj/fvf/7ZdvAcAgGqPlhufdu3aadq0aRo/frwGDBigESNGaMCAAYqJialUeUEHN927d9cnn3yi5557Th9++KFM09TQoUN18803Kz4+XpI0YsSISlXmp+bNm6e0tDQtW7bMd+78888PSdkAALiK4MZn4cKFWrBggV599VWtXLlSo0aNUnR0tIYOHarhw4cHvZJxpeahNmjQQHfccUdlsgZl/fr16tevn2644Qbl5OSoSZMmGjt2rG677baw3xsAAFSdqKgopaenKz09XU899ZReeuklzZ49W88880xkbZz58ccfa8mSJZo8ebKmTp2qN998U3feeadiY2M1cuTIcvMUFxeruLjY9/qn26Yjsrzw746W6XE2kwnOiiq2TE+pc8wyva7NT6dvPfUt071OZztYrEXjdBkYp+vc1PiJHE7X+XFTlN1wyuD+UCBMmC1Vrvz8fK1evVrPPfecDhw4oM6dOwddRrUObrxerzp16qQ5c+ZIkjp27Kh3331XS5YsCRjcZGRkaNasWVVZTQAAgsYKxT8oKirS2rVrtXLlSmVnZ+uCCy7QzTffrNWrV+uiiy4KurxqHdykpqaqTZs2fud+/vOfa+3atQHzTJkyRZMnT/a9LioqUlpaWtjqCAAAnElOTtbZZ5+tG2+8UXPmzKlUa82PVevgpkePHjp06JDfuQ8//LDcdXbOiI2NZW8rAED1x4Bin3Xr1unqq69WlG2XasWEppQwueuuu7Rr1y7NmTNHH330kVauXKmlS5dq3LhxblcNAIAaJSMjQ507d1Z8fLwaNWqkwYMH+zUglJSU6L777lO7du101llnqXHjxho5cqT+85//WJa7fPlyGYZR5jh58mSF65aenq6oqCgVFBTo9ddf1/bt21VQUFDp9xp0cHP22WcrKSmpzNGwYUM1adJEV1xxhd/UbSc6d+6szMxMrVq1Sm3bttXDDz+sBQsWaPjw4SEpHwAAtxj6YdxNpY4g75eTk6Nx48Zp165dysrKUmlpqdLT03XixAlJ0nfffae33npL06dP11tvvaUXXnhBH374oa699lrbshMSEpSXl+d3BLN5dlFRkUaMGOGLI3r16qUmTZrolltusV3YrzxBd0s9+OCDmj17tvr376/LLrtMpmlq9+7d2rx5s8aNG6cjR47o97//vUpLS0MyZXvgwIEaOHCg43IAAKjNNm/e7Pd62bJlatSokfbu3atevXopMTFRWVlZftcsWrRIl112mY4eParzzjsvYNmGYSglJaXSdfvd736nffv26eWXX1a3bt1kGIZ27NihiRMn6rbbbtP/+3//L6jygg5utm/frj/+8Y9l1rn5y1/+oi1btmjt2rVq3769Fi5cyHo0cGzjkbaW6XE2bY/RNvN5U6Ktp3qnRFt3av/XY12B4x7rXy5em99edlPFzbqB0wybqRRmtGWyzFLrdLufjdV+Jke17pQPs6jInEJ8RlRsxVsMXBWiqeA/XfKkomNPz7SIJCUlWV5jGIbtzgDHjx9Xs2bN5PF41KFDBz388MPq2NF6qY4f27Bhg1555RX17NnTd65fv356+umndc0111S4nDOC/uf9yiuv6Oqrry5z/qqrrtIrr7wiSRowYIA+/vjjoCsDAECtYYbgkJSWlqbExETfkZGRYX9r09TkyZPVs2dPtW1b/o/IkydP6v7779fNN9+shISEgGW1bt1ay5cv1/r167Vq1SrFxcWpR48eOnz4cIUegyQ1bNhQiYmJZc4nJibq7LPPrnA5ZwTdcpOUlKSXXnpJd911l9/5l156yRf9nThxwrcVAwAACJ/c3Fy/4KMirTbjx4/XgQMHtH379nLTS0pK9Otf/1per1d//vOfLcvq2rWrunbt6nvdo0cP/eIXv9CiRYu0cOHCCr2HadOmafLkyfrb3/7m2xgzPz9ff/jDHzR9+vQKlfFjQQc306dP1+9//3tt3bpVl112mQzD0JtvvqmNGzfqqaeekiRlZWUFvQ8EAAC1SoimgickJFi2rPzUhAkTtH79em3btk1NmzYtk15SUqIbb7xRR44c0WuvvRZU2dLpbRQ6d+5s23LTsWNHGT9aSv3w4cNq1qyZb2zP0aNHFRsbq//+97+6/fbbg6pD0MHNbbfdpjZt2mjx4sV64YUXZJqmWrdurZycHHXv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7bffrrFN7VZM01RxcXG5aZH6mQjE6lmUJ1I+E1dddZUOHjzod+7WW29V69atdd999yk6OrpMnkj8bFTmOZQnUj4XiBCuDWUOg9///vdmYmKimZ2dbebl5fmO7777znfN/fffb44YMcL3+uOPPzbr169v3nXXXeZ7771nPvPMM2bdunXNf/zjH268hZCpzLN4/PHHzczMTPPDDz8033nnHfP+++83JZlr16514y2EzJQpU8xt27aZR44cMQ8cOGBOnTrVjIqKMrds2WKaZu35TJhm8M8iUj8Tgfx0llBt+mz8mN1zqG2fC9Q8EdVys2TJEklS7969/c4vW7ZMo0ePliTl5eXp6NGjvrTmzZtr48aNuuuuu/Tkk0+qcePGWrhwoa6//vqqqnZYVOZZnDp1Svfcc48+//xz1atXTxdffLE2bNigAQMGVFW1w+KLL77QiBEjlJeXp8TERLVv316bN29W3759JdWez4QU/LOI1M9ERdWmz4YVPheoaQzT/N9oOAAAgAgQkQOKAQBA7UVwAwAAIgrBDQAAiCgENwAAIKIQ3AAAgIhCcAMAACIKwQ0AAIgoBDdANdW7d29NmjTJ7WpYevHFF3XRRRcpOjraV9fyzgFAVSK4AWqp5cuXyzAMyyM7O9uyjNtvv11Dhw5Vbm6uHn744YDnAKAqRdT2CwAqbtiwYbrmmmt8r4cMGaK2bdvqoYce8p1LSkoKmP/48eMqKChQv3791Lhx44DnAKCq0XID1BDffPONRo4cqbPPPlv169dX//79dfjwYb9rnn76aaWlpal+/fq67rrrNH/+fP3sZz8rt7x69eopJSXFd8TExKh+/fq+10lJSZo2bZqaNGmis846S126dPG15GRnZys+Pl6SdOWVV/paeco7BwBVjeAGqCFGjx6tPXv2aP369dq5c6dM09SAAQNUUlIiSfrXv/6lO+64QxMnTtS+ffvUt29fzZ49u9L3u/XWW/Wvf/1Lq1ev1oEDB3TDDTfommuu0eHDh9W9e3cdOnRIkrR27Vrl5eUFPAcAVY1uKaAGOHz4sNavX69//etfvoDh+eefV1paml588UXdcMMNWrRokfr376977rlHktSyZUvt2LFDL7/8ctD3+/e//61Vq1bps88+83Uv3XPPPdq8ebOWLVumOXPmqFGjRpJOd12lpKRIUrnnAKCqEdwANcD777+vOnXqqEuXLr5zDRs2VKtWrfT+++9Lkg4dOqTrrrvOL99ll11WqeDmrbfekmmaatmypd/54uJiNWzYsBLvAACqDsENUAOYphnwvGEYZf7bLp8dr9er6Oho7d27V9HR0X5pDRo0qFSZAFBVCG6AGqBNmzYqLS3VG2+84euW+uqrr/Thhx/q5z//uSSpdevWevPNN/3y7dmzp1L369ixozwejwoKCnT55Zc7qzwAVDEGFAM1QIsWLTRo0CDddttt2r59u/bv369bbrlFTZo00aBBgyRJEyZM0MaNGzV//nwdPnxYf/nLX7Rp06YyrTkV0bJlSw0fPlwjR47UCy+8oCNHjmj37t2aN2+eNm7cGOq3BwAhRXAD1BDLli3TpZdeqoEDB6pbt24yTVMbN25U3bp1JUk9evTQU089pfnz5+uSSy7R5s2bdddddykuLq7S9xs5cqTuvvtutWrVStdee63eeOMNpaWlhfJtAUDIGWZlO+UBVHu33XabPvjgA73++utuVwUAqgxjboAI8qc//Ul9+/bVWWedpU2bNmnFihX685//7Ha1AKBK0XIDRJAbb7xR2dnZOnbsmC644AJNmDBBd9xxh9vVAoAqRXADAAAiCgOKAQBARCG4AQAAEYXgBgAARBSCGwAAEFEIbgAAQEQhuAEAABGF4AYAAEQUghsAABBRCG4AAEBE+f8oG3ogLphTagAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Choose nearest metallicity slice\n", + "plt.figure()\n", + "plt.pcolormesh(\n", + " np.log10(Teff_grid),\n", + " logg_grid,\n", + " values[:, :].T,\n", + " shading='auto'\n", + ")\n", + "plt.xlabel('log Teff')\n", + "plt.ylabel('log g')\n", + "plt.colorbar(label='m_ubv_R')\n", + "plt.title(f'metallicity = 0')\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bf911b4e-a333-4752-ae2e-183adaaef57f", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python [conda env:astro_cosmic]", + "language": "python", + "name": "conda-env-astro_cosmic-py" + }, + "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.0" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/spisea/atmospheres.py b/spisea/atmospheres.py index 71cc5726..550e3298 100755 --- a/spisea/atmospheres.py +++ b/spisea/atmospheres.py @@ -16,21 +16,7 @@ def get_atmosphere_bounds(model_dir, metallicity=0, temperature=20000, gravity=4 """ Given atmosphere model, get temperature and gravity bounds """ - # Open catalog fits file and break out row indices - catalog = Table.read('{0}/grid/{1}/catalog.fits'.format(os.environ['PYSYN_CDBS'], model_dir)) - - teff_arr = [] - z_arr = [] - logg_arr = [] - for cur_row_index in range(len(catalog)): - index = catalog['INDEX'][cur_row_index] - tmp = index.split(',') - teff_arr.append(float(tmp[0])) - z_arr.append(float(tmp[1])) - logg_arr.append(float(tmp[2])) - teff_arr = np.array(teff_arr) - z_arr = np.array(z_arr) - logg_arr = np.array(logg_arr) + teff_arr, z_arr, logg_arr = get_atmosphere_grid(model_dir) # Filter by metallicity. Will chose the closest metallicity to desired input metal_list = np.unique(np.array(z_arr)) @@ -93,6 +79,45 @@ def get_atmosphere_bounds(model_dir, metallicity=0, temperature=20000, gravity=4 return (temperature_new, gravity_new, metallicity_new) +def get_atmosphere_grid(model_dir): + """ + Gets grid of temps, Zs, and loggs of atmosphere grid + + Parameters + ---------- + model_dir : str + Model directory + + Returns + ------- + teff_arr : array-like + Temperature array + + z_arr : array-like + Metallicity array + + logg_arr : array-like + Surface gravity array + """ + # Open catalog fits file and break out row indices + catalog = Table.read('{0}/grid/{1}/catalog.fits'.format(os.environ['PYSYN_CDBS'], model_dir)) + + teff_arr = [] + z_arr = [] + logg_arr = [] + for cur_row_index in range(len(catalog)): + index = catalog['INDEX'][cur_row_index] + tmp = index.split(',') + teff_arr.append(float(tmp[0])) + z_arr.append(float(tmp[1])) + logg_arr.append(float(tmp[2])) + teff_arr = np.array(teff_arr) + z_arr = np.array(z_arr) + logg_arr = np.array(logg_arr) + + return teff_arr, z_arr, logg_arr + + def get_kurucz_atmosphere(metallicity=0, temperature=20000, gravity=4, rebin=False): """ Return atmosphere from the Kurucz pysnphot grid @@ -118,6 +143,7 @@ def get_kurucz_atmosphere(metallicity=0, temperature=20000, gravity=4, rebin=Fal rebin: boolean Always false for this particular function """ + try: sp = pysynphot.Icat('k93models', temperature, metallicity, gravity) except: @@ -139,6 +165,20 @@ def get_kurucz_atmosphere(metallicity=0, temperature=20000, gravity=4, rebin=Fal return sp +def get_kurucz_atmosphere_grid(): + """ + Return atmosphere grid from the Kurucz pysnphot grid + (`Kurucz 1993 `_). + + Grid Range: + + * Teff: 3000 - 50000 K + * gravity: 0 - 5 cgs + * metallicity: -5.0 - 1.0 + """ + teff_arr, z_arr, logg_arr = get_atmosphere_grid('k93models') + return teff_arr, z_arr, logg_arr + def get_castelli_atmosphere(metallicity=0, temperature=20000, gravity=4, rebin=False): """ Return atmospheres from the pysynphot ATLAS9 atlas @@ -190,12 +230,30 @@ def get_castelli_atmosphere(metallicity=0, temperature=20000, gravity=4, rebin=F return sp +def get_castelli_atmosphere_grid(): + """ + Return atmosphere grid from the pysynphot ATLAS9 atlas + (`Castelli & Kurucz 2004 `_). + + Grid Range: + + * Teff: 3500 - 50000 K + * gravity: 0 - 5.0 cgs + * [M/H]: -2.5 - 0.2 + """ + + teff_arr, z_arr, logg_arr = get_atmosphere_grid('ck04models') + return teff_arr, z_arr, logg_arr + def get_nextgen_atmosphere(metallicity=0, temperature=5000, gravity=4, rebin=False): """ metallicity = [M/H] (def = 0) temperature = Kelvin (def = 5000) gravity = log gravity (def = 4.0) """ + if get_grid_only: + teff_arr, z_arr, logg_arr = get_atmosphere_grid('nextgen') + return teff_arr, z_arr, logg_arr try: sp = pysynphot.Icat('nextgen', temperature, metallicity, gravity) except: @@ -217,12 +275,22 @@ def get_nextgen_atmosphere(metallicity=0, temperature=5000, gravity=4, rebin=Fal return sp +def get_nextgen_atmosphere_grid(): + """ + metallicity = [M/H] (def = 0) + temperature = Kelvin (def = 5000) + gravity = log gravity (def = 4.0) + """ + teff_arr, z_arr, logg_arr = get_atmosphere_grid('nextgen') + return teff_arr, z_arr, logg_arr + def get_amesdusty_atmosphere(metallicity=0, temperature=5000, gravity=4, rebin=False): """ metallicity = [M/H] (def = 0) temperature = Kelvin (def = 5000) gravity = log gravity (def = 4.0) """ + sp = pysynphot.Icat('AMESdusty', temperature, metallicity, gravity) # Do some error checking @@ -235,6 +303,15 @@ def get_amesdusty_atmosphere(metallicity=0, temperature=5000, gravity=4, rebin=F return sp +def get_amesdusty_atmosphere_grid(): + """ + metallicity = [M/H] (def = 0) + temperature = Kelvin (def = 5000) + gravity = log gravity (def = 4.0) + """ + teff_arr, z_arr, logg_arr = get_atmosphere_grid('AMESdusty') + return teff_arr, z_arr, logg_arr + def get_phoenix_atmosphere(metallicity=0, temperature=5000, gravity=4, rebin=False): """ @@ -256,8 +333,8 @@ def get_phoenix_atmosphere(metallicity=0, temperature=5000, gravity=4, If true, rebins the atmospheres so that they are the same resolution as the Castelli+04 atmospheres. Default is False, which is often sufficient synthetic photometry in most cases. - """ + try: sp = pysynphot.Icat('phoenix', temperature, metallicity, gravity) except: @@ -279,6 +356,15 @@ def get_phoenix_atmosphere(metallicity=0, temperature=5000, gravity=4, return sp +def get_phoenix_atmosphere_grid(): + """ + Return atmosphere grid from the pysynphot + `PHOENIX atlas `_. + + """ + teff_arr, z_arr, logg_arr = get_atmosphere_grid('phoenix') + return teff_arr, z_arr, logg_arr + def get_cmfgenRot_atmosphere(metallicity=0, temperature=24000, gravity=4.3, rebin=True): """ metallicity = [M/H] (def = 0) @@ -287,6 +373,7 @@ def get_cmfgenRot_atmosphere(metallicity=0, temperature=24000, gravity=4.3, rebi rebin=True: pull from atmospheres at ck04model resolution. """ + # Take care of atmospheres outside the catalog boundaries logg_msg = 'Changing to logg={0:3.1f} for T={1:6.0f} logg={2:4.2f}' if gravity > 4.3: @@ -308,6 +395,21 @@ def get_cmfgenRot_atmosphere(metallicity=0, temperature=24000, gravity=4.3, rebi return sp +def get_cmfgenRot_atmosphere_grid(rebin=True): + """ + metallicity = [M/H] (def = 0) + temperature = Kelvin (def = 24000) + gravity = log gravity (def = 4.3) + + rebin=True: pull from atmospheres at ck04model resolution. + """ + if rebin: + teff_arr, z_arr, logg_arr = get_atmosphere_grid('cmfgen_rot_rebin') + else: + teff_arr, z_arr, logg_arr = get_atmosphere_grid('cmfgen_rot') + return teff_arr, z_arr, logg_arr + + def get_cmfgenRot_atmosphere_closest(metallicity=0, temperature=24000, gravity=4.3, rebin=True, verbose=False): """ @@ -384,6 +486,7 @@ def get_cmfgenRot_atmosphere_closest(metallicity=0, temperature=24000, gravity=4 return sp + def get_cmfgenNoRot_atmosphere(metallicity=0, temperature=22500, gravity=3.98, rebin=True): """ metallicity = [M/H] (def = 0) @@ -392,6 +495,7 @@ def get_cmfgenNoRot_atmosphere(metallicity=0, temperature=22500, gravity=3.98, r rebin=True: pull from atmospheres at ck04model resolution. """ + if rebin: sp = pysynphot.Icat('cmfgen_norot_rebin', temperature, metallicity, gravity) else: @@ -407,12 +511,27 @@ def get_cmfgenNoRot_atmosphere(metallicity=0, temperature=22500, gravity=3.98, r return sp +def get_cmfgenNoRot_atmosphere_grid(rebin=True): + """ + metallicity = [M/H] (def = 0) + temperature = Kelvin (def = 24000) + gravity = log gravity (def = 4.3) + + rebin=True: pull from atmospheres at ck04model resolution. + """ + if rebin: + teff_arr, z_arr, logg_arr = get_atmosphere_grid('cmfgen_norot_rebin') + else: + teff_arr, z_arr, logg_arr = get_atmosphere_grid('cmfgen_norot') + return teff_arr, z_arr, logg_arr + def get_cmfgenNoRot_atmosphere(metallicity=0, temperature=30000, gravity=4.14): """ metallicity = [M/H] (def = 0) temperature = Kelvin (def = 30000) gravity = log gravity (def = 4.14) """ + sp = pysynphot.Icat('cmfgenF15_noRot', temperature, metallicity, gravity) # Do some error checking @@ -425,6 +544,15 @@ def get_cmfgenNoRot_atmosphere(metallicity=0, temperature=30000, gravity=4.14): return sp +def get_cmfgenNoRot_atmosphere_grid(): + """ + metallicity = [M/H] (def = 0) + temperature = Kelvin (def = 30000) + gravity = log gravity (def = 4.14) + """ + teff_arr, z_arr, logg_arr = get_atmosphere_grid('cmfgenF15_noRot') + return teff_arr, z_arr, logg_arr + def get_phoenixv16_atmosphere(metallicity=0, temperature=4000, gravity=4, rebin=True): """ Return PHOENIX v16 atmospheres from @@ -454,8 +582,8 @@ def get_phoenixv16_atmosphere(metallicity=0, temperature=4000, gravity=4, rebin= If true, rebins the atmospheres so that they are the same resolution as the Castelli+04 atmospheres. Default is False, which is often sufficient synthetic photometry in most cases. - """ + atm_model_name = 'phoenix_v16' if rebin == True: atm_model_name = 'phoenix_v16_rebin' @@ -483,6 +611,33 @@ def get_phoenixv16_atmosphere(metallicity=0, temperature=4000, gravity=4, rebin= return sp +def get_phoenixv16_atmosphere_grid(rebin=True): + """ + Return PHOENIX v16 atmosphere grid from + `Husser et al. 2013 `_. + + Models originally downloaded via `ftp `_. + Solar metallicity and [alpha/Fe] is used. + + Grid Range: + + * Teff: 2300 - 7000 K, steps of 100 K; 7000 - 12000 in steps of 200 K + * gravity: 0.0 - 6.0 cgs, steps of 0.5 + * [M/H]: -4.0 - 1.0 + + rebin: boolean + If true, rebins the atmospheres so that they are the same + resolution as the Castelli+04 atmospheres. Default is True + """ + + atm_model_name = 'phoenix_v16' + if rebin == True: + atm_model_name = 'phoenix_v16_rebin' + + teff_arr, z_arr, logg_arr = get_atmosphere_grid(atm_model_name) + return teff_arr, z_arr, logg_arr + + def get_BTSettl_2015_atmosphere(metallicity=0, temperature=2500, gravity=4, rebin=True): """ Return atmosphere from CIFIST2011_2015 grid @@ -511,7 +666,7 @@ def get_BTSettl_2015_atmosphere(metallicity=0, temperature=2500, gravity=4, rebi rebin: boolean If true, rebins the atmospheres so that they are the same resolution as the Castelli+04 atmospheres. Default is False, - which is often sufficient synthetic photometry in most cases. + which is often sufficient synthetic photometry in most cases. """ if rebin == True: atm_name = 'BTSettl_2015_rebin' @@ -540,6 +695,33 @@ def get_BTSettl_2015_atmosphere(metallicity=0, temperature=2500, gravity=4, rebi return sp +def get_BTSettl_2015_atmosphere_grid(rebin=True): + """ + Return atmosphere grid from CIFIST2011_2015 grid + (`Allard et al. 2012 `_, + `Baraffe et al. 2015 `_ ) + + Grid originally downloaded from `website `_. + + Grid Range: + + * Teff: 1200 - 7000 K + * gravity: 2.5 - 5.5 cgs + * [M/H] = 0 + + rebin: boolean + If true, rebins the atmospheres so that they are the same + resolution as the Castelli+04 atmospheres. Default is True + """ + if rebin == True: + atm_name = 'BTSettl_2015_rebin' + else: + atm_name = 'BTSettl_2015' + + teff_arr, z_arr, logg_arr = get_atmosphere_grid(atm_name) + return teff_arr, z_arr, logg_arr + + def get_BTSettl_atmosphere(metallicity=0, temperature=2500, gravity=4.5, rebin=True): """ Return atmosphere from CIFIST2011 grid @@ -640,6 +822,76 @@ def get_BTSettl_atmosphere(metallicity=0, temperature=2500, gravity=4.5, rebin=T return sp +def get_BTSettl_atmosphere_grid(rebin=True): + """ + Return atmosphere grid from CIFIST2011 grid + (`Allard et al. 2012 `_) + + Grid originally downloaded `here `_ + + Notes + ------ + Grid Range: + + * [M/H] = -2.5, -2.0, -1.5, -1.0, -0.5, 0, 0.5 + + Teff and gravity ranges depend on metallicity: + + [M/H] = -2.5 + + * Teff: 2600 - 4600 K + * gravity: 4.5 - 5.5 + + [M/H] = -2.0 + + * Teff: 2600 - 7000 + * gravity: 4.5 - 5.5 + + [M/H] = -1.5 + + * Teff: 2600 - 7000 + * gravity: 4.5 - 5.5 + + [M/H] = -1.0 + + * Teff: 2600 - 7000 + * gravity: Teff < 3200 --> 4.5 - 5.5; Teff > 3200 --> 2.5 - 5.5 + + [M/H] = -0.5 + + * Teff: 1000 -7000 + * gravity: Teff < 3000 --> 4.5 - 5.5; Teff > 3000 --> 3.0 - 6.0 + + [M/H] = 0 + + * Teff: 750 - 7000 + * gravity: Teff < 2500 --> 3.5 - 5.5; Teff > 2500 --> 0 - 5.5 + + [M/H] = 0.5 + + * Teff: 1000 - 5000 + * gravity: 3.5 - 5.0 + + + Alpha enhancement: + + * [M/H]= -0.0, +0.5 no anhancement + * [M/H]= -0.5 with [alpha/H]=+0.2 + * [M/H]= -1.0, -1.5, -2.0, -2.5 with [alpha/H]=+0.4 + + rebin: boolean + If true, rebins the atmospheres so that they are the same + resolution as the Castelli+04 atmospheres. Default is True. + """ + if rebin == True: + atm_name = 'BTSettl_rebin' + else: + atm_name = 'BTSettl' + + teff_arr, z_arr, logg_arr = get_atmosphere_grid(atm_name) + return teff_arr, z_arr, logg_arr + + def get_wdKoester_atmosphere(metallicity=0, temperature=20000, gravity=7): """ Return white dwarf atmospheres from @@ -661,6 +913,7 @@ def get_wdKoester_atmosphere(metallicity=0, temperature=20000, gravity=7): resolution as the Castelli+04 atmospheres. Default is False, which is often sufficient synthetic photometry in most cases. """ + sp = pysynphot.Icat('wdKoester', temperature, metallicity, gravity) # Do some error checking @@ -673,12 +926,21 @@ def get_wdKoester_atmosphere(metallicity=0, temperature=20000, gravity=7): return sp +def get_wdKoester_atmosphere_grid(): + """ + Return white dwarf grid atmospheres from + `Koester et al. 2010 `_ + """ + teff_arr, z_arr, logg_arr = get_atmosphere_grid('wdKoester') + return teff_arr, z_arr, logg_arr + def get_atlas_phoenix_atmosphere(metallicity=0, temperature=5250, gravity=4): """ Return atmosphere that is a linear merge of atlas ck04 model and phoenixV16. Only valid for temps between 5000 - 5500K, gravity from 0 = 5.0 """ + try: sp = pysynphot.Icat('merged_atlas_phoenix', temperature, metallicity, gravity) except: @@ -700,6 +962,15 @@ def get_atlas_phoenix_atmosphere(metallicity=0, temperature=5250, gravity=4): return sp +def get_atlas_phoenix_atmosphere_grid(): + """ + Return atmosphere that is a linear merge of atlas ck04 model and phoenixV16. + + Only valid for temps between 5000 - 5500K, gravity from 0 = 5.0 + """ + teff_arr, z_arr, logg_arr = get_atmosphere_grid('merged_atlas_phoenix') + return teff_arr, z_arr, logg_arr + def get_BTSettl_phoenix_atmosphere(metallicity=0, temperature=5250, gravity=4): """ Return atmosphere that is a linear merge of BTSettl_CITFITS2011_2015 model @@ -728,6 +999,17 @@ def get_BTSettl_phoenix_atmosphere(metallicity=0, temperature=5250, gravity=4): return sp +def get_BTSettl_phoenix_atmosphere_grid(): + """ + Return atmosphere grid that is a linear merge of BTSettl_CITFITS2011_2015 model + and phoenixV16. + + Only valid for temps between 3200 - 3800K, gravity from 2.5 - 5.5 + """ + teff_arr, z_arr, logg_arr = get_atmosphere_grid('merged_BTSettl_phoenix') + return teff_arr, z_arr, logg_arr + + #---------------------------------------------------------------------# def get_merged_atmosphere(metallicity=0, temperature=20000, gravity=4.5, verbose=False, rebin=True): @@ -800,6 +1082,7 @@ def get_merged_atmosphere(metallicity=0, temperature=20000, gravity=4.5, verbose temperature ranges where we switch between model grids, to ensure a smooth transition. """ + # For T < 3800, atmosphere depends on metallicity + gravity. # If solar metallicity, use BTSettl 2015 grid. Only solar metallicity is # currently available here, so if non-solar metallicity, just stick with @@ -837,7 +1120,6 @@ def get_merged_atmosphere(metallicity=0, temperature=20000, gravity=4.5, verbose temperature=temperature, gravity=gravity, rebin=rebin) - # For T > 3800, no metallicity or gravity dependence if (temperature >= 3800) & (temperature < 5000): if verbose: @@ -874,8 +1156,253 @@ def get_merged_atmosphere(metallicity=0, temperature=20000, gravity=4.5, verbose # gravity=gravity) +def get_merged_atmosphere_grid(rebin=True): + + # temp array, metallicity array, logg array + BTSettl_2015_atmosphere_arrs = np.array(get_BTSettl_2015_atmosphere_grid(rebin)) + + BTSettl_phoenix_atmosphere_arrs = np.array(get_BTSettl_phoenix_atmosphere_grid()) + + phoenixv16_atmosphere_arrs = np.array(get_phoenixv16_atmosphere_grid(rebin)) + atlas_phoenix_atmosphere_arrs = np.array(get_atlas_phoenix_atmosphere_grid()) + + castelli_atmosphere_arrs = np.array(get_castelli_atmosphere_grid()) + + BTSettl_2015_atmosphere_idxs = np.where((BTSettl_2015_atmosphere_arrs[0] <= 3200) &\ + (BTSettl_2015_atmosphere_arrs[1] == 0) &\ + (BTSettl_2015_atmosphere_arrs[2] > 2.5)) + BTSettl_2015_atmosphere_arrs = BTSettl_2015_atmosphere_arrs[:,BTSettl_2015_atmosphere_idxs] + + BTSettl_phoenix_atmosphere_idxs = np.where((BTSettl_phoenix_atmosphere_arrs[0] >= 3200) &\ + (BTSettl_phoenix_atmosphere_arrs[0] < 3800) &\ + (BTSettl_phoenix_atmosphere_arrs[1] == 0) &\ + (BTSettl_phoenix_atmosphere_arrs[2] > 2.5)) + BTSettl_phoenix_atmosphere_arrs = BTSettl_phoenix_atmosphere_arrs[:,BTSettl_phoenix_atmosphere_idxs] + + phoenixv16_atmosphere_idxs = np.where(((phoenixv16_atmosphere_arrs[0] <= 3800) & (phoenixv16_atmosphere_arrs[1] == 0) & (phoenixv16_atmosphere_arrs[2] <= 2.5)) |\ + ((phoenixv16_atmosphere_arrs[0] <= 3800) & (phoenixv16_atmosphere_arrs[1] != 0)) |\ + ((phoenixv16_atmosphere_arrs[0] >= 3800) & (phoenixv16_atmosphere_arrs[0] < 5000))) + phoenixv16_atmosphere_arrs = phoenixv16_atmosphere_arrs[:,phoenixv16_atmosphere_idxs] + + atlas_phoenix_atmosphere_idxs = np.where((atlas_phoenix_atmosphere_arrs[0] >= 5000) & (atlas_phoenix_atmosphere_arrs[0] < 5500)) + atlas_phoenix_atmosphere_arrs = atlas_phoenix_atmosphere_arrs[:,atlas_phoenix_atmosphere_idxs] + + castelli_atmosphere_idxs = np.where(castelli_atmosphere_arrs[0] >= 5500) + castelli_atmosphere_arrs = castelli_atmosphere_arrs[:,castelli_atmosphere_idxs] + + super_tarr = np.concatenate((BTSettl_2015_atmosphere_arrs[0][0], BTSettl_phoenix_atmosphere_arrs[0][0], + phoenixv16_atmosphere_arrs[0][0], atlas_phoenix_atmosphere_arrs[0][0], + castelli_atmosphere_arrs[0][0])) + + super_zarr = np.concatenate((BTSettl_2015_atmosphere_arrs[1][0], BTSettl_phoenix_atmosphere_arrs[1][0], + phoenixv16_atmosphere_arrs[1][0], atlas_phoenix_atmosphere_arrs[1][0], + castelli_atmosphere_arrs[1][0])) + super_loggarr = np.concatenate((BTSettl_2015_atmosphere_arrs[2][0], BTSettl_phoenix_atmosphere_arrs[2][0], + phoenixv16_atmosphere_arrs[2][0], atlas_phoenix_atmosphere_arrs[2][0], + castelli_atmosphere_arrs[2][0])) + return super_tarr, super_zarr, super_loggarr + +def get_merged_atmosphere_w_bb_supplement(metallicity=0, temperature=20000, gravity=4.5, verbose=False, + rebin=True): + """ + Return a stellar atmosphere from a suite of different model grids, + depending on the input temperature, (all values in K). + IF OUTSIDE SUPPORTED GRID, WILL RETURN BB ATMOSPHERE + + Parameters + ---------- + metallicity: float + The stellar metallicity, in terms of [Z] + + temperature: float + The stellar temperature, in units of K + + gravity: float + The stellar gravity, in cgs units + + rebin: boolean + If true, rebins the atmospheres so that they are the same + resolution as the Castelli+04 atmospheres. Default is False, + which is often sufficient synthetic photometry in most cases. + + verbose: boolean + True for verbose output + + Notes + ----- + The underlying stellar model grid used changes as a function of + stellar temperature (in K): + + * T > 20,000: ATLAS + * 5500 <= T < 20,000: ATLAS + * 5000 <= T < 5500: ATLAS/PHOENIXv16 merge + * 3800 <= T < 5000: PHOENIXv16 + + For T < 3800, there is an additional gravity and metallicity + dependence: + + If T < 3800 and [M/H] = 0: + + * T < 3800, logg < 2.5: PHOENIX v16 + * 3200 <= T < 3800, logg > 2.5: BTSettl_CIFITS2011_2015/PHOENIXV16 merge + * 3200 < T <= 1200, logg > 2.5: BTSettl_CIFITS2011_2015 + + Otherwise, if T < 3800 and [M/H] != 0: + + * T < 3800: PHOENIX v16 + + References: + + * ATLAS: ATLAS9 models (`Castelli & Kurucz 2004 `_) + * PHOENIXv16 (`Husser et al. 2013 `_) + * BTSettl_CIFITS2011_2015: Baraffee+15, Allard+ (https://phoenix.ens-lyon.fr/Grids/BT-Settl/CIFIST2011_2015/SPECTRA/) + + LTE WARNING: + + The ATLAS atmospheres are calculated with LTE, and so they + are less accurate when non-LTE conditions apply (e.g. T > 20,000 + K). Ultimately we'd like to add a non-LTE atmosphere grid for + the hottest stars in the future. + + HOW BOUNDARIES BETWEEN MODELS ARE TREATED: + + At the boundary between two models grids a temperature range is defined + where the resulting atmosphere is a weighted average between the two + grids. Near one boundary one model + is weighted more heavily, while at the other boundary the other + model is weighted more heavily. These are calculated in the + temperature ranges where we switch between model grids, to + ensure a smooth transition. + """ + + if (temperature <= 1000): + print('BB atmosphere') + return get_bb_atmosphere(temperature=temperature, + metallicity=metallicity, + gravity=gravity, + verbose=verbose) + if (gravity >= 9.8): + print('BB atmosphere') + return get_bb_atmosphere(temperature=temperature, + metallicity=metallicity, + gravity=gravity, + verbose=verbose) + if (temperature < 4.6e3) & (gravity >= 6.5): + print('BB atmosphere') + return get_bb_atmosphere(temperature=temperature, + metallicity=metallicity, + gravity=gravity, + verbose=verbose) + + if (temperature < 3.5e3) & (gravity < 6.5) & (gravity > 6): + print('BB atmosphere') + return get_bb_atmosphere(temperature=temperature, + metallicity=metallicity, + gravity=gravity, + verbose=verbose) + + # For T < 3800, atmosphere depends on metallicity + gravity. + # If solar metallicity, use BTSettl 2015 grid. Only solar metallicity is + # currently available here, so if non-solar metallicity, just stick with + # the Phoenix grid + if (temperature <= 3800) & (metallicity == 0): + # High gravity are in BTSettl regime + if (temperature <= 3200) & (gravity > 2.5): + if verbose: + print( 'BTSettl_2015 atmosphere') + return get_BTSettl_2015_atmosphere(metallicity=metallicity, + temperature=temperature, + gravity=gravity, + rebin=rebin) + + if (temperature >= 3200) & (temperature < 3800) & (gravity > 2.5): + if verbose: + print( 'BTSettl/Phoenixv16 merged atmosphere') + return get_BTSettl_phoenix_atmosphere(metallicity=metallicity, + temperature=temperature, + gravity=gravity) + + # Low gravity is PHOENIX regime + if gravity <= 2.5: + if verbose: + print( 'Phoenixv16 atmosphere') + return get_phoenixv16_atmosphere(metallicity=metallicity, + temperature=temperature, + gravity=gravity, + rebin=rebin) + + if (temperature <= 3800) & (metallicity != 0): + if verbose: + print( 'Phoenixv16 atmosphere') + return get_phoenixv16_atmosphere(metallicity=metallicity, + temperature=temperature, + gravity=gravity, + rebin=rebin) + # For T > 3800, no metallicity or gravity dependence + if (temperature >= 3800) & (temperature < 5000): + if verbose: + print( 'Phoenixv16 atmosphere') + return get_phoenixv16_atmosphere(metallicity=metallicity, + temperature=temperature, + gravity=gravity, + rebin=rebin) + + if (temperature >= 5000) & (temperature < 5500): + if verbose: + print( 'ATLAS/Phoenix merged atmosphere') + return get_atlas_phoenix_atmosphere(metallicity=metallicity, + temperature=temperature, + gravity=gravity) + + if (temperature >= 5500) & (temperature < 20000): + if verbose: + print( 'ATLAS merged atmosphere') + return get_castelli_atmosphere(metallicity=metallicity, + temperature=temperature, + gravity=gravity) + + if temperature >= 20000: + if verbose: + print( 'Still ATLAS merged atmosphere') + return get_castelli_atmosphere(metallicity=metallicity, + temperature=temperature, + gravity=gravity) + + # Returns BB if outside of WD defined atmospheres + else: + if verbose: + print('WD or BB atmosphere') + return get_wd_atmosphere(metallicity=metallicity, + temperature=temperature, + gravity=gravity) + +def get_merged_atmosphere_w_bb_supplement_grid(bb_supplement_tarr='default', bb_supplement_zarr='default', bb_supplement_loggarr='default', rebin=True): + + super_tarr, super_zarr, super_loggarr = get_merged_atmosphere_grid(rebin=rebin) + + wd_tarr, wd_zarr, wd_loggarr = get_wdKoester_atmosphere_grid() + super_tarr = np.concatenate((super_tarr, wd_tarr)) + super_zarr = np.concatenate((super_zarr, wd_zarr)) + super_loggarr = np.concatenate((super_loggarr, wd_loggarr)) + + if bb_supplement_tarr == 'default': + X, Y = np.meshgrid(np.logspace(np.log10(2e3), np.log10(4.6e3), 20), np.linspace(6.5, 8.7, 10)) + X1, Y1 = np.meshgrid(np.logspace(np.log10(2e3), np.log10(3.5e3), 15), np.linspace(6, 6.25, 2)) + X2, Y2 = np.meshgrid(np.logspace(np.log10(1e2), np.log10(1.1e3), 25), np.linspace(3, 4.5, 4)) + X3, Y3 = np.meshgrid(np.logspace(np.log10(8e3), np.log10(2e4), 25), np.linspace(9.8, 11.6, 8)) + bb_supplement_tarr = np.concatenate((X.ravel(), X1.ravel(), X2.ravel(), X3.ravel())) + bb_supplement_loggarr = np.concatenate((Y.ravel(), Y1.ravel(), Y2.ravel(), Y3.ravel())) + bb_supplement_zarr = np.zeros(len(bb_supplement_tarr)) + + + super_tarr = np.concatenate((super_tarr, bb_supplement_tarr)) + super_zarr = np.concatenate((super_zarr, bb_supplement_zarr)) + super_loggarr = np.concatenate((super_loggarr, bb_supplement_loggarr)) + + return super_tarr, super_zarr, super_loggarr + def get_wd_atmosphere(metallicity=0, temperature=20000, gravity=4, verbose=False): """ Return the white dwarf atmosphere from diff --git a/spisea/evolution.py b/spisea/evolution.py index de5de196..c0548f7c 100755 --- a/spisea/evolution.py +++ b/spisea/evolution.py @@ -11,6 +11,8 @@ import pylab as py from spisea.utils import objects from spisea import exceptions +import astropy.units as u +import astropy.constants as c logger = logging.getLogger('evolution') @@ -85,6 +87,7 @@ def __init__(self, model_dir, age_list, mass_list, z_list): self.z_list = z_list self.mass_list = mass_list self.age_list = age_list + self.external_evol = False return @@ -1198,6 +1201,172 @@ def format_isochrones(self): # Return to starting directory os.chdir(start_dir) return + +#===========================================# +# COSMIC Breivik+ 2020 - not normal evo model +#===========================================# +class COSMIC(StellarEvolution): + + def __init__(self, BSEDict='default', keep_disrupted_companions=True, keep_COSMIC_tables=False): + if BSEDict == 'default': + self.BSEDict = BSEDict = {'xi': 1.0, 'bhflag': 1, 'neta': 0.5, + 'windflag': 3, 'wdflag': 1, 'alpha1': 1.0, + 'pts1': 0.001, 'pts3': 0.02, 'pts2': 0.01, + 'epsnov': 0.001, 'hewind': 0.5, 'ck': 1000, + 'bwind': 0.0, 'lambdaf': 0.0, 'mxns': 3.0, + 'beta': -1.0, 'tflag': 1, 'acc2': 1.5, + 'grflag' : 1, 'remnantflag': 4, 'ceflag': 0, + 'eddfac': 1.0, 'ifflag': 0, 'bconst': 3000, + 'sigma': 265.0, 'gamma': -2.0, 'pisn': 45.0, + 'natal_kick_array' : [[-100.0,-100.0,-100.0,-100.0,0.0], [-100.0,-100.0,-100.0,-100.0,0.0]], + 'bhsigmafrac' : 1.0, 'polar_kick_angle' : 90, + 'qcrit_array' : [0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0], + 'cekickflag' : 2, 'cehestarflag' : 0, 'cemergeflag' : 0, + 'ecsn' : 2.25, 'ecsn_mlow' : 1.6, 'aic' : 1, 'ussn' : 0, + 'sigmadiv' :-20.0, 'qcflag' : 1, 'eddlimflag' : 0, + 'fprimc_array' : [2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0], + 'bhspinflag' : 0, 'bhspinmag' : 0.0, 'rejuv_fac' : 1.0, + 'rejuvflag' : 0, 'htpmb' : 1, 'ST_cr' : 1, 'ST_tide' : 1, + 'bdecayfac' : 1, 'rembar_massloss' : 0.5, 'kickflag' : 1, + 'zsun' : 0.014, 'bhms_coll_flag' : 0, 'don_lim' : -1, + 'acc_lim' : -1, 'rtmsflag' : 0, 'wd_mass_lim': 1} + else: + self.BSEDict = BSEDict + + self.external_evol = True + self.z_solar = 0.014 + self.keep_disrupted_companions = keep_disrupted_companions + self.keep_COSMIC_tables = keep_COSMIC_tables + + + def evolve(self, star_systems, companions, logAge, metallicity): + from cosmic.utils import p_from_a, a_from_p + from cosmic.sample.initialbinarytable import InitialBinaryTable + from cosmic.evolve import Evolve + + companion_system_idxs = companions['system_idx'] + m1s = star_systems['mass'] + m2s = np.zeros(len(star_systems)) + m2s[companion_system_idxs] = companions['mass'] + + a_Rsuns = (10**companions['log_a'])*u.AU.to('Rsun') + porbs = np.zeros(len(star_systems)) + porbs[companion_system_idxs] = p_from_a(a_Rsuns, m1s[companion_system_idxs], m2s[companion_system_idxs]) + + eccs = np.zeros(len(star_systems)) + eccs[companion_system_idxs] = companions['e'] + + kstar1s = (m1s >= 0.7).astype(int) # 1 if MS above 0.7 and 0 if MS below 0.7 + kstar2s = (m2s >= 0.7).astype(int) # 1 if MS above 0.7 and 0 if MS below 0.7 + + binary_pop = InitialBinaryTable.InitialBinaries(m1=m1s, m2=m2s, porb=porbs, + ecc=eccs, tphysf=[10**logAge/1e6]*len(m1s), + kstar1=kstar1s, kstar2=kstar2s, metallicity=[self.z_solar*10**metallicity]*len(m1s)) + + bpp, bcm, initC, kick_info = Evolve.evolve(initialbinarytable=binary_pop, BSEDict=self.BSEDict) + if self.keep_COSMIC_tables: + self.bpp = bpp + self.bcm = bcm + self.initC = initC + self.kick_info = kick_info + + final_binaries = bcm[bcm['tphys'] > 0] #only gives the first and last idx, so this takes final one + + + star_systems['mass_current'] = final_binaries['mass_1'] + star_systems['Teff'] = final_binaries['teff_1'] + star_systems['L'] = final_binaries['lum_1'] + star_systems['logg'] = self.calc_logg(final_binaries['mass_1'], final_binaries['rad_1']) + # for kick, just take total since we will assign a random direction later anyway in PopSyCLE + star_systems['kick'] = kick_info.groupby(level=0).nth(0)['vsys_1_total'] # takes first row with priamry info + + companions['mass_current'] = final_binaries['mass_2'][companion_system_idxs] + companions['Teff'] = final_binaries['teff_2'][companion_system_idxs] + companions['L'] = final_binaries['lum_2'][companion_system_idxs] + companions['logg'] = self.calc_logg(final_binaries['mass_2'][companion_system_idxs], final_binaries['rad_2'][companion_system_idxs]) + companions['kick'] = kick_info.groupby(level=0).nth(1)['vsys_2_total'][companion_system_idxs] # takes second row with companion info + + loga = np.log10(final_binaries['sep'][companion_system_idxs]*u.Rsun.to('AU')) + companions['log_a'] = loga + + fixed_phases1 = final_binaries['kstar_1'].to_numpy() + fixed_phases1[np.where((final_binaries['kstar_1'] >= 10) & (final_binaries['kstar_1'] <= 12))[0]] = 101 + fixed_phases1[np.where(final_binaries['kstar_1'] == 13)[0]] = 102 + fixed_phases1[np.where(final_binaries['kstar_1'] == 14)[0]] = 103 + star_systems['phase'] = fixed_phases1 + + fixed_phases2 = final_binaries['kstar_2'].to_numpy() + fixed_phases2[np.where((final_binaries['kstar_2'] >= 10) & (final_binaries['kstar_2'] <= 12))[0]] = 101 + fixed_phases2[np.where(final_binaries['kstar_2'] == 13)[0]] = 102 + fixed_phases2[np.where(final_binaries['kstar_2'] == 14)[0]] = 103 + companions['phase'] = fixed_phases2[companion_system_idxs] + + # maybe add WR designation + + # Take the disrupted binaries and put the companions into the star_system table (if desired) + # don't include massless remnant companions + disrupted_binary_companion_idxs = np.where((final_binaries['bin_state'][companion_system_idxs] == 2) & (final_binaries['kstar_2'][companion_system_idxs] != 15))[0] + if self.keep_disrupted_companions and len(disrupted_binary_companion_idxs) > 0: + disrupted_binary_companions = companions[disrupted_binary_companion_idxs] + disrupted_binary_companions['systemMass'] = disrupted_binary_companions['mass_current'] + disrupted_binary_companions['isMultiple'] = [False]*len(disrupted_binary_companions) + disrupted_binary_companions['N_companions'] = [0]*len(disrupted_binary_companions) + disrupted_binary_companions.remove_columns(['system_idx', 'log_a', 'e', 'i', 'Omega', 'omega']) + star_systems = vstack([star_systems, disrupted_binary_companions]) + + #Drop merged companions and totally disappeared systems + # Also promote companions to primaries when the initial primary "merged" (if desired) + mr_companion_only_idxs = np.where((final_binaries['kstar_1'][companion_system_idxs] != 15) & (final_binaries['kstar_2'][companion_system_idxs] == 15))[0] #mr for massless remnant + disappeared_system_companion_idxs = np.where((final_binaries['kstar_1'][companion_system_idxs] == 15) & (final_binaries['kstar_2'][companion_system_idxs] == 15))[0] + companions_to_mr_primaries_idxs = np.where((final_binaries['kstar_1'][companion_system_idxs] == 15) & (final_binaries['kstar_2'][companion_system_idxs] != 15))[0] + + mr_primary_only_idx = np.where((final_binaries['kstar_1'] == 15) & (final_binaries['kstar_2'] != 15))[0] #mr for massless remnant + disappeared_system_primaries = np.where((final_binaries['kstar_1'] == 15) & (final_binaries['kstar_2'] == 15))[0] + + + delete_primary_idxs = np.concatenate((mr_primary_only_idx, disappeared_system_primaries)) + delete_companion_idxs = np.concatenate((disrupted_binary_companion_idxs, mr_companion_only_idxs, disappeared_system_companion_idxs, companions_to_mr_primaries_idxs)) + primaries_to_deleted_companion_idxs = companions[delete_companion_idxs]['system_idx'] + + #Fix binary specification of primaries that lost their companions + star_systems['isMultiple'][primaries_to_deleted_companion_idxs] = False + star_systems['N_companions'][primaries_to_deleted_companion_idxs] = 0 + + # Promote the companions to merged primaries to primaries + if self.keep_disrupted_companions and len(companions_to_mr_primaries_idxs) > 0: + companions_to_mr_primaries = companions[companions_to_mr_primaries_idxs] + companions_to_mr_primaries['systemMass'] = companions_to_mr_primaries['mass_current'] + companions_to_mr_primaries['isMultiple'] = [False]*len(companions_to_mr_primaries) + companions_to_mr_primaries['N_companions'] = [0]*len(companions_to_mr_primaries) + companions_to_mr_primaries.remove_columns(['system_idx', 'log_a', 'e', 'i', 'Omega', 'omega']) + + star_systems = vstack([star_systems, companions_to_mr_primaries]) + + star_systems.remove_rows(delete_primary_idxs) + companions.remove_rows(delete_companion_idxs) #if kstar 1 is 15 take the seocnd star and if kstar2 is 15 take the other + + #FIXME add assertion about mass_current not being zero + + return star_systems, companions + + + def calc_logg(self, masses, radii): + """ + Inputs + ------ + masses : array-like + Masses of objects in Msun + + radii : array-like + Radii of stars in Rsun + + Returns + ------- + logg : array-like + Log10 surface gravity in cgs + """ + return np.log10(((np.array(c.G.to('Rsun^3/(Msun*s^2)').value*masses/((radii)**2))*u.Rsun/u.s**2).to('cm/s^2')).value) + #==============================# # Merged model classes diff --git a/spisea/synthetic.py b/spisea/synthetic.py index b79da288..38c391cb 100755 --- a/spisea/synthetic.py +++ b/spisea/synthetic.py @@ -28,11 +28,13 @@ from scipy.spatial import cKDTree as KDTree import inspect import astropy.modeling +import sys default_evo_model = evolution.MISTv1() default_red_law = reddening.RedLawNishiyama09() default_atm_func = atm.get_merged_atmosphere default_wd_atm_func = atm.get_wd_atmosphere +default_multiplicity = multiplicity.MultiplicityResolvedDK(CSF_max = 1, companion_max = True) def Vega(): # Use Vega as our zeropoint... assume V=0.03 mag and all colors = 0.0 @@ -132,6 +134,9 @@ def __init__(self, iso, imf, cluster_mass, ifmr=None, verbose=True, seed=None): Cluster.__init__(self, iso, imf, cluster_mass, ifmr=ifmr, verbose=verbose, seed=seed) + + c = constants + # Provide a user warning is random seed is set if seed is not None and verbose: print('WARNING: random seed set to %i' % seed) @@ -144,17 +149,36 @@ def __init__(self, iso, imf, cluster_mass, ifmr=None, verbose=True, seed=seed) # Figure out the filters we will make. - self.filt_names = self.set_filter_names() - self.cluster_mass = cluster_mass + try: + self.filt_names = self.set_filter_names() + except: + self.filt_names = iso.filters + #self.cluster_mass = cluster_mass FIXME + + # Check if using an external evolution model (i.e. COSMIC) + if hasattr(iso, 'external_evol'): + if iso.external_evol == True: + self.external_evol = True + else: + self.external_evol = False ##### # Make isochrone interpolators ##### - interp_keys = ['Teff', 'L', 'logg', 'isWR', 'mass_current', 'phase'] + self.filt_names - self.iso_interps = {} - for ikey in interp_keys: - self.iso_interps[ikey] = interpolate.interp1d(self.iso.points['mass'], self.iso.points[ikey], - kind='linear', bounds_error=False, fill_value=np.nan) + if self.external_evol == False: + interp_keys = ['Teff', 'L', 'logg', 'isWR', 'mass_current', 'phase'] + self.filt_names + self.iso_interps = {} + for ikey in interp_keys: + self.iso_interps[ikey] = interpolate.interp1d(self.iso.points['mass'], self.iso.points[ikey], + kind='linear', bounds_error=False, fill_value=np.nan) + else: + from scipy.interpolate import LinearNDInterpolator + self.iso.points.sort(['Teff', 'logg', 'metallicity']) + interp_keys = self.filt_names + self.iso_interps = {} + for ikey in interp_keys: + self.iso_interps[ikey] = LinearNDInterpolator((self.iso.points['Teff'], self.iso.points['logg'], self.iso.points['metallicity']), self.iso.points[ikey], + fill_value=np.nan) ##### # Make a table to contain all the information about each stellar system. @@ -163,13 +187,110 @@ def __init__(self, iso, imf, cluster_mass, ifmr=None, verbose=True, # Trim out bad systems; specifically, stars with masses outside those provided # by the model isochrone (except for compact objects). - star_systems, compMass = self._remove_bad_systems(star_systems, compMass) + if self.external_evol == False: + star_systems, compMass = self._remove_bad_systems(star_systems, compMass) ##### # Make a table to contain all the information about companions. ##### if self.imf.make_multiples: companions = self._make_companions_table(star_systems, compMass) + + if self.external_evol: + star_systems, companions = iso.evo_model.evolve(star_systems, companions, iso.logAge, iso.metallicity) + + individual_atm = False + + if individual_atm: + + # Loop through radii too! + # Do WD and stars separately + # For each temperature extract the synthetic photometry. + for ii in range(len(star_systems)): + # Loop is currently taking about 0.11 s per iteration + gravity = star_systems['logg'][ii] + T = star_systems['Teff'][ii] + metallicity = iso.metallicity + phase = star_systems['phase'][ii] + R = np.sqrt((star_systems['L']*(units.erg/units.s)/(4*np.pi*c.sigma_sb.cgs*(star_systems['Teff']*units.K)**4)).to('pc^2')).value[ii] + + # Get the atmosphere model now. Wavelength is in Angstroms + # This is the time-intensive call... everything else is negligable. + # If source is a star, pull from star atmospheres. If it is a WD, + # pull from WD atmospheres + nan_mag = False + if phase == 101: + star = iso.wd_atm_func(temperature=T, gravity=gravity, metallicity=metallicity, + verbose=False) + elif phase < 100: + star = iso.atm_func(temperature=T, gravity=gravity, metallicity=metallicity, + rebin=False)#rebin) + else: + nan_mag = True + + # Trim wavelength range down to JHKL range (0.5 - 5.2 microns) + star = spectrum.trimSpectrum(star, iso.wave_range[0], iso.wave_range[1]) + + # Convert into flux observed at Earth (unreddened) + star *= (R / iso.distance)**2 # in erg s^-1 cm^-2 A^-1 + + # Redden the spectrum. This doesn't take much time at all. + red = iso.red_law.reddening(iso.AKs).resample(star.wave) + star *= red + + for filt in self.filt_names: + if nan_mag == True: + star_systems[filt] = np.nan + else: + filt_name = filt.split('_') + filt_val = get_filter_info(filt_name[1] + ',' + filt_name[2], rebin=False, vega=vega) + mag = mag_in_filter(star, filt_val) + star_systems[filt] = mag + + + if individual_atm == False: + for filt in self.filt_names: + filt_name = filt.split('_') + filt_val = get_filter_info(filt_name[1] + ',' + filt_name[2], rebin=False, vega=vega) + + # Rescale magnitudes to correct radius + # Since original grid was done assuming 1 Rsun + star_systems[filt] = self.iso_interps[filt](star_systems['Teff'], star_systems['logg'], iso.metallicity) + flux_val = filt_val.flux0*(10**(-(star_systems[filt] - filt_val.mag0)/2.5)) + R_vals = np.sqrt((star_systems['L']*(units.Lsun)/(4*np.pi*c.sigma_sb.cgs*(star_systems['Teff']*units.K)**4)).to('pc^2')).value + flux_rescaled = flux_val*((R_vals / iso.distance)**2)/((float(1*units.Rsun.to('pc')) / iso.distance)**2) + m_rescaled = -2.5*np.log10(flux_rescaled/filt_val.flux0) + filt_val.mag0 + star_systems[filt] = m_rescaled + + companions[filt] = self.iso_interps[filt](companions['Teff'], companions['logg'], iso.metallicity) + flux_val = filt_val.flux0*(10**(-(companions[filt] - filt_val.mag0)/2.5)) + R_vals = np.sqrt((companions['L']*(units.Lsun)/(4*np.pi*c.sigma_sb.cgs*(companions['Teff']*units.K)**4)).to('pc^2')).value + flux_rescaled = flux_val*((R_vals / iso.distance)**2)/((float(1*units.Rsun.to('pc')) / iso.distance)**2) + m_rescaled = -2.5*np.log10(flux_rescaled/filt_val.flux0) + filt_val.mag0 + companions[filt] = m_rescaled + + # Add companions masses to primaries + N_comp_max = np.max(star_systems['N_companions']) + comp_index = np.zeros((len(star_systems), N_comp_max), dtype=int) + kk = 0 + for ii in range(len(star_systems)): + for cc in range(star_systems['N_companions'][ii]): + comp_index[ii][cc] = kk + kk += 1 + + # Find all the systems with at least one companion... add the flux + # of that companion to the primary. Repeat for 2 companions, + # 3 companions, etc. + for cc in range(1, N_comp_max+1): + # All systems with at least cc companions. + idx = np.where(star_systems['N_companions'] >= cc)[0] + + # Get the location in the companions array for each system and + # the cc'th companion. + cdx = comp_index[idx, cc-1] + star_systems = self._calc_system_mag(star_systems, companions, idx, cdx, filt) + + #star_systems, companions = self._remove_bad_systems_and_companions(star_systems, companions) ##### # Save our arrays to the object @@ -216,32 +337,35 @@ def _make_star_systems_table(self, mass, isMulti, sysMass): star_systems.add_column( Column(np.empty(N_systems, dtype=float), name=filt) ) # Use our pre-built interpolators to fetch values from the isochrone for each star. - star_systems['Teff'] = self.iso_interps['Teff'](star_systems['mass']) - star_systems['L'] = self.iso_interps['L'](star_systems['mass']) - star_systems['logg'] = self.iso_interps['logg'](star_systems['mass']) - star_systems['isWR'] = np.round(self.iso_interps['isWR'](star_systems['mass'])) - star_systems['mass_current'] = self.iso_interps['mass_current'](star_systems['mass']) - star_systems['phase'] = np.round(self.iso_interps['phase'](star_systems['mass'])) - star_systems['metallicity'] = np.ones(N_systems)*self.iso.metallicity - - # For a very small fraction of stars, the star phase falls on integers in-between - # the ones we have definition for, as a result of the interpolation. For these - # stars, round phase down to nearest defined phase (e.g., if phase is 71, - # then round it down to 5, rather than up to 101). - # Note: this only becomes relevant when the cluster is > 10**6 M-sun, this - # effect is so small - # Convert nan_to_num to avoid errors on greater than, less than comparisons - star_systems_phase_non_nan = np.nan_to_num(star_systems['phase'], nan=-99) - bad = np.where( (star_systems_phase_non_nan > 5) & (star_systems_phase_non_nan < 101) & (star_systems_phase_non_nan != 9) & (star_systems_phase_non_nan != -99)) - # Print warning, if desired - verbose=False - if verbose: - for ii in range(len(bad[0])): - print('WARNING: changing phase {0} to 5'.format(star_systems['phase'][bad[0][ii]])) - star_systems['phase'][bad] = 5 - - for filt in self.filt_names: - star_systems[filt] = self.iso_interps[filt](star_systems['mass']) + if self.external_evol == False: + star_systems['Teff'] = self.iso_interps['Teff'](star_systems['mass']) + star_systems['L'] = self.iso_interps['L'](star_systems['mass']) + star_systems['logg'] = self.iso_interps['logg'](star_systems['mass']) + star_systems['isWR'] = np.round(self.iso_interps['isWR'](star_systems['mass'])) + star_systems['mass_current'] = self.iso_interps['mass_current'](star_systems['mass']) + star_systems['phase'] = np.round(self.iso_interps['phase'](star_systems['mass'])) + star_systems['metallicity'] = np.ones(N_systems)*self.iso.metallicity + + # For a very small fraction of stars, the star phase falls on integers in-between + # the ones we have definition for, as a result of the interpolation. For these + # stars, round phase down to nearest defined phase (e.g., if phase is 71, + # then round it down to 5, rather than up to 101). + # Note: this only becomes relevant when the cluster is > 10**6 M-sun, this + # effect is so small + # Convert nan_to_num to avoid errors on greater than, less than comparisons + star_systems_phase_non_nan = np.nan_to_num(star_systems['phase'], nan=-99) + bad = np.where( (star_systems_phase_non_nan > 5) & (star_systems_phase_non_nan < 101) & (star_systems_phase_non_nan != 9) & (star_systems_phase_non_nan != -99)) + # Print warning, if desired + verbose=False + if verbose: + for ii in range(len(bad[0])): + print('WARNING: changing phase {0} to 5'.format(star_systems['phase'][bad[0][ii]])) + star_systems['phase'][bad] = 5 + + if self.external_evol == False: + for filt in self.filt_names: + star_systems[filt] = self.iso_interps[filt](star_systems['mass']) + ##### # Make Remnants @@ -250,7 +374,7 @@ def _make_star_systems_table(self, mass, isMulti, sysMass): # # Remnants have flux = 0 in all bands if they are generated here. ##### - if self.ifmr != None: + if self.ifmr != None and self.external_evol == False: # Identify compact objects as those with Teff = 0 or with phase > 100. highest_mass_iso = self.iso.points['mass'].max() idx_rem = np.where((np.isnan(star_systems['Teff'])) & (star_systems['mass'] > highest_mass_iso))[0] @@ -346,7 +470,7 @@ def _make_companions_table(self, star_systems, compMass): companions['mass'][cdx] = [compMass[ii][cc-1] for ii in idx] comp_mass = companions['mass'][cdx] - if len(idx) > 0: + if len(idx) > 0 and self.external_evol == False: companions['Teff'][cdx] = self.iso_interps['Teff'](comp_mass) companions['L'][cdx] = self.iso_interps['L'](comp_mass) companions['logg'][cdx] = self.iso_interps['logg'](comp_mass) @@ -375,30 +499,12 @@ def _make_companions_table(self, star_systems, compMass): for filt in self.filt_names: # Magnitude of companion companions[filt][cdx] = self.iso_interps[filt](comp_mass) - - mag_s = star_systems[filt][idx] - mag_c = companions[filt][cdx] - - # Add companion flux to system flux. - f1 = 10**(-mag_s / 2.5) - f2 = 10**(-mag_c / 2.5) - - # For dark objects, turn the np.nan fluxes into zeros. - f1 = np.nan_to_num(f1) - f2 = np.nan_to_num(f2) - - # If *both* objects are dark, then keep the magnitude - # as np.nan. Otherwise, add fluxes together - good = np.where( (f1 != 0) | (f2 != 0) ) - bad = np.where( (f1 == 0) & (f2 == 0) ) - - star_systems[filt][idx[good]] = -2.5 * np.log10(f1[good] + f2[good]) - star_systems[filt][idx[bad]] = np.nan + star_systems = self._calc_system_mag(star_systems, companions, idx, cdx, filt) ##### # Make Remnants with flux = 0 in all bands. ##### - if self.ifmr != None: + if self.ifmr != None and self.external_evol == False: # Identify compact objects as those with Teff = 0 or with masses above the max iso mass highest_mass_iso = self.iso.points['mass'].max() cdx_rem = np.where(np.isnan(companions['Teff']) & @@ -428,16 +534,65 @@ def _make_companions_table(self, star_systems, compMass): # Notify if we have a lot of bad ones. # Convert nan_to_num to avoid errors on greater than, less than comparisons - companions_teff_non_nan = np.nan_to_num(companions['Teff'], nan=-99) - idx = np.where(companions_teff_non_nan > 0)[0] - if len(idx) != N_comp_tot and self.verbose: - print( 'Found {0:d} companions out of stellar mass range'.format(N_comp_tot - len(idx))) + if self.external_evol == False: + companions_teff_non_nan = np.nan_to_num(companions['Teff'], nan=-99) + idx = np.where(companions_teff_non_nan > 0)[0] + if len(idx) != N_comp_tot and self.verbose: + print( 'Found {0:d} companions out of stellar mass range'.format(N_comp_tot - len(idx))) # Double check that everything behaved properly. - assert companions['mass'][idx].min() > 0 + #assert companions['mass'][idx].min() > 0 FIXME return companions + def _calc_system_mag(self, star_systems, companions, idx, cdx, filt): + """ + Helper function to calculate the system magnitude from + companion and primary magnitude. + + Parameters + ---------- + star_systems : Astropy table + Star system table. + + companions: Astropy table + Companions table. + + idx : array-like + Indices of primaries with companions + + cdx : array-like + Indices of companions + + filt : str + Filter name + + Returns + ------- + star_systems : Astropy table + Star system table with system magnitdes corrected + """ + mag_s = star_systems[filt][idx] + mag_c = companions[filt][cdx] + + # Add companion flux to system flux. + f1 = 10**(-mag_s / 2.5) + f2 = 10**(-mag_c / 2.5) + + # For dark objects, turn the np.nan fluxes into zeros. + f1 = np.nan_to_num(f1) + f2 = np.nan_to_num(f2) + + # If *both* objects are dark, then keep the magnitude + # as np.nan. Otherwise, add fluxes together + good = np.where( (f1 != 0) | (f2 != 0) ) + bad = np.where( (f1 == 0) & (f2 == 0) ) + + star_systems[filt][idx[good]] = -2.5 * np.log10(f1[good] + f2[good]) + star_systems[filt][idx[bad]] = np.nan + + return star_systems + def _remove_bad_systems(self, star_systems, compMass): """ @@ -1201,6 +1356,344 @@ def plot_mass_magnitude(self, mag, savefile=None): return +class IsochronePhotExternalEvolution(IsochronePhot): + """ + Make an isochrone with synthetic photometry in various filters. + Load from file if possible. + This is for evo_models that do NOT have a grid of isochrones + but rather have their own evolution modules (i.e. COSMIC) + + Parameters + ---------- + logAge : float + The age of the isochrone, in log(years) + + AKs : float + The total extinction in Ks filter, in magnitudes + + distance : float + The distance of the isochrone, in pc + + metallicity : float, optional + The metallicity of the isochrone, in [M/H]. + Default is 0. + + evo_model: model evolution class, optional + Set the stellar evolution model class. + Default is evolution.COSMIC(). + + atm_func: model atmosphere function, optional + Set the stellar atmosphere models for the stars. + Default is atmospheres.get_merged_atmosphere. + + wd_atm_func: white dwarf model atmosphere function, optional + Set the stellar atmosphere models for the white dwafs. + Default is atmospheres.get_wd_atmosphere + + red_law : reddening law object, optional + Define the reddening law for the synthetic photometry. + Default is reddening.RedLawNishiyama09(). + + iso_dir : path, optional + Path to isochrone directory. Code will check isochrone + directory to see if isochrone file already exists; if it + does, it will just read the isochrone. If the isochrone + file doesn't exist, then save isochrone to the isochrone + directory. + + mass_sampling : int, optional + Sample the raw isochrone every `mass_sampling` steps. The default + is mass_sampling = 0, which is the native isochrone mass sampling + of the evolution model. + + wave_range : list, optional + length=2 list with the wavelength min/max of the final spectra. + Units are Angstroms. Default is [3000, 52000]. + + min_mass : float or None, optional + If float, defines the minimum mass in the isochrone. + Unit is solar masses. Default is None + + max_mass : float or None, optional + If float, defines the maxmimum mass in the isochrone. + Units is solar masses. Default is None. + + rebin : boolean, optional + If true, rebins the atmospheres so that they are the same + resolution as the Castelli+04 atmospheres. Default is True, + which is often sufficient synthetic photometry in most cases. + + recomp : boolean, optional + If true, recalculate the isochrone photometry even if + the savefile exists. You should recompute anytime you change + the filter set (see filters below). + + filters : array of strings, optional + Define what filters the synthetic photometry + will be calculated for, via the filter string + identifier. + """ + def __init__(self, logAge, AKs, distance, + metallicity=0.0, + evo_model=default_evo_model, atm_func=default_atm_func, + wd_atm_func = default_wd_atm_func, + wave_range=[3000, 52000], + red_law=default_red_law, mass_sampling=1, atm_grid_dir='./', + min_mass=None, max_mass=None, rebin=True, recomp=False, + filters=['ubv,U', 'ubv,B', 'ubv,V', + 'ubv,R', 'ubv,I']): + + self.evo_model = evo_model + self.atm_func = atm_func + self.wd_atm_func = wd_atm_func + self.wave_range = wave_range + self.distance = distance + self.red_law = red_law + self.AKs = AKs + if hasattr(evo_model, 'external_evol') == False: + raise Exception('The specified evolution model does NOT have external evolution. Use IsochronePhot() instead.') + elif self.evo_model.external_evol == False: + raise Exception('The specified evolution model does NOT have external evolution. Use IsochronePhot() instead.') + + self.external_evol = self.evo_model.external_evol + + self.metallicity = metallicity + self.logAge = logAge + + # Make the iso_dir, if it doesn't already exist + if not os.path.exists(atm_grid_dir): + os.makedirs(atm_grid_dir) + + # Make and input/output file name for the stored photometry. + # For solar metallicity case, allow for legacy isochrones (which didn't have + # metallicity tag since they were all solar metallicity) to be read + # properly + if metallicity == 0.0: + save_file_fmt = '{0}/atm_{1:4.2f}_{2:4s}_p00.fits' + self.save_file = save_file_fmt.format(atm_grid_dir, AKs, str(distance).zfill(5)) + + save_file_legacy = '{0}/atm_{1:4.2f}_{2:4s}.fits' + self.save_file_legacy = save_file_legacy.format(atm_grid_dir, AKs, str(distance).zfill(5)) + else: + # Set metallicity flag + if metallicity < 0: + metal_pre = 'm' + else: + metal_pre = 'p' + metal_flag = int(abs(metallicity)*10) + + save_file_fmt = '{0}/atm_{1:4.2f}_{2:4s}_{3}{4:2s}.fits' + self.save_file = save_file_fmt.format(iso_dir, AKs, str(distance).zfill(5), metal_pre, str(metal_flag).zfill(2)) + self.save_file_legacy = save_file_fmt.format(iso_dir, AKs, str(distance).zfill(5), metal_pre, str(metal_flag).zfill(2)) + + # Expected filters + self.filters = filters + + # Recalculate atmosphere grid if save_file doesn't exist or recomp == True + file_exists = self.check_save_file(evo_model, atm_func, red_law) + + if (not file_exists) | (recomp==True): + self.recalc = True + + c = constants + + t1 = time.time() + + # Assert that the wavelength ranges are within the limits of the + # VEGA model (0.1 - 10 microns) + try: + assert wave_range[0] > 1000 + assert wave_range[1] < 100000 + except: + print('Desired wavelength range invalid. Limit to 1000 - 10000 A') + return + + # The points that will be interpolated over are the grid + # of the ATMOSPHERE MODEL ONLY + # Takes the atm_func and adds the word "_grid" after it to + # call the grid version of it + module = sys.modules[atm_func.__module__] + grid_func = getattr(module, atm_func.__name__ + "_grid") + teff_arr, z_arr, logg_arr = grid_func(rebin=rebin) + + + tab = Table([teff_arr, logg_arr, z_arr], + names=['Teff', 'logg', 'metallicity']) + + + # Initialize output for stellar spectra + self.spec_list = [] + + # Loop through radii too! + # Do WD and stars separately + # For each temperature extract the synthetic photometry. + for ii in range(len(teff_arr)): + # Loop is currently taking about 0.11 s per iteration + gravity = logg_arr[ii] + T = teff_arr[ii] + metallicity = z_arr[ii] + R = float(1*units.Rsun.to('pc')) + + # Get the atmosphere model now. Wavelength is in Angstroms + # This is the time-intensive call... everything else is negligable. + star = atm_func(temperature=T, gravity=gravity, metallicity=metallicity, + rebin=rebin) + + # Trim wavelength range down to JHKL range (0.5 - 5.2 microns) + star = spectrum.trimSpectrum(star, wave_range[0], wave_range[1]) + + # Convert into flux observed at Earth (unreddened) + star *= (R / distance)**2 # in erg s^-1 cm^-2 A^-1 + + # Redden the spectrum. This doesn't take much time at all. + red = red_law.reddening(AKs).resample(star.wave) + star *= red + + # Save the final spectrum to our spec_list for later use. + self.spec_list.append(star) + + # Append all the meta data to the summary table. + tab.meta['REDLAW'] = red_law.name + tab.meta['ATMFUNC'] = atm_func.__name__ + tab.meta['EVOMODEL'] = type(evo_model).__name__ + tab.meta['AKS'] = AKs + tab.meta['DISTANCE'] = distance + tab.meta['WAVEMIN'] = wave_range[0] + tab.meta['WAVEMAX'] = wave_range[1] + + self.points = tab + + t2 = time.time() + print( 'Atmosphere grid generation took {0:f} s.'.format(t2-t1)) + + self.verbose = True + + # Make photometry + self.make_photometry(rebin=rebin, vega=vega) + else: + self.recalc = False + try: + self.points = Table.read(self.save_file) + except: + self.points = Table.read(self.save_file_legacy) + # Add some error checking. + + # Next: do we have all the filters we need? + comp_filters = [] + for ii in self.filters: + col_name = 'm_' + get_filter_col_name(ii) + if col_name not in self.points.keys(): + comp_filters.append(ii) + + # Compute additional filters if needed + if len(comp_filters)>0: + self.verbose = True + print('Missing photometry for',len(comp_filters),'filter - recomputing these columns:',comp_filters) + + # The points that will be interpolated over are the grid + # of the ATMOSPHERE MODEL ONLY + # Takes the atm_func and adds the word "_grid" after it to + # call the grid version of it + module = sys.modules[atm_func.__module__] + grid_func = getattr(module, atm_func.__name__ + "_grid") + teff_arr, z_arr, logg_arr = grid_func(rebin=rebin) + + print('Loading stellar spectra') + # Initialize output for stellar spectra + self.spec_list = [] + # For each isochrone point, extract the synthetic photometry. + for ii in range(len(teff_arr)): + gravity = logg_arr[ii] + T = teff_arr[ii] + metallicity = z_arr[ii] + R = float(1*units.Rsun.to('pc')) + + # Get the atmosphere model now. Wavelength is in Angstroms + # This is the time-intensive call... everything else is negligable. + star = atm_func(temperature=T, gravity=gravity, metallicity=metallicity, + rebin=rebin) + # Trim wavelength range down to appropriate range + star = spectrum.trimSpectrum(star, wave_range[0], wave_range[1]) + # Convert into flux observed at Earth (unreddened) + star *= (R / self.points.meta["DISTANCE"])**2 # in erg s^-1 cm^-2 A^-1 + # Redden the spectrum. This doesn't take much time at all. + red = red_law.reddening(AKs).resample(star.wave) + star *= red + # Save the final spectrum to our spec_list for later use. + self.spec_list.append(star) + + self.make_photometry(rebin=rebin, vega=vega, comp_filters=comp_filters) + + + + return + + def make_photometry(self, rebin=True, vega=vega, comp_filters=None): + """ + Make synthetic photometry for the specified filters. This function + udpates the self.points table to include new columns with the + photometry. + + """ + startTime = time.time() + + meta = self.points.meta + + print( 'Making photometry for atmosphere grid: AKs = %.2f dist = %d' % \ + (meta['AKS'], meta['DISTANCE'])) + print( ' Starting at: ', datetime.datetime.now(), ' Usually takes ~5 minutes') + + npoints = len(self.points) + verbose_fmt = 'M = {0:7.3f} Msun T = {1:5.0f} K m_{2:s} = {3:4.2f}' + + #Calculate all filters, or select filters + if comp_filters is None: + comp_filters = self.filters + + # Loop through the filters, get filter info, make photometry for + # all stars in this filter. + for ii in comp_filters: + prt_fmt = 'Starting filter: {0:s} Elapsed time: {1:.2f} seconds' + print( prt_fmt.format(ii, time.time() - startTime)) + + filt = get_filter_info(ii, rebin=rebin, vega=vega) + filt_name = get_filter_col_name(ii) + + # Make the column to hold magnitudes in this filter. Add to points table. + col_name = 'm_' + filt_name + mag_col = Column(np.zeros(npoints, dtype=float), name=col_name) + self.points.add_column(mag_col) + + # Loop through each star in the isochrone and do the filter integration + print('Starting synthetic photometry') + for ss in range(npoints): + star = self.spec_list[ss] # These are already extincted, observed spectra. + star_mag = mag_in_filter(star, filt) + + self.points[col_name][ss] = star_mag + + if (self.verbose and (ss % 100) == 0): + print( verbose_fmt.format(self.points['Teff'][ss], self.points['logg'][ss], + filt_name, star_mag)) + + endTime = time.time() + print( ' Time taken: {0:.2f} seconds'.format(endTime - startTime)) + + if self.save_file != None: + with warnings.catch_warnings(): + warnings.simplefilter('ignore') + self.points.write(self.save_file, overwrite=True) + + return + + def plot_mass_magnitude(self, mag, savefile=None): + """ + This function is not possible in this Isochrone class + """ + raise Exception('This function is not possible in this Isochrone class') + + return + #===================================================# # Iso table: same as IsochronePhot object, but doesn't do reddening application # or photometry automatically. These are separate functions on the object. From 478c3282d954db619cd0f84588deb74963ac4547 Mon Sep 17 00:00:00 2001 From: nsabrams Date: Tue, 27 Jan 2026 14:45:27 -0800 Subject: [PATCH 02/28] fixed a few more small conflicts --- docs/Cluster_w_COSMIC.ipynb | 151 +++++++++++++++++++----------------- spisea/synthetic.py | 17 ++-- 2 files changed, 90 insertions(+), 78 deletions(-) diff --git a/docs/Cluster_w_COSMIC.ipynb b/docs/Cluster_w_COSMIC.ipynb index 2bcc6532..713a6773 100755 --- a/docs/Cluster_w_COSMIC.ipynb +++ b/docs/Cluster_w_COSMIC.ipynb @@ -65,7 +65,15 @@ "metadata": { "scrolled": true }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "No version information found for evolution model COSMIC.\n" + ] + } + ], "source": [ "# Fetch isochrone\n", "logAge = 10 # Age in log(years)\n", @@ -113,7 +121,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 8, "id": "17d315a9-ec84-4289-a810-855443628e67", "metadata": { "scrolled": true @@ -125,64 +133,67 @@ "text": [ "/opt/mambaforge3/envs/astro_cosmic/lib/python3.11/site-packages/cosmic/utils.py:1687: UserWarning: At least one of your initial binaries is starting in Roche Lobe Overflow:\n", " kstar_1 kstar_2 mass_1 mass_2 porb ecc \\\n", - "582 1.0 1.0 116.027861 92.484134 0.862282 0.840790 \n", - "917 1.0 1.0 93.249056 4.880100 0.984959 0.126383 \n", - "2054 1.0 1.0 122.595315 67.697527 0.029709 0.860986 \n", - "2936 1.0 0.0 28.512173 0.644606 0.185955 0.828483 \n", - "3949 1.0 1.0 36.708844 5.099184 0.068500 0.415908 \n", - "4473 1.0 1.0 11.901563 1.191013 0.500548 0.947242 \n", - "4898 1.0 1.0 27.121218 16.036259 0.185669 0.730699 \n", - "4981 1.0 1.0 7.524916 4.762153 0.113632 0.507614 \n", - "7111 1.0 0.0 2.294603 0.462178 0.382382 0.728774 \n", - "12445 1.0 1.0 13.812780 8.529573 0.096521 0.905398 \n", - "13443 1.0 1.0 33.070690 8.437323 0.108757 0.621895 \n", - "13980 1.0 1.0 15.780719 3.480080 0.256120 0.610062 \n", - "14152 1.0 1.0 4.358243 0.946180 0.482530 0.901946 \n", - "15194 1.0 1.0 73.235018 7.167147 0.178010 0.827868 \n", - "18758 1.0 1.0 9.565150 1.324515 0.499803 0.669640 \n", - "18848 1.0 1.0 28.602152 13.059879 0.506179 0.314764 \n", + "1440 1.0 1.0 84.953667 11.663048 0.876905 0.931278 \n", + "3461 1.0 0.0 14.497658 0.432032 0.316452 0.373763 \n", + "4524 1.0 1.0 43.734965 25.813240 0.086102 0.182706 \n", + "4596 1.0 1.0 11.365734 3.152759 0.258129 0.859164 \n", + "5452 1.0 1.0 79.264723 65.438099 1.013579 0.981040 \n", + "5453 1.0 1.0 144.746349 19.317653 1.490465 0.526429 \n", + "5529 1.0 1.0 20.370581 10.396254 0.426804 0.520938 \n", + "6403 1.0 1.0 28.924458 16.957390 0.454892 0.748762 \n", + "7236 1.0 1.0 48.373542 28.467361 0.213048 0.302529 \n", + "9548 1.0 1.0 18.613090 2.449167 0.560490 0.592169 \n", + "9797 1.0 1.0 23.973515 1.383991 0.074267 0.688942 \n", + "9853 1.0 1.0 67.887280 25.567388 1.540411 0.291563 \n", + "12125 1.0 0.0 3.353695 0.597418 0.218984 0.732055 \n", + "13095 1.0 1.0 27.178998 10.889196 0.563413 0.602920 \n", + "13649 1.0 0.0 4.132947 0.528564 0.262513 0.832788 \n", + "14632 1.0 1.0 84.105227 20.922150 0.136475 0.670406 \n", + "15517 1.0 1.0 52.135141 1.956890 0.333913 0.639657 \n", "\n", " metallicity tphysf mass0_1 mass0_2 ... tacc_1 tacc_2 \\\n", - "582 0.014 10000.0 116.027861 92.484134 ... 0.0 0.0 \n", - "917 0.014 10000.0 93.249056 4.880100 ... 0.0 0.0 \n", - "2054 0.014 10000.0 122.595315 67.697527 ... 0.0 0.0 \n", - "2936 0.014 10000.0 28.512173 0.644606 ... 0.0 0.0 \n", - "3949 0.014 10000.0 36.708844 5.099184 ... 0.0 0.0 \n", - "4473 0.014 10000.0 11.901563 1.191013 ... 0.0 0.0 \n", - "4898 0.014 10000.0 27.121218 16.036259 ... 0.0 0.0 \n", - "4981 0.014 10000.0 7.524916 4.762153 ... 0.0 0.0 \n", - "7111 0.014 10000.0 2.294603 0.462178 ... 0.0 0.0 \n", - "12445 0.014 10000.0 13.812780 8.529573 ... 0.0 0.0 \n", - "13443 0.014 10000.0 33.070690 8.437323 ... 0.0 0.0 \n", - "13980 0.014 10000.0 15.780719 3.480080 ... 0.0 0.0 \n", - "14152 0.014 10000.0 4.358243 0.946180 ... 0.0 0.0 \n", - "15194 0.014 10000.0 73.235018 7.167147 ... 0.0 0.0 \n", - "18758 0.014 10000.0 9.565150 1.324515 ... 0.0 0.0 \n", - "18848 0.014 10000.0 28.602152 13.059879 ... 0.0 0.0 \n", + "1440 0.014 10000.0 84.953667 11.663048 ... 0.0 0.0 \n", + "3461 0.014 10000.0 14.497658 0.432032 ... 0.0 0.0 \n", + "4524 0.014 10000.0 43.734965 25.813240 ... 0.0 0.0 \n", + "4596 0.014 10000.0 11.365734 3.152759 ... 0.0 0.0 \n", + "5452 0.014 10000.0 79.264723 65.438099 ... 0.0 0.0 \n", + "5453 0.014 10000.0 144.746349 19.317653 ... 0.0 0.0 \n", + "5529 0.014 10000.0 20.370581 10.396254 ... 0.0 0.0 \n", + "6403 0.014 10000.0 28.924458 16.957390 ... 0.0 0.0 \n", + "7236 0.014 10000.0 48.373542 28.467361 ... 0.0 0.0 \n", + "9548 0.014 10000.0 18.613090 2.449167 ... 0.0 0.0 \n", + "9797 0.014 10000.0 23.973515 1.383991 ... 0.0 0.0 \n", + "9853 0.014 10000.0 67.887280 25.567388 ... 0.0 0.0 \n", + "12125 0.014 10000.0 3.353695 0.597418 ... 0.0 0.0 \n", + "13095 0.014 10000.0 27.178998 10.889196 ... 0.0 0.0 \n", + "13649 0.014 10000.0 4.132947 0.528564 ... 0.0 0.0 \n", + "14632 0.014 10000.0 84.105227 20.922150 ... 0.0 0.0 \n", + "15517 0.014 10000.0 52.135141 1.956890 ... 0.0 0.0 \n", "\n", " epoch_1 epoch_2 tms_1 tms_2 bhspin_1 bhspin_2 tphys binfrac \n", - "582 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", - "917 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", - "2054 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", - "2936 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", - "3949 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", - "4473 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", - "4898 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", - "4981 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", - "7111 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", - "12445 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", - "13443 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", - "13980 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", - "14152 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", - "15194 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", - "18758 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", - "18848 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "1440 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "3461 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "4524 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "4596 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "5452 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "5453 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "5529 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "6403 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "7236 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "9548 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "9797 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "9853 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "12125 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "13095 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "13649 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "14632 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "15517 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", "\n", - "[16 rows x 38 columns]\n", + "[17 rows x 38 columns]\n", " warnings.warn(\n", - "/u/nsabrams/code/multiplicity/PyPopStar/spisea/evolution.py:1368: RuntimeWarning: divide by zero encountered in log10\n", + "/u/nsabrams/code/multiplicity/PyPopStar/spisea/evolution.py:1408: RuntimeWarning: divide by zero encountered in log10\n", " return np.log10(((np.array(c.G.to('Rsun^3/(Msun*s^2)').value*masses/((radii)**2))*u.Rsun/u.s**2).to('cm/s^2')).value)\n", - "/u/nsabrams/code/multiplicity/PyPopStar/spisea/evolution.py:1368: RuntimeWarning: divide by zero encountered in log10\n", + "/u/nsabrams/code/multiplicity/PyPopStar/spisea/evolution.py:1408: RuntimeWarning: divide by zero encountered in log10\n", " return np.log10(((np.array(c.G.to('Rsun^3/(Msun*s^2)').value*masses/((radii)**2))*u.Rsun/u.s**2).to('cm/s^2')).value)\n", "/opt/mambaforge3/envs/astro_cosmic/lib/python3.11/site-packages/pandas/core/arraylike.py:402: RuntimeWarning: divide by zero encountered in log10\n", " result = getattr(ufunc, method)(*inputs, **kwargs)\n", @@ -206,7 +217,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 9, "id": "467f1672-1f16-4c43-8add-47d0953fcd05", "metadata": {}, "outputs": [], @@ -233,7 +244,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 10, "id": "45ac7b14-e09b-4840-b11d-647e2c5609e4", "metadata": {}, "outputs": [ @@ -243,13 +254,13 @@ "Text(0, 0.5, 'm_ubv_R')" ] }, - "execution_count": 7, + "execution_count": 10, "metadata": {}, "output_type": "execute_result" }, { "data": { - "image/png": "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YezYsTh+/DjuvfdeAMDo0aOxcuVK7TW+vr6SxEpEROTukiOD0TuqPY6VVEoWgzO2NmiKpCMzDz/8MMaMGYNu3bqhW7duePvtt9GuXTscPHhQe46fnx8iIiK0XyEh7rOmnoiIyN2sf+kBhLWT5hd/KRIZwI1WM9XX1+Obb75BdXU1UlJStMd3796Njh07on379hg8eDDefvttdOzY0ex9amtrUVv7x26jVVXNW6pGRETkafJeH+GyJnZSJTC6JE9mCgoKkJKSglu3bqFdu3bYsGEDevToAQBIS0vDo48+iujoaBQVFWH+/PkYNmwYjh49Cj8/P5P3y8zMxJtvvunKPwIREZHXc4ekxRzJl2bX1dWhpKQElZWVWLduHT755BPs2bNHm9DoUiqViI6Oxtq1azF+/HiT9zM1MhMZGcml2URE1OLYOzrTSgDOZ0qbvHjU0mxfX1907doVffv2RWZmJpKTk/H++++bPFehUCA6Ohrnzp0zez8/Pz/t6ijNFxERUUtk72jKHRFQqtQOjsZ5JE9mDImiqDeyouvatWsoLS2FQqFwcVRERESeyd6EptgDOv9qSFozM2/ePKSlpSEyMhI3btzA2rVrsXv3bmzbtg03b97EggULMGHCBCgUChQXF2PevHkIDQ3FI488ImXYREREHkWT0Ngy7RQTGuCscBxO0mTm8uXLePLJJ6FUKiGXy5GUlIRt27ZhxIgRUKvVKCgowBdffIHKykooFAoMHToU2dnZCAwMlDJsIiIij6RJat7cdApfHylB9W3TZbOLJiRCIfd3ZWjNInkBsLNxbyYiIiLzJn98APt/va79/kDGMLdIZLhrNhEREVnlq+dSmj7JzbldATARERGRLZjMEBERkUdjMkNEREQejckMEREReTQmM0REROTRmMwQERGRR2MyQ0RERB6NyQwRERF5NCYzRERE5NGYzBAREZFHYzJDREREHo3JDBEREXk0JjNERETk0ZjMEBERkUdjMkNEREQejckMEREReTQmM0REROTRmMwQERF5EaVKjdzCcihVaqlDcZlWUgdAREREjpGdV4KM9QVoEAGZAGSOT8TEflFSh+V0HJkhIiLyAkqVWpvIAECDCMxbf6pFjNAwmSEiIvICReXV2kRGo14UUVxeI01ALsRkhoiIyAvEhraFTNA/5iMIiAkNkCYgF2IyQ0RE5AUUcn9k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", + "image/png": "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", "text/plain": [ "
" ] @@ -267,7 +278,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 11, "id": "77389803-b5ab-408d-a825-68c2ac30c131", "metadata": {}, "outputs": [ @@ -277,13 +288,13 @@ "Text(0.5, 1.0, 'Singles Only')" ] }, - "execution_count": 8, + "execution_count": 11, "metadata": {}, "output_type": "execute_result" }, { "data": { - "image/png": "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", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjMAAAHFCAYAAAAHcXhbAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAABTrklEQVR4nO3deVhU9f4H8PcBAQeEEQRhTLZQRAPcU6xEMRe00jSzXNIys3KpW7ebmP7UFkHbb5q3umV2yzW3e3PLUtFEDTUUTUwNhHQQURgQBxA4vz+MiWVmmBlm5szyfj3PPDnnnDnzYeRx3n1XQRRFEURERER2ykXqAoiIiIiag2GGiIiI7BrDDBEREdk1hhkiIiKyawwzREREZNcYZoiIiMiuMcwQERGRXWOYISIiIrvGMENERER2jWGGyEkdOXIEDz/8MEJCQuDh4YHAwEDExcXh5ZdfrnfdgAEDMGDAAIvXIwgCFi5caPH3aejatWtISkpCly5d4OnpCR8fH/Tt2xfLly/HrVu3TL7vwoULIQiCGSslIl1aSF0AEVnftm3b8NBDD2HAgAFYunQpFAoFlEoljh49irVr1+Ldd9/VXPvxxx9LWKllZWVlYciQIbhx4wZefvll9OvXD2q1Gt999x1eeOEFbNiwAdu3b4enp6fUpRKRHgwzRE5o6dKlCA8Px65du9CixV//DDz22GNYunRpvWu7dOli7fKsorq6GmPGjEFJSQl+/vlnREZGas4NHz4c8fHxeOyxx/DSSy/hX//6l4SVElFT2M1E5ISuXbsGf3//ekGmlotL/X8WGnYz5eTkQBAEvPPOO3jvvfcQHh6OVq1aIS4uDocPH250v88++wyRkZHw8PBAly5dsHr1akyZMgVhYWFN1pmfn4/p06ejffv2cHd3R3h4OBYtWoSqqqp6161YsQJdu3ZFq1at4O3tjaioKMydO1fvvTdv3oxff/0Vc+bMqRdkao0bNw5DhgzB559/jvz8fJN+9rqmTp0KPz8/3Lx5s9G5hIQE3HXXXU19HESkA8MMkROKi4vDkSNHMHv2bBw5csSksSHLly/H7t278cEHH+Cbb75BWVkZhg8fDpVKpbnm008/xTPPPIPY2Fhs2rQJ8+bNw6JFi7Bv374m75+fn4+7774bu3btwv/93/9hx44dmDp1KpKTkzFt2jTNdWvXrsXzzz+P+Ph4bN68GVu2bMHf/vY3lJWV6b3/7t27AQCjRo3Sec2oUaNQVVXVqF5DfvaGXnjhBRQVFWH16tX1jv/666/Yu3cvZsyYobdeItJDJCKnU1hYKN57770iABGA6ObmJvbr109MTk4WS0tL610bHx8vxsfHa55nZ2eLAMSYmBixqqpKc/znn38WAYhr1qwRRVEUq6urxaCgILFPnz717nfx4kXRzc1NDA0NrXccgLhgwQLN8+nTp4utWrUSL168WO+6d955RwQgnj59WhRFUZw5c6bYunVroz+DYcOGiQDE8vJyndfs2LFDBCAuWbLEqJ9dFEVxwYIFYsN/YuPj48Vu3brVO/bcc8+JPj4+jT53IjIcW2aInFCbNm1w4MABpKenIyUlBSNHjsRvv/2GpKQkxMTEoLCwsMl7jBgxAq6urprnsbGxAICLFy8CAM6ePYv8/Hw8+uij9V4XEhKCe+65p8n7f/fddxg4cCDatWuHqqoqzSMxMREAkJqaCgC4++67UVxcjMcffxxbt241qHZDiaIIAI1mJTX1s+vywgsvICMjAwcPHgQAlJSU4D//+Q8mT56MVq1ama1uImfDMEPkxHr16oVXX30VGzZswOXLl/G3v/0NOTk5jQYBa9OmTZt6zz08PAAAarUawO1xOQAQGBjY6LXajjV05coV/O9//4Obm1u9R+3YktrQMmnSJHzxxRe4ePEixowZg7Zt26JPnz6abiRdQkJCAADZ2dk6r8nJyQEABAcH1zve1M+uy8iRIxEWFobly5cDAL788kuUlZWxi4momRhmiAgA4ObmhgULFgAATp061ez71X7hX7lypdG52gG1+vj7+2PIkCFIT0/X+pg6darm2ieffBJpaWlQqVTYtm0bRFHEAw88oLelZPDgwQCALVu26Lxmy5YtaNGihdnW2XFxccGMGTPw7bffQqlU4uOPP8agQYPQqVMns9yfyFkxzBA5IaVSqfX4mTNnAADt2rVr9nt06tQJQUFBWL9+fb3jubm5SEtLa/L1DzzwAE6dOoWIiAj06tWr0UNbjV5eXkhMTMRrr72GyspKnD59Wuf9H374YXTp0gUpKSn47bffGp1ft24dvv/+ezz99NMICgoy4Cc2zNNPPw13d3dMmDABZ8+excyZM812byJnxXVmiJzQ0KFD0b59ezz44IOIiopCTU0NMjIy8O6776JVq1Z4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", "text/plain": [ "
" ] @@ -310,7 +321,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 12, "id": "594beb18-cdee-4cc4-8d4b-64848ce4700e", "metadata": {}, "outputs": [ @@ -320,13 +331,13 @@ "Text(0.5, 0, 'log(a) [AU]')" ] }, - "execution_count": 9, + "execution_count": 12, "metadata": {}, "output_type": "execute_result" }, { "data": { - "image/png": "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c+zYMT3zzDOBSz+nurzz/fff64svvtBVV10VUu0rV67UoUOH9OGHHyoiIiLQ/tlnn+nOO+/U/v37lZCQoC5duuiVV17R999/HzTKs3nzZrVv3z5QLwB7MYICIKBTp0669dZbdf/992vDhg366KOPdNddd+miiy7SrbfeKknKycnRypUrNWPGDO3cuVMvvfSS3nnnnaBRlauuukrt27fX+++/H2i79NJLdezYMc2aNUtffvml5s+frxdffLFeDZs2bZLT6VTPnj1Dqn3OnDkaMGCAunXrprS0tMAybNgwtW/fXgsWLJAk3XnnnYqMjNTdd9+tkpISffHFF1qwYIHy8/P10EMPnctpAxAGBBQAQQoKCpSenq6BAweqZ8+esixLK1euVKtWrSRJv/3tb/Xiiy9qxowZ6tatm9599139+c9/DhqNiIiI0H333aeFCxcG2n79619rxowZevrpp5WWlqaFCxcqPz+/3vFfeeUV3XnnnYqOjj7rmr/55hutWLFCw4YNq7fN4XBo6NChgcs8LpdL69evl2VZGjx4sLp166bp06friSee0IQJE876mADCy2Gd7qIzAJyl+++/X5999lnQrcHffPONrrjiCpWWliolJeWs9vPtt9+qS5cuKikpUWpq6mn7jRo1SgcPHgzbY+7tOhaAkxhBARCyv/3tb/roo4/0+eefa9asWZo7d65GjhwZ1MftdmvOnDnavXv3We93165deuGFF84YTn709ttvq23btnr77bdDrv9srF+/Xm3btg0aBQLQeBhBARCy4cOHa926dTp06JB+8YtfKCcnR2PGjGm041dVVammpkaSlJSUpJiYmAY/Rm1trb7++mtJUtu2beXxeBr8GABOj4ACAACMwyUeAABgHAIKAAAwDgEFAAAYh4ACAACMQ0ABAADGIaAAAADjEFAAAIBxCCgAAMA4/w+5L2052I6OXQAAAABJRU5ErkJggg==", + "image/png": "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", "text/plain": [ "
" ] @@ -350,7 +361,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 13, "id": "cf7ede5c-417f-4342-8e6a-3b9efae1e43e", "metadata": {}, "outputs": [ @@ -360,13 +371,13 @@ "Text(0, 0.5, 'N objects')" ] }, - "execution_count": 10, + "execution_count": 13, "metadata": {}, "output_type": "execute_result" }, { "data": { - "image/png": "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bt00depU3XvvvYqPj5fE/LqTu+ayZcuWOnnyZJHx//Wvf1XpfBN03Kx27dqKiIhQUlKSS3tSUpIGDhzooaqqB2OM7r77br311lvatm2b2rdv77K/ffv2atmypcvc5ufna8eOHc65jYiIUK1atVz6ZGVl6dChQz4//yNGjNDBgweVmprq/PTp00dTpkxRamqqrrrqKua3Aq699toij0P45ptvFBoaKok/vxV14cIF1ajh+k+Wn5+f8/Zy5td93DWXAwYMUE5Ojvbs2ePss3v3buXk5FTtfFfZsmcfcvn28pdeesmkpaWZmJgYU79+ffPdd995ujSvdtddd5nAwEDz8ccfm6ysLOfnwoULzj5PPvmkCQwMNG+99ZY5ePCgmTx5crG3PLZp08Z89NFHZv/+/ea6667zydtHS+PXd10Zw/xWxJ49e0zNmjXNE088YY4cOWJee+01U69ePfPqq686+zC/5Td9+nTTunVr5+3lb731lmnWrJlZtGiRsw/zW3p5eXnmwIED5sCBA0aSeeaZZ8yBAwecj0Fx11yOGTPGdO/e3Xz22Wfms88+M926deP2clskJCSY0NBQU7t2bdO7d2/nLdIomaRiP2vXrnX2KSwsNEuWLDEtW7Y0/v7+ZsiQIebgwYMu4/z000/m7rvvNk2aNDF169Y1N9xwg8nIyKjib1M9/GfQYX4r5t133zXh4eHG39/fXHPNNWb16tUu+5nf8svNzTULFiwwbdu2NXXq1DFXXXWViYuLMxcvXnT2YX5Lb/v27cX+/3b69OnGGPfN5enTp82UKVNMQECACQgIMFOmTDFnzpypom/5bw5jjKm680cAAABVhzU6AADAWgQdAABgLYIOAACwFkEHAABYi6ADAACsRdABAADWIugAAABrEXQAAIC1CDpANTJs2DDFxMSUuH/GjBmaMGFCqcb67rvv5HA4lJqa6pbavEG7du20fPnyShn7t+a+tLZt26ZrrrnG+Y6mxx57TD179qzwuBWRnZ2t5s2b69ixYx6tA6gMBB3AIs8995zWrVvn6TI8Zu/evbrjjjuc2w6HQ5s2bfJcQcVYtGiR4uLiirygsrIMGzZML7744hX7tGjRQlOnTtWSJUuqpCagKhF0AIsEBgaqUaNGni7DY5o3b6569ep5uowSJScn68iRI7rllluq5Hg//vijkpOTNW7cuN/sO3PmTL322ms6c+ZMFVQGVB2CDlCNffDBBwoMDNT69eslFb10VVhYqD/96U/q0KGD/P391bZtWz3xxBPFjlVYWKg5c+aoU6dO+v7774vtc3n8P/7xjwoKClKjRo30+OOP69KlS1q4cKGaNGmiNm3a6H/+539cfu6BBx5Qp06dVK9ePV111VV65JFH9Msvv7j0WbZsmVq0aKGAgADNnj1bDz74oMslncvH/stf/qJWrVqpadOmio6Odhnn15eu2rVrJ0n63e9+J4fD4dwu7vJeTEyMhg0b5tw+f/68pk2bpgYNGqhVq1Z6+umni8xFfn6+Fi1apNatW6t+/frq37+/Pv7442Ln7bLExERFRkaqTp06JfZJT09Xhw4ddNddd6mwsFDr1q1To0aNtHnzZnXu3Fn16tXTzTffrPPnz+vll19Wu3bt1LhxY82fP18FBQUuY7333nvq0aOHWrdurTNnzmjKlClq3ry56tatq44dO2rt2rXOvt26dVPLli21cePGK34HoLqp6ekCAJRPYmKi7rjjDr3yyiu68cYbi+2zePFirVmzRs8++6wGDRqkrKwsHT58uEi//Px83Xbbbfr222/1ySefqEWLFiUed9u2bWrTpo127typTz/9VLNmzdJnn32mIUOGaPfu3dqwYYPmzp2rUaNGKSQkRJIUEBCgdevWKTg4WAcPHtScOXMUEBCgRYsWSZJee+01PfHEE1q5cqWuvfZaJSYm6umnn1b79u1djr19+3a1atVK27dv19GjRzVp0iT17NlTc+bMKVLn3r171aJFC61du1ZjxoyRn59fqed24cKF2r59uzZu3KiWLVvqoYceUkpKikvwmjlzpr777jslJiYqODhYGzdu1JgxY3Tw4EF17Nix2HF37typyZMnl3jcQ4cOKTIyUtOnT1d8fLyz/cKFC3r++eeVmJiovLw8TZw4URMnTlSjRo20ZcsW/fOf/9RNN92kQYMGadKkSc6fe+edd5x/Nh555BGlpaXp/fffV7NmzXT06FH99NNPLsfv16+fdu3apT/84Q+lnivA61Xpu9IBVMjQoUPNggULTEJCggkMDDTbtm1z2T99+nRz4403GmOMyc3NNf7+/mbNmjXFjpWenm4kmV27dpmRI0eaa6+91pw9e/aKx58+fboJDQ01BQUFzrbOnTubwYMHO7cvXbpk6tevb15//fUSx/nzn/9sIiIinNv9+/c30dHRLn2uvfZa06NHjyLHvnTpkrPtlltuMZMmTXJuh4aGmmeffda5Lcls3LixyHe4PEeXLViwwAwdOtQYY0xeXp6pXbu2SUxMdO4/ffq0qVu3rlmwYIExxpijR48ah8Nhjh075jLOiBEjzOLFi0v83oGBgWb9+vUubUuWLDE9evQwycnJpkmTJuapp55y2b927VojyRw9etTZduedd5p69eqZvLw8Z9vo0aPNnXfe6dz++eefTUBAgPnyyy+NMcaMGzfOzJw5s8TajDHm3nvvNcOGDbtiH6C64YwOUM28+eabOnnypD755BP169evxH7/+Mc/dPHiRY0YMeKK402ePFlt2rTR1q1bS7W+pWvXri4LaYOCghQeHu7c9vPzU9OmTZWdne1s+/vf/67ly5fr6NGjOnfunC5duqSGDRs693/99deaN2+ey3H69eunbdu2FTn2r8/MtGrVSgcPHvzNmsvi22+/VX5+vgYMGOBsa9KkiTp37uzc3r9/v4wx6tSpk8vPXrx4UU2bNi1x7J9++qnYy1YZGRkaOXKkli1bpnvvvbfI/nr16unqq692bgcFBaldu3Zq0KCBS9uv53zbtm1q2rSpunXrJkm66667dNNNN2n//v2KjIzUhAkTNHDgQJfj1K1bVxcuXCixfqA6Yo0OUM307NlTzZs319q1a2WMKbFf3bp1SzXe2LFj9eWXX+rzzz8vVf9atWq5bDscjmLbLt8+/fnnn+vWW29VVFSUNm/erAMHDiguLk75+flFfubXivtuVzpOadWoUaPI2L9e53OlOb2ssLBQfn5+SklJUWpqqvPzj3/8Q88991yJP9esWbNiF/s2b95c/fr1U2JionJzc4vsL+ucS66XrSQpKipK33//vWJiYnT8+HGNGDFC999/v8sYP/74o5o3b37lLw9UMwQdoJq5+uqrtX37dr399tuaP39+if06duyounXrauvWrVcc76677tKTTz6p8ePHa8eOHe4uV59++qlCQ0MVFxenPn36qGPHjkUWO3fu3Fl79uxxadu3b1+Fj12rVq0iC3SbN2+urKwsl7ZfP0uoQ4cOqlWrlkvwO3PmjL755hvndq9evVRQUKDs7Gx16NDB5dOyZcsS6+nVq5fS0tKKtNetW1ebN29WnTp1NHr0aOXl5ZX1q7owxujdd9/V+PHjXdqbN2+uGTNm6NVXX9Xy5cu1evVql/2HDh1Sr169KnRswNsQdIBqqFOnTtq+fbvefPPNEh9iV6dOHT3wwANatGiR1q9fr2+//Vaff/65XnrppSJ958+fr2XLlumGG27QJ5984tZaO3TooIyMDCUmJurbb7/V888/X+TOnvnz5+ull17Syy+/rCNHjmjZsmX68ssvi5zlKat27dpp69atOnHihPNMynXXXad9+/Zp/fr1OnLkiJYsWaJDhw45f6ZBgwaaNWuWFi5cqK1bt+rQoUOaMWOGy+W6Tp06acqUKZo2bZreeustpaena+/evfrTn/6kLVu2lFjP6NGjS5zf+vXr67333lPNmjUVFRWlc+fOlft7p6Sk6Pz58xoyZIiz7dFHH9Xbb7+to0eP6quvvtLmzZvVpUsX5/4LFy4oJSVFkZGR5T4u4I0IOkA11blzZ23btk2vv/667rvvvmL7PPLII7rvvvv06KOPqkuXLpo0aZLLOo5fi4mJ0eOPP66xY8cqOTnZbXXeeOONuvfee3X33XerZ8+eSk5O1iOPPOLSZ8qUKVq8eLHuv/9+9e7dW+np6ZoxY8YVb8MujaefflpJSUkKCQlxnqkYPXq0HnnkES1atEh9+/ZVXl6epk2b5vJzTz31lIYMGaLx48dr5MiRGjRokCIiIlz6rF27VtOmTdN9992nzp07a/z48dq9e7fzTrPi3H777UpLS9PXX39d7P4GDRro/ffflzFGY8eO1fnz58v1vd9++21df/31qlnz/5Zh1q5dW4sXL1b37t01ZMgQ+fn5KTEx0eVn2rZtq8GDB5frmIC3cpjSXJAGgCo2atQotWzZUq+88oqnS3GrRYsWKScnR//93/9dacfo3r27Hn74Yf3+978v9c/069dPMTExuu222yqtLsATuOsKgMdduHBBL774okaPHi0/Pz+9/vrr+uijj5SUlOTp0twuLi5OCQkJKigoKNOzfUorPz9fN910k6Kiokr9M9nZ2br55puv+IwfoLrijA4Aj/vpp580btw47d+/XxcvXlTnzp318MMPa+LEiZ4uDUA1R9ABAADWYjEyAACwFkEHAABYi6ADAACsRdABAADWIugAAABrEXQAAIC1CDoAAMBaBB0AAGCt/w923aKexJluVgAAAABJRU5ErkJggg==", + "image/png": "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na1bt2rIkCEKCQmRw+HQunXrCvRZsmSJWrRooWrVqikyMlLbtm1zWX/mzBl16NBBTZs21ezZsxUUFFRO1QMAAG/m8aBz/vx5dejQQS+99FKh69esWaOYmBjNnz9f+/btU+/evRUdHa309HRnnzp16uiLL75QWlqa/v73v+vEiRNFbi8nJ0fZ2dkuHwAAYCePB53o6GgtWrRII0aMKHT9c889p0mTJmny5Mlq27atFi9erNDQUC1durRA3+DgYLVv315bt24tcntxcXEKDAx0fkJDQ922LwAAwLt4POhcSW5urpKTkxUVFeXSHhUVpaSkJEnSiRMnnEdlsrOztXXrVrVp06bIMefNm6esrCznJyMjo+x2AAAAeJRX33V18uRJ5eXlKTg42KU9ODhYx48flyT98MMPmjRpkowxMsbogQceUPv27Ysc09/fX/7+/mVaNwAA8A5eHXQuczgcLsvGGGdbZGSkUlJSPFAVAADwdl596iooKEh+fn7OozeXZWZmFjjKU1Lx8fEKDw9X165dSzUOAADwXl4ddKpWrarIyEglJia6tCcmJqpnz56lGnv69OlKTU3V7t27SzUOAADwXh4/dXXu3DkdPnzYuZyWlqaUlBTVq1dPzZo1U2xsrMaOHasuXbqoR48eWrZsmdLT0zV16lQPVg0AACoCjwedPXv2qH///s7l2NhYSdL48eO1cuVKjRw5UqdOndLChQt17NgxRUREaMOGDQoLC/NUyQAAoILweNDp16/fVV/ZMG3aNE2bNs2t242Pj1d8fLzy8vLcOi4AAPAeXn2NTlniGh0AAOzns0EHAADYj6ADAACs5bNBh+foAABgP58NOlyjAwCA/Xw26AAAAPsRdAAAgLUIOgAAwFoEHQAAYC2fDTrcdQUAgP18Nuhw1xUAAPbz2aADAADsR9ABAADWIugAAABrEXQAAIC1fDbocNcVAAD289mgw11XAADYz2eDDgAAsB9BBwAAWIugAwAArEXQAQAA1iLoAAAAaxF0AACAtXw26PAcHQAA7OezQYfn6AAAYD+fDToAAMB+BB0AAGAtgg4AALAWQQcAAFir1EEnLy9PKSkpOn36tDvqAQAAcJsSB52YmBi9+uqrkn4JOX379lXnzp0VGhqqTz/91N31AQAAXLMSB51//OMf6tChgyTp/fffV1pamg4ePKiYmBjNnz/f7QUCAABcqxIHnZMnT6pRo0aSpA0bNuiuu+5S69atNWnSJO3fv9/tBZYVHhgIAID9Shx0goODlZqaqry8PH300UcaOHCgJOnChQvy8/Nze4FlhQcGAgBgv8ol/cLEiRN19913q3HjxnI4HLrlllskSTt37tQNN9zg9gIBAACuVYmDzhNPPKGIiAhlZGTorrvukr+/vyTJz89Pc+fOdXuBAAAA16rEQWfVqlUaOXKkM+BcNnr0aCUkJLitMAAAgNIq8TU6EydOVFZWVoH2s2fPauLEiW4pCgAAwB1KHHSMMXI4HAXaf/jhBwUGBrqlKAAAAHco9qmrTp06yeFwyOFwaMCAAapc+d9fzcvLU1pamm699dYyKRIAAOBaFDvoDB8+XJKUkpKiQYMGqVatWs51VatWVfPmzXXHHXe4vUAAAIBrVeygs2DBAklS8+bNNWrUqAIXIwMAAHibEl+jEx4erpSUlALtO3fu1J49e9xREwAAgFuUOOhMnz5dGRkZBdqPHDmi6dOnu6UoAAAAdyhx0ElNTVXnzp0LtHfq1EmpqaluKQoAAMAdShx0/P39deLEiQLtx44dc7kTCwAAwNNKHHRuueUWzZs3z+WhgWfOnNGjjz7qfO9VRcDbywEAsJ/DGGNK8oUjR46oT58+OnXqlDp16iTpl1vOg4ODlZiYqNDQ0DIptKxkZ2crMDBQWVlZql27tlvHbj73g6v2+e7p29y6TQAAfEFxf3+X+FxTkyZN9OWXX+rNN9/UF198oerVq2vixIkaPXq0qlSpUqqiAQAA3OmaLqqpWbOm7rvvPnfXAgAA4FYlvkZHkl5//XX16tVLISEh+v777yVJzz//vN599123FgcAAFAaJQ46S5cuVWxsrKKjo3X69Gnl5eVJkurWravFixe7uz4AAIBrVuKg85e//EXLly/X/PnzXW4n79Kli/bv3+/W4gAAAEqjxEEnLS3NebfVr/n7++v8+fNuKQoAAMAdShx0WrRoUei7rj788EOFh4e7oyYAAAC3KPFdV7NmzdL06dP1888/yxijXbt2afXq1YqLi9Nf//rXsqgRAADgmpQ46EycOFGXLl3S7NmzdeHCBd1zzz1q0qSJXnjhBY0aNaosagQAALgm1/QcnSlTpmjKlCk6efKk8vPz1bBhQ3fXBQAAUGqlegtnUFCQu+oAAABwu2IFnc6dO2vjxo2qW7euOnXqJIfDUWTfWrVq6cYbb9Sjjz5a4d57BQAA7FKsoDNs2DD5+/tLkoYPH37Fvjk5Odq4caPuvfdebdmypdQFAgAAXKtiBZ0FCxYU+t9F+fbbb3XjjTdee1UAAABucM3X6GRmZurrr7+Ww+FQ69atXS5Ivv7663XixAm3FAgAAHCtSvzAwOzsbI0dO1ZNmjRR37591adPHzVp0kT33nuvsrKynP0CAwPdWigAAEBJlTjoTJ48WTt37tT69et15swZZWVlaf369dqzZ4+mTJlSFjUCAABckxIHnQ8++EB/+9vfNGjQINWuXVsBAQEaNGiQli9frg8++KAsaryijIwM9evXT+Hh4Wrfvr3eeuutcq8BAAB4pxJfo1O/fv1CT0sFBgaqbt26bimqJCpXrqzFixerY8eOyszMVOfOnTV48GDVrFmz3GsBAADepcRHdB577DHFxsbq2LFjzrbjx49r1qxZevzxx91aXHE0btxYHTt2lCQ1bNhQ9erV048//ljudQAAAO9TrKDTqVMnde7cWZ07d9bLL7+sHTt2KCwsTC1btlTLli3VrFkzJSUl6ZVXXilxAVu3btWQIUMUEhIih8OhdevWFeizZMkStWjRQtWqVVNkZKS2bdtW6Fh79uxRfn4+DyoEAACSinnq6moPCSyN8+fPq0OHDpo4caLuuOOOAuvXrFmjmJgYLVmyRDfddJNeeeUVRUdHKzU1Vc2aNXP2O3XqlMaNG3fVN6jn5OQoJyfHuZydne2+nQEAAF7FYYwxni7iMofDobVr17oEq+7du6tz585aunSps61t27YaPny44uLiJP0SXm655RZNmTJFY8eOveI2nnjiCT355JMF2rOyslS7dm337Mj/az736hdnf/f0bW7dJgAAviA7O1uBgYFX/f1d4mt0LktOTtYbb7yhN998U/v27bvWYa4oNzdXycnJioqKcmmPiopSUlKSJMkYowkTJujmm2++asiRpHnz5ikrK8v5ycjIKJPaAQCA55X4rqvMzEyNGjVKn376qerUqSNjjLKystS/f38lJCSoQYMGbivu5MmTysvLU3BwsEt7cHCwjh8/Lkn6/PPPtWbNGrVv3955fc/rr7+udu3aFTqmv7+/871dAADAbiUOOjNmzFB2dra++uortW3bVpKUmpqq8ePH68EHH9Tq1avdXuR/vi3dGONs69Wr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fn2zfv16k5aWZt566y1Tq1Yts3jxYmcfX52nDRs2mPnz55u3337bSDJr1651We+uebn11ltNRESESUpKMklJSSYiIsLcfvvt5bWbpXaleTpz5owZOHCgWbNmjTl48KDZvn276d69u4mMjHQZw5vmiaBTBrp162amTp3q0nbDDTeYuXPneqgiz8rMzDSSzJYtW4wxxuTn55tGjRqZp59+2tnn559/NoGBgebll182xvzyl6lKlSomISHB2efIkSOmUqVK5qOPPirfHSgHZ8+eNa1atTKJiYmmb9++zqDDXP3bnDlzTK9evYpcz1z94rbbbjO//e1vXdpGjBhh7r33XmMM83TZf/4Cd9e8pKamGklmx44dzj7bt283kszBgwfLeK/cr7BA+J927dplJDn/Z97b5olTV26Wm5ur5ORkRUVFubRHRUUpKSnJQ1V5VlZWliSpXr16kqS0tDQdP37cZY78/f3Vt29f5xwlJyfr4sWLLn1CQkIUERFh5TxOnz5dt912mwYOHOjSzlz923vvvacuXbrorrvuUsOGDdWpUyctX77cuZ65+kWvXr20ceNGffPNN5KkL774Qp999pkGDx4siXkqirvmZfv27QoMDFT37t2dff7rv/5LgYGB1s5dVlaWHA6H6tSpI8n75snnX+rpbidPnlReXp6Cg4Nd2oODg3X8+HEPVeU5xhjFxsaqV69eioiIkCTnPBQ2R99//72zT9WqVVW3bt0CfWybx4SEBO3du1e7d+8usI65+rd//etfWrp0qWJjY/Xoo49q165devDBB+Xv769x48YxV/9vzpw5ysrK0g033CA/Pz/l5eXpqaee0ujRoyXxM1UUd83L8ePH1bBhwwLjN2zY0Mq5+/nnnzV37lzdc889zhd4ets8EXTKiMPhcFk2xhRo8wUPPPCAvvzyS3322WcF1l3LHNk2jxkZGZo5c6b+53/+R9WqVSuyH3Ml5efnq0uXLvrDH/4gSerUqZO++uorLV26VOPGjXP28/W5WrNmjd544w39/e9/14033qiUlBTFxMQoJCRE48ePd/bz9XkqijvmpbD+Ns7dxYsXNWrUKOXn52vJkiVX7e+peeLUlZsFBQXJz8+vQCLNzMws8H8KtpsxY4bee+89bd68WU2bNnW2N2rUSJKuOEeNGjVSbm6uTp8+XWQfGyQnJyszM1ORkZGqXLmyKleurC1btujFF19U5cqVnfvKXEmNGzdWeHi4S1vbtm2Vnp4uiZ+ry2bNmqW5c+dq1KhRateuncaOHauHHnpIcXFxkpinorhrXho1aqQTJ04UGP9///d/rZq7ixcv6u6771ZaWpoSExOdR3Mk75sngo6bVa1aVZGRkUpMTHRpT0xMVM+ePT1UVfkyxuiBBx7QO++8o02bNqlFixYu61u0aKFGjRq5zFFubq62bNninKPIyEhVqVLFpc+xY8d04MABq+ZxwIAB2r9/v1JSUpyfLl26aMyYMUpJSdF1113HXP2/m266qcBjCr755huFhYVJ4ufqsgsXLqhSJdd/2v38/Jy3lzNPhXPXvPTo0UNZWVnatWuXs8/OnTuVlZVlzdxdDjmHDh3SJ598ovr167us97p5cuulzTDG/Pv28ldffdWkpqaamJgYU7NmTfPdd995urRycf/995vAwEDz6aefmmPHjjk/Fy5ccPZ5+umnTWBgoHnnnXfM/v37zejRowu9jbNp06bmk08+MXv37jU333xzhb+9tTh+fdeVMczVZbt27TKVK1c2Tz31lDl06JB58803TY0aNcwbb7zh7MNcGTN+/HjTpEkT5+3l77zzjgkKCjKzZ8929vHVeTp79qzZt2+f2bdvn5FknnvuObNv3z7n3ULumpdbb73VtG/f3mzfvt1s377dtGvXrkLdXn6lebp48aIZOnSoadq0qUlJSXH5Nz4nJ8c5hjfNE0GnjMTHx5uwsDBTtWpV07lzZ+et1b5AUqGfFStWOPvk5+ebBQsWmEaNGhl/f3/Tp08fs3//fpdxfvrpJ/PAAw+YevXqmerVq5vbb7/dpKenl/PelL//DDrM1b+9//77JiIiwvj7+5sbbrjBLFu2zGU9c2VMdna2mTlzpmnWrJmpVq2aue6668z8+fNdfgn56jxt3ry50H+bxo8fb4xx37ycOnXKjBkzxgQEBJiAgAAzZswYc/r06XLay9K70jylpaUV+W/85s2bnWN40zw5jDHGvceIAAAAvAPX6AAAAGsRdAAAgLUIOgAAwFoEHQAAYC2CDgAAsBZBBwAAWIugAwAArEXQAQAA1iLoABVIv379FBMTU+T6CRMmaPjw4cUa67vvvpPD4VBKSopbavMGzZs31+LFi8tk7KvNfXFt2rRJN9xwg/PdU0888YQ6duxY6nFLIzMzUw0aNNCRI0c8WgdQFgg6gEVeeOEFrVy50tNleMzu3bt13333OZcdDofWrVvnuYIKMXv2bM2fP7/AizfLSr9+/fTyyy9fsU/Dhg01duxYLViwoFxqAsoTQQewSGBgoOrUqePpMjymQYMGqlGjhqfLKFJSUpIOHTqku+66q1y29+OPPyopKUlDhgy5at+JEyfqzTff1OnTp8uhMqD8EHSACuyjjz5SYGCgVq1aJangqav8/Hw988wzatmypfz9/dWsWTM99dRThY6Vn5+vKVOmqHXr1vr+++8L7XN5/D/84Q8KDg5WnTp19OSTT+rSpUuaNWuW6tWrp6ZNm+pvf/uby/fmzJmj1q1bq0aNGrruuuv0+OOP6+LFiy59Fi1apIYNGyogIECTJ0/W3LlzXU7pXN72n//8ZzVu3Fj169fX9OnTXcb59amr5s2bS5J+85vfyOFwOJcLO70XExOjfv36OZfPnz+vcePGqVatWmrcuLGeffbZAnORm5ur2bNnq0mTJqpZs6a6d++uTz/9tNB5uywhIUFRUVGqVq1akX3S0tLUsmVL3X///crPz9fKlStVp04drV+/Xm3atFGNGjV055136vz583rttdfUvHlz1a1bVzNmzFBeXp7LWB988IE6dOigJk2a6PTp0xozZowaNGig6tWrq1WrVlqxYoWzb7t27dSoUSOtXbv2ivsAVDSVPV0AgGuTkJCg++67T6+//rqGDRtWaJ958+Zp+fLlev7559WrVy8dO3ZMBw8eLNAvNzdX99xzj7799lt99tlnatiwYZHb3bRpk5o2baqtW7fq888/16RJk7R9+3b16dNHO3fu1Jo1azR16lTdcsstCg0NlSQFBARo5cqVCgkJ0f79+zVlyhQFBARo9uzZkqQ333xTTz31lJYsWaKbbrpJCQkJevbZZ9WiRQuXbW/evFmNGzfW5s2bdfjwYY0cOVIdO3bUlClTCtS5e/duNWzYUCtWrNCtt94qPz+/Ys/trFmztHnzZq1du1aNGjXSo48+quTkZJfgNXHiRH333XdKSEhQSEiI1q5dq1tvvVX79+9Xq1atCh1369atGj16dJHbPXDggKKiojR+/HjFxcU52y9cuKAXX3xRCQkJOnv2rEaMGKERI0aoTp062rBhg/71r3/pjjvuUK9evTRy5Ejn99577z3nz8bjjz+u1NRUffjhhwoKCtLhw4f1008/uWy/W7du2rZtm377298We64Ar+f296EDKDN9+/Y1M2fONPHx8SYwMNBs2rTJZf348ePNsGHDjDHGZGdnG39/f7N8+fJCx0pLSzOSzLZt28zAgQPNTTfdZM6cOXPF7Y8fP96EhYWZvLw8Z1ubNm1M7969ncuXLl0yNWvWNKtXry5ynD/+8Y8mMjLSudy9e3czffp0lz433XST6dChQ4FtX7p0ydl21113mZEjRzqXw8LCzPPPP+9clmTWrl1bYB8uz9FlM2fONH379jXGGHP27FlTtWpVk5CQ4Fx/6tQpU716dTNz5kxjjDGHDx82DofDHDlyxGWcAQMGmHnz5hW534GBgWbVqlUubQsWLDAdOnQwSUlJpl69euZPf/qTy/oVK1YYSebw4cPOtt/97nemRo0a5uzZs862QYMGmd/97nfO5Z9//tkEBASYL7/80hhjzJAhQ8zEiROLrM0YYx566CHTr1+/K/YBKhqO6AAVzNtvv60TJ07os88+U7du3Yrs989//lM5OTkaMGDAFccbPXq0mjZtqo0bNxbr+pYbb7zR5ULa4OBgRUREOJf9/PxUv359ZWZmOtv+8Y9/aPHixTp8+LDOnTunS5cuqXbt2s71X3/9taZNm+aynW7dumnTpk0Ftv3rIzONGzfW/v37r1pzSXz77bfKzc1Vjx49nG316tVTmzZtnMt79+6VMUatW7d2+W5OTo7q169f5Ng//fRToaet0tPTNXDgQC1atEgPPfRQgfU1atTQ9ddf71wODg5W8+bNVatWLZe2X8/5pk2bVL9+fbVr106SdP/99+uOO+7Q3r17FRUVpeHDh6tnz54u26levbouXLhQZP1ARcQ1OkAF07FjRzVo0EArVqyQMabIftWrVy/WeIMHD9aXX36pHTt2FKt/lSpVXJYdDkehbZdvn96xY4dGjRql6OhorV+/Xvv27dP8+fOVm5tb4Du/Vti+XWk7xVWpUqUCY//6Op8rzell+fn58vPzU3JyslJSUpyff/7zn3rhhReK/F5QUFChF/s2aNBA3bp1U0JCgrKzswusL+mcS66nrSQpOjpa33//vWJiYnT06FENGDBAjzzyiMsYP/74oxo0aHDlnQcqGIIOUMFcf/312rx5s959913NmDGjyH6tWrVS9erVtXHjxiuOd//99+vpp5/W0KFDtWXLFneXq88//1xhYWGaP3++unTpolatWhW42LlNmzbatWuXS9uePXtKve0qVaoUuEC3QYMGOnbsmEvbr58l1LJlS1WpUsUl+J0+fVrffPONc7lTp07Ky8tTZmamWrZs6fJp1KhRkfV06tRJqampBdqrV6+u9evXq1q1aho0aJDOnj1b0l11YYzR+++/r6FDh7q0N2jQQBMmTNAbb7yhxYsXa9myZS7rDxw4oE6dOpVq24C3IegAFVDr1q21efNmvf3220U+xK5atWqaM2eOZs+erVWrVunbb7/Vjh079OqrrxboO2PGDC1atEi33367PvvsM7fW2rJlS6WnpyshIUHffvutXnzxxQJ39syYMUOvvvqqXnvtNR06dEiLFi3Sl19+WeAoT0k1b95cGzdu1PHjx51HUm6++Wbt2bNHq1at0qFDh7RgwQIdOHDA+Z1atWpp0qRJmjVrljZu3KgDBw5owoQJLqfrWrdurTFjxmjcuHF65513lJaWpt27d+uZZ57Rhg0biqxn0KBBRc5vzZo19cEHH6hy5cqKjo7WuXPnrnm/k5OTdf78efXp08fZ9vvf/17vvvuuDh8+rK+++krr169X27ZtnesvXLig5ORkRUVFXfN2AW9E0AEqqDZt2mjTpk1avXq1Hn744UL7PP7443r44Yf1+9//Xm3bttXIkSNdruP4tZiYGD355JMaPHiwkpKS3FbnsGHD9NBDD+mBBx5Qx44dlZSUpMcff9ylz5gxYzRv3jw98sgj6ty5s9LS0jRhwoQr3oZdHM8++6wSExMVGhrqPFIxaNAgPf7445o9e7a6du2qs2fPaty4cS7f+9Of/qQ+ffpo6NChGjhwoHr16qXIyEiXPitWrNC4ceP08MMPq02bNho6dKh27tzpvNOsMPfee69SU1P19ddfF7q+Vq1a+vDDD2WM0eDBg3X+/Plr2u93331Xt912mypX/vdlmFWrVtW8efPUvn179enTR35+fkpISHD5TrNmzdS7d+9r2ibgrRymOCekAaCc3XLLLWrUqJFef/11T5fiVrNnz1ZWVpZeeeWVMttG+/bt9dhjj+nuu+8u9ne6deummJgY3XPPPWVWF+AJ3HUFwOMuXLigl19+WYMGDZKfn59Wr16tTz75RImJiZ4uze3mz5+v+Ph45eXllejZPsWVm5urO+64Q9HR0cX+TmZmpu68884rPuMHqKg4ogPA43766ScNGTJEe/fuVU5Ojtq0aaPHHntMI0aM8HRpACo4gg4AALAWFyMDAABrEXQAAIC1CDoAAMBaBB0AAGAtgg4AALAWQQcAAFiLoAMAAKxF0AEAANb6PxSgl3KR+6GDAAAAAElFTkSuQmCC", "text/plain": [ "
" ] @@ -392,7 +403,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 14, "id": "ce24f553-6020-4000-be02-13feb6c7ba39", "metadata": {}, "outputs": [], @@ -402,7 +413,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 15, "id": "a9b3f917-bf60-4c99-bb57-4270541733f9", "metadata": {}, "outputs": [], @@ -413,7 +424,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 16, "id": "dade2fb6-ae07-4597-9db7-5bfee462599d", "metadata": {}, "outputs": [], @@ -430,7 +441,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 17, "id": "13d68eb1-b495-4051-a150-4c63ddeefc2a", "metadata": {}, "outputs": [ diff --git a/spisea/synthetic.py b/spisea/synthetic.py index 08fd1a08..b9867d8b 100755 --- a/spisea/synthetic.py +++ b/spisea/synthetic.py @@ -547,14 +547,15 @@ def _make_companions_table(self, star_systems, compMass): if len(idx) != N_comp_tot and self.verbose: print( 'Found {0:d} companions out of stellar mass range'.format(N_comp_tot - len(idx))) - # For low-mass stars and substellar objects below isochrone, assume no mass loss and set phase to 98 - low_mass_idxs = (companions['mass']0: - assert companions['mass'][idx].min() > 0 + # For low-mass stars and substellar objects below isochrone, assume no mass loss and set phase to 98 + low_mass_idxs = (companions['mass']0: + assert companions['mass'][idx].min() > 0 return companions From 9b68b9408b9b908409002f6cd20104b63dae0c8f Mon Sep 17 00:00:00 2001 From: nsabrams Date: Thu, 29 Jan 2026 10:16:50 -0800 Subject: [PATCH 03/28] added EVOMODEL names and removed low temp black bodies --- docs/Cluster_w_COSMIC.ipynb | 1951 +++++++++++++++++++++++++++++++++-- spisea/atmospheres.py | 11 +- spisea/evolution.py | 1 + spisea/synthetic.py | 1 + 4 files changed, 1885 insertions(+), 79 deletions(-) diff --git a/docs/Cluster_w_COSMIC.ipynb b/docs/Cluster_w_COSMIC.ipynb index 713a6773..08eeacc7 100755 --- a/docs/Cluster_w_COSMIC.ipynb +++ b/docs/Cluster_w_COSMIC.ipynb @@ -70,7 +70,1805 @@ "name": "stdout", "output_type": "stream", "text": [ - "No version information found for evolution model COSMIC.\n" + "Changing to logg=5.00 for met=0.00 T= 19250 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 8750 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 13500 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 22000 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 10750 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 11500 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 19500 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 14750 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 17000 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 12750 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 15000 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 26000 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 50000 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 6000 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 16750 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 22000 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 17250 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 19500 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 12250 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 7750 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 9500 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 29000 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 26000 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 12750 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 10000 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 12750 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 36000 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 6000 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 26000 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 9750 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 13250 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 10750 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 32000 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 10500 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 7750 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 5500 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 34000 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 7000 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 16500 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 13000 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 7500 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 7250 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 15250 logg=7.25\n", + "Changing to T= 50000 for met=0.00 T= 60000 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 60000 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 15250 logg=7.75\n", + "Changing to T= 50000 for met=0.00 T= 60000 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 60000 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 27000 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 12750 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 11000 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 7500 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 15750 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 18000 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 20000 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 16000 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 12000 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 45000 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 12000 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 9250 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 13500 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 9250 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 5000 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 9750 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 24000 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 7250 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 25000 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 14750 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 13000 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 9250 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 8500 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 8500 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 19250 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 38000 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 18750 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 23000 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 5500 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 14750 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 7500 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 10500 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 15750 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 13500 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 11500 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 30000 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 11250 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 15500 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 11500 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 12500 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 6750 logg=8.25\n", + "Changing to T= 50000 for met=0.00 T= 70000 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 70000 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 19750 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 16250 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 11000 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 16750 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 32000 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 18500 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 15250 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 6250 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 16000 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 36000 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 20000 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 17500 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 17250 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 17750 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 35000 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 18250 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 35000 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 10500 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 15250 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 21000 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 34000 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 19750 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 18500 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 18500 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 14000 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 13000 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 16000 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 13250 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 13500 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 17750 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 11250 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 36000 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 8000 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 12250 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 13500 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 7250 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 9250 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 34000 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 17750 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 28000 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 11000 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 34000 logg=6.75\n", + "Changing to T= 50000 for met=0.00 T= 80000 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 80000 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 30000 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 13500 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 5750 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 15250 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 15500 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 24000 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 11250 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 19750 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 13500 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 11000 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 24000 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 12500 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 22000 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 16750 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 14500 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 18000 logg=7.25\n", + "Changing to T= 50000 for met=0.00 T= 80000 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 80000 logg=7.50\n", + "Changing to T= 50000 for met=0.00 T= 70000 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 70000 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 29000 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 36000 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 18750 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 14000 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 16250 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 11500 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 17000 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 36000 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 19250 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 17250 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 11750 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 9750 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 13000 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 23000 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 22000 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 40000 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 15500 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 12750 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 8000 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 19500 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 19000 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 11000 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 14500 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 18000 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 11250 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 5000 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 15000 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 12500 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 23000 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 7750 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 13250 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 29000 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 32000 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 34000 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 12250 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 17750 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 12250 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 18750 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 36000 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 15250 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 40000 logg=7.00\n", + "Changing to T= 50000 for met=0.00 T= 60000 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 60000 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 29000 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 14250 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 7500 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 8250 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 9000 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 14250 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 13500 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 8750 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 12500 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 28000 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 5250 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 8750 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 10250 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 27000 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 18250 logg=6.50\n", + "Changing to T= 50000 for met=0.00 T= 60000 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 60000 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 19250 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 7750 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 40000 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 7750 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 18250 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 13750 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 45000 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 7000 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 17500 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 9250 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 14250 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 23000 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 16750 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 6250 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 10000 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 19500 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 19500 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 9250 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 30000 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 25000 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 7250 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 14750 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 5000 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 6250 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 14500 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 11750 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 6750 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 18250 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 13000 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 13750 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 8500 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 35000 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 40000 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 17500 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 8000 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 13250 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 18250 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 6000 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 5000 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 34000 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 5500 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 18000 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 10500 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 40000 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 26000 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 35000 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 9250 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 13750 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 12750 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 19000 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 30000 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 10000 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 19250 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 10000 logg=6.75\n", + "Changing to T= 50000 for met=0.00 T= 70000 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 70000 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 9500 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 5500 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 11500 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 22000 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 6250 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 25000 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 19750 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 21000 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 9750 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 16250 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 27000 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 18000 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 14750 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 19250 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 18250 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 14250 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 29000 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 6250 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 12250 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 21000 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 18250 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 26000 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 8000 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 13000 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 17750 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 16750 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 12000 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 26000 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 32000 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 16750 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 11000 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 12750 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 18500 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 19500 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 19750 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 16750 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 29000 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 8750 logg=6.75\n", + "Changing to T= 50000 for met=0.00 T= 70000 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 70000 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 12250 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 5750 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 15750 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 34000 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 9250 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 12500 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 6250 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 12500 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 6500 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 10500 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 12750 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 10750 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 14250 logg=6.50\n", + "Changing to T= 50000 for met=0.00 T= 80000 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 80000 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 17000 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 5250 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 21000 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 29000 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 18000 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 5250 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 15500 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 10250 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 5500 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 38000 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 10500 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 12750 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 18500 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 9250 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 13750 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 12250 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 19000 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 13750 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 8250 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 14250 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 8000 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 7500 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 11500 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 10500 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 6250 logg=9.00\n", + "Changing to T= 50000 for met=0.00 T= 80000 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 80000 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 45000 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 22000 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 19500 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 38000 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 10250 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 17000 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 9750 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 8750 logg=8.50\n", + "Changing to T= 50000 for met=0.00 T= 80000 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 80000 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 14500 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 30000 logg=7.75\n", + "Changing to T= 50000 for met=0.00 T= 80000 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 80000 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 13750 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 6000 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 14750 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 6500 logg=8.50\n", + "Changing to T= 50000 for met=0.00 T= 60000 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 60000 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 13750 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 18500 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 19250 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 29000 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 16500 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 18500 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 23000 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 5750 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 12750 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 25000 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 10250 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 14000 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 7000 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 11250 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 6250 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 11750 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 10250 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 12500 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 15000 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 6500 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 6250 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 5500 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 10250 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 17500 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 23000 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 36000 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 7000 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 11750 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 50000 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 10250 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 11750 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 12000 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 12000 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 50000 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 19750 logg=7.25\n", + "Changing to T= 50000 for met=0.00 T= 60000 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 60000 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 10250 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 7250 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 17750 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 50000 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 17250 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 16000 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 11250 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 11500 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 13750 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 8250 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 13250 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 26000 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 14500 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 9500 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 17000 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 15750 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 14500 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 29000 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 16500 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 8500 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 50000 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 22000 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 13000 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 18750 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 5250 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 26000 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 16750 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 34000 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 13500 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 32000 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 30000 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 13500 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 25000 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 7750 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 26000 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 17750 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 32000 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 14500 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 13000 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 5750 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 34000 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 11750 logg=9.25\n", + "Changing to T= 50000 for met=0.00 T= 60000 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 60000 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 9750 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 29000 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 19750 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 5250 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 16500 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 13750 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 24000 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 12500 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 35000 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 28000 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 24000 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 28000 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 28000 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 12250 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 18750 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 13250 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 8250 logg=9.25\n", + "Changing to T= 50000 for met=0.00 T= 70000 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 70000 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 5500 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 10750 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 25000 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 6000 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 11750 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 8250 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 15000 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 18750 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 18000 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 18000 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 9000 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 11500 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 30000 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 24000 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 45000 logg=8.75\n", + "Changing to T= 50000 for met=0.00 T= 60000 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 60000 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 7000 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 30000 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 8000 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 12500 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 9000 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 5000 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 15000 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 15500 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 5000 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 7250 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 19250 logg=9.00\n", + "Changing to T= 50000 for met=0.00 T= 70000 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 70000 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 10500 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 7000 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 11750 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 5000 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 10000 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 20000 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 7500 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 38000 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 11500 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 9500 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 9750 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 14000 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 8750 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 10750 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 13750 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 19250 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 19250 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 14750 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 6250 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 19750 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 19500 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 8500 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 7500 logg=9.50\n", + "Changing to T= 50000 for met=0.00 T= 70000 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 70000 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 16000 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 50000 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 7500 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 24000 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 45000 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 6750 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 7750 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 16000 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 13000 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 23000 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 32000 logg=6.50\n", + "Changing to T= 50000 for met=0.00 T= 70000 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 70000 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 5250 logg=7.50\n", + "Changing to T= 50000 for met=0.00 T= 70000 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 70000 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 18750 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 9750 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 17750 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 18750 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 28000 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 10000 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 18000 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 8500 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 19250 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 8500 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 11250 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 18750 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 15750 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 8500 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 16750 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 17500 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 15000 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 40000 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 10500 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 11000 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 6500 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 9000 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 8500 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 40000 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 32000 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 19000 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 16000 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 14250 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 15000 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 8000 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 10250 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 19750 logg=8.25\n", + "Changing to T= 50000 for met=0.00 T= 80000 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 80000 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 13250 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 32000 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 17250 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 38000 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 12000 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 17250 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 17000 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 13500 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 10000 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 26000 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 15250 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 32000 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 7250 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 38000 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 6000 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 17500 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 16250 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 16000 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 6500 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 24000 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 5250 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 8000 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 19000 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 18750 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 11750 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 17250 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 22000 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 14000 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 15750 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 27000 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 14750 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 12500 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 12000 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 7750 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 15750 logg=9.00\n", + "Changing to T= 50000 for met=0.00 T= 70000 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 70000 logg=9.25\n", + "Changing to T= 50000 for met=0.00 T= 70000 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 70000 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 9000 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 13250 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 8250 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 5250 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 7500 logg=7.25\n", + "Changing to T= 50000 for met=0.00 T= 60000 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 60000 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 14250 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 9250 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 9500 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 30000 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 5500 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 5250 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 28000 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 9500 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 10750 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 5000 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 22000 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 6750 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 20000 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 12750 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 14750 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 7000 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 15500 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 11750 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 19000 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 17250 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 18500 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 40000 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 27000 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 9000 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 11250 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 30000 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 19000 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 16250 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 18000 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 25000 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 19500 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 6250 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 7250 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 50000 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 50000 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 6250 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 50000 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 9500 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 6500 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 19500 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 6750 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 13750 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 10000 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 19750 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 7500 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 36000 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 20000 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 18500 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 6000 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 35000 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 17000 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 7750 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 9750 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 11000 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 34000 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 21000 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 14250 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 45000 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 14250 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 5500 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 17000 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 21000 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 12500 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 19250 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 7000 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 10500 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 14000 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 35000 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 11750 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 8250 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 15250 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 18250 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 38000 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 9500 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 23000 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 16500 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 7750 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 5500 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 23000 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 5000 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 23000 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 13000 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 15250 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 16250 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 17750 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 8250 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 35000 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 6500 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 6750 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 9250 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 40000 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 21000 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 9000 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 13250 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 15500 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 16000 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 11250 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 19750 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 5000 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 10250 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 16250 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 10250 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 12250 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 6500 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 10750 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 21000 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 6750 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 27000 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 16250 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 12500 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 17500 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 5750 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 45000 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 17000 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 5000 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 17250 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 10750 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 50000 logg=8.25\n", + "Changing to T= 50000 for met=0.00 T= 80000 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 80000 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 14750 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 16000 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 12750 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 11000 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 22000 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 6750 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 17500 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 20000 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 32000 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 35000 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 15250 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 15000 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 16500 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 27000 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 6000 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 15250 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 25000 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 6500 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 11500 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 38000 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 5000 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 15750 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 18750 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 45000 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 19750 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 8250 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 17250 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 10500 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 14500 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 11000 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 40000 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 16500 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 12250 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 13000 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 5250 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 15250 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 18250 logg=8.50\n", + "Changing to T= 50000 for met=0.00 T= 60000 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 60000 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 40000 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 34000 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 14000 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 12000 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 38000 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 19000 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 11250 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 24000 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 26000 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 9000 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 9500 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 18000 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 24000 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 12250 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 28000 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 10750 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 11250 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 11750 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 6750 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 8250 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 14000 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 15000 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 8500 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 35000 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 7000 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 19000 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 20000 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 15000 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 13750 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 8750 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 14500 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 15500 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 8750 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 9250 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 22000 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 19000 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 26000 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 15750 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 15500 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 8750 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 15000 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 7000 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 34000 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 5750 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 12000 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 7250 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 14750 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 15750 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 9500 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 14000 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 50000 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 12250 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 8500 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 14000 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 18750 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 14500 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 12000 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 16500 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 13250 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 13500 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 11500 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 25000 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 7000 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 15000 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 9500 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 27000 logg=7.50\n", + "Changing to T= 50000 for met=0.00 T= 80000 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 80000 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 6750 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 14750 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 30000 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 17000 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 9500 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 36000 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 9000 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 14500 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 9000 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 11750 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 8750 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 32000 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 18500 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 34000 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 9750 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 13500 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 28000 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 6500 logg=6.50\n", + "Changing to T= 50000 for met=0.00 T= 80000 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 80000 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 8000 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 11000 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 14000 logg=8.50\n", + "Changing to T= 50000 for met=0.00 T= 60000 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 60000 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 18500 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 20000 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 8000 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 24000 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 21000 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 8750 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 12000 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 20000 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 12000 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 5750 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 10000 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 16500 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 17000 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 40000 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 10500 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 15250 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 15500 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 10250 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 45000 logg=7.75\n", + "Changing to T= 50000 for met=0.00 T= 60000 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 60000 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 20000 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 6750 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 17500 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 18000 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 5500 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 18250 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 28000 logg=9.50\n", + "Changing to T= 50000 for met=0.00 T= 80000 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 80000 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 5750 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 6250 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 10000 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 11500 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 5000 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 38000 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 16250 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 12750 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 6000 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 16750 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 16750 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 36000 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 10750 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 25000 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 15000 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 14500 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 13750 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 24000 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 50000 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 15500 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 29000 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 35000 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 21000 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 17500 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 25000 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 16000 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 15750 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 18500 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 36000 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 10250 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 13250 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 6000 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 7250 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 30000 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 17750 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 17250 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 15750 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 16500 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 45000 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 10750 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 7750 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 38000 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 16000 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 17000 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 26000 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 7000 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 38000 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 14500 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 7750 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 28000 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 14000 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 6000 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 22000 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 20000 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 10000 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 19000 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 9750 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 5750 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 8250 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 6750 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 8000 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 11000 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 16250 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 27000 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 14250 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 17250 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 45000 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 5750 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 8250 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 10000 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 36000 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 38000 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 8500 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 21000 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 8250 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 17000 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 8750 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 5500 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 14750 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 17500 logg=7.75\n", + "Changing to T= 50000 for met=0.00 T= 80000 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 80000 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 9000 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 16250 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 17750 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 35000 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 35000 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 16500 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 27000 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 9250 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 23000 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 5750 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 40000 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 13000 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 10500 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 16750 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 7250 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 18000 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 27000 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 16750 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 5250 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 25000 logg=7.00\n", + "Changing to T= 50000 for met=0.00 T= 60000 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 60000 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 6500 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 15500 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 28000 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 8000 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 32000 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 16000 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 21000 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 17750 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 18250 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 9750 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 12500 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 15500 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 10000 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 36000 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 13000 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 19000 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 12250 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 8000 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 9500 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 17500 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 9000 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 19250 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 11500 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 45000 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 7250 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 16500 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 19500 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 30000 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 6500 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 23000 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 6500 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 19000 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 15750 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 9000 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 11250 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 10750 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 17500 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 7250 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 8500 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 5250 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 7000 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 50000 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 8750 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 19500 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 27000 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 7500 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 25000 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 18250 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 16250 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 5750 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 11000 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 14250 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 7750 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 20000 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 10750 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 18250 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 7500 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 16250 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 6750 logg=7.25\n", + "Changing to logg=5.00 for met=0.00 T= 29000 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 6000 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 29000 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 14250 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 18500 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 16500 logg=6.75\n", + "Changing to T= 50000 for met=0.00 T= 70000 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 70000 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 20000 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 9750 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 6000 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 45000 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 24000 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 18750 logg=8.25\n", + "Changing to logg=5.00 for met=0.00 T= 23000 logg=7.50\n", + "Changing to T= 50000 for met=0.00 T= 70000 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 70000 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 13250 logg=9.50\n", + "Changing to logg=5.00 for met=0.00 T= 19750 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 11250 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 28000 logg=7.75\n", + "Changing to logg=5.00 for met=0.00 T= 5750 logg=9.25\n", + "Changing to logg=5.00 for met=0.00 T= 5250 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 27000 logg=7.00\n", + "Changing to logg=5.00 for met=0.00 T= 7500 logg=6.75\n", + "Changing to logg=5.00 for met=0.00 T= 17250 logg=8.00\n", + "Changing to logg=5.00 for met=0.00 T= 19500 logg=9.50\n", + "Changing to T= 50000 for met=0.00 T= 80000 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 80000 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 22000 logg=8.75\n", + "Changing to logg=5.00 for met=0.00 T= 12000 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 17750 logg=7.50\n", + "Changing to logg=5.00 for met=0.00 T= 13250 logg=6.50\n", + "Changing to logg=5.00 for met=0.00 T= 5500 logg=8.50\n", + "Changing to logg=5.00 for met=0.00 T= 21000 logg=9.00\n", + "Changing to logg=5.00 for met=0.00 T= 14000 logg=9.00\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/u/nsabrams/code/multiplicity/PyPopStar/spisea/atmospheres.py:1470: UserWarning: Only `temperature` keyword is used for black-body atmosphere\n", + " warnings.warn(\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "Changing to logg=5.00 for met=0.00 T= 2000 logg=6.00\n", + "Changing to logg=5.00 for met=0.00 T= 2082 logg=6.00\n", + "Changing to logg=5.00 for met=0.00 T= 2166 logg=6.00\n", + "Changing to logg=5.00 for met=0.00 T= 2255 logg=6.00\n", + "Changing to logg=5.00 for met=0.00 T= 2347 logg=6.00\n", + "Changing to logg=5.50 for met=0.00 T= 2442 logg=6.00\n", + "Changing to logg=5.50 for met=0.00 T= 2542 logg=6.00\n", + "Changing to logg=5.50 for met=0.00 T= 2646 logg=6.00\n", + "Changing to logg=5.50 for met=0.00 T= 2754 logg=6.00\n", + "Changing to logg=5.50 for met=0.00 T= 2866 logg=6.00\n", + "Changing to logg=5.50 for met=0.00 T= 2983 logg=6.00\n", + "Changing to logg=5.50 for met=0.00 T= 3104 logg=6.00\n", + "Changing to logg=5.50 for met=0.00 T= 3231 logg=6.00\n", + "Changing to logg=5.50 for met=0.00 T= 3363 logg=6.00\n", + "Changing to logg=5.50 for met=0.00 T= 3500 logg=6.00\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "Changing to logg=5.50 for met=0.00 T= 3500 logg=6.25\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "BB atmosphere\n", + "Atmosphere grid generation took 469.690594 s.\n", + "Making photometry for atmosphere grid: AKs = 0.00 dist = 4000\n", + " Starting at: 2026-01-28 18:35:13.544283 Usually takes ~5 minutes\n", + "Starting filter: ubv,U Elapsed time: 0.00 seconds\n", + "Starting synthetic photometry\n", + "M = 1200.000 Msun T = 3 K m_ubv_U = 38.21\n", + "M = 2350.000 Msun T = 4 K m_ubv_U = 31.95\n", + "M = 2500.000 Msun T = 3 K m_ubv_U = 28.71\n", + "M = 3300.000 Msun T = 1 K m_ubv_U = 26.31\n", + "M = 4000.000 Msun T = 6 K m_ubv_U = 22.38\n", + "M = 4800.000 Msun T = 4 K m_ubv_U = 19.86\n", + "M = 2900.000 Msun T = 2 K m_ubv_U = 27.49\n", + "M = 3600.000 Msun T = 6 K m_ubv_U = 24.22\n", + "M = 4400.000 Msun T = 4 K m_ubv_U = 20.97\n", + "M = 2500.000 Msun T = 2 K m_ubv_U = 29.16\n", + "M = 3300.000 Msun T = 0 K m_ubv_U = 26.78\n", + "M = 4000.000 Msun T = 4 K m_ubv_U = 22.18\n", + "M = 4800.000 Msun T = 2 K m_ubv_U = 19.86\n", + "M = 2900.000 Msun T = 0 K m_ubv_U = 27.02\n", + "M = 3600.000 Msun T = 5 K m_ubv_U = 23.84\n", + "M = 4400.000 Msun T = 3 K m_ubv_U = 20.95\n", + "M = 2500.000 Msun T = 1 K m_ubv_U = 27.78\n", + "M = 3200.000 Msun T = 6 K m_ubv_U = 26.12\n", + "M = 4000.000 Msun T = 4 K m_ubv_U = 22.43\n", + "M = 4800.000 Msun T = 2 K m_ubv_U = 20.35\n", + "M = 2800.000 Msun T = 6 K m_ubv_U = 29.21\n", + "M = 3600.000 Msun T = 4 K m_ubv_U = 23.66\n", + "M = 4400.000 Msun T = 2 K m_ubv_U = 21.66\n", + "M = 2700.000 Msun T = 1 K m_ubv_U = 27.15\n", + "M = 4000.000 Msun T = 5 K m_ubv_U = 22.66\n", + "M = 4800.000 Msun T = 3 K m_ubv_U = 20.73\n", + "M = 2900.000 Msun T = 1 K m_ubv_U = 27.27\n", + "M = 3600.000 Msun T = 6 K m_ubv_U = 23.62\n", + "M = 4400.000 Msun T = 4 K m_ubv_U = 22.10\n", + "M = 2500.000 Msun T = 2 K m_ubv_U = 27.67\n", + "M = 3200.000 Msun T = 6 K m_ubv_U = 25.03\n", + "M = 4000.000 Msun T = 4 K m_ubv_U = 23.13\n", + "M = 4800.000 Msun T = 2 K m_ubv_U = 21.97\n", + "M = 5250.000 Msun T = 0 K m_ubv_U = 20.51\n", + "M = 10000.000 Msun T = 3 K m_ubv_U = 15.48\n", + "M = 16000.000 Msun T = 4 K m_ubv_U = 14.00\n", + "M = 40000.000 Msun T = 4 K m_ubv_U = 11.61\n", + "M = 7250.000 Msun T = 4 K m_ubv_U = 17.06\n", + "M = 10500.000 Msun T = 2 K m_ubv_U = 15.23\n", + "M = 18000.000 Msun T = 4 K m_ubv_U = 13.72\n", + "M = 46000.000 Msun T = 4 K m_ubv_U = 11.44\n", + "M = 7500.000 Msun T = 4 K m_ubv_U = 16.84\n", + "M = 10750.000 Msun T = 4 K m_ubv_U = 15.37\n", + "M = 20000.000 Msun T = 4 K m_ubv_U = 13.49\n", + "M = 5500.000 Msun T = 2 K m_ubv_U = 18.80\n", + "M = 8000.000 Msun T = 2 K m_ubv_U = 16.44\n", + "M = 11250.000 Msun T = 4 K m_ubv_U = 15.15\n", + "M = 23000.000 Msun T = 3 K m_ubv_U = 12.97\n", + "M = 5750.000 Msun T = 2 K m_ubv_U = 18.37\n", + "M = 8250.000 Msun T = 3 K m_ubv_U = 16.41\n", + "M = 11750.000 Msun T = 2 K m_ubv_U = 14.93\n", + "M = 25000.000 Msun T = 4 K m_ubv_U = 12.88\n", + "M = 6000.000 Msun T = 2 K m_ubv_U = 18.04\n", + "M = 8500.000 Msun T = 5 K m_ubv_U = 16.30\n", + "M = 12250.000 Msun T = 2 K m_ubv_U = 14.62\n", + "M = 28000.000 Msun T = 4 K m_ubv_U = 12.31\n", + "M = 6250.000 Msun T = 4 K m_ubv_U = 17.99\n", + "M = 9000.000 Msun T = 3 K m_ubv_U = 15.92\n", + "M = 12750.000 Msun T = 2 K m_ubv_U = 14.46\n", + "M = 31000.000 Msun T = 4 K m_ubv_U = 12.02\n", + "M = 6500.000 Msun T = 4 K m_ubv_U = 17.71\n", + "M = 9500.000 Msun T = 2 K m_ubv_U = 15.56\n", + "M = 14000.000 Msun T = 2 K m_ubv_U = 14.07\n", + "M = 34000.000 Msun T = 5 K m_ubv_U = 11.88\n", + "M = 7000.000 Msun T = 0 K m_ubv_U = 17.33\n", + "M = 9750.000 Msun T = 4 K m_ubv_U = 15.62\n", + "M = 20000.000 Msun T = 8 K m_ubv_U = 13.39\n", + "M = 8750.000 Msun T = 8 K m_ubv_U = 16.14\n", + "M = 29000.000 Msun T = 8 K m_ubv_U = 12.39\n", + "M = 17250.000 Msun T = 9 K m_ubv_U = 13.78\n", + "M = 19250.000 Msun T = 7 K m_ubv_U = 13.49\n", + "M = 9250.000 Msun T = 9 K m_ubv_U = 15.91\n", + "M = 10250.000 Msun T = 8 K m_ubv_U = 15.50\n", + "M = 12000.000 Msun T = 8 K m_ubv_U = 14.90\n", + "M = 15750.000 Msun T = 7 K m_ubv_U = 14.03\n", + "M = 7250.000 Msun T = 8 K m_ubv_U = 16.99\n", + "M = 3384.462 Msun T = 7 K m_ubv_U = 23.53\n", + "M = 3384.462 Msun T = 8 K m_ubv_U = 23.53\n", + "M = 8634.788 Msun T = 10 K m_ubv_U = 15.87\n", + "M = 8634.788 Msun T = 11 K m_ubv_U = 15.87\n", + "Starting filter: ubv,V Elapsed time: 48.59 seconds\n", + "Starting synthetic photometry\n", + "M = 1200.000 Msun T = 3 K m_ubv_V = 35.26\n", + "M = 2350.000 Msun T = 4 K m_ubv_V = 27.90\n", + "M = 2500.000 Msun T = 3 K m_ubv_V = 23.30\n", + "M = 3300.000 Msun T = 1 K m_ubv_V = 22.54\n", + "M = 4000.000 Msun T = 6 K m_ubv_V = 20.11\n", + "M = 4800.000 Msun T = 4 K m_ubv_V = 19.07\n", + "M = 2900.000 Msun T = 2 K m_ubv_V = 23.20\n", + "M = 3600.000 Msun T = 6 K m_ubv_V = 20.77\n", + "M = 4400.000 Msun T = 4 K m_ubv_V = 19.62\n", + "M = 2500.000 Msun T = 2 K m_ubv_V = 24.72\n", + "M = 3300.000 Msun T = 0 K m_ubv_V = 22.67\n", + "M = 4000.000 Msun T = 4 K m_ubv_V = 20.22\n", + "M = 4800.000 Msun T = 2 K m_ubv_V = 18.97\n", + "M = 2900.000 Msun T = 0 K m_ubv_V = 23.97\n", + "M = 3600.000 Msun T = 5 K m_ubv_V = 21.04\n", + "M = 4400.000 Msun T = 3 K m_ubv_V = 19.52\n", + "M = 2500.000 Msun T = 1 K m_ubv_V = 26.45\n", + "M = 3200.000 Msun T = 6 K m_ubv_V = 22.15\n", + "M = 4000.000 Msun T = 4 K m_ubv_V = 20.28\n", + "M = 4800.000 Msun T = 2 K m_ubv_V = 19.00\n", + "M = 2800.000 Msun T = 6 K m_ubv_V = 24.27\n", + "M = 3600.000 Msun T = 4 K m_ubv_V = 21.15\n", + "M = 4400.000 Msun T = 2 K m_ubv_V = 19.56\n", + "M = 2700.000 Msun T = 1 K m_ubv_V = 26.75\n", + "M = 4000.000 Msun T = 5 K m_ubv_V = 20.32\n", + "M = 4800.000 Msun T = 3 K m_ubv_V = 18.93\n", + "M = 2900.000 Msun T = 1 K m_ubv_V = 26.33\n", + "M = 3600.000 Msun T = 6 K m_ubv_V = 21.45\n", + "M = 4400.000 Msun T = 4 K m_ubv_V = 19.57\n", + "M = 2500.000 Msun T = 2 K m_ubv_V = 27.48\n", + "M = 3200.000 Msun T = 6 K m_ubv_V = 22.86\n", + "M = 4000.000 Msun T = 4 K m_ubv_V = 20.66\n", + "M = 4800.000 Msun T = 2 K m_ubv_V = 19.01\n", + "M = 5250.000 Msun T = 0 K m_ubv_V = 18.42\n", + "M = 10000.000 Msun T = 3 K m_ubv_V = 15.66\n", + "M = 16000.000 Msun T = 4 K m_ubv_V = 14.74\n", + "M = 40000.000 Msun T = 4 K m_ubv_V = 13.01\n", + "M = 7250.000 Msun T = 4 K m_ubv_V = 16.75\n", + "M = 10500.000 Msun T = 2 K m_ubv_V = 15.59\n", + "M = 18000.000 Msun T = 4 K m_ubv_V = 14.56\n", + "M = 46000.000 Msun T = 4 K m_ubv_V = 12.86\n", + "M = 7500.000 Msun T = 4 K m_ubv_V = 16.68\n", + "M = 10750.000 Msun T = 4 K m_ubv_V = 15.52\n", + "M = 20000.000 Msun T = 4 K m_ubv_V = 14.40\n", + "M = 5500.000 Msun T = 2 K m_ubv_V = 18.11\n", + "M = 8000.000 Msun T = 2 K m_ubv_V = 16.32\n", + "M = 11250.000 Msun T = 4 K m_ubv_V = 15.45\n", + "M = 23000.000 Msun T = 3 K m_ubv_V = 14.09\n", + "M = 5750.000 Msun T = 2 K m_ubv_V = 17.90\n", + "M = 8250.000 Msun T = 3 K m_ubv_V = 16.23\n", + "M = 11750.000 Msun T = 2 K m_ubv_V = 15.38\n", + "M = 25000.000 Msun T = 4 K m_ubv_V = 13.99\n", + "M = 6000.000 Msun T = 2 K m_ubv_V = 17.71\n", + "M = 8500.000 Msun T = 5 K m_ubv_V = 16.20\n", + "M = 12250.000 Msun T = 2 K m_ubv_V = 15.19\n", + "M = 28000.000 Msun T = 4 K m_ubv_V = 13.59\n", + "M = 6250.000 Msun T = 4 K m_ubv_V = 17.42\n", + "M = 9000.000 Msun T = 3 K m_ubv_V = 15.89\n", + "M = 12750.000 Msun T = 2 K m_ubv_V = 15.10\n", + "M = 31000.000 Msun T = 4 K m_ubv_V = 13.36\n", + "M = 6500.000 Msun T = 4 K m_ubv_V = 17.23\n", + "M = 9500.000 Msun T = 2 K m_ubv_V = 15.76\n", + "M = 14000.000 Msun T = 2 K m_ubv_V = 14.90\n", + "M = 34000.000 Msun T = 5 K m_ubv_V = 13.22\n", + "M = 7000.000 Msun T = 0 K m_ubv_V = 16.78\n", + "M = 9750.000 Msun T = 4 K m_ubv_V = 15.64\n", + "M = 20000.000 Msun T = 8 K m_ubv_V = 14.32\n", + "M = 8750.000 Msun T = 8 K m_ubv_V = 16.00\n", + "M = 29000.000 Msun T = 8 K m_ubv_V = 13.62\n", + "M = 17250.000 Msun T = 9 K m_ubv_V = 14.58\n", + "M = 19250.000 Msun T = 7 K m_ubv_V = 14.39\n", + "M = 9250.000 Msun T = 9 K m_ubv_V = 15.82\n", + "M = 10250.000 Msun T = 8 K m_ubv_V = 15.56\n", + "M = 12000.000 Msun T = 8 K m_ubv_V = 15.24\n", + "M = 15750.000 Msun T = 7 K m_ubv_V = 14.73\n", + "M = 7250.000 Msun T = 8 K m_ubv_V = 16.78\n", + "M = 3384.462 Msun T = 7 K m_ubv_V = 21.36\n", + "M = 3384.462 Msun T = 8 K m_ubv_V = 21.36\n", + "M = 8634.788 Msun T = 10 K m_ubv_V = 16.21\n", + "M = 8634.788 Msun T = 11 K m_ubv_V = 16.21\n", + "Starting filter: ubv,R Elapsed time: 96.13 seconds\n", + "Starting synthetic photometry\n", + "M = 1200.000 Msun T = 3 K m_ubv_R = 30.81\n", + "M = 2350.000 Msun T = 4 K m_ubv_R = 25.83\n", + "M = 2500.000 Msun T = 3 K m_ubv_R = 21.96\n", + "M = 3300.000 Msun T = 1 K m_ubv_R = 21.36\n", + "M = 4000.000 Msun T = 6 K m_ubv_R = 19.41\n", + "M = 4800.000 Msun T = 4 K m_ubv_R = 18.59\n", + "M = 2900.000 Msun T = 2 K m_ubv_R = 21.95\n", + "M = 3600.000 Msun T = 6 K m_ubv_R = 19.92\n", + "M = 4400.000 Msun T = 4 K m_ubv_R = 19.04\n", + "M = 2500.000 Msun T = 2 K m_ubv_R = 23.40\n", + "M = 3300.000 Msun T = 0 K m_ubv_R = 21.60\n", + "M = 4000.000 Msun T = 4 K m_ubv_R = 19.51\n", + "M = 4800.000 Msun T = 2 K m_ubv_R = 18.52\n", + "M = 2900.000 Msun T = 0 K m_ubv_R = 22.84\n", + "M = 3600.000 Msun T = 5 K m_ubv_R = 20.18\n", + "M = 4400.000 Msun T = 3 K m_ubv_R = 18.98\n", + "M = 2500.000 Msun T = 1 K m_ubv_R = 24.75\n", + "M = 3200.000 Msun T = 6 K m_ubv_R = 21.14\n", + "M = 4000.000 Msun T = 4 K m_ubv_R = 19.56\n", + "M = 4800.000 Msun T = 2 K m_ubv_R = 18.53\n", + "M = 2800.000 Msun T = 6 K m_ubv_R = 22.92\n", + "M = 3600.000 Msun T = 4 K m_ubv_R = 20.31\n", + "M = 4400.000 Msun T = 2 K m_ubv_R = 18.99\n", + "M = 2700.000 Msun T = 1 K m_ubv_R = 25.14\n", + "M = 4000.000 Msun T = 5 K m_ubv_R = 19.56\n", + "M = 4800.000 Msun T = 3 K m_ubv_R = 18.43\n", + "M = 2900.000 Msun T = 1 K m_ubv_R = 24.80\n", + "M = 3600.000 Msun T = 6 K m_ubv_R = 20.61\n", + "M = 4400.000 Msun T = 4 K m_ubv_R = 18.92\n", + "M = 2500.000 Msun T = 2 K m_ubv_R = 25.78\n", + "M = 3200.000 Msun T = 6 K m_ubv_R = 21.85\n", + "M = 4000.000 Msun T = 4 K m_ubv_R = 19.90\n", + "M = 4800.000 Msun T = 2 K m_ubv_R = 18.40\n", + "M = 5250.000 Msun T = 0 K m_ubv_R = 17.95\n", + "M = 10000.000 Msun T = 3 K m_ubv_R = 15.67\n", + "M = 16000.000 Msun T = 4 K m_ubv_R = 14.80\n", + "M = 40000.000 Msun T = 4 K m_ubv_R = 13.13\n", + "M = 7250.000 Msun T = 4 K m_ubv_R = 16.60\n", + "M = 10500.000 Msun T = 2 K m_ubv_R = 15.59\n", + "M = 18000.000 Msun T = 4 K m_ubv_R = 14.63\n", + "M = 46000.000 Msun T = 4 K m_ubv_R = 12.99\n", + "M = 7500.000 Msun T = 4 K m_ubv_R = 16.53\n", + "M = 10750.000 Msun T = 4 K m_ubv_R = 15.54\n", + "M = 20000.000 Msun T = 4 K m_ubv_R = 14.47\n", + "M = 5500.000 Msun T = 2 K m_ubv_R = 17.77\n", + "M = 8000.000 Msun T = 2 K m_ubv_R = 16.27\n", + "M = 11250.000 Msun T = 4 K m_ubv_R = 15.47\n", + "M = 23000.000 Msun T = 3 K m_ubv_R = 14.18\n", + "M = 5750.000 Msun T = 2 K m_ubv_R = 17.60\n", + "M = 8250.000 Msun T = 3 K m_ubv_R = 16.19\n", + "M = 11750.000 Msun T = 2 K m_ubv_R = 15.40\n", + "M = 25000.000 Msun T = 4 K m_ubv_R = 14.09\n", + "M = 6000.000 Msun T = 2 K m_ubv_R = 17.44\n", + "M = 8500.000 Msun T = 5 K m_ubv_R = 16.12\n", + "M = 12250.000 Msun T = 2 K m_ubv_R = 15.21\n", + "M = 28000.000 Msun T = 4 K m_ubv_R = 13.70\n", + "M = 6250.000 Msun T = 4 K m_ubv_R = 17.14\n", + "M = 9000.000 Msun T = 3 K m_ubv_R = 15.88\n", + "M = 12750.000 Msun T = 2 K m_ubv_R = 15.12\n", + "M = 31000.000 Msun T = 4 K m_ubv_R = 13.46\n", + "M = 6500.000 Msun T = 4 K m_ubv_R = 16.97\n", + "M = 9500.000 Msun T = 2 K m_ubv_R = 15.74\n", + "M = 14000.000 Msun T = 2 K m_ubv_R = 14.92\n", + "M = 34000.000 Msun T = 5 K m_ubv_R = 13.35\n", + "M = 7000.000 Msun T = 0 K m_ubv_R = 16.64\n", + "M = 9750.000 Msun T = 4 K m_ubv_R = 15.65\n", + "M = 20000.000 Msun T = 8 K m_ubv_R = 14.40\n", + "M = 8750.000 Msun T = 8 K m_ubv_R = 15.95\n", + "M = 29000.000 Msun T = 8 K m_ubv_R = 13.73\n", + "M = 17250.000 Msun T = 9 K m_ubv_R = 14.64\n", + "M = 19250.000 Msun T = 7 K m_ubv_R = 14.46\n", + "M = 9250.000 Msun T = 9 K m_ubv_R = 15.80\n", + "M = 10250.000 Msun T = 8 K m_ubv_R = 15.58\n", + "M = 12000.000 Msun T = 8 K m_ubv_R = 15.27\n", + "M = 15750.000 Msun T = 7 K m_ubv_R = 14.79\n", + "M = 7250.000 Msun T = 8 K m_ubv_R = 16.59\n", + "M = 3384.462 Msun T = 7 K m_ubv_R = 20.52\n", + "M = 3384.462 Msun T = 8 K m_ubv_R = 20.52\n", + "M = 8634.788 Msun T = 10 K m_ubv_R = 16.04\n", + "M = 8634.788 Msun T = 11 K m_ubv_R = 16.04\n", + " Time taken: 140.46 seconds\n" ] } ], @@ -85,7 +1883,7 @@ "redlaw = reddening.RedLawCardelli(3.1) # Rv = 3.1\n", "filt_list = ['ubv,U', 'ubv,V', 'ubv,R']\n", "\n", - "iso_dir = 'iso_cosmic/'\n", + "iso_dir = 'atm_cosmic/'\n", "\n", "if not os.path.exists(iso_dir):\n", " os.mkdir(iso_dir)\n", @@ -121,7 +1919,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 5, "id": "17d315a9-ec84-4289-a810-855443628e67", "metadata": { "scrolled": true @@ -133,67 +1931,70 @@ "text": [ "/opt/mambaforge3/envs/astro_cosmic/lib/python3.11/site-packages/cosmic/utils.py:1687: UserWarning: At least one of your initial binaries is starting in Roche Lobe Overflow:\n", " kstar_1 kstar_2 mass_1 mass_2 porb ecc \\\n", - "1440 1.0 1.0 84.953667 11.663048 0.876905 0.931278 \n", - "3461 1.0 0.0 14.497658 0.432032 0.316452 0.373763 \n", - "4524 1.0 1.0 43.734965 25.813240 0.086102 0.182706 \n", - "4596 1.0 1.0 11.365734 3.152759 0.258129 0.859164 \n", - "5452 1.0 1.0 79.264723 65.438099 1.013579 0.981040 \n", - "5453 1.0 1.0 144.746349 19.317653 1.490465 0.526429 \n", - "5529 1.0 1.0 20.370581 10.396254 0.426804 0.520938 \n", - "6403 1.0 1.0 28.924458 16.957390 0.454892 0.748762 \n", - "7236 1.0 1.0 48.373542 28.467361 0.213048 0.302529 \n", - "9548 1.0 1.0 18.613090 2.449167 0.560490 0.592169 \n", - "9797 1.0 1.0 23.973515 1.383991 0.074267 0.688942 \n", - "9853 1.0 1.0 67.887280 25.567388 1.540411 0.291563 \n", - "12125 1.0 0.0 3.353695 0.597418 0.218984 0.732055 \n", - "13095 1.0 1.0 27.178998 10.889196 0.563413 0.602920 \n", - "13649 1.0 0.0 4.132947 0.528564 0.262513 0.832788 \n", - "14632 1.0 1.0 84.105227 20.922150 0.136475 0.670406 \n", - "15517 1.0 1.0 52.135141 1.956890 0.333913 0.639657 \n", + "353 1.0 0.0 45.316990 0.542011 0.514938 0.812602 \n", + "1580 1.0 0.0 25.262665 0.535898 0.166185 0.582260 \n", + "1895 1.0 0.0 3.391836 0.068421 0.256683 0.908815 \n", + "2347 1.0 1.0 21.828894 8.560945 0.142712 0.845244 \n", + "2446 1.0 1.0 266.788235 36.299586 0.254315 0.101827 \n", + "3987 1.0 1.0 65.996710 21.339760 0.069611 0.657800 \n", + "4844 1.0 1.0 221.496477 13.473508 0.026316 0.617358 \n", + "4985 1.0 0.0 44.273694 0.542706 0.792597 0.445727 \n", + "6791 1.0 1.0 58.324942 9.742695 0.369382 0.778012 \n", + "10605 1.0 1.0 2.818451 0.762687 0.195033 0.985095 \n", + "11004 1.0 1.0 6.191172 1.927454 0.570113 0.459832 \n", + "12696 1.0 1.0 12.270252 9.924949 0.147665 0.477165 \n", + "12993 1.0 1.0 14.194480 6.687486 0.319535 0.184319 \n", + "13586 1.0 1.0 24.525936 20.607829 0.072227 0.624382 \n", + "14633 1.0 1.0 15.063556 7.233325 0.288746 0.820126 \n", + "17757 1.0 1.0 31.266282 1.288211 0.365737 0.667141 \n", + "18345 1.0 1.0 98.592925 8.101771 0.104668 0.849371 \n", + "19318 1.0 1.0 150.485031 40.423289 0.094533 0.963610 \n", "\n", " metallicity tphysf mass0_1 mass0_2 ... tacc_1 tacc_2 \\\n", - "1440 0.014 10000.0 84.953667 11.663048 ... 0.0 0.0 \n", - "3461 0.014 10000.0 14.497658 0.432032 ... 0.0 0.0 \n", - "4524 0.014 10000.0 43.734965 25.813240 ... 0.0 0.0 \n", - "4596 0.014 10000.0 11.365734 3.152759 ... 0.0 0.0 \n", - "5452 0.014 10000.0 79.264723 65.438099 ... 0.0 0.0 \n", - "5453 0.014 10000.0 144.746349 19.317653 ... 0.0 0.0 \n", - "5529 0.014 10000.0 20.370581 10.396254 ... 0.0 0.0 \n", - "6403 0.014 10000.0 28.924458 16.957390 ... 0.0 0.0 \n", - "7236 0.014 10000.0 48.373542 28.467361 ... 0.0 0.0 \n", - "9548 0.014 10000.0 18.613090 2.449167 ... 0.0 0.0 \n", - "9797 0.014 10000.0 23.973515 1.383991 ... 0.0 0.0 \n", - "9853 0.014 10000.0 67.887280 25.567388 ... 0.0 0.0 \n", - "12125 0.014 10000.0 3.353695 0.597418 ... 0.0 0.0 \n", - "13095 0.014 10000.0 27.178998 10.889196 ... 0.0 0.0 \n", - "13649 0.014 10000.0 4.132947 0.528564 ... 0.0 0.0 \n", - "14632 0.014 10000.0 84.105227 20.922150 ... 0.0 0.0 \n", - "15517 0.014 10000.0 52.135141 1.956890 ... 0.0 0.0 \n", + "353 0.014 10000.0 45.316990 0.542011 ... 0.0 0.0 \n", + "1580 0.014 10000.0 25.262665 0.535898 ... 0.0 0.0 \n", + "1895 0.014 10000.0 3.391836 0.068421 ... 0.0 0.0 \n", + "2347 0.014 10000.0 21.828894 8.560945 ... 0.0 0.0 \n", + "2446 0.014 10000.0 266.788235 36.299586 ... 0.0 0.0 \n", + "3987 0.014 10000.0 65.996710 21.339760 ... 0.0 0.0 \n", + "4844 0.014 10000.0 221.496477 13.473508 ... 0.0 0.0 \n", + "4985 0.014 10000.0 44.273694 0.542706 ... 0.0 0.0 \n", + "6791 0.014 10000.0 58.324942 9.742695 ... 0.0 0.0 \n", + "10605 0.014 10000.0 2.818451 0.762687 ... 0.0 0.0 \n", + "11004 0.014 10000.0 6.191172 1.927454 ... 0.0 0.0 \n", + "12696 0.014 10000.0 12.270252 9.924949 ... 0.0 0.0 \n", + "12993 0.014 10000.0 14.194480 6.687486 ... 0.0 0.0 \n", + "13586 0.014 10000.0 24.525936 20.607829 ... 0.0 0.0 \n", + "14633 0.014 10000.0 15.063556 7.233325 ... 0.0 0.0 \n", + "17757 0.014 10000.0 31.266282 1.288211 ... 0.0 0.0 \n", + "18345 0.014 10000.0 98.592925 8.101771 ... 0.0 0.0 \n", + "19318 0.014 10000.0 150.485031 40.423289 ... 0.0 0.0 \n", "\n", " epoch_1 epoch_2 tms_1 tms_2 bhspin_1 bhspin_2 tphys binfrac \n", - "1440 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", - "3461 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", - "4524 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", - "4596 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", - "5452 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", - "5453 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", - "5529 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", - "6403 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", - "7236 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", - "9548 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", - "9797 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", - "9853 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", - "12125 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", - "13095 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", - "13649 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", - "14632 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", - "15517 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "353 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "1580 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "1895 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "2347 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "2446 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "3987 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "4844 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "4985 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "6791 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "10605 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "11004 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "12696 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "12993 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "13586 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "14633 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "17757 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "18345 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "19318 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", "\n", - "[17 rows x 38 columns]\n", + "[18 rows x 38 columns]\n", " warnings.warn(\n", - "/u/nsabrams/code/multiplicity/PyPopStar/spisea/evolution.py:1408: RuntimeWarning: divide by zero encountered in log10\n", + "/u/nsabrams/code/multiplicity/PyPopStar/spisea/evolution.py:1409: RuntimeWarning: divide by zero encountered in log10\n", " return np.log10(((np.array(c.G.to('Rsun^3/(Msun*s^2)').value*masses/((radii)**2))*u.Rsun/u.s**2).to('cm/s^2')).value)\n", - "/u/nsabrams/code/multiplicity/PyPopStar/spisea/evolution.py:1408: RuntimeWarning: divide by zero encountered in log10\n", + "/u/nsabrams/code/multiplicity/PyPopStar/spisea/evolution.py:1409: RuntimeWarning: divide by zero encountered in log10\n", " return np.log10(((np.array(c.G.to('Rsun^3/(Msun*s^2)').value*masses/((radii)**2))*u.Rsun/u.s**2).to('cm/s^2')).value)\n", "/opt/mambaforge3/envs/astro_cosmic/lib/python3.11/site-packages/pandas/core/arraylike.py:402: RuntimeWarning: divide by zero encountered in log10\n", " result = getattr(ufunc, method)(*inputs, **kwargs)\n", @@ -217,7 +2018,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 6, "id": "467f1672-1f16-4c43-8add-47d0953fcd05", "metadata": {}, "outputs": [], @@ -244,7 +2045,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 7, "id": "45ac7b14-e09b-4840-b11d-647e2c5609e4", "metadata": {}, "outputs": [ @@ -254,13 +2055,13 @@ "Text(0, 0.5, 'm_ubv_R')" ] }, - "execution_count": 10, + "execution_count": 7, "metadata": {}, "output_type": "execute_result" }, { "data": { - "image/png": "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", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjMAAAGxCAYAAACXwjeMAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAABTFUlEQVR4nO3de1xUdf4/8NcBBQFhBEEuCkIoYXm/pKh5wbznapr5Xc20dd3a0LZvV7H8ZfstQffW7mp+08rcr3mpvLV5y1S8hJmoKJqaIgirg4jCgICgcH5/0EwzzAzM5cycOTOv5+PBY3fOnDnzdoZH58XnKoiiKIKIiIhIobzkLoCIiIjIHgwzREREpGgMM0RERKRoDDNERESkaAwzREREpGgMM0RERKRoDDNERESkaAwzREREpGgt5C7A0err63H9+nUEBgZCEAS5yyEiIiILiKKIiooKREVFwcur6bYXtw8z169fR3R0tNxlEBERkQ0KCwvRoUOHJs9x+zATGBgIoOHDCAoKkrkaIiIiskR5eTmio6N19/GmuH2Y0XYtBQUFMcwQEREpjCVDRDgAmIiIiBSNYYaIiIgUjWGGiIiIFI1hhoiIiBSNYYaIiIgUjWGGiIiIFI1hhoiIiBSNYYaIiIgUjWGGiIiIFI1hhoiIiBSNYYaIiIgUjWGGFEWtqUZmbgnUmmq5SyEiIhfh9htNkvvYdLwAqVtyUC8CXgKQNrkbpvWLkbssIiKSGVtmSBHUmmpdkAGAehFYuOVssy00bMkhInJ/bJkhRcgrqdQFGa06UUR+SRUiVX4mX8OWHCIiz8CWGVKEuNAAeAmGx7wFAbGh/ibPt7Ulh4iIlIdhhhQhUuWHtMnd4C00JBpvQcCSyV3Ntso01ZJDRETuhd1MpBjT+sVgSEIY8kuqEBvqbzbIAL+05OgHmqZacoiISLnYMkOKEqnyQ1J82yaDjPY8a1pyiIhIudgyQ27LmpYcIiJSLoYZcmuRKj+GGCIiN8duJiIiIlI0hhkiIiJSNIYZIiIiUjSGGSIiIlI0hhkiIiJSNIYZIiIiUjSGGSIiIlI0hhkiIiJSNIYZIiIiUjSGGSIiIlI0hhkiIiJSNIYZsopaU43M3BKoNdVyl0JERASAG02SFTYdL0DqlhzUi4CXAKRN7oZp/WLkLouIiDwcW2bIImpNtS7IAEC9CCzccpYtNEREJDuGGbJIXkmlLsho1Yki8kuq5CmIiIjoZwwzZJG40AB4CYbHvAUBsaH+8hRERET0M4YZskikyg9pk7vBW2hINN6CgCWTuyJS5SdzZURE5Ok4AJgsNq1fDIYkhCG/pAqxof4MMkRE5BIYZsgqkSo/hhgiInIp7GYiIiIiRWOYISIiIkVjmCEiIiJF45gZsolaU428kkrEhQYAgO7/czwNERE5G8MMWU1/WwPt0jMiuMUBERHJg91MZJXG2xqIP/8A3OKAiIjkwTBDVjG1rYE+bnFARETOxjBDVjG1rYE+bnFARETOxjBDVvuvR6J1Y2UE4ZdxM9zigIiI5MABwGSxTccLsGBzDvR7mRaMScSvekZxiwMiIpINW2bIItqBv42HyyzddQEAkBTflkGGiIhkwTBDFjE38Lce4IBfIiKSFcOMG1NrqpGZWyLJVOkAH2+TxwWAA36JiEhWHDPjpvQXtpNiMbvK2jqTx+cOiWP3EhERyUrWlplDhw5hwoQJiIqKgiAI2LZtm8Hzs2fPhiAIBj8DBgyQp1gFabywnRSL2QX4eKPxjGwvAXh2UJzthRIREUlA1jBTWVmJHj16YPny5WbPGTNmDNRqte5n586dTqxQmUyNb7FnMbtNxwvwxAeZBoN/vQUBaZO7sVWGiIhkJ2s309ixYzF27Ngmz/H19UVERISTKnIP2oXt9AONrYvZNW7lARpaZLa8kIQe0cESVEtERGQflx8AnJGRgXbt2iEhIQFz585FcXFxk+fX1NSgvLzc4MfTRKr8kDa5G7yFho4hexazM9XKUy8CVbX1UpRKRERkN5ceADx27FhMnToVHTt2RF5eHhYtWoTk5GScOHECvr6+Jl+TlpaGd955x8mVup5p/WIwJCHM7sXspGzlISIicgRBFMUmtg10HkEQsHXrVkyaNMnsOWq1Gh07dsTGjRsxefJkk+fU1NSgpqZG97i8vBzR0dHQaDQICgqSumyP8Mrn2dh88pru8ZTe7fGXp3rKVxAREbm98vJyqFQqi+7fLt/NpC8yMhIdO3bEpUuXzJ7j6+uLoKAggx+ynVpTja2nrhkc23bquiRr1xAREUlBUWHm1q1bKCwsRGRkpNyluCVTi+xJPTOKiIhIarKOmblz5w4uX76se5yXl4fs7GyEhIQgJCQEixcvxpQpUxAZGYn8/HwsXLgQoaGheOKJJ2Ss2j2ZW2QvLjQAAmA0LZtjZoiIyFXIGmaysrIwfPhw3eOXX34ZADBr1iysXLkSOTk5+Ne//oWysjJERkZi+PDh2LRpEwIDA+Uq2S2ZW2RvSEIYDv100+BcAbB5ZhQREZEjyBpmhg0bhqbGH+/Zs8eJ1Xguc11JJ/JLsWCz8U7ZQxLCnFYbERFRcxQ1ZoYcQzv9Wp+3IKC0qtYoyIgATl4tdVZpREREzWKYIbOL7LXxb2nyfNeYzE9ERNTApRfNI+cxtcieuenXfWK5jQEREbkOhhnSiVT5GQzs/er0daNzGu+cTUREJDd2M5FJak010nddMDouAlxjhoiIXArDDJmUV1JpcmyMF8A1ZoiIyKWwm4l01Jpq5JVUIi40wORieQDwxthErjFDREQuhWGGABivAPzG2ESjcwQAv+oZ5fziiIiImsBuJjK5AvDSXRdMrjHD8TJERORqGGYIWfm3jVYAbvxYi+NliIjI1TDMeLhNxwvwh43ZFp//43WN44ohIiKyAcOMB1FrqpGZW6JbDK9x95KWF4D+caYXxsu4eNPkcSIiIrlwALCb085QyvmPBkt3X0C9CAgCsGBsItq38TPZndQnNhhhAb4mrzfsQW4ySUREroVhxo3pz1DSJ4pA2k7jBfG0jueb30gytLXpkENERCQXdjO5KXNdSPbKaiLoEBERyYFhxk3llVRKHmQAoC83mSQiIhfDMOOG1Jpq3LpTAy+Jd4Uc2zUCPaIZZoiIyLVwzIybMTdOxl7zhsfj1dHGqwITERHJjWHGjdgzTqZTWACe6N0e5dX3UHKnBlEqP1wrq0Z8u9aY3LsD92MiIiKXxTDjRqwZJ/NwZGu09PZCdIg/fvvoA+w+IiIixWKYcSPmdro2ZVCndlg4voujSyIiInI4DgB2I5EqP8x9NM6ic1cdvqJbCZiIiEjJGGbczPjukRafu+/8DQdWQkRE5BwMM26msrbO4nMzLhY7sBIiIiLnYJhxM3GhARavL/Pt+Zt45fNsh9ZDRETkaAwzbiZS5Ye0yd0sPn/zyWvYd77IgRURERE5FsOMG5rWL8aq8+esPYFNxwscVA0REZFjMcy4qaBW3ladv2BzDmc3ERGRIjHMuKlZSbFWnS8COMEdsYmISIEYZtzU9AEdrX7NpeIKts4QEZHiMMy4qbySSqtf8/d9lzEwbT/HzxARkaIwzLipuNAAm14nguNniIhIWRhm3FSkyg9Lp1g+RVufCODNrQw0RESkDAwzbmxavxg83jXCptfuv3CTXU5ERKQIDDNubvnTfWx+rQgglV1ORETk4hhmPMBTvdvb/Np6AGuO5EtWCxERkdQYZjzAsqd62vX61Ueu4HQh16AhIiLXxDDjIQY9EGLza0URmLQik+NniIjIJTHMeIjPfpdk1+tFAKlbcvDv09c4hoaIiFwKw4wHOZqabNfr60Vg/oZsDErnLCciInIdDDMeJFLlh9lJ1m9z0Fi9yFlORETkOhhmPMziiV3RqoX916kH8N7X5xloiIhIdgwzHujCu+Mluc7XOWp2ORERkewYZjzUx7NsX0xPX73YMDCYLTRERCQXhhkPNaJLBOJt3IyysXoRWPNdniTXIiIishbDjAfb9+owhAX4SHKt1Yfy2DpDRESyYJjxcMcXjYS/j/2/BiLYOkNERPJgmCH8+MexECS4zqpDedz2gIiInI5hhgAAeenSzHCayG0PiIjIyRhmSCdfokDDBfWIiMiZGGbIgBSBph5AfkkV1JpqZOaWMNgQEZFDSbAWLLmb/PTxiF2ww65rHLl8EzM+ykW9CHgJQNrkbpjWL0aiComIiH7BlhkyKT99PFrYMSp4xYGGIAM0rEOzcMtZttAQEZFDMMyQWZfTxqOVPYlGT50o4kQ+ZzoREZH0GGaoSRfeHSfJOjQAMH/DKXx4MFeSaxEREWkxzFCzfvzjWLw5LtHu64gA0nZdwIeHGGiIiEg6DDNkkblD4iWbur101wWOnyEiIskwzJBVJJm6LTZM3SYiIpICwwxZzd5AIwC4VVnD1hkiIpIEwwxZzd41aEQA89afwqD0/dz6gIiI7MYwQ1aZt+6EZNeqF4EF3PqAiIjsJGuYSUtLQ79+/RAYGIh27dph0qRJuHjxosE5oihi8eLFiIqKgp+fH4YNG4Zz587JVDEdunxT0uuJAN748oyk1yQiIs8ia5g5ePAgUlJS8P3332Pv3r24f/8+Ro0ahcrKSt05y5Ytw1//+lcsX74cx48fR0REBEaOHImKigoZK/dcQzqFSX7NQ5dKcLqQC+oREZFtBFEURbmL0Lp58ybatWuHgwcPYsiQIRBFEVFRUXjppZfwxhtvAABqamoQHh6OpUuX4rnnnmv2muXl5VCpVNBoNAgKCnL0P8EjxC3YAal/af4wohP+e+SDEl+ViIiUypr7t0uNmdFoNACAkJAQAEBeXh6KioowatQo3Tm+vr4YOnQoMjMzTV6jpqYG5eXlBj8krTyJ1pvRd/UWp2oTEZFtXCbMiKKIl19+GYMHD0bXrl0BAEVFRQCA8PBwg3PDw8N1zzWWlpYGlUql+4mOjnZs4R5KqgX0tLZnX8e+86a/UyIioqa4TJiZN28ezpw5gw0bNhg9JwiGmx2Komh0TCs1NRUajUb3U1hY6JB6qSHQ9I1pI8m1RABz1p7AK59nS3I9IiLyHC4RZubPn4+vvvoKBw4cQIcOHXTHIyIiAMCoFaa4uNiotUbL19cXQUFBBj/kOF++MAje0mysDQDYfPIaBwMTEZFVZA0zoihi3rx52LJlC/bv34+4uDiD5+Pi4hAREYG9e/fqjtXW1uLgwYMYOHCgs8slMyKDfCW9XlY+wwwREVlO1jCTkpKCdevWYf369QgMDERRURGKiopQXd2wiJogCHjppZewZMkSbN26FWfPnsXs2bPh7++P6dOny1k66VnxdB9Jrxcb6i/p9YiIyL21kPPNV65cCQAYNmyYwfE1a9Zg9uzZAIDXX38d1dXVeOGFF1BaWor+/fvjm2++QWBgoJOrJXN6RAejrX9L3Kq6J8n17t6rl+Q6RETkGVxqnRlH4DozzmPvnk1ay3/dC4/3iJLkWkREpEyKXWeGlE2q2U3rjl21vxgiIvIYDDMkqS9fGIT89PGIC2ll8zW+v3Ibf95zQcKqiIjInTHMkENcLb1r1+uXH8jlbtpERGQRhhlyiK6R9o9POsEp2kREZAGGGXKIr1581O5rmFnkmYiIyADDDDnMiAfD7Hr9jjNqiSohIiJ3xjBDDvPxs4/Y9fqdZ4u4tQERETWLYYYcKj99vEELjbeVr1/w5RlpCyIiIrcj6wrA5Bn0W2isXVjv/I07OF1Yih7RwVKXRUREboItM+Q0A97b2/xJJmw/dV3iSoiIyJ0wzJDTFFXU2vS6m3fsW7OGiIjcG8MMOY2142V03Hr3MCIishfDDDnNgnGJNr2uqKJG4kqIiMidMMyQ08wdEm/T647nl3JrAyIiMothhhRh3/kbcpdAREQuimGGnGr+cNtaZ7ZnX5O4EiIicheShpm7d+/iz3/+s5SXJDfzyuhEeNvwW3e5uEL6YoiIyC1YfVspKSnBjh078M0336Curg4AcO/ePfz9739HbGws0tPTJS+S3EvukvFoYeVvXs29escUQ0REimfVLSUzMxOdO3fGhAkTMHbsWAwcOBA//vgjHn74Yfzzn//EW2+9hYKCAkfVSm7k8pLxmD88HpZujF11T+QgYCIiMsmqMLNo0SKMHj0aZ86cwR/+8AccP34cjz/+ON566y1cunQJ8+bNg7+/v6NqJTfzyuhE5KWPx/ND4iw6P7+kysEVERGRElkVZk6fPo1Fixaha9euePfddyEIApYuXYpnnnkGgmDp39hEhmruW9aF9J/SSgdXQkRESmRVmLl9+zbCwhp2QPb394e/vz969erlkMLIc7Rt7WvReWu/y3dsIUREpEhW7ZotCAIqKirQqlUriKIIQRBQVVWF8vJyg/OCgoIkLZLch1pTjbySSsSFBiBS5QcAOPzTTYteW1jGbiYiIjJmVZgRRREJCQkGj/VbZrQBRzvLiUjfpuMFSN2Sg3oR8BKAtMndkBgRiGP5pRa9/t59btJERETGrAozBw4ccFQd5ObUmmpdkAGAehFYuOUs6kTLA0rVvXqoNdW6Fh0iIiLAyjAzdOhQqy6enp6O559/Hm3atLHqdeR+8koqdUFGy5ogo7U2Mw8Lxj4kUVVEROQOHLqdwZIlS3D79m1HvgUpRFxoALwaTXhr/NgSJ66WSVIPERG5D4eGGdGGv7zJPUWq/JA2uRv0Z/Db8uvxYERr6YoiIiK3wI0myWmGJIQBegFGBCxeAVjrZnmNlCUREZEbYJghyak11cjMLTHafiCvpBKNG2OsbZzZ82MxtzUgIiIDVg0AJmqOqenX0/rFAPhl3EzjgcDWyi+p4owmIiLSYcsMScbc9GttS0qkyg9vjEm0+31SPjth9zWIiMh9ODTMPProo/Dz41/QnsLc9Gv9DSK7dVDZ/T63q+7hiyzuzk5ERA1sCjPDhw/Hxx9/DI1G0+R5O3fuRGRkpE2FkfKYmn7tLQiIDfVv9pxBD4RY9V6fHbtqa5lERORmbAoz3bp1w1tvvYWIiAhMmTIF27ZtQ21trdS1kcJop197/zz/2lsQsGRyV4PxLebO+ex3SVa9V6sW3tIVTkREiiaINi4GU19fj2+//Rbr16/H1q1b4e3tjSeffBIzZsyweqVgRyovL4dKpYJGo+EGmE6i1lQjv6QKsaH+ZgfqmjpHralGUtp+i97jT092w9S+MZLVTERErsWa+7fNY2a8vLwwatQofPrpp7hx4wY+/PBD/PDDD0hOTrb1kuQmIlV+SIpv2+SMI+05AHTTuL8+fd3i9/j2fLHddRIRkXuwe2p2UVERNm7ciHXr1uHMmTPo16+fFHWRB2g8jduaKdt7zt3Ahwdz8dzQeMcVSEREimBTy0x5eTnWrFmDkSNHIjo6GitXrsSECRPw008/4dixY1LXSG7I1DRuay3ddYEL6BERkW0tM+Hh4QgODsZTTz2FJUuWsDWGrGZqGre16sEF9IiIyMYws337djz22GPw8uKae2SaWlONvJJKxIUGmAwbUq0GXFV7z74LEBGR4tk8mwkAiouLcfHiRQiCgISEBLRr107K2iTB2UzO19SWBubOs8fSKaavT0REyuXw2Uzl5eWYOXMm2rdvj6FDh2LIkCFo3749nn766WYX0iP31tyWBvqm9YvB3/+rp93v+cbmHCzff4njZ4iIPJRNYea3v/0tjh07hq+//hplZWXQaDT4+uuvkZWVhblz50pdo8sytzu0J7NkSwN9fWNDjFYEtsWfv/kJSWn7sek4tzkgIvI0No2Z2bFjB/bs2YPBgwfrjo0ePRqrV6/GmDFjJCvOlTXuSnljTCK6dVCZHSPiKUyNhWm8pYE+7YrAb2zOkeT9F2zOwZCEMI/+DoiIPI1NLTNt27aFSmW8YaBKpUJwcLDdRbk6U10pabsuYPrqYxiU7vqtA45sUbJkS4PGpvWLwdFUaRZbFAGzrUBEROSebGqZeeutt/Dyyy/jX//6l24jyaKiIrz22mtYtGiRpAW6oqamFWvHiLhq64Clg3PtMa1fDIYkhDW7pYG+SJUfWrUA7t63//05w4mIyLNYPJupV69eEIRfBjdcunQJNTU1iIlpuBEWFBTA19cXnTt3xsmTJx1TrQ0cMZtJranGoPT9Tc7C2TB3gG65fldhqm5vQcCRBcOdHrzMTd2OXbBDkutP7x+N+cmdXTJQEhFR86y5f1vcMjNp0iR763Ib2q6UhVvOos5EFmxqjIicmhqc68ybvrnWIbWmWpK1ZwBg/bFCbDhWiHRO2yYicnsWh5m3337bkXUojn5XyplrZVi26yLqRBFeAOYMjpW7PJOaGpzb3CJ3UjE3dXtIQpgkqwLrE8EBwUREnoBL+NpBu/Pzc0PicWTBcPzu0QcAAVh1OM8lBwKbG5x76KebGJS+3ykDmJtqHdKGLSmJAE5eLZX2okRE5FJsGgDs5eVlMH6msbq6OpsLUrKPjlwx2eLgSq0CjQfnAjAYR+PouptqHWqu+85WEl6KiIhckE1hZuvWrQaP7927h1OnTmHt2rV45513JClMaVxlPIolIlV+upoyc0ucWnfjwNJ46rZ+2PL38UJVbT3OXCtD2s4LNr2fAKBPrPsvF0BE5MlsCjMTJ040Ovbkk0/i4YcfxqZNmzBnzhy7C1MaaxeLcxVy1N3c1G39sAUAsaH+NoeZ9CndXC5MEhGRtCQdM9O/f398++23Ul5SMWxZLM4VyFW3drxRc++j1lTjN2t+sPl9EiMCbX4tEREpg127Zuurrq5Gamoqdu3ahYsXL0pxSUk4e9dstabaqsXiXIUr1r3peAEWbM6BPb+gUapW2PzCQJf5NxERkWUcss6MvuDgYIMBwKIooqKiAv7+/li3bp0tl3QLzpre7AiNu3bkpp3CbW/Svq65i6S0/UgZFo9BnUMV+d0QEVHTbAoz77//vsFjLy8vhIWFoX///h6xN5Mplm4ToNZUIyv/NgRBQJ+OwbyxmiH1mjMrMnKxIiMXAJA6LhHPDYmX7uJERCQrm8LMrFmzLDrvhRdewB//+EeEhoba8jaK0dRCcPphpXG3iQBwhVozTA1MlkrazguACDw3lIGGiMgdOHTRvHXr1qG8vNyRb+ESmpqWraXWVBuN/xABpG7Jccju1UqnHZjcxHJGdknbdYGfOxGRm3BomJFobLHLM7VyrZcAlNy5q7th5pVUmhz/US/CIPQomVpTjczcEslCwrR+MchckIwV03vhiZ5RklxT34l8rgxMROQOZN3OIC0tDf369UNgYCDatWuHSZMmGc2Emj17NgRBMPgZMGCATBWb1nh6syA0rDo7f0O2bnuAuNAAmGpkEAD4+yh/V4lNxwscsiVCpMoP47tHYfagWEmup89RrT5ERORcst5FDx48iJSUFHz//ffYu3cv7t+/j1GjRqGystLgvDFjxkCtVut+du7cKVPF5k3rF4MjC4ZjxfRegAhdK0y92NCVBDSMj2l8/xQBPPFBpsvt42QNc2OGpOzG6REdjCm920t2PQDoEMzB10RE7sCmAcBS2b17t8HjNWvWoF27djhx4gSGDBmiO+7r64uIiAhnl2e1SJUfThfmGXUn1YvAmu/ysHDcQxiSEIZvf7yB/7f9nEHgccV9nCzlrK0c/vJUTwS1aoE1mVcluV5Vbb0k1yEiInm5VP+GRqMBAISEhBgcz8jIQLt27ZCQkIC5c+eiuLhYjvKapdZUY/XhPJPPfXQoD2pNNSJVfohv19oo8NSJIvadv+HQ2qQcz6LP1Jghe7ZEaKrWSb2kaZ1RwlYTRERkGZtbZu7evYszZ86guLgY9fWGf+H+6le/AgA8/fTTFq+6K4oiXn75ZQwePBhdu3bVHR87diymTp2Kjh07Ii8vD4sWLUJycjJOnDgBX19fo+vU1NSgpqZG99iZs6nMDfIFgHpA11JhbtrxW9vO4VRBGf7yVE9J67J0DRxbNbd5pJS1tgtqhUdig/GDnYN3lbDVBBERWcam7Qx2796NZ555BiUlJcYXFATU1dVZXUhKSgp27NiBI0eOoEOHDmbPU6vV6NixIzZu3IjJkycbPb948WKTO3c7YzsDtaYag9L3m1wbxVsQcGTBcN0NVP+m3dj2lIHoEf3L4oP2rCxsqqbGtUjF3i0Rmqs1dsEOSeps/PkSEZHrsWY7A5u6mebNm4epU6dCrVajvr7e4MeWIDN//nx89dVXOHDgQJNBBgAiIyPRsWNHXLp0yeTzqamp0Gg0up/CwkKr67FV41lNWqZaKqb1i0HKcNOLtm0/dV3XzWLvLCFL1sCRiqWbR5rTVK1SBZmUYfEMMkREbsambqbi4mK8/PLLCA8Pt+vNRVHE/PnzsXXrVmRkZCAuLq7Z19y6dQuFhYWIjIw0+byvr6/J7idnmdYvBkMSwpBfUgV/Hy9U1dabbal4rEs4/rk/1+j4J5n5+CQzH14/T/G2Z6CwqS4tVx0vYq7WX6/+XrL3WJGRi6yrt7FwXBdU1tZxryYiIjdgU8vMk08+iYyMDLvfPCUlBevWrcP69esRGBiIoqIiFBUVobq6YeDnnTt38Oqrr+Lo0aPIz89HRkYGJkyYgNDQUDzxxBN2v7+jaFsoekQHN9lS0SM6GDEh5m+k9XpBRsvaVpXGrUX2jGdxNHO1Su1YXikmrsg0aO1y5ABpIiJyLJvGzFRVVWHq1KkICwtDt27d0LJlS4PnX3zxRcve3MyqZWvWrMHs2bNRXV2NSZMm4dSpUygrK0NkZCSGDx+O//mf/0F0dLRF72FNn5uznS5suKlaw9bxLvaOZ3GmxrVK1cVkCUcMkCYiIutZc/+2qZtp/fr12LNnD/z8/JCRkWEQSgRBsDjMNJej/Pz8sGfPHltKVIRt2debPUf4+ace9rWqRKr8XD7EaMlZa70IpG7OwZCEMACweeA1ERE5j01h5q233sIf//hHLFiwAF5eLrVUjbJY0CgmAlgwNhHdO7Qx26piz2wnJTiamoyktP1Oe796AG98eQaHL5VABHc3JyJydTYlkdraWkybNo1Bxk6WLgC3dPcFs0HGUXsiuZJIlR8Sw1vb9NpHYm2buXTo5yAD/BwoN3N3cyIiV2VTGpk1axY2bdokdS0ep0d0MB7tHNrseeZ21nbGnkiuYvd/D7X6NU/2bo/jEu2MLQLYcKwA+84XYfXhXJwu5I7bRESuwqZuprq6Oixbtgx79uxB9+7djQYA//Wvf5WkOE+w7MnuFnWhbDpeYNQ646w9kZypqS4za7ubvjx5TdLa/rH/ssHjKb3bS75aMxERWc+mMJOTk4NevXoBAM6ePWvwnLkZSmRapMoP84bHY/kB4/Vm9G3Lvo5t2deROi4Rzw1pWGzP3jVkXG2sTVNbGWifcyWbT17DM0kduQgfEZHMbAozBw4ckLoOj/bq6ETk3qzErrNFzZ6btvMCrt+uxvPD45FXUok3xiZi2a6LVu+J5Oj9mqxlrstMO6vI3NYPctt3vphhhohIZjZvNEnSWvl0H5wuLMX+C8W4e68Oqw7lmd20cu33V7H2+6sAGoLIG2Oanu3UWFPBQa4Wmqa6zESILhlkAMC3pRcyc0tcpnWLiMgTMcy4kB7Rwbq/8kNa+yJt54VmX1MvAst2X7RqIT1XHGvTXJeZqefqrF/vUXJ/+eYnl2ndIiLyVJxb7aKeGxKP1LGJFp1rbosD/SX69f+/Njjok3u/pqa2XTD3XPcoeVd0FgCPmElGROTqbNrOQElceTsDS6g11Zi//iSyrpY1ed7Hs/pgRJcI3WP9MTHa3CLilxYEoOHmqz/WxlSrgrMHCTe17YKp55y51YEllv+6F0Ja+7DbiYjITtbcvxlmFECtqbZoSvK4bhF4bsgD+Pb8DSzfn2t2zI12fycATe7X5GqDhM351T8O48z1cqe/rwDjjUC1XPnzIiJSAoYZPe4QZoCGYPHGZummJm+YOwBJ8W3NPq/WVGNQ+n6jcSq2bHLpLGpNNfadv4G3tp2TuxQArv95ERG5Mmvu3xwzoxDT+sXgaGoyBti4PL8+S8bHNDVI2FVFqvzw9IBY5KePx8ez+uDB8ABZ63H1z4uIyF1wNpOCRKr8sPH5gZjwj8PIsbJbRdslYulaNPYuyCe3EV0iDMYQzVnzA/ZdvOn0Ovx9vFxucUIiInfDbiaFWn0oF+9ZMHVb609PdkOH4ACL16IBGrq2LBkkrCSvf56NL05eMzvWRWq/e/QBfHTkisuPOyIicjUcM6PHXcMMALyw7gR2WrBqMNAwy+bxHlFWv0dTs4uUasaqo/juym2nvFfjQcIcR0NEZBmOmfEQHzzdBynD4y06d96GU3hvx48m10E5XVhqdifoSJUfkuLbutXN91RhmdPeq/FfCo3H0eiv/2PqMRERNY9jZhTutdGJeHpAR7y04RSO5RuHEX2rD+fho8N5WDAuEd3aqxAXGoA/77mIzXq7S3vCTtBJD7SVZfwM0NDV5O/T8DdE46nvT/Rqj62nrrFLiojISuxmciPP/SsLe368Yfd1tqcMdPvNE+VcbE+7n9bS3Rea3HOKXVJE5MnYzeShFk98WJLrZDXTwuMOwgJayvbe9SKQtqvpIANwajcRkaUYZtxIpMoPS6d0M9p3yVpKmX5tj79P7y13Cc0S4BnfBRGRvThmxs1M6xeDIQlhyC+pgr+PF/adL8Y/9l+26hp5JVVQa6rdunvD1Do6rkYEUFx+162/ByIiKbBlxg1pZyD1iA7Gr/vHwNqGmnd3nMeg9P3YdLzAIfW5gsY7cQOumewnrsh06++BiEgKHADsAWzd18lbELDqmd64UlKJR2JD3HJQcON1dB55dy+K79TKXZYBAUBmajJbaIjIo1hz/3bFP0ZJYtqup5c2ZuNYnuWLxdWJIuasPaF7rJ22rV2eP8DHG5W1dYpepj9S5WdQe0J4axTfcc6CepYSAZzIL0WfWHBbBCIiE9gy42H2nS8yCCjWmtQzCl+dvm4w1kQAkD7FPdZEOV1YiokrMuUuw8iM/jHY8EMB16AhIo/BqdlkdiXZEV0iLF412JRt2deNBs2KABZszlH8qrVqTTUqa+swrluE0XNLp3TD9pSBMlTVQBtkgIZBywu3nFX8501EJBV2M7mhxivLNv4r/rXRifjxejkOSLgKrgjg2x9vYGZSrGTXdKbGn1nKsHi08BYQ2toXjz0UruvWmZ3UEZ8eveq0urwE4LeD47DqcJ7Bce0aNKa6m7hLNxF5GrbMuBm1plp3UwbM/xW/5tlH7GqhMeX/bT+nyJk3pj6z/z14Bf/1SAxmJsUaBIJRXY1bbRzFC8DWFwbi2cFxRmsHeQmm16DZdLwAg9L3Y/rqY24/I42ISIthxs3klVQadQOZW0n2tdGJOJqajDEPhUvy3iIagtPpwlKrN0uUc4NFaz6zuNAAJ1UF1AP434xcFJffRdrkbtCbRQ5RBA799EvLmlpTjX+fvmZRkCUicjfsZnIzphaD8xYEsyvJRqr88L/P9MXCLWew/odCu9+/ThQxaUUmRFg+ULW5bjFHs+Yzi1T5IWVYPFZk5Dqltl3nbmDXuRuIDm4F/aH62uCYGBGIHWfUWH04z2iHbqDp7igiInfBlhk303gxOG9BwJLJXZu9mc0f0dnubRC0tDdVS1oGLO0WcyRrP7PXxiQiKT7EafUBQGHpXaNj2uC4ykyQAX4JZXK2fBERORpbZtyQ/pYG2sXgzNEfLJo2uRsWbjmLOgln6zfXMtBUF48zWxOs+cwAYH5yZxzNPeak6sxr6pvShrJDP92UteWLiMjRGGbcVOPF4Ewx1b1zZMFw3Q0daFisbd6GU3bV8s05Nfx9vEyuIGxtt5gjWfKZaTlz7Iwt3p30MEZ0aRgLNSh9v1HL15CEMHY9EZHbYDeThzLXvQMASfFtdTf2x3tEIXVcol3vtSbzKiauyMQrn2cbPde4i8cLwOtjHnT5G612h3JX9da2czj0002rBjcTESkVw4yHsuYm1ylMmlaIzSev4XRhqdHxaf1i8PthD0BAwwyepbsvNDul2FXGgEg0zMghUjfnIMDH22gslFwtX0REjsIw42Ysvclru3f0mbvJ7b9QLFl9+84bX+vDg7lYfiDX4oHDrrCWirZlSz8PCgCeHRhrMIVaTvUAfv/ZCUSqfA2OT+oV5fItX0RE1mCYcSPW3OQjVX54Y0yi7hegqe6d5MR2ktX4j/2XDepSa6qRvuuC0XnmWolcYfYTYLplSwTQPtgPrrTb2fWyGlwrqzE4Zq6FjIhIqRhm3ERzN3lti412QbsPD+YifdcF1P/8+noA6bsu4L0dP5rcz6l3TBvJan1jcw72nS8C0BAKTN37za1wa8sYEEd0SZlr2eoXG2x0XIDrdUdNXJGJ5/6VJXs3HRGRFDibyU00dZM/9NNNLNic0+Q0XqChZWH14TysPpyHlGHxaBPQEo/EhqBHdDCm9YvGyYIyyeqds/YEpvRuj1dHP2g0mwkA3hibaNBKpJ1Crh0DYunsJ0ctyKcduKydyq6dBt0jOtjk8SEJYZi6MhP/KTNeL0Yue368gT0/3oCPNzCpR3sse6qn3CUREdlEEEVXahSXnjVbiCuZWlNtMAUXaLjJb3khSbcir636xwXjWJ5juiW2pwzEhaIK3c1fAPDCsHi8NuaXGVSNA8kTvdpj26nrBmHBVEAx95kcWTBcsjEjak21ybVpzB1PfGsX7t6vN3Upl5CfPl7uEoiIAFh3/2Y3kwJY0k1iahXb18c+iG/P37AryABwWJABgDc2n8G0fjF4feyDEISG1qGVB3N142pMdZ9tO3UdW15Iwoa5A3BkwXCzLS3OmJYcqfLTTWW35PiFd8di/vB4BPp6S1aDlGIX7HDIdV1l9hkRuSd2M7k4a7pJ9FexPfOfMizddcHoZu5qLhTdwenCUizddUE3cFZ/YTdzgaSqth5J8W2bvLYrLcin75XRiXhldCLUmmq88+9z2H32hqz1NNZr8R70jg1G+d37GPVQOCLb+OF2ZQ1CAnwRHeyHyto6xIUGmOwGbHwckH/vLSJyfwwzLszcoN6mVm/VHp/x0fcuH2S0/rTbOHRpW1DsCSTmxrW4yrTkSJUffj803uXCTOnd+9h3oWFH7uP5plvlvARgzuA4/GZwXJPbJZj6HU7dnMMViIlIUgwzLsyafYv0/zI29Tot7awaV8o52f8pMxtY7A0k1u655Gw9ooMRF+qPPIWtyFsv/jJYXIDx5qLasGLqd7EewHtfn8ebj3dxue+DiJSJYcaFWdoq0bgZ/4Vh8SavJwDYljIQ7YJa4Z/7LmP9D8br0IxIDMOLIzoDAP6x7zL2Sbhgnjl3auqROi4Ry3ZdNBlY7A0k1uy5ZEpTXShSeGt8F8xZe0Ly6zpL42BcJ4o4ebUU47v7md3D6uscNXaeVbPLiYgkwdlMLm7T8QKDVonXxzyIbh1UCPDxRmVtHQJ8vPHEB5kWdyltmDsAsaH+GJi+3+zibgKA9CkNN5k/77mA5QdyJfv3NFeXq7WgOGu8x+QPvpN06rsraOUNvDOpW5PLAkg9u4yI3Ic192+2zLgg/ZYA/VaJ7y7fRPruCwYhRBBg1Yqz/j5eOHG1tMnXiAAW/Dyu4dXRibhVWYsNPxTa/O+xhDbAyH1T0//sAVg9ZslWW14YhH3ni/De1z/iyi33mPFzt65hgcSmmOs2JSKyBsOMizHXEvBV9nWTLSTWtqvtOFOEVYevNHueCOBv31zEjAEd0SUy0Lo3sVLK8Phmb2anC0vxQ/5t3SJ+9jLVddT4s//t4DiLxyxJYUSXCIzoEgEA2He+CCsOXMaZ/2jgwsvS2M0VZpcRkfKxm8mFOHLhO6BhUSHRypYcRxv+YBjWPPtIk+e88nk2Np+8pns8pXd7/MWO1Wr1Q4sAYO6jcRjfPdKou84LAEyMWXJ2t8jCraex/th/nPZ+jiSgoTWxXkSTCx4SEbGbSaHMzV46nl9qd5DxFgTMGRyLVYfz7LySebOTOuLTo1etek3jIKO/bUFlbR2qa+8bBBmgYaPEZ5I62tRC03iqsAhg1c+zchp/xvUAfjf4AXx8JE/Wqd3zkxPcIszob+3gamOjiEjZGGZciLnZS9rNC00N8vUWBEzqFaVb3l9/6rWX0LDHUff2bXRN+R8dyZNs/RkBwMNRQRjcuS0ejlJBEASrw0zsgh1YPr0X+nQMNlivpDlZ+aU2hRlz09ZNvaW3IODZwbF4dnCsrDffSJUfxnWNwM6zRU5/b6kM69wWEAQcvnQTtXX1eKxLOCJVfg6fKUZEnoHdTC6m8ewlbTO8/nEvAL8fHo/BncJ0N1j9vYAAmL35bjpegAVbclyqqwmwfv2blEb7NwGWTaE21ZWnz8uFu0B6vrMHZdX35S7Dat4CUGfi8360cyiOXCrRBW9O0yYifdbcvxlmXJC1mxfacv2TV0txu7IWIQE++PF6OT7IyHWphfSa03jsijVTqDcdL0Dq5hw0HlerHZ9UVVvvsl0gqw/l4m/fXkRVrZK+LcsIADJTk5tcENIVvxMicgyGGT1KDDNy0A9KxeV3sf9CMUJb++Jo7i2bujcCWnohMrgVLhfbv7KtuS62DXMHICm+rU27Y6s11XjjyzM4dKlEd8zegcXOdLqwFKsPXcF/yqpwqfgOKmvcY8pTz2gVXh+TqAsuBoO1BWDB2EQ8N8T0opBE5F4YZvQwzNhvxJ8zkFtS6ZT30l8aH/hl9+/Gm2bqh5XM3BJMX33M6FrasGOKLQHIle07X4SdOWrcuXsfe350/KrNjiYAeGF4PFZm5BoF2dSxiXhuKAMNkbvjbCaS1L5Xh+HXq47i6JXbDn8vET/fyIbFY3DnX8YEtfFraXZ/Jls2o7Rm3ysl0F+jRq2pxqff5eGr09eh1tTIXJltRAArzKw8vXTXBfyqZ5TJ7qis/NsQBAF9OgYr8nskItuwZYYsdrqwFNtPXUflvfuICfHHl1n/Qd4tx2yQaKqVpKkxQ+YGTpvjbi0z5mjHR/1lz0VccdB3JYfGrW6bjhcYbJugvyUHwHE3RErEbiY9DDOOte98ETIu3sR3l2/hisRdUU11E5li7QBpawOQ0p0uLMW+88XwbemFvT/eQHahRu6SbPZYYhh+VJej4u49PBLbFvsu3jQ6x0sAvluQbDDln7OmiJSDYUaPnGHG0/4aHPHnA8gtkeavf+2NyNGfm1QzxJTodGEpVh++gq/PKHf9muasmN4L8zeccvsWOCJ3ZM3928tJNXmcTccLMCh9P6avPoZB6fux6XiB3CU53L5Xh2PWgI6SXEsUgUM/Gf+1LbVIlR+S4tt65I2tR3Qwlk/vg+XTe8ldisNcKbljdmwUEbkPWcPMypUr0b17dwQFBSEoKAhJSUnYtWuX7nlRFLF48WJERUXBz88Pw4YNw7lz52Ss2DKNl8zX7ras1rjHbshNeWdSVxxNTca7kx5Gl4jWaOVt26+YCM/5zOTWp2PDCtPu6K/fXIKpf9qZa2XOLoWIHEjWMNOhQwekp6cjKysLWVlZSE5OxsSJE3WBZdmyZfjrX/+K5cuX4/jx44iIiMDIkSNRUVEhZ9nNamqmjCeIVPnh6QGx2PXSUFx4byyWTulm8oaiJQB4ZVRno+Oe9JnJKVLlh7TJ3dwy0JjrQ1+26yKDMpEbkTXMTJgwAePGjUNCQgISEhLw3nvvoXXr1vj+++8hiiLef/99vPnmm5g8eTK6du2KtWvXoqqqCuvXr5ez7GZppwrra26qsDub1i8G21IGmgw0XgIwuXd7/PWbS0bPOeozU2uqkZlbwpuZnmn9YvDdgmR0bhcgdymSMxVo6kQRO86o+TtA5CZcZsxMXV0dNm7ciMrKSiQlJSEvLw9FRUUYNWqU7hxfX18MHToUmZmZMlbaPO1fut5Cw+1brt2WXUmP6GCkT/nlM/EC8Lshcdj6wkBsOXnN5A3n9TEPSv6ZeeJYJktFqvyw9+Vh+HhWH8QEu8/vqgCYDNLv7jjP3wEiNyH7onk5OTlISkrC3bt30bp1a2zduhUPPfSQLrCEh4cbnB8eHo6rV83vzFxTU4Oaml8WCisvL3dM4c2Y1i8GQxLCPHamjCmmPpPM3BKzXQHdO7SR9P3NjWUakhDG70ePdgG+04Wl+Mf+S9h33nggduOVml3d5N7tdTvL6+PvAJF7kD3MPPjgg8jOzkZZWRk2b96MWbNm4eDBg7rnBcHwbypRFI2O6UtLS8M777zjsHqtEany438gG2n8mcSFBpi8MXoJkLyLyd1W/XW0HtHB+HjWI1BrqnEivxRl1bXIyi/F9uzrigoyIoDNJ69h/vB4qPx98O6O8wbP83eASPlk72by8fFBp06d0LdvX6SlpaFHjx74+9//joiIhqXZi4oM18AoLi42aq3Rl5qaCo1Go/spLCx0aP1kn0iVH9IbDRAWfl7YTOqbiy1jmTi+puE7erxHFEZ0CcdXp5UVZPT980Au1nyXZ/Z3QP+75vdOpCyyt8w0JooiampqEBcXh4iICOzduxe9ejWsg1FbW4uDBw9i6dKlZl/v6+sLX19fZ5VLEtB2P53IL4UgAL0dtK+OdiyTuT2eGtPfsZkrx5pu2VKaa2V3Me7hCOz58YbB74D+KsHarCPC9PfuaYthEimBrGFm4cKFGDt2LKKjo1FRUYGNGzciIyMDu3fvhiAIeOmll7BkyRJ07twZnTt3xpIlS+Dv74/p06fLWTY5QMNf/46/MVg6lonja4yZ2tBTiXaeK0Lfjm3QrX0bTOoVhXZBrQz26dL/59WLQOqWHN33zoBL5JpkDTM3btzAzJkzoVaroVKp0L17d+zevRsjR44EALz++uuorq7GCy+8gNLSUvTv3x/ffPMNAgMD5SybFM6SsUwcX2OsccuWnIOAE9q1RnJiGKKC/fD29h+triPrahmyrpZhTWY+ukS0bjKg1YvAmu/y8OygOIPNLOtFYIFe0CEi+XBvJiIT1JpqDEzbb3CTFABkpjp+vyhXp7+fFQAs338ZG34oUHyLTVO8ALwyKgF/+uYno+dWTO+F8d2jnF8UkZuz5v7tcmNmiFyWG66Qa4vGLVvvPdEN85I7Ib+kClW197D15HXsPKt2q3BTD5gMMkDDPmJEJC+GGSIT8koqjbouRBEe3c3UFP2AM6JLhK715sy1MizbddFofRd3IQDoExuse8zBwUTyYJghMsHUYFf9ady8aTVNG26S4tviVz2iGoLNf8qwbLfpYKO0Rfi00qc0LCGg1lRjzZE8rD6cZ3YWFBE5DsfMEJmx6XiB0TTuaf1iOKPFDroWG71g4y0IeH3Mg1i6+4JBeFRCwEkZFo+Ytv4GA4O1vAUBRxYMBwAGXyIbWHP/ZpghaoL+YFftX+D603iBX25avFFZp/Fn2zg8zhkci1WH8+Qu0y7TH4nBhh8K2FpDZAMOACaSSOPBrpyyLZ3Gn23jNYAA4KMjeQaft9LWuVn/wy+bWDZes4ZdlUTSYZghskJzY2nIPo0DTuMVm18f+yCW7rqgqECjT7tmTdsAX6TvusAWGyKJMMwQWcHaLRHIPqZWbG7j19Lg8//9sAew/ECu3KVabNUhw66zehFI3ZyDAN8W6GNiKw+24BA1j2NmiGzQeLwHOVdT421cgf7+TtZo3ErTeLD5nMFx+M3gOP7OkUfgAGA9DDNEnsHUTCln8fEW8LdpPXG7shYhAT7o3THYYPNKa+jPgmo82BxoCErpU9gtRe6PA4CJyOMYrG3TM0q3aF/azgsOf++DrxvPZtN2ka35Lg8fHcpDPRq2RRDRdItNnShixxk1IlStTAYhEQ0DiRMjAtEjOtj4BCIPxJYZIifguAf5qDXVWLbrPL7KVqMOgH9LoOqe9O+Tnz6+yRq03WJfnb5uUcBqrquKLTTk7tjNpIdhhuTGRfZcT+yCHZJfMz7UH//zRDfEhQYAaHqhvIVbzmD9D4XNXlMAIDQxHd1bELDlhSRU1tYxKJPbYZjRwzBDcuIie67LEYHGlKUmWk9M/V4IgulNK5f/uhfOXCvD6kN5JltptK9jUCZ3Y83928tJNRF5pKYW2SN55aePR9+YNg5/nzc250CtqTY4pp3i7y00dCZ5CwJShsVDaLQzu7cgoE9sMBaOewjbUgaa3LhdG4DqRWDhlrNG76Wl1lQjM7fE7PNESsYBwEQOxEX2XNuXLwwyeDwo7Vtc09RI/j5Jaft1/9/XG7j43niDNXTO/KcMS3dfMGiZabyGUY/oYKRP+WWNIy8A9Y3ex9xq1OzqJHfHbiYiBzO3YSW5Jmd1P2n5tRBQfd/wP8NeALamDDQ5W0k7mNjfxwtPfJDZbBcmuzpJqTg1m8iFmFrFllxXfvp4h7XQmNI4yAANLS5VtY3bXRrob/lgyWrU3E+MPAFbZoiImvHO9rP4v6NXcV+m9382qSPentjV5HPNrUbtqJYZLjdAjsbZTHoYZohIas7uimrMxxuIUrVCSnJnTO3bfJel1F2dHINDzsAwo4dhhogc4YusArz+ZY7V+y85Ulv/FkjqFIq5jz5gNN5Gqv3EOAaHnIVjZoiIHGxq3xhdq8jQpftwtfQufL2Bh9urcKZQAxNDYRzuVtV9fH2mCF+fKQIABPu1wMLxXTC1bwy+Pn0d73/7Eypr69FCAHxaeMHLCxgcH4q3J1q+8/uaI3nNjsFhFxQ5G1tmiIgc4IusAnx48ArySyplCTbWilL5wqeFFwJ8WiA2LAA+XgKulFQiwLcFOgT7I6atP1StWmLR9nMmX586NhHPDY1nFxRJht1MehhmiEhu+84XIePiTew/fwNqTQ0Swltj938PlX3sjdRiQ/yQf9twUT4vAN+lJrOFhqzGMKOHYYaIXNmIPx9ArpuvCO3f0gsxbf3h28ILwX4+uFFxFyr/lpj76AMY0SVC7vLIRTHM6GGYITKPYxtcg3ZwblXtPcxZe0LucpyqjV9LtAv0gab6Htr4t0SPDm0wumsE/Hxa8PfSwzHM6GGYITLN2rENDD7OM2PVURzLuw3fFl4I8muJJ/t0wCujE3XPz1t3AjvOFkFEw87a7vwf8TatvNHarwXCWrdCbKg/SivvoV1gK8wYEGNyhWRyHwwzehhmiIxZO72WgzqV4YusAqw6mIurt6pgZgFht+LjBfSOCUa/B0Jwp/o+Dl66CT8fb4ztFokpvTswdCscw4wehhkiY5m5JZi++pjR8Q1zByApvq3BMa4rolyTV3yHk4VlTZ7z9IBoaKruIa+kEndq7yPg5+6dll4CrtyqRKBPC5wqLEOlAtPRw1GBGNwpFB2C/QEB2HeuCOeLKjCua6TZFZXJdXCdGSJqkjW7eXNvH+XakjIIXRbtQvU900GkY4gf3p3U3aJrfZFVgM++L4CXADwUFYR7dQ2/FLX363GhqBw19+vg28IbiRGB2HehGOV36yT7d9jq3PUKnLteYXR8zdGrWHP0KpITw1B7rw63Ku8Boojyu/fQLqgV5iV3knxgMrtpHYstM0QeytIl7tkyo3x/2XMB/zyQa3AsrLUPjr810mHvue98ET46cgV5N6sgQkSIvw98W3ihjZ8PLt6ogLrcORt52ioiyBcpyZ2QcbEY5dX3EBcSgFtVtRjTNcKiLST0sZvWNuxm0sMwQ2SepUvcS723D8nji6wCfHPuBkY9HG71DVlqak019p2/gWN5t3BRXYHyu/eg8muJmnv1RmvVuJpWLQTEtPXHnbt1iGrTCrX361FaVYtJPdsbDNQG+MeAPRhm9DDMEElDqr19iJpzurAU648V4Nx1Dcqq7kEQgNBAX8S29Udm7m3ccPFWHR8vwMtbwIDYtpjStwPmb8g2OsfU+DQyxDEzRCS5SJUfQww5RY/o4CanXZ8uLMW7X59H7s0KJLQLRP8H2qK8+h6+OPkf3KmRf6xObT2AehEZl0qQcanE6Hlz49PIdmyZISIit3G6sBT7LxSj5E4NblfWomNb/4bZTAD++e0l3LhTK3OFhhIjWmPplO5cM8cEdjPpYZghIiKt04WlWP9DAQpKKuHv2wI19+tw+849iKKI8zfuyFpbSy/g6f4dOW38ZwwzehhmiIjIUqsP5WL32SIMjG+LcFUr3WymG5oaXC113sDkDipfrHi6j0e32DDM6GGYISIiKZwuLMX27OsouF2JwttVutlMJ66WwVFLCrZv44vvFjzmoKu7NoYZPQwzRETkaKsP5eLDg7mouHsPjhiDPOiBEHz2uyTpL+zCGGb0MMwQEZGzrT6Ui+X7L6Hibh1aeEGyvbL+9GQ32dcIchaGGT0MM0RE5Ar+sucCPjpyBdX37L/tPtW7PZY91dP+olwYw4wehhkiInJFf9lzAZ+fKMDtinuwNd/MHx5vtOqwu2CY0cMwQ0RESvBFVgFe+zLHpte6Y/cTw4wehhkiIlKSd7afxZqjV2167bNJ7rNODcOMHoYZIiJSotc/z8bnJ6/Z9NoRD4bh42cfkbgi52KY0cMwQ0RESjZ91VFkXrlt02sjgnzxyqgERXZBMczoYZghIiKlU2uqMWzpftTYMcW7e1QQvnrxUemKcjCGGT0MM0RE5C72nS/Cb9eegD037g6qVljxdG+X3yqBYUYPwwwREbmbfeeLMGftCbuu0dILWDLZdWdBWXP/9nJSTURERCSREV0ikJ8+Ho93jbD5Gvfqgde+zEHimzskrEwebJkhIiJSuH3ni/DO9nMoKLtr8zXy08dLWJH92DJDRETkQUZ0icChBSOQnz4e3aNs+8N9zpofJK7KeVrIXQARERFJRztj6XRhKf6w8RTyb1Vb9Lp9F286siyHYssMERGRG+oRHYyM15JxNDUZD0cEWvSa2AXKHD/DMENEROTGIlV+2PHSEIsHDHdbvNsJVUmLYYaIiMhDLH+6T7MDfSvu1uGLrAInVSQNhhkiIiIPM394fJPP27p7t1wYZoiIiDzMK6MTmw0ASho/wzBDRETkga5YsK7M659nO74QCTDMEBEReajmups+P3nNSZXYh2GGiIjIQ70yOhFCM+coobtJ1jCzcuVKdO/eHUFBQQgKCkJSUhJ27dqle3727NkQBMHgZ8CAATJWTERE5F7yLOhuGvDeXidUYjtZw0yHDh2Qnp6OrKwsZGVlITk5GRMnTsS5c+d054wZMwZqtVr3s3PnThkrJiIicj9HU5ObfL6oohaxC3bgL3suOKki68gaZiZMmIBx48YhISEBCQkJeO+999C6dWt8//33unN8fX0RERGh+wkJCZGxYiIiIvcTqfJDWOuWzZ73zwO5iF2ww+XWoXGZMTN1dXXYuHEjKisrkZSUpDuekZGBdu3aISEhAXPnzkVxcbGMVRIREbmn42+Nsvjc177McamWGkEURVHOAnJycpCUlIS7d++idevWWL9+PcaNGwcA2LRpE1q3bo2OHTsiLy8PixYtwv3793HixAn4+vqavF5NTQ1qamp0j8vLyxEdHW3RFuJERESezpYBv396shum9o2RtI7y8nKoVCqL7t+yh5na2loUFBSgrKwMmzdvxkcffYSDBw/ioYceMjpXrVajY8eO2LhxIyZPnmzyeosXL8Y777xjdJxhhoiIyDK2BJr2bVrhuwUjJKtBUWGmscceewzx8fH48MMPTT7fuXNn/Pa3v8Ubb7xh8nm2zBAREdlv6LL9uHq72qrXPNmrPf48rack729NmHGZMTNaoigahBF9t27dQmFhISIjI82+3tfXVzfVW/tDRERE1jn4ejK2pwxEe1Uri1/z5alrUGusC0BSkDXMLFy4EIcPH0Z+fj5ycnLw5ptvIiMjAzNmzMCdO3fw6quv4ujRo8jPz0dGRgYmTJiA0NBQPPHEE3KWTURE5BF6RAfju9QROJqajBD/5mc7AUB+SZWDqzLWwunvqOfGjRuYOXMm1Go1VCoVunfvjt27d2PkyJGorq5GTk4O/vWvf6GsrAyRkZEYPnw4Nm3ahMDAQDnLJiIi8iiRKj+c/H+jsO98EX679gTMjU/xAhAb6u/M0gC44JgZqVnT50ZERETN+yKrAO99/SPK7tbpjgkA0qd0w7R+0sxqsub+LWvLDBERESnP1L4xmNo3BmpNNU5eLYUoAn1igxGp8pOlHoYZIiIiskmkyg/ju8sTYPS53GwmIiIiImswzBAREZGiMcwQERGRojHMEBERkaIxzBAREZGiMcwQERGRojHMEBERkaIxzBAREZGiMcwQERGRojHMEBERkaIxzBAREZGiuf3eTNpNwcvLy2WuhIiIiCylvW9r7+NNcfswU1FRAQCIjo6WuRIiIiKyVkVFBVQqVZPnCKIlkUfB6uvrcf36dQQGBkIQBKe+d3l5OaKjo1FYWIigoCCnvjfx83cF/A7kx+9AfvwObCOKIioqKhAVFQUvr6ZHxbh9y4yXlxc6dOggaw1BQUH8BZYRP3/58TuQH78D+fE7sF5zLTJaHABMREREisYwQ0RERIrGMONAvr6+ePvtt+Hr6yt3KR6Jn7/8+B3Ij9+B/PgdOJ7bDwAmIiIi98aWGSIiIlI0hhkiIiJSNIYZIiIiUjSGGQf54IMPEBcXh1atWqFPnz44fPiw3CV5lEOHDmHChAmIioqCIAjYtm2b3CV5lLS0NPTr1w+BgYFo164dJk2ahIsXL8pdlkdZuXIlunfvrlvbJCkpCbt27ZK7LI+VlpYGQRDw0ksvyV2KW2KYcYBNmzbhpZdewptvvolTp07h0UcfxdixY1FQUCB3aR6jsrISPXr0wPLly+UuxSMdPHgQKSkp+P7777F3717cv38fo0aNQmVlpdyleYwOHTogPT0dWVlZyMrKQnJyMiZOnIhz587JXZrHOX78OFatWoXu3bvLXYrb4mwmB+jfvz969+6NlStX6o516dIFkyZNQlpamoyVeSZBELB161ZMmjRJ7lI81s2bN9GuXTscPHgQQ4YMkbscjxUSEoI//elPmDNnjtyleIw7d+6gd+/e+OCDD/Duu++iZ8+eeP/99+Uuy+2wZUZitbW1OHHiBEaNGmVwfNSoUcjMzJSpKiJ5aTQaAA03U3K+uro6bNy4EZWVlUhKSpK7HI+SkpKC8ePH47HHHpO7FLfm9nszOVtJSQnq6uoQHh5ucDw8PBxFRUUyVUUkH1EU8fLLL2Pw4MHo2rWr3OV4lJycHCQlJeHu3bto3bo1tm7dioceekjusjzGxo0bcfLkSRw/flzuUtwew4yDNN6hWxRFp+/aTeQK5s2bhzNnzuDIkSNyl+JxHnzwQWRnZ6OsrAybN2/GrFmzcPDgQQYaJygsLMQf/vAHfPPNN2jVqpXc5bg9hhmJhYaGwtvb26gVpri42Ki1hsjdzZ8/H1999RUOHTok++71nsjHxwedOnUCAPTt2xfHjx/H3//+d3z44YcyV+b+Tpw4geLiYvTp00d3rK6uDocOHcLy5ctRU1MDb29vGSt0LxwzIzEfHx/06dMHe/fuNTi+d+9eDBw4UKaqiJxLFEXMmzcPW7Zswf79+xEXFyd3SYSG76WmpkbuMjzCiBEjkJOTg+zsbN1P3759MWPGDGRnZzPISIwtMw7w8ssvY+bMmejbty+SkpKwatUqFBQU4Pnnn5e7NI9x584dXL58Wfc4Ly8P2dnZCAkJQUxMjIyVeYaUlBSsX78e27dvR2BgoK6lUqVSwc/PT+bqPMPChQsxduxYREdHo6KiAhs3bkRGRgZ2794td2keITAw0GiMWEBAANq2bcuxYw7AMOMA06ZNw61bt/DHP/4RarUaXbt2xc6dO9GxY0e5S/MYWVlZGD58uO7xyy+/DACYNWsWPv30U5mq8hzaZQmGDRtmcHzNmjWYPXu28wvyQDdu3MDMmTOhVquhUqnQvXt37N69GyNHjpS7NCLJcZ0ZIiIiUjSOmSEiIiJFY5ghIiIiRWOYISIiIkVjmCEiIiJFY5ghIiIiRWOYISIiIkVjmCEiIiJFY5ghIiIiRWOYIaImLV68GD179pS7DEURBAHbtm2Tuwwij8EwQ0Sy2bx5M7y9vVFQUGDy+cTERLz44otOrsr1DRs2DIIgQBAE+Pj4ID4+HqmpqdxEkjwWwwwRyeZXv/oV2rZti7Vr1xo999133+HixYuYM2eODJW5vrlz50KtVuPy5ctYtmwZVqxYgcWLF8tdFpEsGGaIFGTYsGGYP38+XnrpJQQHByM8PByrVq1CZWUlnn32WQQGBiI+Ph67du2y6Hqffvop2rRpY3Bs27ZtEATB6NwPP/wQ0dHR8Pf3x9SpU1FWVgYA2LNnD1q1aqV7rPXiiy9i6NChTb5/y5YtMXPmTHz66adovE3cJ598gj59+qBHjx4W/VtMycjIgCAI2LNnD3r16gU/Pz8kJyejuLgYu3btQpcuXRAUFIRf//rXqKqqsuiasbGxeP/99w2O9ezZ0yhIqNVqjB07Fn5+foiLi8MXX3yhey4pKQkLFiwwOP/mzZto2bIlDhw4YFEd/v7+iIiIQExMDKZMmYKRI0fim2++sei1RO6GYYZIYdauXYvQ0FD88MMPmD9/Pn7/+99j6tSpGDhwIE6ePInRo0dj5syZFt+cLXH58mV8/vnn+Pe//43du3cjOzsbKSkpAIDHHnsMbdq0webNm3Xn19XV4fPPP8eMGTOavfacOXNw5coVHDx4UHessrISn3/+uWStMosXL8by5cuRmZmJwsJCPPXUU3j//fexfv167NixA3v37sU///lPSd5La9GiRZgyZQpOnz6Np59+Gr/+9a9x/vx5AMCMGTOwYcMGgwC3adMmhIeHNxsATTl9+jS+++47tGzZUrL6iRRFJCLFGDp0qDh48GDd4/v374sBAQHizJkzdcfUarUIQDx69Giz11uzZo2oUqkMjm3dulXU/0/D22+/LXp7e4uFhYW6Y7t27RK9vLxEtVotiqIovvjii2JycrLu+T179og+Pj7i7du3Lfp39e/fX3zmmWd0jz/55BPRz89PLC0ttej15hw4cEAEIH777be6Y2lpaSIAMTc3V3fsueeeE0ePHm3RNTt27Cj+7W9/MzjWo0cP8e2339Y9BiA+//zzBuf0799f/P3vfy+KoigWFxeLLVq0EA8dOqR7PikpSXzttdcsqmHo0KFiy5YtxYCAANHHx0cEIHp5eYlffvmlRa8ncjdsmSFSmO7du+v+v7e3N9q2bYtu3brpjoWHhwMAiouLJXvPmJgYdOjQQfc4KSkJ9fX1uHjxIoCGloaMjAxcv34dAPDZZ59h3LhxCA4Otuj6c+bMwZdffomKigoADV1MkydPNuoC0yooKEDr1q11P0uWLGny+vqfWXh4OPz9/fHAAw8YHJPy8wIaPqPGj7UtM2FhYRg5ciQ+++wzAEBeXh6OHj1qUUuW1owZM5CdnY2jR4/iqaeewm9+8xtMmTJFun8AkYIwzBApTOOuBEEQDI5px7vU19c3ey0vLy+jsSr37t1r9nXa99D+7yOPPIL4+Hhs3LgR1dXV2Lp1K55++ulmr6P1X//1XxAEAZs2bcLly5dx5MiRJruYoqKikJ2drft5/vnnm7x+48/H1GdoyecF2P6Zad9Ha8aMGfjyyy9x7949rF+/Hg8//LBV44NUKhU6deqE3r17Y926dTh48CA+/vhji19P5E4YZog8WFhYGCoqKlBZWak7lp2dbXReQUGBrtUFAI4ePQovLy8kJCTojk2fPh2fffYZ/v3vf8PLywvjx4+3uI7AwEBMnToVa9aswSeffIIHHngAw4YNM3t+ixYt0KlTJ91PSEiIxe9lr7CwMKjVat3j8vJy5OXlGZ33/fffGz1OTEzUPZ40aRLu3r2L3bt3Y/369VaFv8ZatmyJhQsX4q233pJ0rBSRUjDMEHmw/v37w9/fHwsXLsTly5exfv16fPrpp0bntWrVCrNmzcLp06dx+PBhvPjii3jqqacQERGhO2fGjBk4efIk3nvvPTz55JNo1aqVVbXMmTMHmZmZWLlyJX7zm9+YnFHlCpKTk/F///d/OHz4MM6ePYtZs2bB29vb6LwvvvgCn3zyCX766Se8/fbb+OGHHzBv3jzd8wEBAZg4cSIWLVqE8+fPY/r06XbVNX36dAiCgA8++MCu6xApEcMMkQcLCQnBunXrsHPnTnTr1g0bNmwwuVZJp06dMHnyZIwbNw6jRo1C165djW6anTt3Rr9+/XDmzBmrxn5oDR48GA8++CDKy8sxa9YsW/9JDpeamoohQ4bg8ccfx7hx4zBp0iTEx8cbnffOO+9g48aN6N69O9auXYvPPvsMDz30kME5M2bMwOnTp/Hoo48iJibGrrp8fHwwb948LFu2DHfu3LHrWkRKI4iNO3+JiIiIFIQtM0RERKRoDDNEbuz55583mMKs/9PcDCCpjB071mwNzU2pdrbGU74b/5jbQ0pKhw8fbrIGIjLGbiYiN1ZcXIzy8nKTzwUFBaFdu3YOr+HatWuorq42+VxISIhTZyI15/79+8jPzzf7fGxsLFq0aOHQGqqrq3Ht2jWzz3fq1Mmh70+kRAwzREREpGjsZiIiIiJFY5ghIiIiRWOYISIiIkVjmCEiIiJFY5ghIiIiRWOYISIiIkVjmCEiIiJFY5ghIiIiRfv/XhHs74dEoOwAAAAASUVORK5CYII=", "text/plain": [ "
" ] @@ -278,7 +2079,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 8, "id": "77389803-b5ab-408d-a825-68c2ac30c131", "metadata": {}, "outputs": [ @@ -288,13 +2089,13 @@ "Text(0.5, 1.0, 'Singles Only')" ] }, - "execution_count": 11, + "execution_count": 8, "metadata": {}, "output_type": "execute_result" }, { "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjMAAAHFCAYAAAAHcXhbAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAABTrklEQVR4nO3deVhU9f4H8PcBAQeEEQRhTLZQRAPcU6xEMRe00jSzXNIys3KpW7ebmP7UFkHbb5q3umV2yzW3e3PLUtFEDTUUTUwNhHQQURgQBxA4vz+MiWVmmBlm5szyfj3PPDnnnDnzYeRx3n1XQRRFEURERER2ykXqAoiIiIiag2GGiIiI7BrDDBEREdk1hhkiIiKyawwzREREZNcYZoiIiMiuMcwQERGRXWOYISIiIrvGMENERER2jWGGyEkdOXIEDz/8MEJCQuDh4YHAwEDExcXh5ZdfrnfdgAEDMGDAAIvXIwgCFi5caPH3aejatWtISkpCly5d4OnpCR8fH/Tt2xfLly/HrVu3TL7vwoULIQiCGSslIl1aSF0AEVnftm3b8NBDD2HAgAFYunQpFAoFlEoljh49irVr1+Ldd9/VXPvxxx9LWKllZWVlYciQIbhx4wZefvll9OvXD2q1Gt999x1eeOEFbNiwAdu3b4enp6fUpRKRHgwzRE5o6dKlCA8Px65du9CixV//DDz22GNYunRpvWu7dOli7fKsorq6GmPGjEFJSQl+/vlnREZGas4NHz4c8fHxeOyxx/DSSy/hX//6l4SVElFT2M1E5ISuXbsGf3//ekGmlotL/X8WGnYz5eTkQBAEvPPOO3jvvfcQHh6OVq1aIS4uDocPH250v88++wyRkZHw8PBAly5dsHr1akyZMgVhYWFN1pmfn4/p06ejffv2cHd3R3h4OBYtWoSqqqp6161YsQJdu3ZFq1at4O3tjaioKMydO1fvvTdv3oxff/0Vc+bMqRdkao0bNw5DhgzB559/jvz8fJN+9rqmTp0KPz8/3Lx5s9G5hIQE3HXXXU19HESkA8MMkROKi4vDkSNHMHv2bBw5csSksSHLly/H7t278cEHH+Cbb75BWVkZhg8fDpVKpbnm008/xTPPPIPY2Fhs2rQJ8+bNw6JFi7Bv374m75+fn4+7774bu3btwv/93/9hx44dmDp1KpKTkzFt2jTNdWvXrsXzzz+P+Ph4bN68GVu2bMHf/vY3lJWV6b3/7t27AQCjRo3Sec2oUaNQVVXVqF5DfvaGXnjhBRQVFWH16tX1jv/666/Yu3cvZsyYobdeItJDJCKnU1hYKN57770iABGA6ObmJvbr109MTk4WS0tL610bHx8vxsfHa55nZ2eLAMSYmBixqqpKc/znn38WAYhr1qwRRVEUq6urxaCgILFPnz717nfx4kXRzc1NDA0NrXccgLhgwQLN8+nTp4utWrUSL168WO+6d955RwQgnj59WhRFUZw5c6bYunVroz+DYcOGiQDE8vJyndfs2LFDBCAuWbLEqJ9dFEVxwYIFYsN/YuPj48Vu3brVO/bcc8+JPj4+jT53IjIcW2aInFCbNm1w4MABpKenIyUlBSNHjsRvv/2GpKQkxMTEoLCwsMl7jBgxAq6urprnsbGxAICLFy8CAM6ePYv8/Hw8+uij9V4XEhKCe+65p8n7f/fddxg4cCDatWuHqqoqzSMxMREAkJqaCgC4++67UVxcjMcffxxbt241qHZDiaIIAI1mJTX1s+vywgsvICMjAwcPHgQAlJSU4D//+Q8mT56MVq1ama1uImfDMEPkxHr16oVXX30VGzZswOXLl/G3v/0NOTk5jQYBa9OmTZt6zz08PAAAarUawO1xOQAQGBjY6LXajjV05coV/O9//4Obm1u9R+3YktrQMmnSJHzxxRe4ePEixowZg7Zt26JPnz6abiRdQkJCAADZ2dk6r8nJyQEABAcH1zve1M+uy8iRIxEWFobly5cDAL788kuUlZWxi4momRhmiAgA4ObmhgULFgAATp061ez71X7hX7lypdG52gG1+vj7+2PIkCFIT0/X+pg6darm2ieffBJpaWlQqVTYtm0bRFHEAw88oLelZPDgwQCALVu26Lxmy5YtaNGihdnW2XFxccGMGTPw7bffQqlU4uOPP8agQYPQqVMns9yfyFkxzBA5IaVSqfX4mTNnAADt2rVr9nt06tQJQUFBWL9+fb3jubm5SEtLa/L1DzzwAE6dOoWIiAj06tWr0UNbjV5eXkhMTMRrr72GyspKnD59Wuf9H374YXTp0gUpKSn47bffGp1ft24dvv/+ezz99NMICgoy4Cc2zNNPPw13d3dMmDABZ8+excyZM812byJnxXVmiJzQ0KFD0b59ezz44IOIiopCTU0NMjIy8O6776JVq1Z4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", + "image/png": "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", "text/plain": [ "
" ] @@ -321,7 +2122,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 9, "id": "594beb18-cdee-4cc4-8d4b-64848ce4700e", "metadata": {}, "outputs": [ @@ -331,13 +2132,13 @@ "Text(0.5, 0, 'log(a) [AU]')" ] }, - "execution_count": 12, + "execution_count": 9, "metadata": {}, "output_type": "execute_result" }, { "data": { - "image/png": "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", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAigAAAGwCAYAAACD0J42AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAhiklEQVR4nO3de1TUdf7H8dcEMorCJIIzkqhsUVYY62KZbKWmYqip2UnbbljWal5OrJpp/pFum5hb6KZpNw+aN9w9u5ZHrRVPXnPdgM1St1otSUuIVAIkGhS/vz/2NL+dUGOU4fsBno9z5hznO5+Zec+cTZ/7mZvDsixLAAAABrnM7gEAAAB+ikABAADGIVAAAIBxCBQAAGAcAgUAABiHQAEAAMYhUAAAgHFC7R7gYpw9e1bHjh1TRESEHA6H3eMAAIA6sCxLFRUVio2N1WWXXXiPpFEGyrFjxxQXF2f3GAAA4CIcPXpUHTt2vOCaRhkoERERkv77ACMjI22eBgAA1EV5ebni4uJ8/45fSKMMlB9f1omMjCRQAABoZOry9gzeJAsAAIxDoAAAAOMQKAAAwDgECgAAMA6BAgAAjEOgAAAA4xAoAADAOAQKAAAwDoECAACMQ6AAAADjECgAAMA4BAoAADAOgQIAAIxDoAAAAOMQKAAAwDihdg8ANCZdpm+s89rCuYODOAkANG3soAAAAOMQKAAAwDgECgAAMA6BAgAAjEOgAAAA4xAoAADAOAQKAAAwDoECAACMQ6AAAADjECgAAMA4BAoAADAOgQIAAIxDoAAAAOMQKAAAwDgECgAAMA6BAgAAjEOgAAAA4xAoAADAOAQKAAAwDoECAACMQ6AAAADjECgAAMA4BAoAADAOgQIAAIxDoAAAAOMQKAAAwDgECgAAMA6BAgAAjEOgAAAA4xAoAADAOAQKAAAwDoECAACMQ6AAAADjBBQomZmZuvHGGxUREaH27dtr+PDh+uyzz/zWWJalWbNmKTY2Vq1atVKfPn104MABvzVer1eTJk1SdHS0WrduraFDh+qrr7669EcDAACahIACZfv27ZowYYL27Nmj3NxcnTlzRqmpqaqsrPStmTdvnrKysrRo0SLl5eXJ4/FowIABqqio8K3JyMjQunXrlJOTo127dunUqVMaMmSIampq6u+RAQCARsthWZZ1sVf+9ttv1b59e23fvl233XabLMtSbGysMjIy9NRTT0n6726J2+3W888/r7Fjx6qsrEwxMTFasWKFRo0aJUk6duyY4uLitGnTJg0cOLDW/Xi9Xnm9Xt/58vJyxcXFqaysTJGRkRc7PhCwLtM31nlt4dzBQZwEABqf8vJyuVyuOv37HXopd1RWViZJioqKkiQdPnxYxcXFSk1N9a1xOp3q3bu3du/erbFjx6qgoECnT5/2WxMbG6vExETt3r37nIGSmZmp2bNnX8qoQIMLJGYkggYA/tdFv0nWsixNnjxZt9xyixITEyVJxcXFkiS32+231u12+y4rLi5WWFiY2rZte941PzVjxgyVlZX5TkePHr3YsQEAQCNw0TsoEydO1Mcff6xdu3bVuszhcPidtyyr1rGfutAap9Mpp9N5saMCAIBG5qJ2UCZNmqT169dr69at6tixo++4x+ORpFo7ISUlJb5dFY/Ho+rqapWWlp53DQAAaN4CChTLsjRx4kT97W9/03vvvaf4+Hi/y+Pj4+XxeJSbm+s7Vl1dre3btyslJUWSlJycrBYtWvitKSoq0v79+31rAABA8xbQSzwTJkzQ6tWr9fbbbysiIsK3U+JyudSqVSs5HA5lZGRozpw5SkhIUEJCgubMmaPw8HDdd999vrVjxozRlClT1K5dO0VFRWnq1Knq1q2b+vfvX/+PEAAANDoBBcqSJUskSX369PE7np2drdGjR0uSpk2bpqqqKo0fP16lpaXq2bOnNm/erIiICN/6+fPnKzQ0VCNHjlRVVZX69eunZcuWKSQk5NIeDQAAaBIu6XtQ7BLI56iB+hToR4cDwceMATR1gfz7zW/xAAAA4xAoAADAOAQKAAAwDoECAACMQ6AAAADjECgAAMA4BAoAADAOgQIAAIxDoAAAAOMQKAAAwDgECgAAMA6BAgAAjEOgAAAA4xAoAADAOAQKAAAwDoECAACMQ6AAAADjECgAAMA4BAoAADAOgQIAAIxDoAAAAOOE2j0AgP/qMn1jndcWzh0cxEkAwH7soAAAAOMQKAAAwDgECgAAMA6BAgAAjEOgAAAA4xAoAADAOAQKAAAwDoECAACMQ6AAAADjECgAAMA4BAoAADAOgQIAAIxDoAAAAOMQKAAAwDgECgAAMA6BAgAAjEOgAAAA4xAoAADAOAQKAAAwDoECAACMQ6AAAADjECgAAMA4oXYPACBwXaZvrPPawrmDgzgJAAQHOygAAMA4BAoAADAOgQIAAIxDoAAAAOMQKAAAwDgECgAAMA6BAgAAjMP3oKDZC+Q7RQAADYMdFAAAYBwCBQAAGIdAAQAAxiFQAACAcQgUAABgHAIFAAAYh0ABAADGIVAAAIBxCBQAAGAcAgUAABiHQAEAAMYhUAAAgHEIFAAAYBx+zRho4gL9tebCuYODNAkA1F3AOyg7duzQnXfeqdjYWDkcDr311lt+l48ePVoOh8PvdPPNN/ut8Xq9mjRpkqKjo9W6dWsNHTpUX3311SU9EAAA0HQEHCiVlZVKSkrSokWLzrvmjjvuUFFRke+0adMmv8szMjK0bt065eTkaNeuXTp16pSGDBmimpqawB8BAABocgJ+iSctLU1paWkXXON0OuXxeM55WVlZmZYuXaoVK1aof//+kqSVK1cqLi5OW7Zs0cCBAwMdCQAANDFBeZPstm3b1L59e1199dV67LHHVFJS4rusoKBAp0+fVmpqqu9YbGysEhMTtXv37nPentfrVXl5ud8JAAA0XfUeKGlpaVq1apXee+89vfjii8rLy9Ptt98ur9crSSouLlZYWJjatm3rdz23263i4uJz3mZmZqZcLpfvFBcXV99jAwAAg9T7p3hGjRrl+3NiYqJ69Oihzp07a+PGjRoxYsR5r2dZlhwOxzkvmzFjhiZPnuw7X15eTqQAANCEBf17UDp06KDOnTvr4MGDkiSPx6Pq6mqVlpb6rSspKZHb7T7nbTidTkVGRvqdAABA0xX0QDlx4oSOHj2qDh06SJKSk5PVokUL5ebm+tYUFRVp//79SklJCfY4AACgEQj4JZ5Tp07p0KFDvvOHDx/W3r17FRUVpaioKM2aNUt33323OnTooMLCQj399NOKjo7WXXfdJUlyuVwaM2aMpkyZonbt2ikqKkpTp05Vt27dfJ/qAQAAzVvAgZKfn6++ffv6zv/43pD09HQtWbJE+/bt05tvvqnvvvtOHTp0UN++fbV27VpFRET4rjN//nyFhoZq5MiRqqqqUr9+/bRs2TKFhITUw0MCAACNncOyLMvuIQJVXl4ul8ulsrIy3o+CSxboV8E3dXzVPYBgCeTfb34sEAAAGIcfCwTgJ5AdJXZbAAQLOygAAMA4BAoAADAOgQIAAIxDoAAAAOMQKAAAwDgECgAAMA6BAgAAjEOgAAAA4xAoAADAOAQKAAAwDoECAACMQ6AAAADjECgAAMA4BAoAADAOgQIAAIwTavcAAJqHLtM31nlt4dzBQZwEQGPADgoAADAOgQIAAIxDoAAAAOMQKAAAwDgECgAAMA6f4gFw0QL5ZA4ABIIdFAAAYBwCBQAAGIdAAQAAxiFQAACAcQgUAABgHAIFAAAYh0ABAADG4XtQABgn0O9X4dePgaaHHRQAAGAcAgUAABiHQAEAAMYhUAAAgHEIFAAAYBwCBQAAGIdAAQAAxiFQAACAcQgUAABgHAIFAAAYh0ABAADGIVAAAIBxCBQAAGAcAgUAABiHQAEAAMYhUAAAgHEIFAAAYBwCBQAAGIdAAQAAxiFQAACAcQgUAABgHAIFAAAYh0ABAADGIVAAAIBxCBQAAGAcAgUAABiHQAEAAMYhUAAAgHEIFAAAYBwCBQAAGIdAAQAAxiFQAACAcQgUAABgHAIFAAAYh0ABAADGIVAAAIBxQgO9wo4dO/THP/5RBQUFKioq0rp16zR8+HDf5ZZlafbs2XrttddUWlqqnj176uWXX9b111/vW+P1ejV16lStWbNGVVVV6tevnxYvXqyOHTvWy4MC0Lx0mb6xzmsL5w4O4iQA6kvAOyiVlZVKSkrSokWLznn5vHnzlJWVpUWLFikvL08ej0cDBgxQRUWFb01GRobWrVunnJwc7dq1S6dOndKQIUNUU1Nz8Y8EAAA0GQHvoKSlpSktLe2cl1mWpQULFmjmzJkaMWKEJGn58uVyu91avXq1xo4dq7KyMi1dulQrVqxQ//79JUkrV65UXFyctmzZooEDB17CwwEAAE1Bvb4H5fDhwyouLlZqaqrvmNPpVO/evbV7925JUkFBgU6fPu23JjY2VomJib41P+X1elVeXu53AgAATVfAOygXUlxcLElyu91+x91ut7788kvfmrCwMLVt27bWmh+v/1OZmZmaPXt2fY6KJi6Q9ySgeeH9KkDjEJRP8TgcDr/zlmXVOvZTF1ozY8YMlZWV+U5Hjx6tt1kBAIB56jVQPB6PJNXaCSkpKfHtqng8HlVXV6u0tPS8a37K6XQqMjLS7wQAAJqueg2U+Ph4eTwe5ebm+o5VV1dr+/btSklJkSQlJyerRYsWfmuKioq0f/9+3xoAANC8BfwelFOnTunQoUO+84cPH9bevXsVFRWlTp06KSMjQ3PmzFFCQoISEhI0Z84chYeH67777pMkuVwujRkzRlOmTFG7du0UFRWlqVOnqlu3br5P9QAAgOYt4EDJz89X3759fecnT54sSUpPT9eyZcs0bdo0VVVVafz48b4vatu8ebMiIiJ815k/f75CQ0M1cuRI3xe1LVu2TCEhIfXwkAAAQGPnsCzLsnuIQJWXl8vlcqmsrIz3o+Cc+BQP6gOf4gHqVyD/fvNbPAAAwDgECgAAMA6BAgAAjEOgAAAA4xAoAADAOAQKAAAwDoECAACMQ6AAAADjECgAAMA4BAoAADAOgQIAAIxDoAAAAOMQKAAAwDgECgAAMA6BAgAAjBNq9wAA0Bx1mb6xzmsL5w4O4iSAmdhBAQAAxiFQAACAcQgUAABgHAIFAAAYh0ABAADGIVAAAIBxCBQAAGAcAgUAABiHQAEAAMYhUAAAgHEIFAAAYBx+iwcAzoPfywHsww4KAAAwDoECAACMQ6AAAADjECgAAMA4BAoAADAOgQIAAIxDoAAAAOMQKAAAwDgECgAAMA6BAgAAjEOgAAAA4xAoAADAOPxYIBqFQH60DQDQ+LGDAgAAjEOgAAAA4xAoAADAOAQKAAAwDoECAACMw6d4AKAe8EkzoH6xgwIAAIxDoAAAAOMQKAAAwDgECgAAMA6BAgAAjEOgAAAA4xAoAADAOAQKAAAwDoECAACMQ6AAAADjECgAAMA4BAoAADAOgQIAAIzDrxkDgOGC+UvJhXMHB2WOQG4XOBd2UAAAgHEIFAAAYBxe4gEA1DteDsKlYgcFAAAYh0ABAADG4SUe1Cu2dQEA9YEdFAAAYJx6D5RZs2bJ4XD4nTwej+9yy7I0a9YsxcbGqlWrVurTp48OHDhQ32MAAIBGLCg7KNdff72Kiop8p3379vkumzdvnrKysrRo0SLl5eXJ4/FowIABqqioCMYoAACgEQrKe1BCQ0P9dk1+ZFmWFixYoJkzZ2rEiBGSpOXLl8vtdmv16tUaO3bsOW/P6/XK6/X6zpeXlwdjbAAAYIig7KAcPHhQsbGxio+P17333qsvvvhCknT48GEVFxcrNTXVt9bpdKp3797avXv3eW8vMzNTLpfLd4qLiwvG2AAAwBD1Hig9e/bUm2++qb///e96/fXXVVxcrJSUFJ04cULFxcWSJLfb7Xcdt9vtu+xcZsyYobKyMt/p6NGj9T02AAAwSL2/xJOWlub7c7du3dSrVy9deeWVWr58uW6++WZJksPh8LuOZVm1jv0vp9Mpp9NZ36MCAABDBf17UFq3bq1u3brp4MGDGj58uCSpuLhYHTp08K0pKSmptasCAGgeAv21Zr5DqXkI+vegeL1effLJJ+rQoYPi4+Pl8XiUm5vru7y6ulrbt29XSkpKsEcBAACNRL3voEydOlV33nmnOnXqpJKSEv3hD39QeXm50tPT5XA4lJGRoTlz5ighIUEJCQmaM2eOwsPDdd9999X3KACAnxHo7gXQUOo9UL766iv95je/0fHjxxUTE6Obb75Ze/bsUefOnSVJ06ZNU1VVlcaPH6/S0lL17NlTmzdvVkRERH2PAgAAGql6D5ScnJwLXu5wODRr1izNmjWrvu8aAAA0EfwWDwAAMA6BAgAAjEOgAAAA4xAoAADAOAQKAAAwTtC/SRY4H75/AUCwBfL3TCDfUMu33wYfgQIAgPg/TabhJR4AAGAcAgUAABiHQAEAAMYhUAAAgHEIFAAAYBwCBQAAGIePGQMAGhU+Dtw8sIMCAACMQ6AAAADj8BIPfhbbqQCAhsYOCgAAMA6BAgAAjEOgAAAA4xAoAADAOAQKAAAwDoECAACMQ6AAAADjECgAAMA4BAoAADAOgQIAAIxDoAAAAOMQKAAAwDgECgAAMA6BAgAAjEOgAAAA4xAoAADAOAQKAAAwDoECAACMQ6AAAADjhNo9ABpel+kb7R4BAIALYgcFAAAYhx0UAACCLJCd68K5g4M4SePBDgoAADAOgQIAAIzDSzwAABiEl4P+ix0UAABgHAIFAAAYh5d4LhFbcQAA1D92UAAAgHEIFAAAYBxe4mki+Pp6AEBTwg4KAAAwDoECAACMQ6AAAADjECgAAMA4BAoAADAOgQIAAIxDoAAAAOPwPSgAADRSgX4HVmP6yRV2UAAAgHHYQTkHvpUVANAUNaYfuCVQDEYoAQCaK17iAQAAxiFQAACAcQgUAABgHAIFAAAYhzfJNiDe9AoAQN2wgwIAAIxDoAAAAOMQKAAAwDi2BsrixYsVHx+vli1bKjk5WTt37rRzHAAAYAjbAmXt2rXKyMjQzJkz9eGHH+rWW29VWlqajhw5YtdIAADAELYFSlZWlsaMGaNHH31U1157rRYsWKC4uDgtWbLErpEAAIAhbPmYcXV1tQoKCjR9+nS/46mpqdq9e3et9V6vV16v13e+rKxMklReXh6U+c56vw/K7QIA0FgE49/YH2/TsqyfXWtLoBw/flw1NTVyu91+x91ut4qLi2utz8zM1OzZs2sdj4uLC9qMAAA0Z64FwbvtiooKuVyuC66x9YvaHA6H33nLsmodk6QZM2Zo8uTJvvNnz57VyZMn1a5du3Ouby7Ky8sVFxeno0ePKjIy0u5xbMfzURvPiT+eD388H7XxnPir7+fDsixVVFQoNjb2Z9faEijR0dEKCQmptVtSUlJSa1dFkpxOp5xOp9+xyy+/PJgjNiqRkZH8h/Q/eD5q4znxx/Phj+ejNp4Tf/X5fPzczsmPbHmTbFhYmJKTk5Wbm+t3PDc3VykpKXaMBAAADGLbSzyTJ0/Wgw8+qB49eqhXr1567bXXdOTIEY0bN86ukQAAgCFsC5RRo0bpxIkT+v3vf6+ioiIlJiZq06ZN6ty5s10jNTpOp1PPPPNMrZe/miuej9p4TvzxfPjj+aiN58Sfnc+Hw6rLZ30AAAAaEL/FAwAAjEOgAAAA4xAoAADAOAQKAAAwDoHSBBQWFmrMmDGKj49Xq1atdOWVV+qZZ55RdXW13aPZ6rnnnlNKSorCw8Ob5Rf7LV68WPHx8WrZsqWSk5O1c+dOu0eyzY4dO3TnnXcqNjZWDodDb731lt0j2SozM1M33nijIiIi1L59ew0fPlyfffaZ3WPZZsmSJbrhhht8X0bWq1cvvfPOO3aPZYzMzEw5HA5lZGQ06P0SKE3Ap59+qrNnz+rVV1/VgQMHNH/+fL3yyit6+umn7R7NVtXV1brnnnv0+OOP2z1Kg1u7dq0yMjI0c+ZMffjhh7r11luVlpamI0eO2D2aLSorK5WUlKRFixbZPYoRtm/frgkTJmjPnj3Kzc3VmTNnlJqaqsrKSrtHs0XHjh01d+5c5efnKz8/X7fffruGDRumAwcO2D2a7fLy8vTaa6/phhtuaPg7t9AkzZs3z4qPj7d7DCNkZ2dbLpfL7jEa1E033WSNGzfO71jXrl2t6dOn2zSROSRZ69ats3sMo5SUlFiSrO3bt9s9ijHatm1rvfHGG3aPYauKigorISHBys3NtXr37m098cQTDXr/7KA0UWVlZYqKirJ7DNigurpaBQUFSk1N9Tuempqq3bt32zQVTFZWViZJ/J0hqaamRjk5OaqsrFSvXr3sHsdWEyZM0ODBg9W/f39b7t/WXzNGcHz++edauHChXnzxRbtHgQ2OHz+umpqaWj+86Xa7a/1AJ2BZliZPnqxbbrlFiYmJdo9jm3379qlXr1764Ycf1KZNG61bt07XXXed3WPZJicnR//617+Ul5dn2wzsoBhs1qxZcjgcFzzl5+f7XefYsWO64447dM899+jRRx+1afLguZjnpLlyOBx+5y3LqnUMmDhxoj7++GOtWbPG7lFsdc0112jv3r3as2ePHn/8caWnp+vf//633WPZ4ujRo3riiSe0cuVKtWzZ0rY52EEx2MSJE3XvvfdecE2XLl18fz527Jj69u3r+/HFpijQ56Q5io6OVkhISK3dkpKSklq7KmjeJk2apPXr12vHjh3q2LGj3ePYKiwsTFdddZUkqUePHsrLy9Of/vQnvfrqqzZP1vAKCgpUUlKi5ORk37Gamhrt2LFDixYtktfrVUhISNDnIFAMFh0drejo6Dqt/frrr9W3b18lJycrOztbl13WNDfHAnlOmquwsDAlJycrNzdXd911l+94bm6uhg0bZuNkMIVlWZo0aZLWrVunbdu2KT4+3u6RjGNZlrxer91j2KJfv37at2+f37GHH35YXbt21VNPPdUgcSIRKE3CsWPH1KdPH3Xq1EkvvPCCvv32W99lHo/HxsnsdeTIEZ08eVJHjhxRTU2N9u7dK0m66qqr1KZNG3uHC7LJkyfrwQcfVI8ePXw7akeOHNG4cePsHs0Wp06d0qFDh3znDx8+rL179yoqKkqdOnWycTJ7TJgwQatXr9bbb7+tiIgI326by+VSq1atbJ6u4T399NNKS0tTXFycKioqlJOTo23btundd9+1ezRbRERE1Ho/UuvWrdWuXbuGfZ9Sg35mCEGRnZ1tSTrnqTlLT08/53OydetWu0drEC+//LLVuXNnKywszPrVr37VrD9CunXr1nP+byE9Pd3u0Wxxvr8vsrOz7R7NFo888ojvv5WYmBirX79+1ubNm+0eyyh2fMzYYVmW1XA5BAAA8POa5hsVAABAo0agAAAA4xAoAADAOAQKAAAwDoECAACMQ6AAAADjECgAAMA4BAoAADAOgQI0c3369FFGRkZQbvu2227T6tWr67x+w4YN6t69u86ePXvBdaNHj/b9evVbb711iVOe27Zt23z3MXz48KDcB4DzI1AABMWGDRtUXFz8s78+/b+GDBkih8NRp6i54447VFRUpLS0tFqX/fa3v1VISIhycnJqXTZ69OhzBsfevXvlcDhUWFgoSUpJSVFRUZFGjhxZ5/kB1B8CBUBQvPTSS3r44YcD/mXthx9+WAsXLvzZdU6nUx6PR06n0+/4999/r7Vr1+rJJ5/U0qVLA7rv/xUWFiaPx9MsfzwPMAGBAsBPaWmpHnroIbVt21bh4eFKS0vTwYMH/da8/vrriouLU3h4uO666y5lZWXp8ssv911+/PhxbdmyRUOHDvW7XlZWlrp166bWrVsrLi5O48eP16lTp/zWDB06VB988IG++OKLi5r/L3/5i6677jrNmDFD77//vm9HBEDjQqAA8DN69Gjl5+dr/fr1+sc//iHLsjRo0CCdPn1akvT+++9r3LhxeuKJJ7R3714NGDBAzz33nN9t7Nq1S+Hh4br22mv9jl922WV66aWXtH//fi1fvlzvvfeepk2b5remc+fOat++vXbu3HlR8y9dulQPPPCAXC6XBg0apOzs7Iu6HQD2IlAA+Bw8eFDr16/XG2+8oVtvvVVJSUlatWqVvv76a9+bURcuXKi0tDRNnTpVV199tcaPH1/rfSCFhYVyu921Xt7JyMhQ3759FR8fr9tvv13PPvus/vznP9ea44orrrionY+DBw9qz549GjVqlCTpgQceUHZ29s++6RaAeQgUAD6ffPKJQkND1bNnT9+xdu3a6ZprrtEnn3wiSfrss8900003+V3vp+erqqrUsmXLWre/detWDRgwQFdccYUiIiL00EMP6cSJE6qsrPRb16pVK33//fcBz7906VINHDhQ0dHRkqRBgwapsrJSW7ZsCfi2ANiLQAHgY1nWeY87HI5afz7f9aKjo1VaWup37Msvv9SgQYOUmJiov/71ryooKNDLL78sSb6Xj3508uRJxcTEBDR7TU2N3nzzTW3cuFGhoaEKDQ1VeHi4Tp486fdm2cjISJWVldW6/nfffSdJcrlcAd0vgOAItXsAAOa47rrrdObMGf3zn/9USkqKJOnEiRP6z3/+43s/SdeuXfXBBx/4XS8/P9/vfPfu3VVcXKzS0lK1bdvWt+bMmTN68cUXfS/9nOvlnR9++EGff/65unfvHtDsmzZtUkVFhT788EOFhIT4jn/66ae6//77deLECbVr105du3bVmjVr9MMPP/jt8uTl5SkmJsY3LwB7sYMCwCchIUHDhg3TY489pl27dumjjz7SAw88oCuuuELDhg2TJE2aNEmbNm1SVlaWDh48qFdffVXvvPOO365K9+7dFRMTo/fff9937Morr9SZM2e0cOFCffHFF1qxYoVeeeWVWjPs2bNHTqdTvXr1Cmj2pUuXavDgwUpKSlJiYqLvdPfddysmJkYrV66UJN1///0KDQ3Vgw8+qPz8fH3++edauXKlMjMz9eSTT17M0wYgCAgUAH6ys7OVnJysIUOGqFevXrIsS5s2bVKLFi0kSb/+9a/1yiuvKCsrS0lJSXr33Xf1u9/9zm83IiQkRI888ohWrVrlO/bLX/5SWVlZev7555WYmKhVq1YpMzOz1v2vWbNG999/v8LDw+s88zfffKONGzfq7rvvrnWZw+HQiBEjfC/zuFwu7dy5U5Zlafjw4UpKStK8efP07LPPasqUKXW+TwDB5bDO96IzANTRY489pk8//dTvo8HffPONrr/+ehUUFKhz5851up1vv/1WXbt2VX5+vuLj48+7bvTo0fruu++C9jX3dt0XgP/HDgqAgL3wwgv66KOPdOjQIS1cuFDLly9Xenq63xq3262lS5fqyJEjdb7dw4cPa/HixReMkx9t2LBBbdq00YYNGwKevy527typNm3a+O0CAWg47KAACNjIkSO1bds2VVRU6Be/+IUmTZqkcePGNdj9l5SUqLy8XJLUoUMHtW7dut7vo6qqSl9//bUkqU2bNvJ4PPV+HwDOj0ABAADG4SUeAABgHAIFAAAYh0ABAADGIVAAAIBxCBQAAGAcAgUAABiHQAEAAMYhUAAAgHH+D6SgIATCuVEQAAAAAElFTkSuQmCC", "text/plain": [ "
" ] @@ -361,7 +2162,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 10, "id": "cf7ede5c-417f-4342-8e6a-3b9efae1e43e", "metadata": {}, "outputs": [ @@ -371,13 +2172,13 @@ "Text(0, 0.5, 'N objects')" ] }, - "execution_count": 13, + "execution_count": 10, "metadata": {}, "output_type": "execute_result" }, { "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjoAAAGwCAYAAACgi8/jAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAxFElEQVR4nO3deVjVZd7H8c8RFTfEBUVRRMslCVdcHs01DcNyGVvUzG3UxjSTKLessXxsqJmprAktnUazGvFqSiuzekhNLVxRSmMsbSjIjUdTcClQuJ8/ejzTGUBBDpzDfd6v6zrX1e/+3ef+fX+3KJ9+q8MYYwQAAGChSp4uAAAAoKwQdAAAgLUIOgAAwFoEHQAAYC2CDgAAsBZBBwAAWIugAwAArFXZ0wV4Wn5+vo4ePaqAgAA5HA5PlwMAAIrBGKOzZ88qJCRElSoVfdzG54PO0aNHFRoa6ukyAADANcjIyFDTpk2LXO/zQScgIEDSLxNVu3ZtD1cDAACKIzs7W6Ghoc7f40Xx+aBz+XRV7dq1CToAAFQwV7vshIuRAQCAtQg6AADAWgQdAABgLYIOAACwFkEHAABYi6ADAACsRdABAADWIugAAABrEXQAAIC1CDoAAMBaPht04uPjFR4erq5du3q6FAAAUEYcxhjj6SI8KTs7W4GBgcrKyuJdVwAAVBDF/f3ts0d0AACA/Qg6AADAWpU9XYDNms/94Kp9vnv6tnKoBAAA38QRHQAAYC2CDgAAsBZBBwAAWIugAwAArEXQAQAA1iLoAAAAaxF0AACAtQg6AADAWgQdAABgLYIOAACwFkEHAABYi6ADAACsRdABAADWIugAAABrWRN0Lly4oLCwMD3yyCOeLgUAAHgJa4LOU089pe7du3u6DAAA4EWsCDqHDh3SwYMHNXjwYE+XAgAAvIjHg87WrVs1ZMgQhYSEyOFwaN26dQX6LFmyRC1atFC1atUUGRmpbdu2uax/5JFHFBcXV04VAwCAisLjQef8+fPq0KGDXnrppULXr1mzRjExMZo/f7727dun3r17Kzo6Wunp6ZKkd999V61bt1br1q2Ltb2cnBxlZ2e7fAAAgJ0qe7qA6OhoRUdHF7n+ueee06RJkzR58mRJ0uLFi/Xxxx9r6dKliouL044dO5SQkKC33npL586d08WLF1W7dm39/ve/L3S8uLg4Pfnkk2WyLwAAwLt4/IjOleTm5io5OVlRUVEu7VFRUUpKSpL0S3DJyMjQd999pz//+c+aMmVKkSFHkubNm6esrCznJyMjo0z3AQAAeI7Hj+hcycmTJ5WXl6fg4GCX9uDgYB0/fvyaxvT395e/v787ygMAAF7Oq4POZQ6Hw2XZGFOgTZImTJhQThUBAICKwKtPXQUFBcnPz6/A0ZvMzMwCR3lKKj4+XuHh4eratWupxgEAAN7Lq4NO1apVFRkZqcTERJf2xMRE9ezZs1RjT58+Xampqdq9e3epxgEAAN7L46euzp07p8OHDzuX09LSlJKSonr16qlZs2aKjY3V2LFj1aVLF/Xo0UPLli1Tenq6pk6d6sGqAQBAReDxoLNnzx7179/fuRwbGytJGj9+vFauXKmRI0fq1KlTWrhwoY4dO6aIiAht2LBBYWFhnioZAABUEB4POv369ZMx5op9pk2bpmnTprl1u/Hx8YqPj1deXp5bxwUAAN7Dq6/RKUtcowMAgP18NugAAAD7EXQAAIC1fDbo8BwdAADs57NBh2t0AACwn88GHQAAYD+CDgAAsBZBBwAAWIugAwAArOWzQYe7rgAAsJ/PBh3uugIAwH4+G3QAAID9CDoAAMBaBB0AAGAtgg4AALCWzwYd7roCAMB+Pht0uOsKAAD7+WzQAQAA9iPoAAAAaxF0AACAtQg6AADAWgQdAABgLYIOAACwls8GHZ6jAwCA/Xw26PAcHQAA7OezQQcAANiPoAMAAKxF0AEAANYi6AAAAGsRdAAAgLUIOgAAwFoEHQAAYC2fDTo8MBAAAPv5bNDhgYEAANjPZ4MOAACwH0EHAABYi6ADAACsRdABAADWIugAAABrEXQAAIC1CDoAAMBaBB0AAGAtgg4AALAWQQcAAFiLoAMAAKxF0AEAANby2aDD28sBALCfzwYd3l4OAID9fDboAAAA+xF0AACAtQg6AADAWgQdAABgLYIOAACwFkEHAABYi6ADAACsRdABAADWIugAAABrEXQAAIC1CDoAAMBaBB0AAGAtgg4AALAWQQcAAFiLoAMAAKxF0AEAANYi6AAAAGtV+KBz9uxZde3aVR07dlS7du20fPlyT5cEAAC8RGVPF1BaNWrU0JYtW1SjRg1duHBBERERGjFihOrXr+/p0gAAgIdV+CM6fn5+qlGjhiTp559/Vl5enowxHq4KAAB4A48Hna1bt2rIkCEKCQmRw+HQunXrCvRZsmSJWrRooWrVqikyMlLbtm1zWX/mzBl16NBBTZs21ezZsxUUFFRO1QMAAG/m8aBz/vx5dejQQS+99FKh69esWaOYmBjNnz9f+/btU+/evRUdHa309HRnnzp16uiLL75QWlqa/v73v+vEiRNFbi8nJ0fZ2dkuHwAAYCePB53o6GgtWrRII0aMKHT9c889p0mTJmny5Mlq27atFi9erNDQUC1durRA3+DgYLVv315bt24tcntxcXEKDAx0fkJDQ922LwAAwLt4POhcSW5urpKTkxUVFeXSHhUVpaSkJEnSiRMnnEdlsrOztXXrVrVp06bIMefNm6esrCznJyMjo+x2AAAAeJRX33V18uRJ5eXlKTg42KU9ODhYx48flyT98MMPmjRpkowxMsbogQceUPv27Ysc09/fX/7+/mVaNwAA8A5eHXQuczgcLsvGGGdbZGSkUlJSPFAVAADwdl596iooKEh+fn7OozeXZWZmFjjKU1Lx8fEKDw9X165dSzUOAADwXl4ddKpWrarIyEglJia6tCcmJqpnz56lGnv69OlKTU3V7t27SzUOAADwXh4/dXXu3DkdPnzYuZyWlqaUlBTVq1dPzZo1U2xsrMaOHasuXbqoR48eWrZsmdLT0zV16lQPVg0AACoCjwedPXv2qH///s7l2NhYSdL48eO1cuVKjRw5UqdOndLChQt17NgxRUREaMOGDQoLC/NUyQAAoILweNDp16/fVV/ZMG3aNE2bNs2t242Pj1d8fLzy8vLcOi4AAPAeXn2NTlniGh0AAOzns0EHAADYj6ADAACs5bNBh+foAABgP58NOlyjAwCA/Xw26AAAAPsRdAAAgLUIOgAAwFoEHQAAYC2fDTrcdQUAgP18Nuhw1xUAAPbz2aADAADsR9ABAADWIugAAABrEXQAAIC1fDbocNcVAAD289mgw11XAADYz2eDDgAAsB9BBwAAWIugAwAArEXQAQAA1iLoAAAAaxF0AACAtXw26PAcHQAA7OezQYfn6AAAYD+fDToAAMB+BB0AAGAtgg4AALAWQQcAAFir1EEnLy9PKSkpOn36tDvqAQAAcJsSB52YmBi9+uqrkn4JOX379lXnzp0VGhqqTz/91N31AQAAXLMSB51//OMf6tChgyTp/fffV1pamg4ePKiYmBjNnz/f7QUCAABcqxIHnZMnT6pRo0aSpA0bNuiuu+5S69atNWnSJO3fv9/tBZYVHhgIAID9Shx0goODlZqaqry8PH300UcaOHCgJOnChQvy8/Nze4FlhQcGAgBgv8ol/cLEiRN19913q3HjxnI4HLrlllskSTt37tQNN9zg9gIBAACuVYmDzhNPPKGIiAhlZGTorrvukr+/vyTJz89Pc+fOdXuBAAAA16rEQWfVqlUaOXKkM+BcNnr0aCUkJLitMAAAgNIq8TU6EydOVFZWVoH2s2fPauLEiW4pCgAAwB1KHHSMMXI4HAXaf/jhBwUGBrqlKAAAAHco9qmrTp06yeFwyOFwaMCAAapc+d9fzcvLU1pamm699dYyKRIAAOBaFDvoDB8+XJKUkpKiQYMGqVatWs51VatWVfPmzXXHHXe4vUAAAIBrVeygs2DBAklS8+bNNWrUqAIXIwMAAHibEl+jEx4erpSUlALtO3fu1J49e9xREwAAgFuUOOhMnz5dGRkZBdqPHDmi6dOnu6UoAAAAdyhx0ElNTVXnzp0LtHfq1EmpqaluKQoAAMAdShx0/P39deLEiQLtx44dc7kTCwAAwNNKHHRuueUWzZs3z+WhgWfOnNGjjz7qfO9VRcDbywEAsJ/DGGNK8oUjR46oT58+OnXqlDp16iTpl1vOg4ODlZiYqNDQ0DIptKxkZ2crMDBQWVlZql27tlvHbj73g6v2+e7p29y6TQAAfEFxf3+X+FxTkyZN9OWXX+rNN9/UF198oerVq2vixIkaPXq0qlSpUqqiAQAA3OmaLqqpWbOm7rvvPnfXAgAA4FYlvkZHkl5//XX16tVLISEh+v777yVJzz//vN599123FgcAAFAaJQ46S5cuVWxsrKKjo3X69Gnl5eVJkurWravFixe7uz4AAIBrVuKg85e//EXLly/X/PnzXW4n79Kli/bv3+/W4gAAAEqjxEEnLS3NebfVr/n7++v8+fNuKQoAAMAdShx0WrRoUei7rj788EOFh4e7oyYAAAC3KPFdV7NmzdL06dP1888/yxijXbt2afXq1YqLi9Nf//rXsqgRAADgmpQ46EycOFGXLl3S7NmzdeHCBd1zzz1q0qSJXnjhBY0aNaosagQAALgm1/QcnSlTpmjKlCk6efKk8vPz1bBhQ3fXBQAAUGqlegtnUFCQu+oAAABwu2IFnc6dO2vjxo2qW7euOnXqJIfDUWTfWrVq6cYbb9Sjjz5a4d57BQAA7FKsoDNs2DD5+/tLkoYPH37Fvjk5Odq4caPuvfdebdmypdQFAgAAXKtiBZ0FCxYU+t9F+fbbb3XjjTdee1UAAABucM3X6GRmZurrr7+Ww+FQ69atXS5Ivv7663XixAm3FAgAAHCtSvzAwOzsbI0dO1ZNmjRR37591adPHzVp0kT33nuvsrKynP0CAwPdWigAAEBJlTjoTJ48WTt37tT69et15swZZWVlaf369dqzZ4+mTJlSFjUCAABckxIHnQ8++EB/+9vfNGjQINWuXVsBAQEaNGiQli9frg8++KAsaryijIwM9evXT+Hh4Wrfvr3eeuutcq8BAAB4pxJfo1O/fv1CT0sFBgaqbt26bimqJCpXrqzFixerY8eOyszMVOfOnTV48GDVrFmz3GsBAADepcRHdB577DHFxsbq2LFjzrbjx49r1qxZevzxx91aXHE0btxYHTt2lCQ1bNhQ9erV048//ljudQAAAO9TrKDTqVMnde7cWZ07d9bLL7+sHTt2KCwsTC1btlTLli3VrFkzJSUl6ZVXXilxAVu3btWQIUMUEhIih8OhdevWFeizZMkStWjRQtWqVVNkZKS2bdtW6Fh79uxRfn4+DyoEAACSinnq6moPCSyN8+fPq0OHDpo4caLuuOOOAuvXrFmjmJgYLVmyRDfddJNeeeUVRUdHKzU1Vc2aNXP2O3XqlMaNG3fVN6jn5OQoJyfHuZydne2+nQEAAF7FYYwxni7iMofDobVr17oEq+7du6tz585aunSps61t27YaPny44uLiJP0SXm655RZNmTJFY8eOveI2nnjiCT355JMF2rOyslS7dm337Mj/az736hdnf/f0bW7dJgAAviA7O1uBgYFX/f1d4mt0LktOTtYbb7yhN998U/v27bvWYa4oNzdXycnJioqKcmmPiopSUlKSJMkYowkTJujmm2++asiRpHnz5ikrK8v5ycjIKJPaAQCA55X4rqvMzEyNGjVKn376qerUqSNjjLKystS/f38lJCSoQYMGbivu5MmTysvLU3BwsEt7cHCwjh8/Lkn6/PPPtWbNGrVv3955fc/rr7+udu3aFTqmv7+/871dAADAbiUOOjNmzFB2dra++uortW3bVpKUmpqq8ePH68EHH9Tq1avdXuR/vi3dGONs69Wr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fn2zfv16k5aWZt566y1Tq1Yts3jxYmcfX52nDRs2mPnz55u3337bSDJr1651We+uebn11ltNRESESUpKMklJSSYiIsLcfvvt5bWbpXaleTpz5owZOHCgWbNmjTl48KDZvn276d69u4mMjHQZw5vmiaBTBrp162amTp3q0nbDDTeYuXPneqgiz8rMzDSSzJYtW4wxxuTn55tGjRqZp59+2tnn559/NoGBgebll182xvzyl6lKlSomISHB2efIkSOmUqVK5qOPPirfHSgHZ8+eNa1atTKJiYmmb9++zqDDXP3bnDlzTK9evYpcz1z94rbbbjO//e1vXdpGjBhh7r33XmMM83TZf/4Cd9e8pKamGklmx44dzj7bt283kszBgwfLeK/cr7BA+J927dplJDn/Z97b5olTV26Wm5ur5ORkRUVFubRHRUUpKSnJQ1V5VlZWliSpXr16kqS0tDQdP37cZY78/f3Vt29f5xwlJyfr4sWLLn1CQkIUERFh5TxOnz5dt912mwYOHOjSzlz923vvvacuXbrorrvuUsOGDdWpUyctX77cuZ65+kWvXr20ceNGffPNN5KkL774Qp999pkGDx4siXkqirvmZfv27QoMDFT37t2dff7rv/5LgYGB1s5dVlaWHA6H6tSpI8n75snnX+rpbidPnlReXp6Cg4Nd2oODg3X8+HEPVeU5xhjFxsaqV69eioiIkCTnPBQ2R99//72zT9WqVVW3bt0CfWybx4SEBO3du1e7d+8usI65+rd//etfWrp0qWJjY/Xoo49q165devDBB+Xv769x48YxV/9vzpw5ysrK0g033CA/Pz/l5eXpqaee0ujRoyXxM1UUd83L8ePH1bBhwwLjN2zY0Mq5+/nnnzV37lzdc889zhd4ets8EXTKiMPhcFk2xhRo8wUPPPCAvvzyS3322WcF1l3LHNk2jxkZGZo5c6b+53/+R9WqVSuyH3Ml5efnq0uXLvrDH/4gSerUqZO++uorLV26VOPGjXP28/W5WrNmjd544w39/e9/14033qiUlBTFxMQoJCRE48ePd/bz9XkqijvmpbD+Ns7dxYsXNWrUKOXn52vJkiVX7e+peeLUlZsFBQXJz8+vQCLNzMws8H8KtpsxY4bee+89bd68WU2bNnW2N2rUSJKuOEeNGjVSbm6uTp8+XWQfGyQnJyszM1ORkZGqXLmyKleurC1btujFF19U5cqVnfvKXEmNGzdWeHi4S1vbtm2Vnp4uiZ+ry2bNmqW5c+dq1KhRateuncaOHauHHnpIcXFxkpinorhrXho1aqQTJ04UGP9///d/rZq7ixcv6u6771ZaWpoSExOdR3Mk75sngo6bVa1aVZGRkUpMTHRpT0xMVM+ePT1UVfkyxuiBBx7QO++8o02bNqlFixYu61u0aKFGjRq5zFFubq62bNninKPIyEhVqVLFpc+xY8d04MABq+ZxwIAB2r9/v1JSUpyfLl26aMyYMUpJSdF1113HXP2/m266qcBjCr755huFhYVJ4ufqsgsXLqhSJdd/2v38/Jy3lzNPhXPXvPTo0UNZWVnatWuXs8/OnTuVlZVlzdxdDjmHDh3SJ598ovr167us97p5cuulzTDG/Pv28ldffdWkpqaamJgYU7NmTfPdd995urRycf/995vAwEDz6aefmmPHjjk/Fy5ccPZ5+umnTWBgoHnnnXfM/v37zejRowu9jbNp06bmk08+MXv37jU333xzhb+9tTh+fdeVMczVZbt27TKVK1c2Tz31lDl06JB58803TY0aNcwbb7zh7MNcGTN+/HjTpEkT5+3l77zzjgkKCjKzZ8929vHVeTp79qzZt2+f2bdvn5FknnvuObNv3z7n3ULumpdbb73VtG/f3mzfvt1s377dtGvXrkLdXn6lebp48aIZOnSoadq0qUlJSXH5Nz4nJ8c5hjfNE0GnjMTHx5uwsDBTtWpV07lzZ+et1b5AUqGfFStWOPvk5+ebBQsWmEaNGhl/f3/Tp08fs3//fpdxfvrpJ/PAAw+YevXqmerVq5vbb7/dpKenl/PelL//DDrM1b+9//77JiIiwvj7+5sbbrjBLFu2zGU9c2VMdna2mTlzpmnWrJmpVq2aue6668z8+fNdfgn56jxt3ry50H+bxo8fb4xx37ycOnXKjBkzxgQEBJiAgAAzZswYc/r06XLay9K70jylpaUV+W/85s2bnWN40zw5jDHGvceIAAAAvAPX6AAAAGsRdAAAgLUIOgAAwFoEHQAAYC2CDgAAsBZBBwAAWIugAwAArEXQAQAA1iLoABVIv379FBMTU+T6CRMmaPjw4cUa67vvvpPD4VBKSopbavMGzZs31+LFi8tk7KvNfXFt2rRJN9xwg/PdU0888YQ6duxY6nFLIzMzUw0aNNCRI0c8WgdQFgg6gEVeeOEFrVy50tNleMzu3bt13333OZcdDofWrVvnuYIKMXv2bM2fP7/AizfLSr9+/fTyyy9fsU/Dhg01duxYLViwoFxqAsoTQQewSGBgoOrUqePpMjymQYMGqlGjhqfLKFJSUpIOHTqku+66q1y29+OPPyopKUlDhgy5at+JEyfqzTff1OnTp8uhMqD8EHSACuyjjz5SYGCgVq1aJangqav8/Hw988wzatmypfz9/dWsWTM99dRThY6Vn5+vKVOmqHXr1vr+++8L7XN5/D/84Q8KDg5WnTp19OSTT+rSpUuaNWuW6tWrp6ZNm+pvf/uby/fmzJmj1q1bq0aNGrruuuv0+OOP6+LFiy59Fi1apIYNGyogIECTJ0/W3LlzXU7pXN72n//8ZzVu3Fj169fX9OnTXcb59amr5s2bS5J+85vfyOFwOJcLO70XExOjfv36OZfPnz+vcePGqVatWmrcuLGeffbZAnORm5ur2bNnq0mTJqpZs6a6d++uTz/9tNB5uywhIUFRUVGqVq1akX3S0tLUsmVL3X///crPz9fKlStVp04drV+/Xm3atFGNGjV055136vz583rttdfUvHlz1a1bVzNmzFBeXp7LWB988IE6dOigJk2a6PTp0xozZowaNGig6tWrq1WrVlqxYoWzb7t27dSoUSOtXbv2ivsAVDSVPV0AgGuTkJCg++67T6+//rqGDRtWaJ958+Zp+fLlev7559WrVy8dO3ZMBw8eLNAvNzdX99xzj7799lt99tlnatiwYZHb3bRpk5o2baqtW7fq888/16RJk7R9+3b16dNHO3fu1Jo1azR16lTdcsstCg0NlSQFBARo5cqVCgkJ0f79+zVlyhQFBARo9uzZkqQ333xTTz31lJYsWaKbbrpJCQkJevbZZ9WiRQuXbW/evFmNGzfW5s2bdfjwYY0cOVIdO3bUlClTCtS5e/duNWzYUCtWrNCtt94qPz+/Ys/trFmztHnzZq1du1aNGjXSo48+quTkZJfgNXHiRH333XdKSEhQSEiI1q5dq1tvvVX79+9Xq1atCh1369atGj16dJHbPXDggKKiojR+/HjFxcU52y9cuKAXX3xRCQkJOnv2rEaMGKERI0aoTp062rBhg/71r3/pjjvuUK9evTRy5Ejn99577z3nz8bjjz+u1NRUffjhhwoKCtLhw4f1008/uWy/W7du2rZtm377298We64Ar+f296EDKDN9+/Y1M2fONPHx8SYwMNBs2rTJZf348ePNsGHDjDHGZGdnG39/f7N8+fJCx0pLSzOSzLZt28zAgQPNTTfdZM6cOXPF7Y8fP96EhYWZvLw8Z1ubNm1M7969ncuXLl0yNWvWNKtXry5ynD/+8Y8mMjLSudy9e3czffp0lz433XST6dChQ4FtX7p0ydl21113mZEjRzqXw8LCzPPPP+9clmTWrl1bYB8uz9FlM2fONH379jXGGHP27FlTtWpVk5CQ4Fx/6tQpU716dTNz5kxjjDGHDx82DofDHDlyxGWcAQMGmHnz5hW534GBgWbVqlUubQsWLDAdOnQwSUlJpl69euZPf/qTy/oVK1YYSebw4cPOtt/97nemRo0a5uzZs862QYMGmd/97nfO5Z9//tkEBASYL7/80hhjzJAhQ8zEiROLrM0YYx566CHTr1+/K/YBKhqO6AAVzNtvv60TJ07os88+U7du3Yrs989//lM5OTkaMGDAFccbPXq0mjZtqo0bNxbr+pYbb7zR5ULa4OBgRUREOJf9/PxUv359ZWZmOtv+8Y9/aPHixTp8+LDOnTunS5cuqXbt2s71X3/9taZNm+aynW7dumnTpk0Ftv3rIzONGzfW/v37r1pzSXz77bfKzc1Vjx49nG316tVTmzZtnMt79+6VMUatW7d2+W5OTo7q169f5Ng//fRToaet0tPTNXDgQC1atEgPPfRQgfU1atTQ9ddf71wODg5W8+bNVatWLZe2X8/5pk2bVL9+fbVr106SdP/99+uOO+7Q3r17FRUVpeHDh6tnz54u26levbouXLhQZP1ARcQ1OkAF07FjRzVo0EArVqyQMabIftWrVy/WeIMHD9aXX36pHTt2FKt/lSpVXJYdDkehbZdvn96xY4dGjRql6OhorV+/Xvv27dP8+fOVm5tb4Du/Vti+XWk7xVWpUqUCY//6Op8rzell+fn58vPzU3JyslJSUpyff/7zn3rhhReK/F5QUFChF/s2aNBA3bp1U0JCgrKzswusL+mcS66nrSQpOjpa33//vWJiYnT06FENGDBAjzzyiMsYP/74oxo0aHDlnQcqGIIOUMFcf/312rx5s959913NmDGjyH6tWrVS9erVtXHjxiuOd//99+vpp5/W0KFDtWXLFneXq88//1xhYWGaP3++unTpolatWhW42LlNmzbatWuXS9uePXtKve0qVaoUuEC3QYMGOnbsmEvbr58l1LJlS1WpUsUl+J0+fVrffPONc7lTp07Ky8tTZmamWrZs6fJp1KhRkfV06tRJqampBdqrV6+u9evXq1q1aho0aJDOnj1b0l11YYzR+++/r6FDh7q0N2jQQBMmTNAbb7yhxYsXa9myZS7rDxw4oE6dOpVq24C3IegAFVDr1q21efNmvf3220U+xK5atWqaM2eOZs+erVWrVunbb7/Vjh079OqrrxboO2PGDC1atEi33367PvvsM7fW2rJlS6WnpyshIUHffvutXnzxxQJ39syYMUOvvvqqXnvtNR06dEiLFi3Sl19+WeAoT0k1b95cGzdu1PHjx51HUm6++Wbt2bNHq1at0qFDh7RgwQIdOHDA+Z1atWpp0qRJmjVrljZu3KgDBw5owoQJLqfrWrdurTFjxmjcuHF65513lJaWpt27d+uZZ57Rhg0biqxn0KBBRc5vzZo19cEHH6hy5cqKjo7WuXPnrnm/k5OTdf78efXp08fZ9vvf/17vvvuuDh8+rK+++krr169X27ZtnesvXLig5ORkRUVFXfN2AW9E0AEqqDZt2mjTpk1avXq1Hn744UL7PP7443r44Yf1+9//Xm3bttXIkSNdruP4tZiYGD355JMaPHiwkpKS3FbnsGHD9NBDD+mBBx5Qx44dlZSUpMcff9ylz5gxYzRv3jw98sgj6ty5s9LS0jRhwoQr3oZdHM8++6wSExMVGhrqPFIxaNAgPf7445o9e7a6du2qs2fPaty4cS7f+9Of/qQ+ffpo6NChGjhwoHr16qXIyEiXPitWrNC4ceP08MMPq02bNho6dKh27tzpvNOsMPfee69SU1P19ddfF7q+Vq1a+vDDD2WM0eDBg3X+/Plr2u93331Xt912mypX/vdlmFWrVtW8efPUvn179enTR35+fkpISHD5TrNmzdS7d+9r2ibgrRymOCekAaCc3XLLLWrUqJFef/11T5fiVrNnz1ZWVpZeeeWVMttG+/bt9dhjj+nuu+8u9ne6deummJgY3XPPPWVWF+AJ3HUFwOMuXLigl19+WYMGDZKfn59Wr16tTz75RImJiZ4uze3mz5+v+Ph45eXllejZPsWVm5urO+64Q9HR0cX+TmZmpu68884rPuMHqKg4ogPA43766ScNGTJEe/fuVU5Ojtq0aaPHHntMI0aM8HRpACo4gg4AALAWFyMDAABrEXQAAIC1CDoAAMBaBB0AAGAtgg4AALAWQQcAAFiLoAMAAKxF0AEAANb6PxSgl3KR+6GDAAAAAElFTkSuQmCC", + "image/png": "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XW3BwcHq3r27a/nAgQMyxqhbt25u3y0qKlKrVq3KHfunn34672mr7OxsjRw5UitWrNCCBQvKrG/SpIkuueQS13JoaKg6deqkZs2aubX9+jffvn27WrVqpcsuu0ySdPvtt+u6667TgQMHFBsbq/Hjx2vQoEFu22ncuLHOnDlTbv1AXcQ1OkAd07t3b7Vu3Vrr1q2TMabcfo0bN67QeKNHj9ann36qjz76qEL9GzRo4LbscDjO23bu9umPPvpIN954o+Li4rRlyxZ9/PHHWrJkiYqLi8t859fOt28X2k5F1atXr8zYv77O50K/6TmlpaUKCAhQWlqa0tPTXZ/PP/9cTz75ZLnfCwkJOe/Fvq1bt9aAAQOUnJysgoKCMusr+5tL7qetJCkuLk7ffvutEhISdPToUY0YMUJ33XWX2xg//PCDWrdufeGdB+oYgg5Qx1xyySXasWOHXn/9dc2bN6/cfl27dlXjxo21bdu2C453++236+GHH9bYsWO1c+dOT5erDz/8UBEREVqyZIn69eunrl27lrnYuXv37tq7d69b2/79+6u97QYNGpS5QLd169bKzc11a/v1s4S6dOmiBg0auAW/kydP6quvvnIt9+nTRyUlJcrLy1OXLl3cPm3bti23nj59+igjI6NMe+PGjbVlyxY1atRIo0aN0qlTpyq7q26MMXrzzTc1duxYt/bWrVtr2rRpevHFF7Vy5UqtWbPGbf2hQ4fUp0+fam0b8DUEHaAO6tatm3bs2KFXX3213IfYNWrUSHfffbcWLVqkDRs26Ouvv9ZHH32k5557rkzfefPmacWKFfrd736nDz74wKO1dunSRdnZ2UpOTtbXX3+tp556qsydPfPmzdNzzz2n559/XocPH9aKFSv06aefljnKU1mdOnXStm3bdOzYMdeRlKuuukr79+/Xhg0bdPjwYS1btkyHDh1yfadZs2aaMWOGFi5cqG3btunQoUOaNm2a2+m6bt266eabb9aUKVP02muvKSsrS/v27dMjjzyirVu3llvPqFGjyv19mzZtqrfeekv169dXXFycTp8+XeX9TktLU2FhoYYOHepqu//++/X6668rMzNTn332mbZs2aIePXq41p85c0ZpaWmKjY2t8nYBX0TQAeqo7t27a/v27Xr55Zd15513nrfP0qVLdeedd+r+++9Xjx49NHHiRLfrOH4tISFBDz74oEaPHq3U1FSP1Tlu3DgtWLBAc+fOVe/evZWamqqlS5e69bn55pu1ePFi3XXXXerbt6+ysrI0bdq0C96GXRGPPfaYUlJSFB4e7jpSMWrUKC1dulSLFi1S//79derUKU2ZMsXte48++qiGDh2qsWPHauTIkRo8eLBiYmLc+qxbt05TpkzRnXfeqe7du2vs2LHas2eP606z87nllluUkZGhL7/88rzrmzVrprffflvGGI0ePVqFhYVV2u/XX39d1157rerX/7/LMBs2bKjFixerV69eGjp0qAICApScnOz2nY4dO2rIkCFV2ibgqxymIiekAaCWXX311Wrbtq1eeOEFb5fiUYsWLVJ+fr7+9re/1dg2evXqpfvuu09/+MMfKvydAQMGKCEhQTfddFON1QV4A3ddAfC6M2fO6JlnntGoUaMUEBCgl19+We+9955SUlK8XZrHLVmyRE6nUyUlJZV6tk9FFRcX67rrrlNcXFyFv5OXl6frr7/+gs/4AeoqjugA8LqffvpJY8aM0YEDB1RUVKTu3bvrvvvu04QJE7xdGoA6jqADAACsxcXIAADAWgQdAABgLYIOAACwFkEHAABYi6ADAACsRdABAADWIugAAABrEXQAAIC1/h+g1tuncMTQpgAAAABJRU5ErkJggg==", "text/plain": [ "
" ] @@ -403,7 +2204,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 11, "id": "ce24f553-6020-4000-be02-13feb6c7ba39", "metadata": {}, "outputs": [], @@ -413,7 +2214,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 12, "id": "a9b3f917-bf60-4c99-bb57-4270541733f9", "metadata": {}, "outputs": [], @@ -424,7 +2225,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 13, "id": "dade2fb6-ae07-4597-9db7-5bfee462599d", "metadata": {}, "outputs": [], @@ -441,7 +2242,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 14, "id": "13d68eb1-b495-4051-a150-4c63ddeefc2a", "metadata": {}, "outputs": [ @@ -475,7 +2276,7 @@ { "cell_type": "code", "execution_count": null, - "id": "bf911b4e-a333-4752-ae2e-183adaaef57f", + "id": "74efc7b1-7cae-4781-9c05-9dccb8adbde4", "metadata": {}, "outputs": [], "source": [] diff --git a/spisea/atmospheres.py b/spisea/atmospheres.py index 550e3298..0f94453e 100755 --- a/spisea/atmospheres.py +++ b/spisea/atmospheres.py @@ -1276,7 +1276,7 @@ def get_merged_atmosphere_w_bb_supplement(metallicity=0, temperature=20000, grav temperature ranges where we switch between model grids, to ensure a smooth transition. """ - + if (temperature <= 1000): print('BB atmosphere') return get_bb_atmosphere(temperature=temperature, @@ -1303,6 +1303,7 @@ def get_merged_atmosphere_w_bb_supplement(metallicity=0, temperature=20000, grav gravity=gravity, verbose=verbose) + # For T < 3800, atmosphere depends on metallicity + gravity. # If solar metallicity, use BTSettl 2015 grid. Only solar metallicity is # currently available here, so if non-solar metallicity, just stick with @@ -1390,10 +1391,12 @@ def get_merged_atmosphere_w_bb_supplement_grid(bb_supplement_tarr='default', bb_ if bb_supplement_tarr == 'default': X, Y = np.meshgrid(np.logspace(np.log10(2e3), np.log10(4.6e3), 20), np.linspace(6.5, 8.7, 10)) X1, Y1 = np.meshgrid(np.logspace(np.log10(2e3), np.log10(3.5e3), 15), np.linspace(6, 6.25, 2)) - X2, Y2 = np.meshgrid(np.logspace(np.log10(1e2), np.log10(1.1e3), 25), np.linspace(3, 4.5, 4)) + #X2, Y2 = np.meshgrid(np.logspace(np.log10(2e2), np.log10(1.1e3), 20), np.linspace(3, 4.5, 4)) X3, Y3 = np.meshgrid(np.logspace(np.log10(8e3), np.log10(2e4), 25), np.linspace(9.8, 11.6, 8)) - bb_supplement_tarr = np.concatenate((X.ravel(), X1.ravel(), X2.ravel(), X3.ravel())) - bb_supplement_loggarr = np.concatenate((Y.ravel(), Y1.ravel(), Y2.ravel(), Y3.ravel())) + bb_supplement_tarr = np.concatenate((X.ravel(), X1.ravel(), X3.ravel())) + bb_supplement_loggarr = np.concatenate((Y.ravel(), Y1.ravel(), Y3.ravel())) + #bb_supplement_tarr = np.concatenate((X.ravel(), X1.ravel(), X2.ravel(), X3.ravel())) + #bb_supplement_loggarr = np.concatenate((Y.ravel(), Y1.ravel(), Y2.ravel(), Y3.ravel())) bb_supplement_zarr = np.zeros(len(bb_supplement_tarr)) diff --git a/spisea/evolution.py b/spisea/evolution.py index 3e9e4a30..f474aab8 100755 --- a/spisea/evolution.py +++ b/spisea/evolution.py @@ -1277,6 +1277,7 @@ def __init__(self, BSEDict='default', keep_disrupted_companions=True, keep_COSMI self.z_solar = 0.014 self.keep_disrupted_companions = keep_disrupted_companions self.keep_COSMIC_tables = keep_COSMIC_tables + self.model_version_name = "COSMIC" def evolve(self, star_systems, companions, logAge, metallicity): diff --git a/spisea/synthetic.py b/spisea/synthetic.py index b9867d8b..ca8d5c53 100755 --- a/spisea/synthetic.py +++ b/spisea/synthetic.py @@ -1596,6 +1596,7 @@ def __init__(self, logAge, AKs, distance, tab.meta['REDLAW'] = red_law.name tab.meta['ATMFUNC'] = atm_func.__name__ tab.meta['EVOMODEL'] = type(evo_model).__name__ + tab.meta['EVOMODELVERSION'] = evo_model.model_version_name tab.meta['AKS'] = AKs tab.meta['DISTANCE'] = distance tab.meta['WAVEMIN'] = wave_range[0] From 6a442bf611e9b222ceecdda124ca00bf0d2278d2 Mon Sep 17 00:00:00 2001 From: nsabrams Date: Sat, 21 Feb 2026 13:41:26 -0800 Subject: [PATCH 04/28] added fix to companion system idxs --- spisea/evolution.py | 15 +++++++++++++-- spisea/synthetic.py | 4 ++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/spisea/evolution.py b/spisea/evolution.py index f474aab8..a76f9470 100755 --- a/spisea/evolution.py +++ b/spisea/evolution.py @@ -1274,7 +1274,7 @@ def __init__(self, BSEDict='default', keep_disrupted_companions=True, keep_COSMI self.BSEDict = BSEDict self.external_evol = True - self.z_solar = 0.014 + self.z_solar = 0.02 #0.014 self.keep_disrupted_companions = keep_disrupted_companions self.keep_COSMIC_tables = keep_COSMIC_tables self.model_version_name = "COSMIC" @@ -1344,6 +1344,9 @@ def evolve(self, star_systems, companions, logAge, metallicity): # maybe add WR designation + # Add number for system idx since we're about to manipuluate them a bunch + star_systems['system_idx'] = np.arange(len(star_systems)) + # Take the disrupted binaries and put the companions into the star_system table (if desired) # don't include massless remnant companions disrupted_binary_companion_idxs = np.where((final_binaries['bin_state'][companion_system_idxs] == 2) & (final_binaries['kstar_2'][companion_system_idxs] != 15))[0] @@ -1353,6 +1356,7 @@ def evolve(self, star_systems, companions, logAge, metallicity): disrupted_binary_companions['isMultiple'] = [False]*len(disrupted_binary_companions) disrupted_binary_companions['N_companions'] = [0]*len(disrupted_binary_companions) disrupted_binary_companions.remove_columns(['system_idx', 'log_a', 'e', 'i', 'Omega', 'omega']) + disrupted_binary_companions['system_idx'] = np.arange(len(disrupted_binary_companions)) + len(star_systems) star_systems = vstack([star_systems, disrupted_binary_companions]) #Drop merged companions and totally disappeared systems @@ -1380,12 +1384,19 @@ def evolve(self, star_systems, companions, logAge, metallicity): companions_to_mr_primaries['isMultiple'] = [False]*len(companions_to_mr_primaries) companions_to_mr_primaries['N_companions'] = [0]*len(companions_to_mr_primaries) companions_to_mr_primaries.remove_columns(['system_idx', 'log_a', 'e', 'i', 'Omega', 'omega']) - + companions_to_mr_primaries['system_idx'] = np.arange(len(companions_to_mr_primaries)) + len(star_systems) + len(disrupted_binary_companions) star_systems = vstack([star_systems, companions_to_mr_primaries]) star_systems.remove_rows(delete_primary_idxs) companions.remove_rows(delete_companion_idxs) #if kstar 1 is 15 take the seocnd star and if kstar2 is 15 take the other + #Reassign system_idx vals + star_systems['system_idx_new'] = np.arange(len(star_systems)) + mapping = np.empty(star_systems['system_idx'].max() + 1, dtype=int) + mapping[star_systems['system_idx']] = star_systems['system_idx_new'] + companions['system_idx'] = mapping[companions['system_idx']] + star_systems.remove_columns(['system_idx', 'system_idx_new']) + #FIXME add assertion about mass_current not being zero return star_systems, companions diff --git a/spisea/synthetic.py b/spisea/synthetic.py index ca8d5c53..a86378fa 100755 --- a/spisea/synthetic.py +++ b/spisea/synthetic.py @@ -1523,8 +1523,8 @@ def __init__(self, logAge, AKs, distance, metal_flag = int(abs(metallicity)*10) save_file_fmt = '{0}/atm_{1:4.2f}_{2:4s}_{3}{4:2s}.fits' - self.save_file = save_file_fmt.format(iso_dir, AKs, str(distance).zfill(5), metal_pre, str(metal_flag).zfill(2)) - self.save_file_legacy = save_file_fmt.format(iso_dir, AKs, str(distance).zfill(5), metal_pre, str(metal_flag).zfill(2)) + self.save_file = save_file_fmt.format(atm_grid_dir, AKs, str(distance).zfill(5), metal_pre, str(metal_flag).zfill(2)) + self.save_file_legacy = save_file_fmt.format(atm_grid_dir, AKs, str(distance).zfill(5), metal_pre, str(metal_flag).zfill(2)) # Expected filters self.filters = filters From 2bf310d6fd99fbf6499cc4eccb261ee6eee3c290 Mon Sep 17 00:00:00 2001 From: nsabrams Date: Sun, 22 Feb 2026 06:54:12 -0800 Subject: [PATCH 05/28] added fix for cosmic systems that don't make it to the end of bcm --- spisea/evolution.py | 49 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 40 insertions(+), 9 deletions(-) diff --git a/spisea/evolution.py b/spisea/evolution.py index a76f9470..9ed01bba 100755 --- a/spisea/evolution.py +++ b/spisea/evolution.py @@ -1312,7 +1312,31 @@ def evolve(self, star_systems, companions, logAge, metallicity): self.kick_info = kick_info final_binaries = bcm[bcm['tphys'] > 0] #only gives the first and last idx, so this takes final one + + # Add number for system idx since we're about to manipuluate them a bunch + star_systems['system_idx'] = np.arange(len(star_systems)) + # Remove systems that don't show up in bcm final (very few) + if len(final_binaries) != len(star_systems): + start_bins = bcm[bcm['tphys'] == 0]['bin_num'].values + end_bins = bcm[bcm['tphys'] != 0]['bin_num'].values + + bad_bin_nums = np.setdiff1d(start_bins, end_bins) + good_bin_nums = np.intersect1d(start_bins, end_bins) + + bad_system_mask = np.isin(star_systems['system_idx'], bad_bin_nums) + bad_system_idxs = np.where(bad_system_mask)[0] + + bad_companion_rows = np.where(np.isin(companions['system_idx'], bad_bin_nums))[0] + + companions.remove_rows(bad_companion_rows) + star_systems.remove_rows(bad_system_idxs) + + keep_mask = np.ones(len(companion_system_idxs), dtype=bool) + keep_mask[bad_companion_rows] = False + companion_system_idxs = companion_system_idxs[keep_mask] + + kick_info = kick_info.loc[kick_info.index.isin(good_bin_nums)] star_systems['mass_current'] = final_binaries['mass_1'] star_systems['Teff'] = final_binaries['teff_1'] @@ -1336,16 +1360,14 @@ def evolve(self, star_systems, companions, logAge, metallicity): fixed_phases1[np.where(final_binaries['kstar_1'] == 14)[0]] = 103 star_systems['phase'] = fixed_phases1 - fixed_phases2 = final_binaries['kstar_2'].to_numpy() - fixed_phases2[np.where((final_binaries['kstar_2'] >= 10) & (final_binaries['kstar_2'] <= 12))[0]] = 101 - fixed_phases2[np.where(final_binaries['kstar_2'] == 13)[0]] = 102 - fixed_phases2[np.where(final_binaries['kstar_2'] == 14)[0]] = 103 - companions['phase'] = fixed_phases2[companion_system_idxs] + fixed_phases2 = final_binaries['kstar_2'][companion_system_idxs].to_numpy() + fixed_phases2[np.where((final_binaries['kstar_2'][companion_system_idxs] >= 10) & (final_binaries['kstar_2'][companion_system_idxs] <= 12))[0]] = 101 + fixed_phases2[np.where(final_binaries['kstar_2'][companion_system_idxs] == 13)[0]] = 102 + fixed_phases2[np.where(final_binaries['kstar_2'][companion_system_idxs] == 14)[0]] = 103 + companions['phase'] = fixed_phases2 # maybe add WR designation - # Add number for system idx since we're about to manipuluate them a bunch - star_systems['system_idx'] = np.arange(len(star_systems)) # Take the disrupted binaries and put the companions into the star_system table (if desired) # don't include massless remnant companions @@ -1374,8 +1396,14 @@ def evolve(self, star_systems, companions, logAge, metallicity): primaries_to_deleted_companion_idxs = companions[delete_companion_idxs]['system_idx'] #Fix binary specification of primaries that lost their companions - star_systems['isMultiple'][primaries_to_deleted_companion_idxs] = False - star_systems['N_companions'][primaries_to_deleted_companion_idxs] = 0 + #star_systems['isMultiple'][primaries_to_deleted_companion_idxs] = False + #star_systems['N_companions'][primaries_to_deleted_companion_idxs] = 0 + + mask = np.isin(star_systems['system_idx'], + primaries_to_deleted_companion_idxs) + + star_systems['N_companions'][mask] = 0 + star_systems['isMultiple'][mask] = False # Promote the companions to merged primaries to primaries if self.keep_disrupted_companions and len(companions_to_mr_primaries_idxs) > 0: @@ -1399,6 +1427,9 @@ def evolve(self, star_systems, companions, logAge, metallicity): #FIXME add assertion about mass_current not being zero + # Make sure we didn't break anything by manipulating the number of companions + assert star_systems['N_companions'].sum() == len(companions) + return star_systems, companions From 3e7f7a950653d173d3cc95dfbfd7072e45de2072 Mon Sep 17 00:00:00 2001 From: nsabrams Date: Sun, 22 Feb 2026 07:24:03 -0800 Subject: [PATCH 06/28] handle if there are no disrupted binary companions --- spisea/evolution.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/spisea/evolution.py b/spisea/evolution.py index 9ed01bba..105103a1 100755 --- a/spisea/evolution.py +++ b/spisea/evolution.py @@ -1372,6 +1372,7 @@ def evolve(self, star_systems, companions, logAge, metallicity): # Take the disrupted binaries and put the companions into the star_system table (if desired) # don't include massless remnant companions disrupted_binary_companion_idxs = np.where((final_binaries['bin_state'][companion_system_idxs] == 2) & (final_binaries['kstar_2'][companion_system_idxs] != 15))[0] + disrupted_binary_companions_num = 0 if self.keep_disrupted_companions and len(disrupted_binary_companion_idxs) > 0: disrupted_binary_companions = companions[disrupted_binary_companion_idxs] disrupted_binary_companions['systemMass'] = disrupted_binary_companions['mass_current'] @@ -1380,6 +1381,7 @@ def evolve(self, star_systems, companions, logAge, metallicity): disrupted_binary_companions.remove_columns(['system_idx', 'log_a', 'e', 'i', 'Omega', 'omega']) disrupted_binary_companions['system_idx'] = np.arange(len(disrupted_binary_companions)) + len(star_systems) star_systems = vstack([star_systems, disrupted_binary_companions]) + disrupted_binary_companions_num = len(disrupted_binary_companions) #Drop merged companions and totally disappeared systems # Also promote companions to primaries when the initial primary "merged" (if desired) @@ -1412,7 +1414,7 @@ def evolve(self, star_systems, companions, logAge, metallicity): companions_to_mr_primaries['isMultiple'] = [False]*len(companions_to_mr_primaries) companions_to_mr_primaries['N_companions'] = [0]*len(companions_to_mr_primaries) companions_to_mr_primaries.remove_columns(['system_idx', 'log_a', 'e', 'i', 'Omega', 'omega']) - companions_to_mr_primaries['system_idx'] = np.arange(len(companions_to_mr_primaries)) + len(star_systems) + len(disrupted_binary_companions) + companions_to_mr_primaries['system_idx'] = np.arange(len(companions_to_mr_primaries)) + len(star_systems) + disrupted_binary_companions_num star_systems = vstack([star_systems, companions_to_mr_primaries]) star_systems.remove_rows(delete_primary_idxs) From 39d3c4c6f31c70c8ce8172432cd1cefd9d9baa70 Mon Sep 17 00:00:00 2001 From: nsabrams Date: Mon, 23 Feb 2026 12:50:20 -0800 Subject: [PATCH 07/28] no longer handle if some binaries didn't make it. Just raise exception --- spisea/evolution.py | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/spisea/evolution.py b/spisea/evolution.py index 105103a1..308ebe80 100755 --- a/spisea/evolution.py +++ b/spisea/evolution.py @@ -1318,25 +1318,7 @@ def evolve(self, star_systems, companions, logAge, metallicity): # Remove systems that don't show up in bcm final (very few) if len(final_binaries) != len(star_systems): - start_bins = bcm[bcm['tphys'] == 0]['bin_num'].values - end_bins = bcm[bcm['tphys'] != 0]['bin_num'].values - - bad_bin_nums = np.setdiff1d(start_bins, end_bins) - good_bin_nums = np.intersect1d(start_bins, end_bins) - - bad_system_mask = np.isin(star_systems['system_idx'], bad_bin_nums) - bad_system_idxs = np.where(bad_system_mask)[0] - - bad_companion_rows = np.where(np.isin(companions['system_idx'], bad_bin_nums))[0] - - companions.remove_rows(bad_companion_rows) - star_systems.remove_rows(bad_system_idxs) - - keep_mask = np.ones(len(companion_system_idxs), dtype=bool) - keep_mask[bad_companion_rows] = False - companion_system_idxs = companion_system_idxs[keep_mask] - - kick_info = kick_info.loc[kick_info.index.isin(good_bin_nums)] + raise Exception("Some binaries didn't make it. Something went wrong with COSMIC") star_systems['mass_current'] = final_binaries['mass_1'] star_systems['Teff'] = final_binaries['teff_1'] From 2bf5f6964139274a4540290272c9b4db06e46e0b Mon Sep 17 00:00:00 2001 From: nsabrams Date: Wed, 25 Mar 2026 08:30:27 -0700 Subject: [PATCH 08/28] cleaned up some cosmic things --- spisea/synthetic.py | 137 +++++++++++++++----------------------------- 1 file changed, 45 insertions(+), 92 deletions(-) diff --git a/spisea/synthetic.py b/spisea/synthetic.py index a86378fa..33164567 100755 --- a/spisea/synthetic.py +++ b/spisea/synthetic.py @@ -159,7 +159,7 @@ def __init__(self, iso, imf, cluster_mass, ifmr=None, verbose=True, self.filt_names = self.set_filter_names() except: self.filt_names = iso.filters - #self.cluster_mass = cluster_mass FIXME + self.cluster_mass = cluster_mass #FIXME? # Check if using an external evolution model (i.e. COSMIC) if hasattr(iso, 'external_evol'): @@ -183,7 +183,8 @@ def __init__(self, iso, imf, cluster_mass, ifmr=None, verbose=True, interp_keys = self.filt_names self.iso_interps = {} for ikey in interp_keys: - self.iso_interps[ikey] = LinearNDInterpolator((self.iso.points['Teff'], self.iso.points['logg'], self.iso.points['metallicity']), self.iso.points[ikey], + self.iso_interps[ikey] = LinearNDInterpolator((self.iso.points['Teff'], self.iso.points['logg'], + self.iso.points['metallicity']), self.iso.points[ikey], fill_value=np.nan) ##### @@ -193,7 +194,7 @@ def __init__(self, iso, imf, cluster_mass, ifmr=None, verbose=True, # Trim out bad systems; specifically, stars with masses outside those provided # by the model isochrone (except for compact objects). - + # Assumes external evolution software (i.e. COSMIC) will handle systems that fall outside of range if self.external_evol == False: star_systems, compMass = self._remove_bad_systems(star_systems, compMass, keep_low_mass_stars) @@ -203,100 +204,52 @@ def __init__(self, iso, imf, cluster_mass, ifmr=None, verbose=True, if self.imf.make_multiples: companions = self._make_companions_table(star_systems, compMass) + # Assigns atmospheres based on grid for external evolution software + # Must be done here instead of in Isochrone() since the systems are evolved after generation above if self.external_evol: star_systems, companions = iso.evo_model.evolve(star_systems, companions, iso.logAge, iso.metallicity) - - individual_atm = False - - if individual_atm: - - # Loop through radii too! - # Do WD and stars separately - # For each temperature extract the synthetic photometry. + + for filt in self.filt_names: + filt_name = filt.split('_') + filt_val = get_filter_info(filt_name[1] + ',' + filt_name[2], rebin=False, vega=vega) + + # Rescale magnitudes to correct radius + # Since original grid was done assuming 1 Rsun + star_systems[filt] = self.iso_interps[filt](star_systems['Teff'], star_systems['logg'], iso.metallicity) + flux_val = filt_val.flux0*(10**(-(star_systems[filt] - filt_val.mag0)/2.5)) + R_vals = np.sqrt((star_systems['L']*(units.Lsun)/(4*np.pi*c.sigma_sb.cgs*(star_systems['Teff']*units.K)**4)).to('pc^2')).value + flux_rescaled = flux_val*((R_vals / iso.distance)**2)/((float(1*units.Rsun.to('pc')) / iso.distance)**2) + m_rescaled = -2.5*np.log10(flux_rescaled/filt_val.flux0) + filt_val.mag0 + star_systems[filt] = m_rescaled + + companions[filt] = self.iso_interps[filt](companions['Teff'], companions['logg'], iso.metallicity) + flux_val = filt_val.flux0*(10**(-(companions[filt] - filt_val.mag0)/2.5)) + R_vals = np.sqrt((companions['L']*(units.Lsun)/(4*np.pi*c.sigma_sb.cgs*(companions['Teff']*units.K)**4)).to('pc^2')).value + flux_rescaled = flux_val*((R_vals / iso.distance)**2)/((float(1*units.Rsun.to('pc')) / iso.distance)**2) + m_rescaled = -2.5*np.log10(flux_rescaled/filt_val.flux0) + filt_val.mag0 + companions[filt] = m_rescaled + + # Add companions masses to primaries + N_comp_max = np.max(star_systems['N_companions']) + comp_index = np.zeros((len(star_systems), N_comp_max), dtype=int) + kk = 0 for ii in range(len(star_systems)): - # Loop is currently taking about 0.11 s per iteration - gravity = star_systems['logg'][ii] - T = star_systems['Teff'][ii] - metallicity = iso.metallicity - phase = star_systems['phase'][ii] - R = np.sqrt((star_systems['L']*(units.erg/units.s)/(4*np.pi*c.sigma_sb.cgs*(star_systems['Teff']*units.K)**4)).to('pc^2')).value[ii] - - # Get the atmosphere model now. Wavelength is in Angstroms - # This is the time-intensive call... everything else is negligable. - # If source is a star, pull from star atmospheres. If it is a WD, - # pull from WD atmospheres - nan_mag = False - if phase == 101: - star = iso.wd_atm_func(temperature=T, gravity=gravity, metallicity=metallicity, - verbose=False) - elif phase < 100: - star = iso.atm_func(temperature=T, gravity=gravity, metallicity=metallicity, - rebin=False)#rebin) - else: - nan_mag = True - - # Trim wavelength range down to JHKL range (0.5 - 5.2 microns) - star = spectrum.trimSpectrum(star, iso.wave_range[0], iso.wave_range[1]) + for cc in range(star_systems['N_companions'][ii]): + comp_index[ii][cc] = kk + kk += 1 + + # Find all the systems with at least one companion... add the flux + # of that companion to the primary. Repeat for 2 companions, + # 3 companions, etc. + for cc in range(1, N_comp_max+1): + # All systems with at least cc companions. + idx = np.where(star_systems['N_companions'] >= cc)[0] - # Convert into flux observed at Earth (unreddened) - star *= (R / iso.distance)**2 # in erg s^-1 cm^-2 A^-1 - - # Redden the spectrum. This doesn't take much time at all. - red = iso.red_law.reddening(iso.AKs).resample(star.wave) - star *= red - - for filt in self.filt_names: - if nan_mag == True: - star_systems[filt] = np.nan - else: - filt_name = filt.split('_') - filt_val = get_filter_info(filt_name[1] + ',' + filt_name[2], rebin=False, vega=vega) - mag = mag_in_filter(star, filt_val) - star_systems[filt] = mag - + # Get the location in the companions array for each system and + # the cc'th companion. + cdx = comp_index[idx, cc-1] + star_systems = self._calc_system_mag(star_systems, companions, idx, cdx, filt) - if individual_atm == False: - for filt in self.filt_names: - filt_name = filt.split('_') - filt_val = get_filter_info(filt_name[1] + ',' + filt_name[2], rebin=False, vega=vega) - - # Rescale magnitudes to correct radius - # Since original grid was done assuming 1 Rsun - star_systems[filt] = self.iso_interps[filt](star_systems['Teff'], star_systems['logg'], iso.metallicity) - flux_val = filt_val.flux0*(10**(-(star_systems[filt] - filt_val.mag0)/2.5)) - R_vals = np.sqrt((star_systems['L']*(units.Lsun)/(4*np.pi*c.sigma_sb.cgs*(star_systems['Teff']*units.K)**4)).to('pc^2')).value - flux_rescaled = flux_val*((R_vals / iso.distance)**2)/((float(1*units.Rsun.to('pc')) / iso.distance)**2) - m_rescaled = -2.5*np.log10(flux_rescaled/filt_val.flux0) + filt_val.mag0 - star_systems[filt] = m_rescaled - - companions[filt] = self.iso_interps[filt](companions['Teff'], companions['logg'], iso.metallicity) - flux_val = filt_val.flux0*(10**(-(companions[filt] - filt_val.mag0)/2.5)) - R_vals = np.sqrt((companions['L']*(units.Lsun)/(4*np.pi*c.sigma_sb.cgs*(companions['Teff']*units.K)**4)).to('pc^2')).value - flux_rescaled = flux_val*((R_vals / iso.distance)**2)/((float(1*units.Rsun.to('pc')) / iso.distance)**2) - m_rescaled = -2.5*np.log10(flux_rescaled/filt_val.flux0) + filt_val.mag0 - companions[filt] = m_rescaled - - # Add companions masses to primaries - N_comp_max = np.max(star_systems['N_companions']) - comp_index = np.zeros((len(star_systems), N_comp_max), dtype=int) - kk = 0 - for ii in range(len(star_systems)): - for cc in range(star_systems['N_companions'][ii]): - comp_index[ii][cc] = kk - kk += 1 - - # Find all the systems with at least one companion... add the flux - # of that companion to the primary. Repeat for 2 companions, - # 3 companions, etc. - for cc in range(1, N_comp_max+1): - # All systems with at least cc companions. - idx = np.where(star_systems['N_companions'] >= cc)[0] - - # Get the location in the companions array for each system and - # the cc'th companion. - cdx = comp_index[idx, cc-1] - star_systems = self._calc_system_mag(star_systems, companions, idx, cdx, filt) - #star_systems, companions = self._remove_bad_systems_and_companions(star_systems, companions) ##### From 887c03ac6bfe7e269542776cd381c2357139f0a1 Mon Sep 17 00:00:00 2001 From: nsabrams Date: Sat, 28 Mar 2026 19:18:25 -0700 Subject: [PATCH 09/28] update bse dict --- spisea/evolution.py | 45 ++++++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/spisea/evolution.py b/spisea/evolution.py index 308ebe80..1534f6a7 100755 --- a/spisea/evolution.py +++ b/spisea/evolution.py @@ -1249,27 +1249,30 @@ class COSMIC(StellarEvolution): def __init__(self, BSEDict='default', keep_disrupted_companions=True, keep_COSMIC_tables=False): if BSEDict == 'default': - self.BSEDict = BSEDict = {'xi': 1.0, 'bhflag': 1, 'neta': 0.5, - 'windflag': 3, 'wdflag': 1, 'alpha1': 1.0, - 'pts1': 0.001, 'pts3': 0.02, 'pts2': 0.01, - 'epsnov': 0.001, 'hewind': 0.5, 'ck': 1000, - 'bwind': 0.0, 'lambdaf': 0.0, 'mxns': 3.0, - 'beta': -1.0, 'tflag': 1, 'acc2': 1.5, - 'grflag' : 1, 'remnantflag': 4, 'ceflag': 0, - 'eddfac': 1.0, 'ifflag': 0, 'bconst': 3000, - 'sigma': 265.0, 'gamma': -2.0, 'pisn': 45.0, - 'natal_kick_array' : [[-100.0,-100.0,-100.0,-100.0,0.0], [-100.0,-100.0,-100.0,-100.0,0.0]], - 'bhsigmafrac' : 1.0, 'polar_kick_angle' : 90, - 'qcrit_array' : [0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0], - 'cekickflag' : 2, 'cehestarflag' : 0, 'cemergeflag' : 0, - 'ecsn' : 2.25, 'ecsn_mlow' : 1.6, 'aic' : 1, 'ussn' : 0, - 'sigmadiv' :-20.0, 'qcflag' : 1, 'eddlimflag' : 0, - 'fprimc_array' : [2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0], - 'bhspinflag' : 0, 'bhspinmag' : 0.0, 'rejuv_fac' : 1.0, - 'rejuvflag' : 0, 'htpmb' : 1, 'ST_cr' : 1, 'ST_tide' : 1, - 'bdecayfac' : 1, 'rembar_massloss' : 0.5, 'kickflag' : 1, - 'zsun' : 0.014, 'bhms_coll_flag' : 0, 'don_lim' : -1, - 'acc_lim' : -1, 'rtmsflag' : 0, 'wd_mass_lim': 1} + self.BSEDict = { + "pts1": 0.001, "pts2": 0.01, "pts3": 0.02, "zsun": 0.014, "windflag": 3, + "eddlimflag": 0, "neta": 0.5, "bwind": 0.0, "hewind": 0.5, "beta": 0.125, + "xi": 0.5, "acc2": 1.5, "LBV_flag": 1, "alpha1": 1.0, "lambdaf": 0.0, + "ceflag": 1, "cekickflag": 2, "cemergeflag": 1, "cehestarflag": 0, + "qcflag": 5, + "qcrit_array": [0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0], + "kickflag": 5, "sigma": 265.0, "bhflag": 1, "bhsigmafrac": 1.0, + "sigmadiv": -20.0, "ecsn": 2.25, "ecsn_mlow": 1.6, "aic": 1, "ussn": 1, + "polar_kick_angle": 90.0, + "natal_kick_array": [[-100.0, -100.0, -100.0, -100.0, 0.0], [-100.0, -100.0, -100.0, -100.0, 0.0]], + "mm_mu_ns": 400.0, "mm_mu_bh": 200.0, "remnantflag": 4, + "fryer_mass_limit": 0, "mxns": 3.0, "rembar_massloss": 0.5, + "wd_mass_lim": 1, "maltsev_mode": 0, "maltsev_fallback": 0.5, + "maltsev_pf_prob": 0.1, "pisn": -2, "ppi_co_shift": 0.0, + "ppi_extra_ml": 0.0, "bhspinflag": 0, "bhspinmag": 0.0, "grflag": 1, + "eddfac": 10, "gamma": -2, "don_lim": -1, "acc_lim": -1, "tflag": 1, + "ST_tide": 1, + "fprimc_array": [2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0], + "ifflag": 1, "wdflag": 1, "epsnov": 0.001, "bdecayfac": 1, + "bconst": 3000, "ck": 1000, "rejuv_fac": 1.0, "rejuvflag": 0, + "bhms_coll_flag": 0, "htpmb": 1, "ST_cr": 1, "rtmsflag": 0 + } + else: self.BSEDict = BSEDict From 973e1860af7e148ba94f5748f5f9bc2033f10887 Mon Sep 17 00:00:00 2001 From: nsabrams Date: Mon, 30 Mar 2026 17:30:14 -0700 Subject: [PATCH 10/28] change method for getting filter name --- spisea/synthetic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spisea/synthetic.py b/spisea/synthetic.py index 33164567..20e6bcd7 100755 --- a/spisea/synthetic.py +++ b/spisea/synthetic.py @@ -211,7 +211,7 @@ def __init__(self, iso, imf, cluster_mass, ifmr=None, verbose=True, for filt in self.filt_names: filt_name = filt.split('_') - filt_val = get_filter_info(filt_name[1] + ',' + filt_name[2], rebin=False, vega=vega) + filt_val = get_filter_info(get_obs_str(filt), rebin=False, vega=vega) # Rescale magnitudes to correct radius # Since original grid was done assuming 1 Rsun From 527ab2865bedf37e4b0d2f38ba4d2465f9cbc5f4 Mon Sep 17 00:00:00 2001 From: nsabrams Date: Thu, 2 Apr 2026 18:07:23 -0700 Subject: [PATCH 11/28] added read out when cosmic has a mismatch issue --- docs/Cluster_w_COSMIC.ipynb | 1920 +---------------------------------- spisea/evolution.py | 6 +- 2 files changed, 59 insertions(+), 1867 deletions(-) diff --git a/docs/Cluster_w_COSMIC.ipynb b/docs/Cluster_w_COSMIC.ipynb index 08eeacc7..3cec4912 100755 --- a/docs/Cluster_w_COSMIC.ipynb +++ b/docs/Cluster_w_COSMIC.ipynb @@ -65,1813 +65,7 @@ "metadata": { "scrolled": true }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Changing to logg=5.00 for met=0.00 T= 19250 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 8750 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 13500 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 22000 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 10750 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 11500 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 19500 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 14750 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 17000 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 12750 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 15000 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 26000 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 50000 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 6000 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 16750 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 22000 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 17250 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 19500 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 12250 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 7750 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 9500 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 29000 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 26000 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 12750 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 10000 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 12750 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 36000 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 6000 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 26000 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 9750 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 13250 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 10750 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 32000 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 10500 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 7750 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 5500 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 34000 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 7000 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 16500 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 13000 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 7500 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 7250 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 15250 logg=7.25\n", - "Changing to T= 50000 for met=0.00 T= 60000 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 60000 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 15250 logg=7.75\n", - "Changing to T= 50000 for met=0.00 T= 60000 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 60000 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 27000 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 12750 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 11000 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 7500 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 15750 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 18000 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 20000 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 16000 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 12000 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 45000 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 12000 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 9250 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 13500 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 9250 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 5000 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 9750 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 24000 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 7250 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 25000 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 14750 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 13000 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 9250 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 8500 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 8500 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 19250 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 38000 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 18750 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 23000 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 5500 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 14750 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 7500 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 10500 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 15750 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 13500 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 11500 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 30000 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 11250 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 15500 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 11500 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 12500 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 6750 logg=8.25\n", - "Changing to T= 50000 for met=0.00 T= 70000 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 70000 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 19750 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 16250 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 11000 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 16750 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 32000 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 18500 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 15250 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 6250 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 16000 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 36000 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 20000 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 17500 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 17250 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 17750 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 35000 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 18250 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 35000 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 10500 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 15250 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 21000 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 34000 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 19750 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 18500 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 18500 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 14000 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 13000 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 16000 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 13250 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 13500 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 17750 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 11250 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 36000 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 8000 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 12250 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 13500 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 7250 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 9250 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 34000 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 17750 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 28000 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 11000 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 34000 logg=6.75\n", - "Changing to T= 50000 for met=0.00 T= 80000 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 80000 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 30000 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 13500 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 5750 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 15250 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 15500 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 24000 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 11250 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 19750 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 13500 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 11000 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 24000 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 12500 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 22000 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 16750 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 14500 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 18000 logg=7.25\n", - "Changing to T= 50000 for met=0.00 T= 80000 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 80000 logg=7.50\n", - "Changing to T= 50000 for met=0.00 T= 70000 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 70000 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 29000 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 36000 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 18750 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 14000 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 16250 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 11500 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 17000 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 36000 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 19250 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 17250 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 11750 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 9750 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 13000 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 23000 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 22000 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 40000 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 15500 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 12750 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 8000 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 19500 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 19000 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 11000 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 14500 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 18000 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 11250 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 5000 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 15000 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 12500 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 23000 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 7750 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 13250 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 29000 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 32000 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 34000 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 12250 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 17750 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 12250 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 18750 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 36000 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 15250 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 40000 logg=7.00\n", - "Changing to T= 50000 for met=0.00 T= 60000 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 60000 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 29000 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 14250 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 7500 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 8250 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 9000 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 14250 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 13500 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 8750 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 12500 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 28000 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 5250 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 8750 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 10250 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 27000 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 18250 logg=6.50\n", - "Changing to T= 50000 for met=0.00 T= 60000 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 60000 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 19250 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 7750 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 40000 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 7750 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 18250 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 13750 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 45000 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 7000 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 17500 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 9250 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 14250 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 23000 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 16750 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 6250 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 10000 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 19500 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 19500 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 9250 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 30000 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 25000 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 7250 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 14750 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 5000 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 6250 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 14500 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 11750 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 6750 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 18250 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 13000 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 13750 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 8500 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 35000 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 40000 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 17500 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 8000 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 13250 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 18250 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 6000 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 5000 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 34000 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 5500 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 18000 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 10500 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 40000 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 26000 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 35000 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 9250 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 13750 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 12750 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 19000 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 30000 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 10000 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 19250 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 10000 logg=6.75\n", - "Changing to T= 50000 for met=0.00 T= 70000 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 70000 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 9500 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 5500 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 11500 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 22000 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 6250 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 25000 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 19750 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 21000 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 9750 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 16250 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 27000 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 18000 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 14750 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 19250 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 18250 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 14250 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 29000 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 6250 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 12250 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 21000 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 18250 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 26000 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 8000 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 13000 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 17750 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 16750 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 12000 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 26000 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 32000 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 16750 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 11000 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 12750 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 18500 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 19500 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 19750 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 16750 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 29000 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 8750 logg=6.75\n", - "Changing to T= 50000 for met=0.00 T= 70000 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 70000 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 12250 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 5750 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 15750 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 34000 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 9250 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 12500 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 6250 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 12500 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 6500 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 10500 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 12750 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 10750 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 14250 logg=6.50\n", - "Changing to T= 50000 for met=0.00 T= 80000 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 80000 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 17000 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 5250 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 21000 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 29000 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 18000 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 5250 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 15500 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 10250 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 5500 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 38000 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 10500 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 12750 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 18500 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 9250 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 13750 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 12250 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 19000 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 13750 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 8250 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 14250 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 8000 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 7500 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 11500 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 10500 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 6250 logg=9.00\n", - "Changing to T= 50000 for met=0.00 T= 80000 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 80000 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 45000 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 22000 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 19500 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 38000 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 10250 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 17000 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 9750 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 8750 logg=8.50\n", - "Changing to T= 50000 for met=0.00 T= 80000 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 80000 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 14500 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 30000 logg=7.75\n", - "Changing to T= 50000 for met=0.00 T= 80000 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 80000 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 13750 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 6000 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 14750 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 6500 logg=8.50\n", - "Changing to T= 50000 for met=0.00 T= 60000 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 60000 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 13750 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 18500 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 19250 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 29000 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 16500 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 18500 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 23000 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 5750 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 12750 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 25000 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 10250 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 14000 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 7000 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 11250 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 6250 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 11750 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 10250 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 12500 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 15000 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 6500 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 6250 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 5500 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 10250 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 17500 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 23000 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 36000 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 7000 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 11750 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 50000 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 10250 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 11750 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 12000 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 12000 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 50000 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 19750 logg=7.25\n", - "Changing to T= 50000 for met=0.00 T= 60000 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 60000 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 10250 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 7250 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 17750 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 50000 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 17250 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 16000 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 11250 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 11500 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 13750 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 8250 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 13250 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 26000 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 14500 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 9500 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 17000 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 15750 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 14500 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 29000 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 16500 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 8500 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 50000 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 22000 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 13000 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 18750 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 5250 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 26000 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 16750 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 34000 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 13500 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 32000 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 30000 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 13500 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 25000 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 7750 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 26000 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 17750 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 32000 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 14500 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 13000 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 5750 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 34000 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 11750 logg=9.25\n", - "Changing to T= 50000 for met=0.00 T= 60000 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 60000 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 9750 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 29000 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 19750 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 5250 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 16500 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 13750 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 24000 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 12500 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 35000 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 28000 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 24000 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 28000 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 28000 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 12250 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 18750 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 13250 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 8250 logg=9.25\n", - "Changing to T= 50000 for met=0.00 T= 70000 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 70000 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 5500 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 10750 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 25000 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 6000 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 11750 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 8250 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 15000 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 18750 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 18000 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 18000 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 9000 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 11500 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 30000 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 24000 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 45000 logg=8.75\n", - "Changing to T= 50000 for met=0.00 T= 60000 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 60000 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 7000 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 30000 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 8000 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 12500 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 9000 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 5000 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 15000 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 15500 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 5000 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 7250 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 19250 logg=9.00\n", - "Changing to T= 50000 for met=0.00 T= 70000 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 70000 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 10500 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 7000 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 11750 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 5000 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 10000 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 20000 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 7500 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 38000 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 11500 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 9500 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 9750 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 14000 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 8750 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 10750 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 13750 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 19250 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 19250 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 14750 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 6250 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 19750 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 19500 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 8500 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 7500 logg=9.50\n", - "Changing to T= 50000 for met=0.00 T= 70000 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 70000 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 16000 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 50000 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 7500 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 24000 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 45000 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 6750 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 7750 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 16000 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 13000 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 23000 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 32000 logg=6.50\n", - "Changing to T= 50000 for met=0.00 T= 70000 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 70000 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 5250 logg=7.50\n", - "Changing to T= 50000 for met=0.00 T= 70000 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 70000 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 18750 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 9750 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 17750 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 18750 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 28000 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 10000 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 18000 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 8500 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 19250 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 8500 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 11250 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 18750 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 15750 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 8500 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 16750 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 17500 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 15000 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 40000 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 10500 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 11000 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 6500 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 9000 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 8500 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 40000 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 32000 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 19000 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 16000 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 14250 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 15000 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 8000 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 10250 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 19750 logg=8.25\n", - "Changing to T= 50000 for met=0.00 T= 80000 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 80000 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 13250 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 32000 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 17250 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 38000 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 12000 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 17250 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 17000 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 13500 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 10000 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 26000 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 15250 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 32000 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 7250 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 38000 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 6000 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 17500 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 16250 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 16000 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 6500 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 24000 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 5250 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 8000 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 19000 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 18750 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 11750 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 17250 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 22000 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 14000 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 15750 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 27000 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 14750 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 12500 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 12000 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 7750 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 15750 logg=9.00\n", - "Changing to T= 50000 for met=0.00 T= 70000 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 70000 logg=9.25\n", - "Changing to T= 50000 for met=0.00 T= 70000 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 70000 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 9000 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 13250 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 8250 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 5250 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 7500 logg=7.25\n", - "Changing to T= 50000 for met=0.00 T= 60000 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 60000 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 14250 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 9250 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 9500 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 30000 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 5500 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 5250 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 28000 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 9500 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 10750 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 5000 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 22000 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 6750 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 20000 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 12750 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 14750 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 7000 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 15500 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 11750 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 19000 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 17250 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 18500 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 40000 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 27000 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 9000 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 11250 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 30000 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 19000 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 16250 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 18000 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 25000 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 19500 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 6250 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 7250 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 50000 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 50000 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 6250 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 50000 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 9500 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 6500 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 19500 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 6750 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 13750 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 10000 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 19750 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 7500 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 36000 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 20000 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 18500 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 6000 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 35000 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 17000 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 7750 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 9750 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 11000 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 34000 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 21000 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 14250 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 45000 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 14250 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 5500 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 17000 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 21000 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 12500 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 19250 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 7000 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 10500 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 14000 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 35000 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 11750 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 8250 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 15250 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 18250 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 38000 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 9500 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 23000 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 16500 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 7750 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 5500 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 23000 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 5000 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 23000 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 13000 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 15250 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 16250 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 17750 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 8250 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 35000 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 6500 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 6750 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 9250 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 40000 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 21000 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 9000 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 13250 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 15500 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 16000 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 11250 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 19750 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 5000 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 10250 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 16250 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 10250 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 12250 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 6500 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 10750 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 21000 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 6750 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 27000 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 16250 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 12500 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 17500 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 5750 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 45000 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 17000 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 5000 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 17250 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 10750 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 50000 logg=8.25\n", - "Changing to T= 50000 for met=0.00 T= 80000 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 80000 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 14750 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 16000 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 12750 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 11000 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 22000 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 6750 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 17500 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 20000 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 32000 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 35000 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 15250 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 15000 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 16500 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 27000 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 6000 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 15250 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 25000 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 6500 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 11500 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 38000 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 5000 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 15750 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 18750 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 45000 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 19750 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 8250 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 17250 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 10500 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 14500 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 11000 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 40000 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 16500 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 12250 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 13000 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 5250 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 15250 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 18250 logg=8.50\n", - "Changing to T= 50000 for met=0.00 T= 60000 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 60000 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 40000 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 34000 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 14000 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 12000 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 38000 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 19000 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 11250 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 24000 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 26000 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 9000 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 9500 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 18000 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 24000 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 12250 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 28000 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 10750 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 11250 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 11750 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 6750 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 8250 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 14000 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 15000 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 8500 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 35000 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 7000 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 19000 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 20000 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 15000 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 13750 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 8750 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 14500 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 15500 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 8750 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 9250 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 22000 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 19000 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 26000 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 15750 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 15500 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 8750 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 15000 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 7000 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 34000 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 5750 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 12000 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 7250 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 14750 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 15750 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 9500 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 14000 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 50000 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 12250 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 8500 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 14000 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 18750 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 14500 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 12000 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 16500 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 13250 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 13500 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 11500 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 25000 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 7000 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 15000 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 9500 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 27000 logg=7.50\n", - "Changing to T= 50000 for met=0.00 T= 80000 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 80000 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 6750 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 14750 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 30000 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 17000 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 9500 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 36000 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 9000 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 14500 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 9000 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 11750 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 8750 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 32000 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 18500 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 34000 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 9750 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 13500 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 28000 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 6500 logg=6.50\n", - "Changing to T= 50000 for met=0.00 T= 80000 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 80000 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 8000 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 11000 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 14000 logg=8.50\n", - "Changing to T= 50000 for met=0.00 T= 60000 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 60000 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 18500 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 20000 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 8000 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 24000 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 21000 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 8750 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 12000 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 20000 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 12000 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 5750 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 10000 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 16500 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 17000 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 40000 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 10500 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 15250 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 15500 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 10250 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 45000 logg=7.75\n", - "Changing to T= 50000 for met=0.00 T= 60000 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 60000 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 20000 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 6750 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 17500 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 18000 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 5500 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 18250 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 28000 logg=9.50\n", - "Changing to T= 50000 for met=0.00 T= 80000 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 80000 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 5750 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 6250 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 10000 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 11500 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 5000 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 38000 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 16250 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 12750 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 6000 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 16750 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 16750 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 36000 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 10750 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 25000 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 15000 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 14500 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 13750 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 24000 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 50000 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 15500 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 29000 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 35000 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 21000 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 17500 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 25000 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 16000 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 15750 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 18500 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 36000 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 10250 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 13250 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 6000 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 7250 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 30000 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 17750 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 17250 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 15750 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 16500 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 45000 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 10750 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 7750 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 38000 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 16000 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 17000 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 26000 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 7000 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 38000 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 14500 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 7750 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 28000 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 14000 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 6000 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 22000 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 20000 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 10000 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 19000 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 9750 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 5750 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 8250 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 6750 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 8000 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 11000 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 16250 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 27000 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 14250 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 17250 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 45000 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 5750 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 8250 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 10000 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 36000 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 38000 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 8500 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 21000 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 8250 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 17000 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 8750 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 5500 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 14750 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 17500 logg=7.75\n", - "Changing to T= 50000 for met=0.00 T= 80000 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 80000 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 9000 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 16250 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 17750 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 35000 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 35000 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 16500 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 27000 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 9250 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 23000 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 5750 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 40000 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 13000 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 10500 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 16750 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 7250 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 18000 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 27000 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 16750 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 5250 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 25000 logg=7.00\n", - "Changing to T= 50000 for met=0.00 T= 60000 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 60000 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 6500 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 15500 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 28000 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 8000 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 32000 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 16000 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 21000 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 17750 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 18250 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 9750 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 12500 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 15500 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 10000 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 36000 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 13000 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 19000 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 12250 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 8000 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 9500 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 17500 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 9000 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 19250 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 11500 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 45000 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 7250 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 16500 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 19500 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 30000 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 6500 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 23000 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 6500 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 19000 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 15750 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 9000 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 11250 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 10750 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 17500 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 7250 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 8500 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 5250 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 7000 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 50000 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 8750 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 19500 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 27000 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 7500 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 25000 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 18250 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 16250 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 5750 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 11000 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 14250 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 7750 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 20000 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 10750 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 18250 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 7500 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 16250 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 6750 logg=7.25\n", - "Changing to logg=5.00 for met=0.00 T= 29000 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 6000 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 29000 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 14250 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 18500 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 16500 logg=6.75\n", - "Changing to T= 50000 for met=0.00 T= 70000 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 70000 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 20000 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 9750 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 6000 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 45000 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 24000 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 18750 logg=8.25\n", - "Changing to logg=5.00 for met=0.00 T= 23000 logg=7.50\n", - "Changing to T= 50000 for met=0.00 T= 70000 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 70000 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 13250 logg=9.50\n", - "Changing to logg=5.00 for met=0.00 T= 19750 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 11250 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 28000 logg=7.75\n", - "Changing to logg=5.00 for met=0.00 T= 5750 logg=9.25\n", - "Changing to logg=5.00 for met=0.00 T= 5250 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 27000 logg=7.00\n", - "Changing to logg=5.00 for met=0.00 T= 7500 logg=6.75\n", - "Changing to logg=5.00 for met=0.00 T= 17250 logg=8.00\n", - "Changing to logg=5.00 for met=0.00 T= 19500 logg=9.50\n", - "Changing to T= 50000 for met=0.00 T= 80000 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 80000 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 22000 logg=8.75\n", - "Changing to logg=5.00 for met=0.00 T= 12000 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 17750 logg=7.50\n", - "Changing to logg=5.00 for met=0.00 T= 13250 logg=6.50\n", - "Changing to logg=5.00 for met=0.00 T= 5500 logg=8.50\n", - "Changing to logg=5.00 for met=0.00 T= 21000 logg=9.00\n", - "Changing to logg=5.00 for met=0.00 T= 14000 logg=9.00\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/u/nsabrams/code/multiplicity/PyPopStar/spisea/atmospheres.py:1470: UserWarning: Only `temperature` keyword is used for black-body atmosphere\n", - " warnings.warn(\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "Changing to logg=5.00 for met=0.00 T= 2000 logg=6.00\n", - "Changing to logg=5.00 for met=0.00 T= 2082 logg=6.00\n", - "Changing to logg=5.00 for met=0.00 T= 2166 logg=6.00\n", - "Changing to logg=5.00 for met=0.00 T= 2255 logg=6.00\n", - "Changing to logg=5.00 for met=0.00 T= 2347 logg=6.00\n", - "Changing to logg=5.50 for met=0.00 T= 2442 logg=6.00\n", - "Changing to logg=5.50 for met=0.00 T= 2542 logg=6.00\n", - "Changing to logg=5.50 for met=0.00 T= 2646 logg=6.00\n", - "Changing to logg=5.50 for met=0.00 T= 2754 logg=6.00\n", - "Changing to logg=5.50 for met=0.00 T= 2866 logg=6.00\n", - "Changing to logg=5.50 for met=0.00 T= 2983 logg=6.00\n", - "Changing to logg=5.50 for met=0.00 T= 3104 logg=6.00\n", - "Changing to logg=5.50 for met=0.00 T= 3231 logg=6.00\n", - "Changing to logg=5.50 for met=0.00 T= 3363 logg=6.00\n", - "Changing to logg=5.50 for met=0.00 T= 3500 logg=6.00\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "Changing to logg=5.50 for met=0.00 T= 3500 logg=6.25\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "BB atmosphere\n", - "Atmosphere grid generation took 469.690594 s.\n", - "Making photometry for atmosphere grid: AKs = 0.00 dist = 4000\n", - " Starting at: 2026-01-28 18:35:13.544283 Usually takes ~5 minutes\n", - "Starting filter: ubv,U Elapsed time: 0.00 seconds\n", - "Starting synthetic photometry\n", - "M = 1200.000 Msun T = 3 K m_ubv_U = 38.21\n", - "M = 2350.000 Msun T = 4 K m_ubv_U = 31.95\n", - "M = 2500.000 Msun T = 3 K m_ubv_U = 28.71\n", - "M = 3300.000 Msun T = 1 K m_ubv_U = 26.31\n", - "M = 4000.000 Msun T = 6 K m_ubv_U = 22.38\n", - "M = 4800.000 Msun T = 4 K m_ubv_U = 19.86\n", - "M = 2900.000 Msun T = 2 K m_ubv_U = 27.49\n", - "M = 3600.000 Msun T = 6 K m_ubv_U = 24.22\n", - "M = 4400.000 Msun T = 4 K m_ubv_U = 20.97\n", - "M = 2500.000 Msun T = 2 K m_ubv_U = 29.16\n", - "M = 3300.000 Msun T = 0 K m_ubv_U = 26.78\n", - "M = 4000.000 Msun T = 4 K m_ubv_U = 22.18\n", - "M = 4800.000 Msun T = 2 K m_ubv_U = 19.86\n", - "M = 2900.000 Msun T = 0 K m_ubv_U = 27.02\n", - "M = 3600.000 Msun T = 5 K m_ubv_U = 23.84\n", - "M = 4400.000 Msun T = 3 K m_ubv_U = 20.95\n", - "M = 2500.000 Msun T = 1 K m_ubv_U = 27.78\n", - "M = 3200.000 Msun T = 6 K m_ubv_U = 26.12\n", - "M = 4000.000 Msun T = 4 K m_ubv_U = 22.43\n", - "M = 4800.000 Msun T = 2 K m_ubv_U = 20.35\n", - "M = 2800.000 Msun T = 6 K m_ubv_U = 29.21\n", - "M = 3600.000 Msun T = 4 K m_ubv_U = 23.66\n", - "M = 4400.000 Msun T = 2 K m_ubv_U = 21.66\n", - "M = 2700.000 Msun T = 1 K m_ubv_U = 27.15\n", - "M = 4000.000 Msun T = 5 K m_ubv_U = 22.66\n", - "M = 4800.000 Msun T = 3 K m_ubv_U = 20.73\n", - "M = 2900.000 Msun T = 1 K m_ubv_U = 27.27\n", - "M = 3600.000 Msun T = 6 K m_ubv_U = 23.62\n", - "M = 4400.000 Msun T = 4 K m_ubv_U = 22.10\n", - "M = 2500.000 Msun T = 2 K m_ubv_U = 27.67\n", - "M = 3200.000 Msun T = 6 K m_ubv_U = 25.03\n", - "M = 4000.000 Msun T = 4 K m_ubv_U = 23.13\n", - "M = 4800.000 Msun T = 2 K m_ubv_U = 21.97\n", - "M = 5250.000 Msun T = 0 K m_ubv_U = 20.51\n", - "M = 10000.000 Msun T = 3 K m_ubv_U = 15.48\n", - "M = 16000.000 Msun T = 4 K m_ubv_U = 14.00\n", - "M = 40000.000 Msun T = 4 K m_ubv_U = 11.61\n", - "M = 7250.000 Msun T = 4 K m_ubv_U = 17.06\n", - "M = 10500.000 Msun T = 2 K m_ubv_U = 15.23\n", - "M = 18000.000 Msun T = 4 K m_ubv_U = 13.72\n", - "M = 46000.000 Msun T = 4 K m_ubv_U = 11.44\n", - "M = 7500.000 Msun T = 4 K m_ubv_U = 16.84\n", - "M = 10750.000 Msun T = 4 K m_ubv_U = 15.37\n", - "M = 20000.000 Msun T = 4 K m_ubv_U = 13.49\n", - "M = 5500.000 Msun T = 2 K m_ubv_U = 18.80\n", - "M = 8000.000 Msun T = 2 K m_ubv_U = 16.44\n", - "M = 11250.000 Msun T = 4 K m_ubv_U = 15.15\n", - "M = 23000.000 Msun T = 3 K m_ubv_U = 12.97\n", - "M = 5750.000 Msun T = 2 K m_ubv_U = 18.37\n", - "M = 8250.000 Msun T = 3 K m_ubv_U = 16.41\n", - "M = 11750.000 Msun T = 2 K m_ubv_U = 14.93\n", - "M = 25000.000 Msun T = 4 K m_ubv_U = 12.88\n", - "M = 6000.000 Msun T = 2 K m_ubv_U = 18.04\n", - "M = 8500.000 Msun T = 5 K m_ubv_U = 16.30\n", - "M = 12250.000 Msun T = 2 K m_ubv_U = 14.62\n", - "M = 28000.000 Msun T = 4 K m_ubv_U = 12.31\n", - "M = 6250.000 Msun T = 4 K m_ubv_U = 17.99\n", - "M = 9000.000 Msun T = 3 K m_ubv_U = 15.92\n", - "M = 12750.000 Msun T = 2 K m_ubv_U = 14.46\n", - "M = 31000.000 Msun T = 4 K m_ubv_U = 12.02\n", - "M = 6500.000 Msun T = 4 K m_ubv_U = 17.71\n", - "M = 9500.000 Msun T = 2 K m_ubv_U = 15.56\n", - "M = 14000.000 Msun T = 2 K m_ubv_U = 14.07\n", - "M = 34000.000 Msun T = 5 K m_ubv_U = 11.88\n", - "M = 7000.000 Msun T = 0 K m_ubv_U = 17.33\n", - "M = 9750.000 Msun T = 4 K m_ubv_U = 15.62\n", - "M = 20000.000 Msun T = 8 K m_ubv_U = 13.39\n", - "M = 8750.000 Msun T = 8 K m_ubv_U = 16.14\n", - "M = 29000.000 Msun T = 8 K m_ubv_U = 12.39\n", - "M = 17250.000 Msun T = 9 K m_ubv_U = 13.78\n", - "M = 19250.000 Msun T = 7 K m_ubv_U = 13.49\n", - "M = 9250.000 Msun T = 9 K m_ubv_U = 15.91\n", - "M = 10250.000 Msun T = 8 K m_ubv_U = 15.50\n", - "M = 12000.000 Msun T = 8 K m_ubv_U = 14.90\n", - "M = 15750.000 Msun T = 7 K m_ubv_U = 14.03\n", - "M = 7250.000 Msun T = 8 K m_ubv_U = 16.99\n", - "M = 3384.462 Msun T = 7 K m_ubv_U = 23.53\n", - "M = 3384.462 Msun T = 8 K m_ubv_U = 23.53\n", - "M = 8634.788 Msun T = 10 K m_ubv_U = 15.87\n", - "M = 8634.788 Msun T = 11 K m_ubv_U = 15.87\n", - "Starting filter: ubv,V Elapsed time: 48.59 seconds\n", - "Starting synthetic photometry\n", - "M = 1200.000 Msun T = 3 K m_ubv_V = 35.26\n", - "M = 2350.000 Msun T = 4 K m_ubv_V = 27.90\n", - "M = 2500.000 Msun T = 3 K m_ubv_V = 23.30\n", - "M = 3300.000 Msun T = 1 K m_ubv_V = 22.54\n", - "M = 4000.000 Msun T = 6 K m_ubv_V = 20.11\n", - "M = 4800.000 Msun T = 4 K m_ubv_V = 19.07\n", - "M = 2900.000 Msun T = 2 K m_ubv_V = 23.20\n", - "M = 3600.000 Msun T = 6 K m_ubv_V = 20.77\n", - "M = 4400.000 Msun T = 4 K m_ubv_V = 19.62\n", - "M = 2500.000 Msun T = 2 K m_ubv_V = 24.72\n", - "M = 3300.000 Msun T = 0 K m_ubv_V = 22.67\n", - "M = 4000.000 Msun T = 4 K m_ubv_V = 20.22\n", - "M = 4800.000 Msun T = 2 K m_ubv_V = 18.97\n", - "M = 2900.000 Msun T = 0 K m_ubv_V = 23.97\n", - "M = 3600.000 Msun T = 5 K m_ubv_V = 21.04\n", - "M = 4400.000 Msun T = 3 K m_ubv_V = 19.52\n", - "M = 2500.000 Msun T = 1 K m_ubv_V = 26.45\n", - "M = 3200.000 Msun T = 6 K m_ubv_V = 22.15\n", - "M = 4000.000 Msun T = 4 K m_ubv_V = 20.28\n", - "M = 4800.000 Msun T = 2 K m_ubv_V = 19.00\n", - "M = 2800.000 Msun T = 6 K m_ubv_V = 24.27\n", - "M = 3600.000 Msun T = 4 K m_ubv_V = 21.15\n", - "M = 4400.000 Msun T = 2 K m_ubv_V = 19.56\n", - "M = 2700.000 Msun T = 1 K m_ubv_V = 26.75\n", - "M = 4000.000 Msun T = 5 K m_ubv_V = 20.32\n", - "M = 4800.000 Msun T = 3 K m_ubv_V = 18.93\n", - "M = 2900.000 Msun T = 1 K m_ubv_V = 26.33\n", - "M = 3600.000 Msun T = 6 K m_ubv_V = 21.45\n", - "M = 4400.000 Msun T = 4 K m_ubv_V = 19.57\n", - "M = 2500.000 Msun T = 2 K m_ubv_V = 27.48\n", - "M = 3200.000 Msun T = 6 K m_ubv_V = 22.86\n", - "M = 4000.000 Msun T = 4 K m_ubv_V = 20.66\n", - "M = 4800.000 Msun T = 2 K m_ubv_V = 19.01\n", - "M = 5250.000 Msun T = 0 K m_ubv_V = 18.42\n", - "M = 10000.000 Msun T = 3 K m_ubv_V = 15.66\n", - "M = 16000.000 Msun T = 4 K m_ubv_V = 14.74\n", - "M = 40000.000 Msun T = 4 K m_ubv_V = 13.01\n", - "M = 7250.000 Msun T = 4 K m_ubv_V = 16.75\n", - "M = 10500.000 Msun T = 2 K m_ubv_V = 15.59\n", - "M = 18000.000 Msun T = 4 K m_ubv_V = 14.56\n", - "M = 46000.000 Msun T = 4 K m_ubv_V = 12.86\n", - "M = 7500.000 Msun T = 4 K m_ubv_V = 16.68\n", - "M = 10750.000 Msun T = 4 K m_ubv_V = 15.52\n", - "M = 20000.000 Msun T = 4 K m_ubv_V = 14.40\n", - "M = 5500.000 Msun T = 2 K m_ubv_V = 18.11\n", - "M = 8000.000 Msun T = 2 K m_ubv_V = 16.32\n", - "M = 11250.000 Msun T = 4 K m_ubv_V = 15.45\n", - "M = 23000.000 Msun T = 3 K m_ubv_V = 14.09\n", - "M = 5750.000 Msun T = 2 K m_ubv_V = 17.90\n", - "M = 8250.000 Msun T = 3 K m_ubv_V = 16.23\n", - "M = 11750.000 Msun T = 2 K m_ubv_V = 15.38\n", - "M = 25000.000 Msun T = 4 K m_ubv_V = 13.99\n", - "M = 6000.000 Msun T = 2 K m_ubv_V = 17.71\n", - "M = 8500.000 Msun T = 5 K m_ubv_V = 16.20\n", - "M = 12250.000 Msun T = 2 K m_ubv_V = 15.19\n", - "M = 28000.000 Msun T = 4 K m_ubv_V = 13.59\n", - "M = 6250.000 Msun T = 4 K m_ubv_V = 17.42\n", - "M = 9000.000 Msun T = 3 K m_ubv_V = 15.89\n", - "M = 12750.000 Msun T = 2 K m_ubv_V = 15.10\n", - "M = 31000.000 Msun T = 4 K m_ubv_V = 13.36\n", - "M = 6500.000 Msun T = 4 K m_ubv_V = 17.23\n", - "M = 9500.000 Msun T = 2 K m_ubv_V = 15.76\n", - "M = 14000.000 Msun T = 2 K m_ubv_V = 14.90\n", - "M = 34000.000 Msun T = 5 K m_ubv_V = 13.22\n", - "M = 7000.000 Msun T = 0 K m_ubv_V = 16.78\n", - "M = 9750.000 Msun T = 4 K m_ubv_V = 15.64\n", - "M = 20000.000 Msun T = 8 K m_ubv_V = 14.32\n", - "M = 8750.000 Msun T = 8 K m_ubv_V = 16.00\n", - "M = 29000.000 Msun T = 8 K m_ubv_V = 13.62\n", - "M = 17250.000 Msun T = 9 K m_ubv_V = 14.58\n", - "M = 19250.000 Msun T = 7 K m_ubv_V = 14.39\n", - "M = 9250.000 Msun T = 9 K m_ubv_V = 15.82\n", - "M = 10250.000 Msun T = 8 K m_ubv_V = 15.56\n", - "M = 12000.000 Msun T = 8 K m_ubv_V = 15.24\n", - "M = 15750.000 Msun T = 7 K m_ubv_V = 14.73\n", - "M = 7250.000 Msun T = 8 K m_ubv_V = 16.78\n", - "M = 3384.462 Msun T = 7 K m_ubv_V = 21.36\n", - "M = 3384.462 Msun T = 8 K m_ubv_V = 21.36\n", - "M = 8634.788 Msun T = 10 K m_ubv_V = 16.21\n", - "M = 8634.788 Msun T = 11 K m_ubv_V = 16.21\n", - "Starting filter: ubv,R Elapsed time: 96.13 seconds\n", - "Starting synthetic photometry\n", - "M = 1200.000 Msun T = 3 K m_ubv_R = 30.81\n", - "M = 2350.000 Msun T = 4 K m_ubv_R = 25.83\n", - "M = 2500.000 Msun T = 3 K m_ubv_R = 21.96\n", - "M = 3300.000 Msun T = 1 K m_ubv_R = 21.36\n", - "M = 4000.000 Msun T = 6 K m_ubv_R = 19.41\n", - "M = 4800.000 Msun T = 4 K m_ubv_R = 18.59\n", - "M = 2900.000 Msun T = 2 K m_ubv_R = 21.95\n", - "M = 3600.000 Msun T = 6 K m_ubv_R = 19.92\n", - "M = 4400.000 Msun T = 4 K m_ubv_R = 19.04\n", - "M = 2500.000 Msun T = 2 K m_ubv_R = 23.40\n", - "M = 3300.000 Msun T = 0 K m_ubv_R = 21.60\n", - "M = 4000.000 Msun T = 4 K m_ubv_R = 19.51\n", - "M = 4800.000 Msun T = 2 K m_ubv_R = 18.52\n", - "M = 2900.000 Msun T = 0 K m_ubv_R = 22.84\n", - "M = 3600.000 Msun T = 5 K m_ubv_R = 20.18\n", - "M = 4400.000 Msun T = 3 K m_ubv_R = 18.98\n", - "M = 2500.000 Msun T = 1 K m_ubv_R = 24.75\n", - "M = 3200.000 Msun T = 6 K m_ubv_R = 21.14\n", - "M = 4000.000 Msun T = 4 K m_ubv_R = 19.56\n", - "M = 4800.000 Msun T = 2 K m_ubv_R = 18.53\n", - "M = 2800.000 Msun T = 6 K m_ubv_R = 22.92\n", - "M = 3600.000 Msun T = 4 K m_ubv_R = 20.31\n", - "M = 4400.000 Msun T = 2 K m_ubv_R = 18.99\n", - "M = 2700.000 Msun T = 1 K m_ubv_R = 25.14\n", - "M = 4000.000 Msun T = 5 K m_ubv_R = 19.56\n", - "M = 4800.000 Msun T = 3 K m_ubv_R = 18.43\n", - "M = 2900.000 Msun T = 1 K m_ubv_R = 24.80\n", - "M = 3600.000 Msun T = 6 K m_ubv_R = 20.61\n", - "M = 4400.000 Msun T = 4 K m_ubv_R = 18.92\n", - "M = 2500.000 Msun T = 2 K m_ubv_R = 25.78\n", - "M = 3200.000 Msun T = 6 K m_ubv_R = 21.85\n", - "M = 4000.000 Msun T = 4 K m_ubv_R = 19.90\n", - "M = 4800.000 Msun T = 2 K m_ubv_R = 18.40\n", - "M = 5250.000 Msun T = 0 K m_ubv_R = 17.95\n", - "M = 10000.000 Msun T = 3 K m_ubv_R = 15.67\n", - "M = 16000.000 Msun T = 4 K m_ubv_R = 14.80\n", - "M = 40000.000 Msun T = 4 K m_ubv_R = 13.13\n", - "M = 7250.000 Msun T = 4 K m_ubv_R = 16.60\n", - "M = 10500.000 Msun T = 2 K m_ubv_R = 15.59\n", - "M = 18000.000 Msun T = 4 K m_ubv_R = 14.63\n", - "M = 46000.000 Msun T = 4 K m_ubv_R = 12.99\n", - "M = 7500.000 Msun T = 4 K m_ubv_R = 16.53\n", - "M = 10750.000 Msun T = 4 K m_ubv_R = 15.54\n", - "M = 20000.000 Msun T = 4 K m_ubv_R = 14.47\n", - "M = 5500.000 Msun T = 2 K m_ubv_R = 17.77\n", - "M = 8000.000 Msun T = 2 K m_ubv_R = 16.27\n", - "M = 11250.000 Msun T = 4 K m_ubv_R = 15.47\n", - "M = 23000.000 Msun T = 3 K m_ubv_R = 14.18\n", - "M = 5750.000 Msun T = 2 K m_ubv_R = 17.60\n", - "M = 8250.000 Msun T = 3 K m_ubv_R = 16.19\n", - "M = 11750.000 Msun T = 2 K m_ubv_R = 15.40\n", - "M = 25000.000 Msun T = 4 K m_ubv_R = 14.09\n", - "M = 6000.000 Msun T = 2 K m_ubv_R = 17.44\n", - "M = 8500.000 Msun T = 5 K m_ubv_R = 16.12\n", - "M = 12250.000 Msun T = 2 K m_ubv_R = 15.21\n", - "M = 28000.000 Msun T = 4 K m_ubv_R = 13.70\n", - "M = 6250.000 Msun T = 4 K m_ubv_R = 17.14\n", - "M = 9000.000 Msun T = 3 K m_ubv_R = 15.88\n", - "M = 12750.000 Msun T = 2 K m_ubv_R = 15.12\n", - "M = 31000.000 Msun T = 4 K m_ubv_R = 13.46\n", - "M = 6500.000 Msun T = 4 K m_ubv_R = 16.97\n", - "M = 9500.000 Msun T = 2 K m_ubv_R = 15.74\n", - "M = 14000.000 Msun T = 2 K m_ubv_R = 14.92\n", - "M = 34000.000 Msun T = 5 K m_ubv_R = 13.35\n", - "M = 7000.000 Msun T = 0 K m_ubv_R = 16.64\n", - "M = 9750.000 Msun T = 4 K m_ubv_R = 15.65\n", - "M = 20000.000 Msun T = 8 K m_ubv_R = 14.40\n", - "M = 8750.000 Msun T = 8 K m_ubv_R = 15.95\n", - "M = 29000.000 Msun T = 8 K m_ubv_R = 13.73\n", - "M = 17250.000 Msun T = 9 K m_ubv_R = 14.64\n", - "M = 19250.000 Msun T = 7 K m_ubv_R = 14.46\n", - "M = 9250.000 Msun T = 9 K m_ubv_R = 15.80\n", - "M = 10250.000 Msun T = 8 K m_ubv_R = 15.58\n", - "M = 12000.000 Msun T = 8 K m_ubv_R = 15.27\n", - "M = 15750.000 Msun T = 7 K m_ubv_R = 14.79\n", - "M = 7250.000 Msun T = 8 K m_ubv_R = 16.59\n", - "M = 3384.462 Msun T = 7 K m_ubv_R = 20.52\n", - "M = 3384.462 Msun T = 8 K m_ubv_R = 20.52\n", - "M = 8634.788 Msun T = 10 K m_ubv_R = 16.04\n", - "M = 8634.788 Msun T = 11 K m_ubv_R = 16.04\n", - " Time taken: 140.46 seconds\n" - ] - } - ], + "outputs": [], "source": [ "# Fetch isochrone\n", "logAge = 10 # Age in log(years)\n", @@ -1919,7 +113,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 9, "id": "17d315a9-ec84-4289-a810-855443628e67", "metadata": { "scrolled": true @@ -1929,72 +123,66 @@ "name": "stderr", "output_type": "stream", "text": [ - "/opt/mambaforge3/envs/astro_cosmic/lib/python3.11/site-packages/cosmic/utils.py:1687: UserWarning: At least one of your initial binaries is starting in Roche Lobe Overflow:\n", + "/opt/mambaforge3/envs/astro_cosmic/lib/python3.11/site-packages/cosmic/utils.py:1324: UserWarning: At least one of your initial binaries is starting in Roche Lobe Overflow:\n", " kstar_1 kstar_2 mass_1 mass_2 porb ecc \\\n", - "353 1.0 0.0 45.316990 0.542011 0.514938 0.812602 \n", - "1580 1.0 0.0 25.262665 0.535898 0.166185 0.582260 \n", - "1895 1.0 0.0 3.391836 0.068421 0.256683 0.908815 \n", - "2347 1.0 1.0 21.828894 8.560945 0.142712 0.845244 \n", - "2446 1.0 1.0 266.788235 36.299586 0.254315 0.101827 \n", - "3987 1.0 1.0 65.996710 21.339760 0.069611 0.657800 \n", - "4844 1.0 1.0 221.496477 13.473508 0.026316 0.617358 \n", - "4985 1.0 0.0 44.273694 0.542706 0.792597 0.445727 \n", - "6791 1.0 1.0 58.324942 9.742695 0.369382 0.778012 \n", - "10605 1.0 1.0 2.818451 0.762687 0.195033 0.985095 \n", - "11004 1.0 1.0 6.191172 1.927454 0.570113 0.459832 \n", - "12696 1.0 1.0 12.270252 9.924949 0.147665 0.477165 \n", - "12993 1.0 1.0 14.194480 6.687486 0.319535 0.184319 \n", - "13586 1.0 1.0 24.525936 20.607829 0.072227 0.624382 \n", - "14633 1.0 1.0 15.063556 7.233325 0.288746 0.820126 \n", - "17757 1.0 1.0 31.266282 1.288211 0.365737 0.667141 \n", - "18345 1.0 1.0 98.592925 8.101771 0.104668 0.849371 \n", - "19318 1.0 1.0 150.485031 40.423289 0.094533 0.963610 \n", + "913 1.0 1.0 36.226198 21.011972 0.059753 0.276916 \n", + "2592 1.0 1.0 79.074503 4.929898 0.064817 0.957888 \n", + "5131 1.0 1.0 119.959908 28.001784 0.090811 0.649207 \n", + "5752 1.0 1.0 12.882534 5.568839 0.113793 0.443804 \n", + "7023 1.0 1.0 7.866092 2.351273 0.179980 0.925944 \n", + "7431 1.0 1.0 96.571261 88.946686 0.114503 0.870712 \n", + "8343 1.0 1.0 16.781999 15.103265 0.072249 0.456203 \n", + "8745 1.0 1.0 18.382829 9.790526 0.778778 0.724077 \n", + "10560 1.0 1.0 2.365459 0.847537 0.309513 0.608170 \n", + "12893 1.0 1.0 73.141720 9.824216 0.284091 0.976405 \n", + "13291 1.0 1.0 13.282887 0.767718 0.339531 0.842305 \n", + "15588 1.0 1.0 57.713263 24.994475 0.474699 0.783841 \n", + "16606 1.0 1.0 4.359086 1.573977 0.398929 0.557661 \n", + "17213 1.0 1.0 16.901245 15.158980 0.823797 0.152604 \n", + "18387 1.0 1.0 6.214054 4.708508 0.510991 0.503864 \n", + "21167 1.0 1.0 82.717318 38.064096 0.478343 0.185265 \n", "\n", " metallicity tphysf mass0_1 mass0_2 ... tacc_1 tacc_2 \\\n", - "353 0.014 10000.0 45.316990 0.542011 ... 0.0 0.0 \n", - "1580 0.014 10000.0 25.262665 0.535898 ... 0.0 0.0 \n", - "1895 0.014 10000.0 3.391836 0.068421 ... 0.0 0.0 \n", - "2347 0.014 10000.0 21.828894 8.560945 ... 0.0 0.0 \n", - "2446 0.014 10000.0 266.788235 36.299586 ... 0.0 0.0 \n", - "3987 0.014 10000.0 65.996710 21.339760 ... 0.0 0.0 \n", - "4844 0.014 10000.0 221.496477 13.473508 ... 0.0 0.0 \n", - "4985 0.014 10000.0 44.273694 0.542706 ... 0.0 0.0 \n", - "6791 0.014 10000.0 58.324942 9.742695 ... 0.0 0.0 \n", - "10605 0.014 10000.0 2.818451 0.762687 ... 0.0 0.0 \n", - "11004 0.014 10000.0 6.191172 1.927454 ... 0.0 0.0 \n", - "12696 0.014 10000.0 12.270252 9.924949 ... 0.0 0.0 \n", - "12993 0.014 10000.0 14.194480 6.687486 ... 0.0 0.0 \n", - "13586 0.014 10000.0 24.525936 20.607829 ... 0.0 0.0 \n", - "14633 0.014 10000.0 15.063556 7.233325 ... 0.0 0.0 \n", - "17757 0.014 10000.0 31.266282 1.288211 ... 0.0 0.0 \n", - "18345 0.014 10000.0 98.592925 8.101771 ... 0.0 0.0 \n", - "19318 0.014 10000.0 150.485031 40.423289 ... 0.0 0.0 \n", + "913 0.02 10000.0 36.226198 21.011972 ... 0.0 0.0 \n", + "2592 0.02 10000.0 79.074503 4.929898 ... 0.0 0.0 \n", + "5131 0.02 10000.0 119.959908 28.001784 ... 0.0 0.0 \n", + "5752 0.02 10000.0 12.882534 5.568839 ... 0.0 0.0 \n", + "7023 0.02 10000.0 7.866092 2.351273 ... 0.0 0.0 \n", + "7431 0.02 10000.0 96.571261 88.946686 ... 0.0 0.0 \n", + "8343 0.02 10000.0 16.781999 15.103265 ... 0.0 0.0 \n", + "8745 0.02 10000.0 18.382829 9.790526 ... 0.0 0.0 \n", + "10560 0.02 10000.0 2.365459 0.847537 ... 0.0 0.0 \n", + "12893 0.02 10000.0 73.141720 9.824216 ... 0.0 0.0 \n", + "13291 0.02 10000.0 13.282887 0.767718 ... 0.0 0.0 \n", + "15588 0.02 10000.0 57.713263 24.994475 ... 0.0 0.0 \n", + "16606 0.02 10000.0 4.359086 1.573977 ... 0.0 0.0 \n", + "17213 0.02 10000.0 16.901245 15.158980 ... 0.0 0.0 \n", + "18387 0.02 10000.0 6.214054 4.708508 ... 0.0 0.0 \n", + "21167 0.02 10000.0 82.717318 38.064096 ... 0.0 0.0 \n", "\n", " epoch_1 epoch_2 tms_1 tms_2 bhspin_1 bhspin_2 tphys binfrac \n", - "353 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", - "1580 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", - "1895 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", - "2347 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", - "2446 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", - "3987 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", - "4844 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", - "4985 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", - "6791 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", - "10605 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", - "11004 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", - "12696 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", - "12993 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", - "13586 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", - "14633 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", - "17757 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", - "18345 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", - "19318 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "913 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "2592 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "5131 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "5752 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "7023 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "7431 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "8343 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "8745 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "10560 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "12893 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "13291 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "15588 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "16606 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "17213 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "18387 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", + "21167 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 \n", "\n", - "[18 rows x 38 columns]\n", + "[16 rows x 38 columns]\n", " warnings.warn(\n", - "/u/nsabrams/code/multiplicity/PyPopStar/spisea/evolution.py:1409: RuntimeWarning: divide by zero encountered in log10\n", + "/u/nsabrams/code/multiplicity/PyPopStar/spisea/evolution.py:1442: RuntimeWarning: divide by zero encountered in log10\n", " return np.log10(((np.array(c.G.to('Rsun^3/(Msun*s^2)').value*masses/((radii)**2))*u.Rsun/u.s**2).to('cm/s^2')).value)\n", - "/u/nsabrams/code/multiplicity/PyPopStar/spisea/evolution.py:1409: RuntimeWarning: divide by zero encountered in log10\n", + "/u/nsabrams/code/multiplicity/PyPopStar/spisea/evolution.py:1442: RuntimeWarning: divide by zero encountered in log10\n", " return np.log10(((np.array(c.G.to('Rsun^3/(Msun*s^2)').value*masses/((radii)**2))*u.Rsun/u.s**2).to('cm/s^2')).value)\n", "/opt/mambaforge3/envs/astro_cosmic/lib/python3.11/site-packages/pandas/core/arraylike.py:402: RuntimeWarning: divide by zero encountered in log10\n", " result = getattr(ufunc, method)(*inputs, **kwargs)\n", diff --git a/spisea/evolution.py b/spisea/evolution.py index 1534f6a7..a04f2354 100755 --- a/spisea/evolution.py +++ b/spisea/evolution.py @@ -1321,7 +1321,11 @@ def evolve(self, star_systems, companions, logAge, metallicity): # Remove systems that don't show up in bcm final (very few) if len(final_binaries) != len(star_systems): - raise Exception("Some binaries didn't make it. Something went wrong with COSMIC") + import pandas as pd + initC.to_hdf('initiC_fail.hf', key="df", mode="w") + mask = ~bcm.loc[bcm['tphys'] == 0, 'bin_num'].isin(final_binaries['bin_num']) + print('missing binaries', bcm.loc[bcm['tphys'] == 0].loc[mask]) + raise Exception("Some binaries didn't make it. Something went wrong with COSMIC. intC saved to {}".format('initiC_fail.hf')) star_systems['mass_current'] = final_binaries['mass_1'] star_systems['Teff'] = final_binaries['teff_1'] From c24c3c6bb6bee392c6b8db970459c55a73207d9c Mon Sep 17 00:00:00 2001 From: nsabrams Date: Wed, 15 Apr 2026 13:13:27 -0700 Subject: [PATCH 12/28] update BSE dict to use 0.02 for solar metallicity --- spisea/evolution.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spisea/evolution.py b/spisea/evolution.py index a04f2354..0fa1e533 100755 --- a/spisea/evolution.py +++ b/spisea/evolution.py @@ -1250,7 +1250,7 @@ class COSMIC(StellarEvolution): def __init__(self, BSEDict='default', keep_disrupted_companions=True, keep_COSMIC_tables=False): if BSEDict == 'default': self.BSEDict = { - "pts1": 0.001, "pts2": 0.01, "pts3": 0.02, "zsun": 0.014, "windflag": 3, + "pts1": 0.001, "pts2": 0.01, "pts3": 0.02, "zsun": 0.02, "windflag": 3, "eddlimflag": 0, "neta": 0.5, "bwind": 0.0, "hewind": 0.5, "beta": 0.125, "xi": 0.5, "acc2": 1.5, "LBV_flag": 1, "alpha1": 1.0, "lambdaf": 0.0, "ceflag": 1, "cekickflag": 2, "cemergeflag": 1, "cehestarflag": 0, From b1892410b77849c27e519a3b707282388f152311 Mon Sep 17 00:00:00 2001 From: nsabrams Date: Wed, 15 Apr 2026 15:58:48 -0700 Subject: [PATCH 13/28] rotate cosmic kicks to be with respect to binary inclination --- spisea/evolution.py | 86 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 83 insertions(+), 3 deletions(-) diff --git a/spisea/evolution.py b/spisea/evolution.py index 0fa1e533..94890cc8 100755 --- a/spisea/evolution.py +++ b/spisea/evolution.py @@ -13,6 +13,7 @@ from spisea import exceptions import astropy.units as u import astropy.constants as c +from astropy import coordinates as coords logger = logging.getLogger('evolution') @@ -1326,19 +1327,57 @@ def evolve(self, star_systems, companions, logAge, metallicity): mask = ~bcm.loc[bcm['tphys'] == 0, 'bin_num'].isin(final_binaries['bin_num']) print('missing binaries', bcm.loc[bcm['tphys'] == 0].loc[mask]) raise Exception("Some binaries didn't make it. Something went wrong with COSMIC. intC saved to {}".format('initiC_fail.hf')) + + + # initializes kick columns with zeros + star_systems['kick_x'] = 0 + star_systems['kick_y'] = 0 + star_systems['kick_z'] = 0 + + # rotates output kicks from cosmic to inclination + # picks random direction for singles + inclinations = np.arccos(2 * np.random.rand(len(star_systems)) - 1.0) # initializes random inclinations in radians + existing_inclinations = np.deg2rad(companions['i']) + inclinations[companion_system_idxs] = existing_inclinations + inclinations = np.repeat(inclinations, 2) # accounts for two rows per system in kick table + rotated_kick_values_1 = self.get_kick_differential(kick_info['delta_vsysx_1'], kick_info['delta_vsysy_1'], + kick_info['delta_vsysz_1'], inclination = inclinations) + rotated_kick_values_2 = self.get_kick_differential(kick_info['delta_vsysx_2'], kick_info['delta_vsysy_2'], + kick_info['delta_vsysz_2'], inclination = inclinations) + kick_info['delta_vsysx_1_rot'] = rotated_kick_values_1.d_x + kick_info['delta_vsysy_1_rot'] = rotated_kick_values_1.d_y + kick_info['delta_vsysz_1_rot'] = rotated_kick_values_1.d_z + + kick_info['delta_vsysx_2_rot'] = rotated_kick_values_2.d_x + kick_info['delta_vsysy_2_rot'] = rotated_kick_values_2.d_y + kick_info['delta_vsysz_2_rot'] = rotated_kick_values_2.d_z + star_systems['mass_current'] = final_binaries['mass_1'] star_systems['Teff'] = final_binaries['teff_1'] star_systems['L'] = final_binaries['lum_1'] star_systems['logg'] = self.calc_logg(final_binaries['mass_1'], final_binaries['rad_1']) - # for kick, just take total since we will assign a random direction later anyway in PopSyCLE - star_systems['kick'] = kick_info.groupby(level=0).nth(0)['vsys_1_total'] # takes first row with priamry info + + # Takes second row with priamry info for binaries + # This allows for if first object is kicked but not disrupted + multiples_mask = star_systems['isMultiple'] == 1 + star_systems['kick_x'][multiples_mask] = kick_info.groupby(level=0).nth(1).loc[multiples_mask, 'delta_vsysx_1_rot'] + star_systems['kick_y'][multiples_mask] = kick_info.groupby(level=0).nth(1).loc[multiples_mask, 'delta_vsysy_1_rot'] + star_systems['kick_z'][multiples_mask] = kick_info.groupby(level=0).nth(1).loc[multiples_mask, 'delta_vsysz_1_rot'] + # Takes first row with primary info for singles since second row is blank + singles_mask = star_systems['isMultiple'] == 0 + star_systems['kick_x'][singles_mask] = kick_info.groupby(level=0).nth(0).loc[singles_mask, 'delta_vsysx_1_rot'] + star_systems['kick_y'][singles_mask] = kick_info.groupby(level=0).nth(0).loc[singles_mask, 'delta_vsysy_1_rot'] + star_systems['kick_z'][singles_mask] = kick_info.groupby(level=0).nth(0).loc[singles_mask, 'delta_vsysz_1_rot'] companions['mass_current'] = final_binaries['mass_2'][companion_system_idxs] companions['Teff'] = final_binaries['teff_2'][companion_system_idxs] companions['L'] = final_binaries['lum_2'][companion_system_idxs] companions['logg'] = self.calc_logg(final_binaries['mass_2'][companion_system_idxs], final_binaries['rad_2'][companion_system_idxs]) - companions['kick'] = kick_info.groupby(level=0).nth(1)['vsys_2_total'][companion_system_idxs] # takes second row with companion info + # Takes second row with companion info + companions['kick_x'] = kick_info.groupby(level=0).nth(1)['delta_vsysx_2_rot'][companion_system_idxs] + companions['kick_y'] = kick_info.groupby(level=0).nth(1)['delta_vsysy_2_rot'][companion_system_idxs] + companions['kick_z'] = kick_info.groupby(level=0).nth(1)['delta_vsysz_2_rot'][companion_system_idxs] loga = np.log10(final_binaries['sep'][companion_system_idxs]*u.Rsun.to('AU')) companions['log_a'] = loga @@ -1441,6 +1480,47 @@ def calc_logg(self, masses, radii): """ return np.log10(((np.array(c.G.to('Rsun^3/(Msun*s^2)').value*masses/((radii)**2))*u.Rsun/u.s**2).to('cm/s^2')).value) + def get_kick_differential(self, delta_v_sys_x, delta_v_sys_y, delta_v_sys_z, phase=None, inclination=None): + """Calculate the :class:`~astropy.coordinates.CylindricalDifferential` from a combination of the natal + kick, Blauuw kick and orbital motion. + + via cogsworth https://github.com/TomWagg/cogsworth/blob/main/cogsworth/kicks.py + + Parameters + ---------- + delta_v_sys_x : :class:`~astropy.units.Quantity` [velocity] + Change in systemic velocity due to natal and Blauuw kicks in BSE :math:`(v_x, v_y, v_z)` frame + (see Fig A1 of `Hurley+02 `_) + delta_v_sys_y : :class:`~astropy.units.Quantity` [velocity] + Change in systemic velocity due to natal and Blauuw kicks in BSE :math:`(v_x, v_y, v_z)` frame + (see Fig A1 of `Hurley+02 `_) + delta_v_sys_z : :class:`~astropy.units.Quantity` [velocity] + Change in systemic velocity due to natal and Blauuw kicks in BSE :math:`(v_x, v_y, v_z)` frame + (see Fig A1 of `Hurley+02 `_) + phase : np.array + Orbital phase angle in radians + inclination : np.array + Inclination to the Galactic plane in radians + + Returns + ------- + kick_differential : :class:`~astropy.coordinates.CylindricalDifferential` + Kick differential + """ + # orbital phase angle and inclination to Galactic plane + thetas = np.random.uniform(0, 2 * np.pi, size = len(delta_v_sys_x)) if phase is None else phase + phis = np.arccos(2 * np.random.rand(len(delta_v_sys_x)) - 1.0) if inclination is None else inclination + + # rotate BSE (v_x, v_y, v_z) into Galactocentric (v_X, v_Y, v_Z) + v_X = delta_v_sys_x * np.cos(thetas) - delta_v_sys_y * np.sin(thetas) * np.cos(phis)\ + + delta_v_sys_z * np.sin(thetas) * np.sin(phis) + v_Y = delta_v_sys_x * np.sin(thetas) + delta_v_sys_y * np.cos(thetas) * np.cos(phis)\ + - delta_v_sys_z * np.cos(thetas) * np.sin(phis) + v_Z = delta_v_sys_y * np.sin(phis) + delta_v_sys_z * np.cos(phis) + kick_differential = coords.CartesianDifferential(v_X, v_Y, v_Z) + + return kick_differential + #==============================# # Merged model classes From 2c28c4363a603a86dbcfd316010865453f46c5c5 Mon Sep 17 00:00:00 2001 From: nsabrams Date: Wed, 15 Apr 2026 16:51:11 -0700 Subject: [PATCH 14/28] added code to remove systems cosmic drops and save them to file --- spisea/evolution.py | 67 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 57 insertions(+), 10 deletions(-) diff --git a/spisea/evolution.py b/spisea/evolution.py index 94890cc8..a34c39ff 100755 --- a/spisea/evolution.py +++ b/spisea/evolution.py @@ -1309,24 +1309,65 @@ def evolve(self, star_systems, companions, logAge, metallicity): kstar1=kstar1s, kstar2=kstar2s, metallicity=[self.z_solar*10**metallicity]*len(m1s)) bpp, bcm, initC, kick_info = Evolve.evolve(initialbinarytable=binary_pop, BSEDict=self.BSEDict) - if self.keep_COSMIC_tables: - self.bpp = bpp - self.bcm = bcm - self.initC = initC - self.kick_info = kick_info - + final_binaries = bcm[bcm['tphys'] > 0] #only gives the first and last idx, so this takes final one - + # Add number for system idx since we're about to manipuluate them a bunch star_systems['system_idx'] = np.arange(len(star_systems)) # Remove systems that don't show up in bcm final (very few) if len(final_binaries) != len(star_systems): - import pandas as pd - initC.to_hdf('initiC_fail.hf', key="df", mode="w") + # Save or append to initC + initC_fail_path = 'initC_fail.csv' + exists = os.path.exists(initC_fail_path) + initC.to_csv( + initC_fail_path, + mode='a' if exists else 'w', + header=not exists, + index=False + ) + + # Save or append failing binary bcm values to table mask = ~bcm.loc[bcm['tphys'] == 0, 'bin_num'].isin(final_binaries['bin_num']) + failing_binaries = bcm.loc[bcm['tphys'] == 0].loc[mask] + print('missing binaries', bcm.loc[bcm['tphys'] == 0].loc[mask]) - raise Exception("Some binaries didn't make it. Something went wrong with COSMIC. intC saved to {}".format('initiC_fail.hf')) + missing_binary_csv_path = 'missing_cosmic_binaries_bcm.csv' + exists = os.path.exists( missing_binary_csv_path) + failing_binaries.to_csv( + missing_binary_csv_path, + mode='a' if exists else 'w', + header=not exists, + index=False + ) + + # Remove failing binaries from all tables and redefine quantites + for bin_num in failing_binaries['bin_num']: + bad_ss = np.where(star_systems['system_idx'] == bin_num) + star_systems.remove_rows(bad_ss) + bad_companions = np.where(companions['system_idx'] == bin_num) + companions.remove_rows(bad_companions) + + companion_system_idxs = companions['system_idx'] + m1s = star_systems['mass'] + m2s = np.zeros(len(star_systems)) + m2s[companion_system_idxs] = companions['mass'] + + a_Rsuns = (10**companions['log_a'])*u.AU.to('Rsun') + porbs = np.zeros(len(star_systems)) + porbs[companion_system_idxs] = p_from_a(a_Rsuns, m1s[companion_system_idxs], m2s[companion_system_idxs]) + + eccs = np.zeros(len(star_systems)) + eccs[companion_system_idxs] = companions['e'] + + kstar1s = (m1s >= 0.7).astype(int) # 1 if MS above 0.7 and 0 if MS below 0.7 + kstar2s = (m2s >= 0.7).astype(int) # 1 if MS above 0.7 and 0 if MS below 0.7 + + bpp = bpp[bpp['bin_num'] != bin_num] + bcm = bcm[bcm['bin_num'] != bin_num] + kick_info = kick_info[kick_info['bin_num'] != bin_num] + + print("WARNING: Some binaries didn't make it. Something went wrong with COSMIC. Saved to initC_fail.csv and missing_cosmic_binaries_bcm.csv") # initializes kick columns with zeros @@ -1459,6 +1500,12 @@ def evolve(self, star_systems, companions, logAge, metallicity): # Make sure we didn't break anything by manipulating the number of companions assert star_systems['N_companions'].sum() == len(companions) + + if self.keep_COSMIC_tables: + self.bpp = bpp + self.bcm = bcm + self.initC = initC + self.kick_info = kick_info return star_systems, companions From 7c95b47677f73d367c7e0abf1c8c425b36607a78 Mon Sep 17 00:00:00 2001 From: nsabrams Date: Thu, 16 Apr 2026 15:42:35 -0700 Subject: [PATCH 15/28] attempt to fix removal of failing binaries --- spisea/evolution.py | 74 ++++++++++++++++++++++++++++++--------------- 1 file changed, 49 insertions(+), 25 deletions(-) diff --git a/spisea/evolution.py b/spisea/evolution.py index a34c39ff..cf37dd8f 100755 --- a/spisea/evolution.py +++ b/spisea/evolution.py @@ -1309,7 +1309,9 @@ def evolve(self, star_systems, companions, logAge, metallicity): kstar1=kstar1s, kstar2=kstar2s, metallicity=[self.z_solar*10**metallicity]*len(m1s)) bpp, bcm, initC, kick_info = Evolve.evolve(initialbinarytable=binary_pop, BSEDict=self.BSEDict) - + + #import pandas as pd + #bcm = pd.concat([bcm.iloc[:1], bcm.iloc[2:]]) final_binaries = bcm[bcm['tphys'] > 0] #only gives the first and last idx, so this takes final one # Add number for system idx since we're about to manipuluate them a bunch @@ -1342,30 +1344,52 @@ def evolve(self, star_systems, companions, logAge, metallicity): ) # Remove failing binaries from all tables and redefine quantites - for bin_num in failing_binaries['bin_num']: - bad_ss = np.where(star_systems['system_idx'] == bin_num) - star_systems.remove_rows(bad_ss) - bad_companions = np.where(companions['system_idx'] == bin_num) - companions.remove_rows(bad_companions) - - companion_system_idxs = companions['system_idx'] - m1s = star_systems['mass'] - m2s = np.zeros(len(star_systems)) - m2s[companion_system_idxs] = companions['mass'] - - a_Rsuns = (10**companions['log_a'])*u.AU.to('Rsun') - porbs = np.zeros(len(star_systems)) - porbs[companion_system_idxs] = p_from_a(a_Rsuns, m1s[companion_system_idxs], m2s[companion_system_idxs]) - - eccs = np.zeros(len(star_systems)) - eccs[companion_system_idxs] = companions['e'] - - kstar1s = (m1s >= 0.7).astype(int) # 1 if MS above 0.7 and 0 if MS below 0.7 - kstar2s = (m2s >= 0.7).astype(int) # 1 if MS above 0.7 and 0 if MS below 0.7 - - bpp = bpp[bpp['bin_num'] != bin_num] - bcm = bcm[bcm['bin_num'] != bin_num] - kick_info = kick_info[kick_info['bin_num'] != bin_num] + bad_bin_nums = failing_binaries['bin_num'] + bad_mask_ss = np.isin(star_systems['system_idx'], bad_bin_nums) + star_systems.remove_rows(np.where(bad_mask_ss)[0]) + + bad_mask_comp = np.isin(companions['system_idx'], bad_bin_nums) + companions.remove_rows(np.where(bad_mask_comp)[0]) + + bpp = bpp[~bpp['bin_num'].isin(bad_bin_nums)] + bcm = bcm[~bcm['bin_num'].isin(bad_bin_nums)] + kick_info = kick_info[~kick_info['bin_num'].isin(bad_bin_nums)] + + # Redefine system idx since companions refer to the positions + star_systems['old_system_idx'] = star_systems['system_idx'] + star_systems['system_idx'] = np.arange(len(star_systems)) + idx_map = dict(zip(star_systems['old_system_idx'], star_systems['system_idx'])) + companions['system_idx'] = np.array([idx_map[i] for i in companions['system_idx']]) + + # redefine the bin_num to the new values too + bpp['bin_num'] = bpp['bin_num'].map(idx_map) + bcm['bin_num'] = bcm['bin_num'].map(idx_map) + kick_info['bin_num'] = kick_info['bin_num'].map(idx_map) + + assert(set(companions['system_idx']) - set(star_systems['system_idx']) == set()) + assert(set(bpp['bin_num']) - set(star_systems['system_idx']) == set()) + assert(set(bcm['bin_num']) - set(star_systems['system_idx']) == set()) + assert(set(kick_info['bin_num']) - set(star_systems['system_idx']) == set()) + + # reset the index to the bin_num column + bpp = bpp.set_index('bin_num', drop=False) + bcm = bcm.set_index('bin_num', drop=False) + kick_info = kick_info.set_index('bin_num', drop=False) + + companion_system_idxs = companions['system_idx'] + m1s = star_systems['mass'] + m2s = np.zeros(len(star_systems)) + m2s[companion_system_idxs] = companions['mass'] + + a_Rsuns = (10**companions['log_a'])*u.AU.to('Rsun') + porbs = np.zeros(len(star_systems)) + porbs[companion_system_idxs] = p_from_a(a_Rsuns, m1s[companion_system_idxs], m2s[companion_system_idxs]) + + eccs = np.zeros(len(star_systems)) + eccs[companion_system_idxs] = companions['e'] + + kstar1s = (m1s >= 0.7).astype(int) # 1 if MS above 0.7 and 0 if MS below 0.7 + kstar2s = (m2s >= 0.7).astype(int) # 1 if MS above 0.7 and 0 if MS below 0.7 print("WARNING: Some binaries didn't make it. Something went wrong with COSMIC. Saved to initC_fail.csv and missing_cosmic_binaries_bcm.csv") From 8476e0746c887d67502e238a4ee29662f550aafd Mon Sep 17 00:00:00 2001 From: nsabrams Date: Thu, 16 Apr 2026 22:03:38 -0700 Subject: [PATCH 16/28] fix dropping systems --- spisea/evolution.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/spisea/evolution.py b/spisea/evolution.py index cf37dd8f..b59ca95f 100755 --- a/spisea/evolution.py +++ b/spisea/evolution.py @@ -1310,8 +1310,6 @@ def evolve(self, star_systems, companions, logAge, metallicity): bpp, bcm, initC, kick_info = Evolve.evolve(initialbinarytable=binary_pop, BSEDict=self.BSEDict) - #import pandas as pd - #bcm = pd.concat([bcm.iloc[:1], bcm.iloc[2:]]) final_binaries = bcm[bcm['tphys'] > 0] #only gives the first and last idx, so this takes final one # Add number for system idx since we're about to manipuluate them a bunch @@ -1390,9 +1388,10 @@ def evolve(self, star_systems, companions, logAge, metallicity): kstar1s = (m1s >= 0.7).astype(int) # 1 if MS above 0.7 and 0 if MS below 0.7 kstar2s = (m2s >= 0.7).astype(int) # 1 if MS above 0.7 and 0 if MS below 0.7 + + final_binaries = bcm[bcm['tphys'] > 0] #only gives the first and last idx, so this takes final one print("WARNING: Some binaries didn't make it. Something went wrong with COSMIC. Saved to initC_fail.csv and missing_cosmic_binaries_bcm.csv") - # initializes kick columns with zeros star_systems['kick_x'] = 0 From 3994949808a634f9e0271128a4adcd7483cbf560 Mon Sep 17 00:00:00 2001 From: nsabrams Date: Thu, 11 Jun 2026 17:50:15 -0700 Subject: [PATCH 17/28] switched to sum of rows for kicks --- spisea/evolution.py | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/spisea/evolution.py b/spisea/evolution.py index f3d3c0bc..e2c406d5 100755 --- a/spisea/evolution.py +++ b/spisea/evolution.py @@ -1716,26 +1716,30 @@ def evolve(self, star_systems, companions, logAge, metallicity): star_systems['L'] = final_binaries['lum_1'] star_systems['logg'] = self.calc_logg(final_binaries['mass_1'], final_binaries['rad_1']) - # Takes second row with priamry info for binaries - # This allows for if first object is kicked but not disrupted - multiples_mask = star_systems['isMultiple'] == 1 - star_systems['kick_x'][multiples_mask] = kick_info.groupby(level=0).nth(1).loc[multiples_mask, 'delta_vsysx_1_rot'] - star_systems['kick_y'][multiples_mask] = kick_info.groupby(level=0).nth(1).loc[multiples_mask, 'delta_vsysy_1_rot'] - star_systems['kick_z'][multiples_mask] = kick_info.groupby(level=0).nth(1).loc[multiples_mask, 'delta_vsysz_1_rot'] - # Takes first row with primary info for singles since second row is blank - singles_mask = star_systems['isMultiple'] == 0 - star_systems['kick_x'][singles_mask] = kick_info.groupby(level=0).nth(0).loc[singles_mask, 'delta_vsysx_1_rot'] - star_systems['kick_y'][singles_mask] = kick_info.groupby(level=0).nth(0).loc[singles_mask, 'delta_vsysy_1_rot'] - star_systems['kick_z'][singles_mask] = kick_info.groupby(level=0).nth(0).loc[singles_mask, 'delta_vsysz_1_rot'] + # Takes sum of the delta kicks in case there was a kick, no disruption, then second kick + # Even for isolated stars, take sum since second row is blank + primary_kick_sum = ( + kick_info + .groupby(level=0)[["delta_vsysx_1_rot", "delta_vsysy_1_rot", "delta_vsysz_1_rot"]] + .sum() + ) + star_systems["kick_x"] = primary_kick_sum["delta_vsysx_1_rot"].reindex(star_systems["system_idx"], fill_value=0).to_numpy() + star_systems["kick_y"] = primary_kick_sum["delta_vsysy_1_rot"].reindex(star_systems["system_idx"], fill_value=0).to_numpy() + star_systems["kick_z"] = primary_kick_sum["delta_vsysz_1_rot"].reindex(star_systems["system_idx"], fill_value=0).to_numpy() companions['mass_current'] = final_binaries['mass_2'][companion_system_idxs] companions['Teff'] = final_binaries['teff_2'][companion_system_idxs] companions['L'] = final_binaries['lum_2'][companion_system_idxs] companions['logg'] = self.calc_logg(final_binaries['mass_2'][companion_system_idxs], final_binaries['rad_2'][companion_system_idxs]) - # Takes second row with companion info - companions['kick_x'] = kick_info.groupby(level=0).nth(1)['delta_vsysx_2_rot'][companion_system_idxs] - companions['kick_y'] = kick_info.groupby(level=0).nth(1)['delta_vsysy_2_rot'][companion_system_idxs] - companions['kick_z'] = kick_info.groupby(level=0).nth(1)['delta_vsysz_2_rot'][companion_system_idxs] + # Also take sum of companion kicks + companion_kick_sum = ( + kick_info + .groupby(level=0)[["delta_vsysx_2_rot", "delta_vsysy_2_rot", "delta_vsysz_2_rot"]] + .sum() + ) + companions['kick_x'] = companion_kick_sum["delta_vsysx_2_rot"].reindex(companion_system_idxs, fill_value=0).to_numpy() + companions['kick_y'] = companion_kick_sum["delta_vsysy_2_rot"].reindex(companion_system_idxs, fill_value=0).to_numpy() + companions['kick_z'] = companion_kick_sum["delta_vsysz_2_rot"].reindex(companion_system_idxs, fill_value=0).to_numpy() loga = np.log10(final_binaries['sep'][companion_system_idxs]*u.Rsun.to('AU')) companions['log_a'] = loga From 809acc20e41b57005f164f09a0464b122cce391f Mon Sep 17 00:00:00 2001 From: nsabrams Date: Thu, 11 Jun 2026 17:56:31 -0700 Subject: [PATCH 18/28] switch recomp isochrone to false --- docs/Cluster_w_COSMIC.ipynb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/Cluster_w_COSMIC.ipynb b/docs/Cluster_w_COSMIC.ipynb index a9a21f89..00314a16 100755 --- a/docs/Cluster_w_COSMIC.ipynb +++ b/docs/Cluster_w_COSMIC.ipynb @@ -60,7 +60,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "id": "90c33d5c-7c52-4dd1-9545-25b00db26032", "metadata": { "scrolled": true @@ -1132,7 +1132,7 @@ "iso = synthetic.IsochronePhotExternalEvolution(logAge, AKs, dist, metallicity=metallicity,\n", " evo_model=evo_merged, atm_func=atm_func,\n", " filters=filt_list, red_law=redlaw,\n", - " atm_grid_dir=iso_dir, mass_sampling=3, recomp=True)" + " atm_grid_dir=iso_dir, mass_sampling=3, recomp=False)" ] }, { From b6b678c2ccd546de11c3d1598771cef52dfe55bc Mon Sep 17 00:00:00 2001 From: nsabrams Date: Fri, 12 Jun 2026 14:06:04 -0700 Subject: [PATCH 19/28] fixed interpolator call issue --- spisea/atmospheres.py | 131 ++++++++++++------------------------------ spisea/synthetic.py | 5 +- 2 files changed, 40 insertions(+), 96 deletions(-) diff --git a/spisea/atmospheres.py b/spisea/atmospheres.py index 6451ebb9..051cc8c8 100755 --- a/spisea/atmospheres.py +++ b/spisea/atmospheres.py @@ -1176,9 +1176,9 @@ def get_merged_atmosphere(metallicity=0, temperature=20000, gravity=4.5, verbose * T < 3800, logg < 2.5: PHOENIX v16 * 3200 <= T < 3800, logg > 2.5: BTSettl_CIFITS2011_2015/PHOENIXV16 merge - * 3200 < T <= 1200, logg > 2.5: BTSettl_CIFITS2011_2015 - * 1200 < T <= 1000, logg >= 3.5: BTSettl_CIFITS2011_2015/Meisner2023 merge - * 1000 < T <= 250, logg > 2.5: Meisner2023 + * 1200 < T <= 3200, logg > 2.5: BTSettl_CIFITS2011_2015 + * 1000 <= T <= 1200, logg >= 2.5: Meisner2023 + * 250 <= T < 1000: Meisner2023 Otherwise, if T < 3800 and [M/H] != 0: @@ -1406,7 +1406,9 @@ def get_merged_atmosphere_w_bb_supplement(metallicity=0, temperature=20000, grav * T < 3800, logg < 2.5: PHOENIX v16 * 3200 <= T < 3800, logg > 2.5: BTSettl_CIFITS2011_2015/PHOENIXV16 merge - * 3200 < T <= 1200, logg > 2.5: BTSettl_CIFITS2011_2015 + * 1200 < T <= 3200, logg > 2.5: BTSettl_CIFITS2011_2015 + * 1000 <= T <= 1200, logg >= 2.5: Meisner2023 + * 250 <= T < 1000: Meisner2023 Otherwise, if T < 3800 and [M/H] != 0: @@ -1417,6 +1419,7 @@ def get_merged_atmosphere_w_bb_supplement(metallicity=0, temperature=20000, grav * ATLAS: ATLAS9 models (`Castelli & Kurucz 2004 `_) * PHOENIXv16 (`Husser et al. 2013 `_) * BTSettl_CIFITS2011_2015: Baraffee+15, Allard+ (https://phoenix.ens-lyon.fr/Grids/BT-Settl/CIFIST2011_2015/SPECTRA/) + * Meisner2023: ATMO 1D models (`Meisner et al. 2023 `_) LTE WARNING: @@ -1436,110 +1439,51 @@ def get_merged_atmosphere_w_bb_supplement(metallicity=0, temperature=20000, grav ensure a smooth transition. """ - if (temperature <= 1000): - print('BB atmosphere') - return get_bb_atmosphere(temperature=temperature, - metallicity=metallicity, - gravity=gravity, - verbose=verbose) if (gravity >= 9.8): - print('BB atmosphere') + if verbose: + print('BB atmosphere') return get_bb_atmosphere(temperature=temperature, metallicity=metallicity, gravity=gravity, verbose=verbose) if (temperature < 4.6e3) & (gravity >= 6.5): - print('BB atmosphere') + if verbose: + print('BB atmosphere') return get_bb_atmosphere(temperature=temperature, metallicity=metallicity, gravity=gravity, verbose=verbose) if (temperature < 3.5e3) & (gravity < 6.5) & (gravity > 6): - print('BB atmosphere') + if verbose: + print('BB atmosphere') return get_bb_atmosphere(temperature=temperature, metallicity=metallicity, gravity=gravity, verbose=verbose) - - - # For T < 3800, atmosphere depends on metallicity + gravity. - # If solar metallicity, use BTSettl 2015 grid. Only solar metallicity is - # currently available here, so if non-solar metallicity, just stick with - # the Phoenix grid - if (temperature <= 3800) & (metallicity == 0): - # High gravity are in BTSettl regime - if (temperature <= 3200) & (gravity > 2.5): - if verbose: - print( 'BTSettl_2015 atmosphere') - return get_BTSettl_2015_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity, - rebin=rebin) - - if (temperature >= 3200) & (temperature < 3800) & (gravity > 2.5): - if verbose: - print( 'BTSettl/Phoenixv16 merged atmosphere') - return get_BTSettl_phoenix_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity) - # Low gravity is PHOENIX regime - if gravity <= 2.5: - if verbose: - print( 'Phoenixv16 atmosphere') - return get_phoenixv16_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity, - rebin=rebin) - - if (temperature <= 3800) & (metallicity != 0): - if verbose: - print( 'Phoenixv16 atmosphere') - return get_phoenixv16_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity, - rebin=rebin) - # For T > 3800, no metallicity or gravity dependence - if (temperature >= 3800) & (temperature < 5000): - if verbose: - print( 'Phoenixv16 atmosphere') - return get_phoenixv16_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity, - rebin=rebin) - - if (temperature >= 5000) & (temperature < 5500): - if verbose: - print( 'ATLAS/Phoenix merged atmosphere') - return get_atlas_phoenix_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - if (temperature >= 5500) & (temperature < 20000): - if verbose: - print( 'ATLAS merged atmosphere') - return get_castelli_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - if temperature >= 20000: - if verbose: - print( 'Still ATLAS merged atmosphere') - return get_castelli_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - # Returns BB if outside of WD defined atmospheres - else: + if gravity > 6: if verbose: print('WD or BB atmosphere') return get_wd_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity) + temperature=temperature, + gravity=gravity, + verbose=verbose) + + return get_merged_atmosphere(metallicity=metallicity, + temperature=temperature, + gravity=gravity, + verbose=verbose, + rebin=rebin) def get_merged_atmosphere_w_bb_supplement_grid(bb_supplement_tarr='default', bb_supplement_zarr='default', bb_supplement_loggarr='default', rebin=True): + """ + Return the atmosphere parameter grid used by + get_merged_atmosphere_w_bb_supplement. + This is the standard merged atmosphere grid plus the white dwarf grid and + blackbody supplement points for high-gravity regions. + """ super_tarr, super_zarr, super_loggarr = get_merged_atmosphere_grid(rebin=rebin) wd_tarr, wd_zarr, wd_loggarr = get_wdKoester_atmosphere_grid() @@ -1548,14 +1492,15 @@ def get_merged_atmosphere_w_bb_supplement_grid(bb_supplement_tarr='default', bb_ super_loggarr = np.concatenate((super_loggarr, wd_loggarr)) if bb_supplement_tarr == 'default': - X, Y = np.meshgrid(np.logspace(np.log10(2e3), np.log10(4.6e3), 20), np.linspace(6.5, 8.7, 10)) - X1, Y1 = np.meshgrid(np.logspace(np.log10(2e3), np.log10(3.5e3), 15), np.linspace(6, 6.25, 2)) - #X2, Y2 = np.meshgrid(np.logspace(np.log10(2e2), np.log10(1.1e3), 20), np.linspace(3, 4.5, 4)) - X3, Y3 = np.meshgrid(np.logspace(np.log10(8e3), np.log10(2e4), 25), np.linspace(9.8, 11.6, 8)) - bb_supplement_tarr = np.concatenate((X.ravel(), X1.ravel(), X3.ravel())) - bb_supplement_loggarr = np.concatenate((Y.ravel(), Y1.ravel(), Y3.ravel())) - #bb_supplement_tarr = np.concatenate((X.ravel(), X1.ravel(), X2.ravel(), X3.ravel())) - #bb_supplement_loggarr = np.concatenate((Y.ravel(), Y1.ravel(), Y2.ravel(), Y3.ravel())) + X_highg, Y_highg = np.meshgrid(np.logspace(np.log10(2e3), np.log10(2e4), 35), + np.linspace(9.8, 11.6, 8)) + X_cool_highg, Y_cool_highg = np.meshgrid(np.logspace(np.log10(2e3), np.log10(4.6e3), 20), + np.linspace(6.5, 9.7, 10)) + X_cool_midg, Y_cool_midg = np.meshgrid(np.logspace(np.log10(2e3), np.log10(3.5e3), 15), + np.linspace(6.1, 6.4, 4)) + + bb_supplement_tarr = np.concatenate((X_highg.ravel(), X_cool_highg.ravel(), X_cool_midg.ravel())) + bb_supplement_loggarr = np.concatenate((Y_highg.ravel(), Y_cool_highg.ravel(), Y_cool_midg.ravel())) bb_supplement_zarr = np.zeros(len(bb_supplement_tarr)) diff --git a/spisea/synthetic.py b/spisea/synthetic.py index 820a923d..12ee0e6a 100755 --- a/spisea/synthetic.py +++ b/spisea/synthetic.py @@ -215,8 +215,7 @@ def __init__(self, iso, imf, cluster_mass, ifmr=None, verbose=True, interp_keys = ['Teff', 'L', 'logg', 'isWR', 'mass_current', 'phase'] + self.filt_names self.iso_interps = {} for ikey in interp_keys: - self.iso_interps[ikey] = Interpolator(self.iso.points['mass'], self.iso.points[ikey], - kind='linear', bounds_error=False, fill_value=np.nan) + self.iso_interps[ikey] = Interpolator(self.iso.points['mass'], self.iso.points[ikey]) else: from scipy.interpolate import LinearNDInterpolator self.iso.points.sort(['Teff', 'logg', 'metallicity']) @@ -332,7 +331,7 @@ def _make_star_systems_table(self, mass, isMulti, sysMass): # Add columns for the Teff, L, logg, isWR, mass_current, phase, and filters. for key in ['Teff', 'L', 'logg', 'mass_current', 'phase']: star_systems.add_column(Column(np.empty(N_systems, dtype=float), name=key)) - star_systems.add_column(Column(np.zeros(N_systems, dtype=bool), name='isWR')) + star_systems.add_column(Column(np.zeros(N_systems, dtype=bool), name='isWR')) # for models with no WR designation, this remains 0 star_systems['metallicity'] = np.ones(N_systems) * self.iso.metallicity # Add the filter columns to the table. They are empty so far. From 252f2a65c94bb903229f3ebda38b102f7fa7711d Mon Sep 17 00:00:00 2001 From: nsabrams Date: Mon, 15 Jun 2026 16:03:43 -0700 Subject: [PATCH 20/28] fixed companion mass checks --- spisea/evolution.py | 2 -- spisea/synthetic.py | 6 +++--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/spisea/evolution.py b/spisea/evolution.py index e2c406d5..1129f54f 100755 --- a/spisea/evolution.py +++ b/spisea/evolution.py @@ -1817,8 +1817,6 @@ def evolve(self, star_systems, companions, logAge, metallicity): companions['system_idx'] = mapping[companions['system_idx']] star_systems.remove_columns(['system_idx', 'system_idx_new']) - #FIXME add assertion about mass_current not being zero - # Preserve a scalar kick magnitude alongside the vector components. for table in (star_systems, companions): table['kick'] = np.sqrt(table['kick_x']**2 + table['kick_y']**2 + table['kick_z']**2) diff --git a/spisea/synthetic.py b/spisea/synthetic.py index 12ee0e6a..1eee1237 100755 --- a/spisea/synthetic.py +++ b/spisea/synthetic.py @@ -688,9 +688,9 @@ def _make_companions_table(self, star_systems, compMass): companions['phase'][low_mass_idxs] = 98 # FIXME SHOULD BE ADDED FOR EXTERNALEVOL TOO - # Double check that everything behaved properly. - if len(idx)>0: - assert companions['mass'][companions_teff_non_nan > 0].min() > 0, "Companion mass is not positive" + # Double check that everything behaved properly. + if len(idx)>0: + assert companions['mass'][companions_teff_non_nan > 0].min() > 0, "Companion mass is not positive" return star_systems, companions From bd69b57a7cd66a90fef8ba8472ead60b1fcb2c24 Mon Sep 17 00:00:00 2001 From: nsabrams Date: Tue, 16 Jun 2026 10:39:49 -0700 Subject: [PATCH 21/28] added unit and integration tests via claude --- spisea/tests/test_models.py | 76 ++++++++++++++++ spisea/tests/test_synthetic.py | 157 +++++++++++++++++++++++++++++++++ 2 files changed, 233 insertions(+) diff --git a/spisea/tests/test_models.py b/spisea/tests/test_models.py index 35970431..c3cd7aa2 100644 --- a/spisea/tests/test_models.py +++ b/spisea/tests/test_models.py @@ -91,6 +91,82 @@ def test_synthpop_MIST_extension(): return +def test_COSMIC_init(): + """ + Test the COSMIC external evolution model constructor: default flags, + default BSEDict, and that user-supplied options are stored. + """ + # Default construction + evo = evolution.COSMIC() + assert evo.external_evol is True + assert evo.z_solar == 0.02 + assert evo.model_version_name == 'COSMIC' + assert evo.keep_disrupted_companions is True + assert evo.keep_COSMIC_tables is False + + # Default BSEDict should be a populated dictionary of BSE parameters + assert isinstance(evo.BSEDict, dict) + assert len(evo.BSEDict) > 0 + + # User-supplied options should be stored + custom_dict = {'windflag': 3, 'neta': 0.5} + evo2 = evolution.COSMIC(BSEDict=custom_dict, keep_disrupted_companions=False, + keep_COSMIC_tables=True) + assert evo2.BSEDict == custom_dict + assert evo2.keep_disrupted_companions is False + assert evo2.keep_COSMIC_tables is True + + return + +def test_COSMIC_calc_logg(): + """ + Test the COSMIC.calc_logg helper. For the Sun (M=1 Msun, R=1 Rsun) + the surface gravity should be logg ~ 4.438 (cgs). + """ + evo = evolution.COSMIC() + + # Scalar solar value + assert np.isclose(evo.calc_logg(1.0, 1.0), 4.438, atol=0.01) + + # Array input should be handled element-wise + masses = np.array([1.0, 2.0]) + radii = np.array([1.0, 2.0]) + logg = evo.calc_logg(masses, radii) + assert np.isclose(logg[0], 4.438, atol=0.01) + # logg scales as log10(M/R^2); doubling both M and R lowers logg by log10(2) + assert np.isclose(logg[0] - logg[1], np.log10(2.0), atol=0.01) + + return + +def test_COSMIC_get_kick_differential(): + """ + Test the COSMIC.get_kick_differential helper. The transformation is a + pure rotation (Rz(theta) * Rx(phi)) of the kick vector, so it must + preserve the vector magnitude. A zero kick must map to a zero kick. + """ + evo = evolution.COSMIC() + + # Zero kick in -> zero kick out + zeros = np.zeros(3) + phase = np.array([0.3, 1.1, 2.0]) + incl = np.array([0.5, 1.5, 2.5]) + kd_zero = evo.get_kick_differential(zeros, zeros, zeros, phase=phase, inclination=incl) + assert np.allclose(kd_zero.d_x.value, 0.0) + assert np.allclose(kd_zero.d_y.value, 0.0) + assert np.allclose(kd_zero.d_z.value, 0.0) + + # Magnitude is preserved under the rotation + vx = np.array([10.0, -5.0, 3.0]) + vy = np.array([2.0, 7.0, -1.0]) + vz = np.array([-4.0, 1.0, 8.0]) + kd = evo.get_kick_differential(vx, vy, vz, phase=phase, inclination=incl) + + mag_in = np.sqrt(vx**2 + vy**2 + vz**2) + mag_out = np.sqrt(kd.d_x.value**2 + kd.d_y.value**2 + kd.d_z.value**2) + np.testing.assert_allclose(mag_out, mag_in, rtol=1e-10) + + return + def test_atmosphere_models(): """ Test the rebinned atmosphere models used for synthetic photometry diff --git a/spisea/tests/test_synthetic.py b/spisea/tests/test_synthetic.py index 7762fd93..f11582c6 100755 --- a/spisea/tests/test_synthetic.py +++ b/spisea/tests/test_synthetic.py @@ -2,6 +2,9 @@ import pdb import time import spisea +import pytest +import warnings +import importlib import numpy as np import pylab as plt from astropy.table import Table @@ -941,6 +944,160 @@ def test_compact_object_companions(): assert (len(nan_lum_companions) == 0) | (all(np.isnan(nan_lum_companions['phase'])) == False) +def _require_cosmic(): + """ + Skip the calling test if the optional `cosmic` package is not installed, + emitting a warning so the skip is visible (rather than silent). + """ + if importlib.util.find_spec('cosmic') is None: + msg = ('COSMIC integration test skipped: the optional `cosmic` package ' + 'is not installed. Run in an environment with COSMIC (e.g. ' + '`astro_cosmic`) to exercise these tests.') + warnings.warn(msg) + pytest.skip(msg) + + return + +def test_COSMIC_evolve(): + """ + Test the COSMIC external evolution model's evolve() method directly on a + small, hand-built set of star systems and companions. Uses a young, low-mass + population so no compact remnants/disruptions occur, keeping the run fast + and avoiding the merger/disruption branches. + + Skipped (with a warning) if the optional `cosmic` package is not installed. + """ + _require_cosmic() + + from astropy.table import Table + + # Build a minimal star_systems table: 2 binaries + 1 single + star_systems = Table() + star_systems['mass'] = np.array([1.0, 0.9, 0.5]) + star_systems['isMultiple'] = np.array([True, True, False]) + star_systems['N_companions'] = np.array([1, 1, 0]) + star_systems['systemMass'] = np.array([1.5, 1.3, 0.5]) + + # Companions for the first two systems + companions = Table() + companions['system_idx'] = np.array([0, 1]) + companions['mass'] = np.array([0.5, 0.4]) + companions['log_a'] = np.array([1.0, 1.5]) # log10(AU) + companions['e'] = np.array([0.1, 0.2]) + companions['i'] = np.array([30.0, 60.0]) # degrees + companions['Omega'] = np.array([0.0, 0.0]) + companions['omega'] = np.array([0.0, 0.0]) + + evo = evolution.COSMIC(keep_disrupted_companions=False, keep_COSMIC_tables=True) + ss, comp = evo.evolve(star_systems, companions, logAge=8.0, metallicity=0.0) + + # Check that evolve() populated the expected output columns + expected_cols = ['mass_current', 'Teff', 'L', 'logg', 'phase', + 'kick', 'kick_x', 'kick_y', 'kick_z'] + for col in expected_cols: + assert col in ss.colnames, 'star_systems missing column {0}'.format(col) + assert col in comp.colnames, 'companions missing column {0}'.format(col) + + # Core bookkeeping invariant: companion count must match companion table length + assert np.sum(ss['N_companions']) == len(comp) + + # Scalar kick must be the magnitude of the kick vector components + np.testing.assert_allclose( + ss['kick'], np.sqrt(ss['kick_x']**2 + ss['kick_y']**2 + ss['kick_z']**2)) + np.testing.assert_allclose( + comp['kick'], np.sqrt(comp['kick_x']**2 + comp['kick_y']**2 + comp['kick_z']**2)) + + # Young, low-mass stars should remain stellar (no compact remnants here). + # Compact-object phase codes are 101 (WD), 102 (NS), 103 (BH). + assert np.all(ss['phase'] < 100) + assert np.all(comp['phase'] < 100) + + # keep_COSMIC_tables=True should store the raw COSMIC output tables + for attr in ['bpp', 'bcm', 'initC', 'kick_info']: + assert hasattr(evo, attr), 'COSMIC model missing table {0}'.format(attr) + + return + +def test_COSMIC_ResolvedCluster(): + """ + Test the full COSMIC cluster pipeline, mirroring the Cluster_w_COSMIC + tutorial: build an IsochronePhotExternalEvolution, then a ResolvedCluster + with binary multiplicity (CSF_max=1, companion_max=True), and check the + output tables. + + Skipped (with a warning) if the optional `cosmic` package is not installed. + """ + _require_cosmic() + + # Cluster/isochrone parameters (kept small/cheap) + logAge = 9.0 + AKs = 0.0 + distance = 4000 + metallicity = 0.0 + cluster_mass = 10**3. + mass_sampling = 10 + atm_grid_dir = f'{spisea_path}/tests/atm_cosmic' + + filt_list = ['ubv,V'] + + # External evolution model (keep tables so we can verify them) + evo = evolution.COSMIC(keep_COSMIC_tables=True) + atm_func = atmospheres.get_merged_atmosphere_w_bb_supplement + red_law = reddening.RedLawCardelli(3.1) + + iso = syn.IsochronePhotExternalEvolution( + logAge, + AKs, + distance, + metallicity=metallicity, + evo_model=evo, + atm_func=atm_func, + red_law=red_law, + filters=filt_list, + atm_grid_dir=atm_grid_dir, + mass_sampling=mass_sampling, + recomp=False + ) + + # COSMIC only supports binaries: resolved multiplicity, no higher-order systems + clust_multiplicity = multiplicity.MultiplicityResolvedDK(CSF_max=1, companion_max=True) + my_imf = imf.Kroupa_2001(multiplicity=clust_multiplicity) + + cluster = syn.ResolvedCluster(iso, my_imf, cluster_mass) + star_systems = cluster.star_systems + companions = cluster.companions + + # Basic sanity: stars and companions were produced + assert len(star_systems) > 0 + assert len(companions) > 0 + + # Core bookkeeping invariant + assert np.sum(star_systems['N_companions']) == len(companions) + + # Kick columns present and self-consistent on both tables + for tab in (star_systems, companions): + for col in ['kick', 'kick_x', 'kick_y', 'kick_z']: + assert col in tab.colnames + np.testing.assert_allclose( + tab['kick'], np.sqrt(tab['kick_x']**2 + tab['kick_y']**2 + tab['kick_z']**2)) + + # Synthetic photometry column should exist + assert 'm_ubv_V' in star_systems.colnames + + # All phase codes should be in the allowed set: + # 0-9 stellar phases, 101 (WD), 102 (NS), 103 (BH) + allowed_phases = set(range(0, 10)) | {101, 102, 103} + ss_phases = set(np.unique(star_systems['phase']).astype(int).tolist()) + comp_phases = set(np.unique(companions['phase']).astype(int).tolist()) + assert ss_phases.issubset(allowed_phases), 'Unexpected star phases: {0}'.format(ss_phases - allowed_phases) + assert comp_phases.issubset(allowed_phases), 'Unexpected companion phases: {0}'.format(comp_phases - allowed_phases) + + # keep_COSMIC_tables=True should expose the raw COSMIC tables on the evo model + for attr in ['bpp', 'bcm', 'initC', 'kick_info']: + assert hasattr(iso.evo_model, attr), 'COSMIC model missing table {0}'.format(attr) + + return + #=================================# # Additional timing functions #=================================# From 5a5748103df9b525e7f131c23771a57c54acf721 Mon Sep 17 00:00:00 2001 From: nsabrams Date: Tue, 16 Jun 2026 10:45:43 -0700 Subject: [PATCH 22/28] updated to new cosmic default bsedict but kept zsolar = 0.02 --- spisea/evolution.py | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/spisea/evolution.py b/spisea/evolution.py index 1129f54f..a4d1a824 100755 --- a/spisea/evolution.py +++ b/spisea/evolution.py @@ -1545,28 +1545,28 @@ class COSMIC(StellarEvolution): def __init__(self, BSEDict='default', keep_disrupted_companions=True, keep_COSMIC_tables=False): if BSEDict == 'default': self.BSEDict = { - "pts1": 0.001, "pts2": 0.01, "pts3": 0.02, "zsun": 0.02, "windflag": 3, - "eddlimflag": 0, "neta": 0.5, "bwind": 0.0, "hewind": 0.5, "beta": 0.125, - "xi": 0.5, "acc2": 1.5, "LBV_flag": 1, "alpha1": 1.0, "lambdaf": 0.0, - "ceflag": 1, "cekickflag": 2, "cemergeflag": 1, "cehestarflag": 0, - "qcflag": 5, - "qcrit_array": [0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0], - "kickflag": 5, "sigma": 265.0, "bhflag": 1, "bhsigmafrac": 1.0, - "sigmadiv": -20.0, "ecsn": 2.25, "ecsn_mlow": 1.6, "aic": 1, "ussn": 1, - "polar_kick_angle": 90.0, - "natal_kick_array": [[-100.0, -100.0, -100.0, -100.0, 0.0], [-100.0, -100.0, -100.0, -100.0, 0.0]], - "mm_mu_ns": 400.0, "mm_mu_bh": 200.0, "remnantflag": 4, - "fryer_mass_limit": 0, "mxns": 3.0, "rembar_massloss": 0.5, - "wd_mass_lim": 1, "maltsev_mode": 0, "maltsev_fallback": 0.5, - "maltsev_pf_prob": 0.1, "pisn": -2, "ppi_co_shift": 0.0, - "ppi_extra_ml": 0.0, "bhspinflag": 0, "bhspinmag": 0.0, "grflag": 1, - "eddfac": 10, "gamma": -2, "don_lim": -1, "acc_lim": -1, "tflag": 1, - "ST_tide": 1, - "fprimc_array": [2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0], - "ifflag": 1, "wdflag": 1, "epsnov": 0.001, "bdecayfac": 1, - "bconst": 3000, "ck": 1000, "rejuv_fac": 1.0, "rejuvflag": 0, - "bhms_coll_flag": 0, "htpmb": 1, "ST_cr": 1, "rtmsflag": 0 - } + "pts1": 0.001, "pts2": 0.01, "pts3": 0.02, "zsun": 0.02, "windflag": 3, + "eddlimflag": 0, "neta": 0.5, "bwind": 0.0, "hewind": 0.5, "beta": 0.125, + "xi": 0.5, "acc2": 1.5, "LBV_flag": 1, "alpha1": [1.0, 1.0], + "lambdaf": 0.0, "ceflag": 1, "cekickflag": 2, "cemergeflag": 1, + "cehestarflag": 0, "qcflag": 5, + "qcrit_array": [0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0], + "kickflag": 5, "sigma": 265.0, "bhflag": 1, "bhsigmafrac": 1.0, + "sigmadiv": -20.0, "ecsn": 2.25, "ecsn_mlow": 1.6, "aic": 1, "ussn": 1, + "polar_kick_angle": 90.0, + "natal_kick_array": [[-100.0, -100.0, -100.0, -100.0, 0.0], [-100.0, -100.0, -100.0, -100.0, 0.0]], + "mm_mu_ns": 400.0, "mm_mu_bh": 200.0, "remnantflag": 4, + "fryer_mass_limit": 0, "mxns": 3.0, "fryer_fmix": 1.0, + "fryer_mcrit_nsbh": 5.75, "rembar_massloss": 0.5, "wd_mass_lim": 1, + "maltsev_mode": 0, "maltsev_fallback": 0.5, "maltsev_pf_prob": 0.1, + "pisn": -2, "ppi_co_shift": 0.0, "ppi_extra_ml": 0.0, "bhspinflag": 0, + "bhspinmag": 0.0, "grflag": 1, "eddfac": 10, "gamma": -2, "don_lim": -1, + "acc_lim": [-1, -1], "smt_periastron_check": 0, "tflag": 1, "ST_tide": 1, + "fprimc_array": [2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0], + "ifflag": 1, "wdflag": 1, "epsnov": 0.001, "bdecayfac": 1, + "bconst": 3000, "ck": 1000, "rejuv_fac": 1.0, "rejuvflag": 0, + "bhms_coll_flag": 0, "htpmb": 1, "ST_cr": 1, "rtmsflag": 0 + } else: self.BSEDict = BSEDict From 07f3d53ec559b67dc81845654968b54287c4d31e Mon Sep 17 00:00:00 2001 From: nsabrams Date: Tue, 16 Jun 2026 11:04:48 -0700 Subject: [PATCH 23/28] added copy=True to accomidate more updated versions of numpy and pandas --- spisea/evolution.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spisea/evolution.py b/spisea/evolution.py index a4d1a824..be93e066 100755 --- a/spisea/evolution.py +++ b/spisea/evolution.py @@ -1744,13 +1744,13 @@ def evolve(self, star_systems, companions, logAge, metallicity): loga = np.log10(final_binaries['sep'][companion_system_idxs]*u.Rsun.to('AU')) companions['log_a'] = loga - fixed_phases1 = final_binaries['kstar_1'].to_numpy() + fixed_phases1 = final_binaries['kstar_1'].to_numpy(copy=True) fixed_phases1[np.where((final_binaries['kstar_1'] >= 10) & (final_binaries['kstar_1'] <= 12))[0]] = 101 fixed_phases1[np.where(final_binaries['kstar_1'] == 13)[0]] = 102 fixed_phases1[np.where(final_binaries['kstar_1'] == 14)[0]] = 103 star_systems['phase'] = fixed_phases1 - fixed_phases2 = final_binaries['kstar_2'][companion_system_idxs].to_numpy() + fixed_phases2 = final_binaries['kstar_2'][companion_system_idxs].to_numpy(copy=True) fixed_phases2[np.where((final_binaries['kstar_2'][companion_system_idxs] >= 10) & (final_binaries['kstar_2'][companion_system_idxs] <= 12))[0]] = 101 fixed_phases2[np.where(final_binaries['kstar_2'][companion_system_idxs] == 13)[0]] = 102 fixed_phases2[np.where(final_binaries['kstar_2'][companion_system_idxs] == 14)[0]] = 103 From d5905b9cb472ecf473382eef2aab968494fd3ba6 Mon Sep 17 00:00:00 2001 From: nsabrams Date: Wed, 17 Jun 2026 14:38:00 -0700 Subject: [PATCH 24/28] added docs for cosmic --- docs/evo_models.rst | 10 ++++++++++ docs/make_isochrone.rst | 13 ++++++++++++- docs/multiplicity.rst | 5 +++++ 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/docs/evo_models.rst b/docs/evo_models.rst index 4cabc35c..d066ae2e 100644 --- a/docs/evo_models.rst +++ b/docs/evo_models.rst @@ -73,11 +73,18 @@ Below is a table of the evolution model grids currently supported by SPISEA. - 6.00 - 10.00 - -0.5, 0, 0.5 - Marley et al. (2021) + * - ``COSMIC`` :sup:`b` + - 0.08 - 150 + - - + - -2.3 - 0.18 + - Breivik et al. (2020) .. rubric:: Footnotes :sup:`a` Actual maximum value given by the Sonora models (Marley et al., 2021) relies on the age of the cluster. For example, for log(Age)=6.0, the mass range is limited to 0.0005 - 0.011 M\ :sub:`⊙`. +:sup:`b` COSMIC evolves the stars externally and does not use SPISEA's standard isochrone-grid architecture. Instead, it uses a custom atmosphere grid that is created on the fly. See Breivik et al. (2020) for more details on COSMIC. When COSMIC is used, the IFMR is ignored. + Please note the stellar mass range, age range, and metallicity values of the evolution model grid you choose: @@ -142,4 +149,7 @@ Specific Evolution Model Classes :show-inheritance: .. autoclass:: evolution.Phillips2020 + :show-inheritance: + +.. autoclass:: evolution.COSMIC :show-inheritance: \ No newline at end of file diff --git a/docs/make_isochrone.rst b/docs/make_isochrone.rst index 5f764c93..11ae9bd1 100644 --- a/docs/make_isochrone.rst +++ b/docs/make_isochrone.rst @@ -89,11 +89,18 @@ Tips and Tricks: The IsochronePhot Object reddening law have changed, the original file will be overwritten by the new isochrone. - *To avoid files from being unintentially overwritten, we recommend + *To avoid files from being unintentionally overwritten, we recommend that users specify different iso_dir paths when making isochrones with different evolution models, atmosphere models, or reddening laws.* +* For external evolution models (i.e. COSMIC), you should use + IsochronePhotExternalEvolution + instead of IsochronePhot. This is because those evolution models do not have isochrones but + instead evolve the stars externally. The first time you run a new AKs, metallicity, or distance, + this will take ~10-20 mins because it is creating a new atmosphere grid. This table is saved in the + specified iso_dir, under the filename atm___.fits. + Base Isochrone Class ---------------------------- .. autoclass:: synthetic.Isochrone @@ -108,6 +115,10 @@ Isochrone Sub-classes :show-inheritance: :members: make_photometry, plot_CMD, plot_mass_magnitude +.. autoclass:: synthetic.IsochronePhotExternalEvolution + :show-inheritance: + :members: make_photometry, plot_CMD, plot_mass_magnitude + Photometry Conversion Functions ----------------------------- diff --git a/docs/multiplicity.rst b/docs/multiplicity.rst index 69011c8c..1b7709f9 100644 --- a/docs/multiplicity.rst +++ b/docs/multiplicity.rst @@ -27,6 +27,11 @@ returned in the ``star_systems`` table off the cluster object is the same for both unresolved and resolved multiplicity classes: it represents the combined photometry of all stars within a given system. +For most selected evolution models, the multiples are evolved as single stars. +To evolve binaries (does not support higher order multiples), you should use one of the ``MultiplicityResolved`` classes +and the ``COSMIC`` evolution model. +See the example jupyter notebook `Cluster_w_COSMIC.ipynb `_ for an example. + Unresolved Multiplicity Classes ------------------------------------------ From c14fb3d4e514c9120e6574fe9b677155d864202c Mon Sep 17 00:00:00 2001 From: nsabrams Date: Wed, 17 Jun 2026 14:42:33 -0700 Subject: [PATCH 25/28] removed backup merge conflict files --- docs/contributors_BACKUP_57328.rst | 54 - docs/contributors_BASE_57328.rst | 36 - docs/contributors_LOCAL_57328.rst | 38 - docs/contributors_REMOTE_57328.rst | 50 - spisea/atmospheres_BACKUP_22350.py | 2524 ---------------------------- spisea/atmospheres_BACKUP_58456.py | 2524 ---------------------------- spisea/atmospheres_BASE_58456.py | 2165 ------------------------ spisea/atmospheres_LOCAL_58456.py | 2508 --------------------------- spisea/atmospheres_REMOTE_58456.py | 2172 ------------------------ 9 files changed, 12071 deletions(-) delete mode 100644 docs/contributors_BACKUP_57328.rst delete mode 100644 docs/contributors_BASE_57328.rst delete mode 100644 docs/contributors_LOCAL_57328.rst delete mode 100644 docs/contributors_REMOTE_57328.rst delete mode 100755 spisea/atmospheres_BACKUP_22350.py delete mode 100755 spisea/atmospheres_BACKUP_58456.py delete mode 100644 spisea/atmospheres_BASE_58456.py delete mode 100644 spisea/atmospheres_LOCAL_58456.py delete mode 100644 spisea/atmospheres_REMOTE_58456.py diff --git a/docs/contributors_BACKUP_57328.rst b/docs/contributors_BACKUP_57328.rst deleted file mode 100644 index 741f832f..00000000 --- a/docs/contributors_BACKUP_57328.rst +++ /dev/null @@ -1,54 +0,0 @@ -.. _contributors: - -============ -Contributors -============ -Jessica Lu -- Lead Developer; developed initial package framework; collaboratively developed all aspects of code - -Matthew Hosek Jr -- Lead Developer; collaboratively developed all aspects of code - -Casey Lam -- implemented first IFMR module (IFMR_Raithel18) - -Abhimat Gautam -- implemented non-solar metallicity evolution model -support for MIST models as well as blackbody atmosphere function - -Kelly Lockhart -- helped develop UnresolvedCluster class - -Dongwon Kim -- code testing/debugging - -Siyao Jia -- helped with early code and documentation development - -Natasha Abrams -- developed resolved multiplicity capabilities -(ResolvedMultiplicityDK class) - -Michael Medford -- developed resolved multiplicity capabilities -(ResolvedMultiplicityDK class) - -Sam Rose -- developed metallicity-dependent IFMRs (IFMR_Spera15 and IFMR_N20_Sukhbold) - -Rebecca Lewis -- added HAWK-I filter support, code testing/debugging - -Manuel Parra-Royón -- installation using Docker containers and Singularity - -Javier Moldón -- installation using Docker containers and Singularity - -Winston Zhang -- bugfix to make redlaw paths correct regardless of -what operating system is used - -<<<<<<< HEAD -Caitlin Begbie -- added brown dwarf physics and capabilities -======= -Sage Hironaka Remulla -- added Rubin Observatory filters - -Lingfeng Wei -- bugfix to improve creation of iso_dir in -IsochronePhot, implemented faster cluster generation and test -functions for primary and companion star mass generation (v2.3), -updated random state generators (v2.4) - -Macy Huston -- New metallicity bound + isochrone filter checks, -imf_mass_lim bugfix, roman filter bugfix, added Euclid filters, Synthpop compatibility -updates (v2.2), improvements for reading in/updated existing isochrone -files, Vega mag to ST mag conversion function (v2.4) - -Anna Pusack -- Added IRTF L-band filter support ->>>>>>> upstream/dev diff --git a/docs/contributors_BASE_57328.rst b/docs/contributors_BASE_57328.rst deleted file mode 100644 index 40edaee7..00000000 --- a/docs/contributors_BASE_57328.rst +++ /dev/null @@ -1,36 +0,0 @@ -.. _contributors: - -============ -Contributors -============ -Jessica Lu -- Lead Developer; developed initial package framework; collaboratively developed all aspects of code - -Matthew Hosek Jr -- Lead Developer; collaboratively developed all aspects of code - -Casey Lam -- implemented first IFMR module (IFMR_Raithel18) - -Abhimat Gautam -- implemented non-solar metallicity evolution model -support for MIST models as well as blackbody atmosphere function - -Kelly Lockhart -- helped develop UnresolvedCluster class - -Dongwon Kim -- code testing/debugging - -Siyao Jia -- helped with early code and documentation development - -Natasha Abrams -- developed resolved multiplicity capabilities -(ResolvedMultiplicityDK class) - -Michael Medford -- developed resolved multiplicity capabilities -(ResolvedMultiplicityDK class) - -Sam Rose -- developed metallicity-dependent IFMRs (IFMR_Spera15 and IFMR_N20_Sukhbold) - -Rebecca Lewis -- added HAWK-I filter support, code testing/debugging - -Manuel Parra-Royón -- installation using Docker containers and Singularity - -Javier Moldón -- installation using Docker containers and Singularity - -Winston Zhang -- bugfix to make redlaw paths correct regardless of -what operating system is used diff --git a/docs/contributors_LOCAL_57328.rst b/docs/contributors_LOCAL_57328.rst deleted file mode 100644 index e62072d7..00000000 --- a/docs/contributors_LOCAL_57328.rst +++ /dev/null @@ -1,38 +0,0 @@ -.. _contributors: - -============ -Contributors -============ -Jessica Lu -- Lead Developer; developed initial package framework; collaboratively developed all aspects of code - -Matthew Hosek Jr -- Lead Developer; collaboratively developed all aspects of code - -Casey Lam -- implemented first IFMR module (IFMR_Raithel18) - -Abhimat Gautam -- implemented non-solar metallicity evolution model -support for MIST models as well as blackbody atmosphere function - -Kelly Lockhart -- helped develop UnresolvedCluster class - -Dongwon Kim -- code testing/debugging - -Siyao Jia -- helped with early code and documentation development - -Natasha Abrams -- developed resolved multiplicity capabilities -(ResolvedMultiplicityDK class) - -Michael Medford -- developed resolved multiplicity capabilities -(ResolvedMultiplicityDK class) - -Sam Rose -- developed metallicity-dependent IFMRs (IFMR_Spera15 and IFMR_N20_Sukhbold) - -Rebecca Lewis -- added HAWK-I filter support, code testing/debugging - -Manuel Parra-Royón -- installation using Docker containers and Singularity - -Javier Moldón -- installation using Docker containers and Singularity - -Winston Zhang -- bugfix to make redlaw paths correct regardless of -what operating system is used - -Caitlin Begbie -- added brown dwarf physics and capabilities diff --git a/docs/contributors_REMOTE_57328.rst b/docs/contributors_REMOTE_57328.rst deleted file mode 100644 index 1944147e..00000000 --- a/docs/contributors_REMOTE_57328.rst +++ /dev/null @@ -1,50 +0,0 @@ -.. _contributors: - -============ -Contributors -============ -Jessica Lu -- Lead Developer; developed initial package framework; collaboratively developed all aspects of code - -Matthew Hosek Jr -- Lead Developer; collaboratively developed all aspects of code - -Casey Lam -- implemented first IFMR module (IFMR_Raithel18) - -Abhimat Gautam -- implemented non-solar metallicity evolution model -support for MIST models as well as blackbody atmosphere function - -Kelly Lockhart -- helped develop UnresolvedCluster class - -Dongwon Kim -- code testing/debugging - -Siyao Jia -- helped with early code and documentation development - -Natasha Abrams -- developed resolved multiplicity capabilities -(ResolvedMultiplicityDK class) - -Michael Medford -- developed resolved multiplicity capabilities -(ResolvedMultiplicityDK class) - -Sam Rose -- developed metallicity-dependent IFMRs (IFMR_Spera15 and IFMR_N20_Sukhbold) - -Rebecca Lewis -- added HAWK-I filter support, code testing/debugging - -Manuel Parra-Royón -- installation using Docker containers and Singularity - -Javier Moldón -- installation using Docker containers and Singularity - -Winston Zhang -- bugfix to make redlaw paths correct regardless of -what operating system is used - -Sage Hironaka Remulla -- added Rubin Observatory filters - -Lingfeng Wei -- bugfix to improve creation of iso_dir in -IsochronePhot, implemented faster cluster generation and test -functions for primary and companion star mass generation (v2.3), -updated random state generators (v2.4) - -Macy Huston -- New metallicity bound + isochrone filter checks, -imf_mass_lim bugfix, roman filter bugfix, added Euclid filters, Synthpop compatibility -updates (v2.2), improvements for reading in/updated existing isochrone -files, Vega mag to ST mag conversion function (v2.4) - -Anna Pusack -- Added IRTF L-band filter support diff --git a/spisea/atmospheres_BACKUP_22350.py b/spisea/atmospheres_BACKUP_22350.py deleted file mode 100755 index e3d2233c..00000000 --- a/spisea/atmospheres_BACKUP_22350.py +++ /dev/null @@ -1,2524 +0,0 @@ -import logging -import numpy as np -import pysynphot -import os -import glob -from astropy.io import fits -from astropy.table import Table, Column -import pysynphot -import time -import pdb -import warnings - -log = logging.getLogger('atmospheres') - -def get_atmosphere_bounds(model_dir, metallicity=0, temperature=20000, gravity=4, verbose=False): - """ - Given atmosphere model, get temperature and gravity bounds - """ - # Open catalog fits file and break out row indices - catalog = Table.read('{0}/grid/{1}/catalog.fits'.format(os.environ['PYSYN_CDBS'], model_dir)) - - teff_arr = [] - z_arr = [] - logg_arr = [] - for cur_row_index in range(len(catalog)): - index = catalog['INDEX'][cur_row_index] - tmp = index.split(',') - teff_arr.append(float(tmp[0])) - z_arr.append(float(tmp[1])) - logg_arr.append(float(tmp[2])) - teff_arr = np.array(teff_arr) - z_arr = np.array(z_arr) - logg_arr = np.array(logg_arr) - - # Filter by metallicity. Will chose the closest metallicity to desired input - metal_list = np.unique(np.array(z_arr)) - metal_idx = np.argmin(np.abs(metal_list - metallicity)) - metallicity_new = metal_list[metal_idx] - - z_filt = np.where(z_arr == metal_list[metal_idx]) - teff_arr = teff_arr[z_filt] - logg_arr = logg_arr[z_filt] - - # # Now find the closest atmosphere in parameter space to - # # the one we want. We'll find the match with the lowest - # # fractional difference - # teff_diff = (teff_arr - temperature) / temperature - # logg_diff = (logg_arr - gravity) / gravity - # - # diff_tot = abs(teff_diff) + abs(logg_diff) - # idx_f = np.argmin(diff_tot) - # - # temperature_new = teff_arr[idx_f] - # gravity_new = logg_arr[idx_f] - - # First check if temperature within bounds - temperature_new = temperature - if temperature > np.max(teff_arr): - temperature_new = np.max(teff_arr) - if temperature < np.min(teff_arr): - temperature_new = np.min(teff_arr) - - # If temperature within bounds, then check if metallicity within bounds - teff_diff = np.abs(teff_arr - temperature) - sorted_min_diffs = np.unique(teff_diff) - - ## Find two closest temperatures - teff_close_1 = teff_arr[np.where(teff_diff == sorted_min_diffs[0])[0][0]] - teff_close_2 = teff_arr[np.where(teff_diff == sorted_min_diffs[1])[0][0]] - - logg_arr_1 = logg_arr[np.where(teff_arr == teff_close_1)] - logg_arr_2 = logg_arr[np.where(teff_arr == teff_close_2)] - - ## Switch to most conservative bound of logg out of two closest temps - gravity_new = gravity - if gravity > np.min([np.max(logg_arr_1), np.max(logg_arr_2)]): - gravity_new = np.min([np.max(logg_arr_1), np.max(logg_arr_2)]) - if gravity < np.max([np.min(logg_arr_1), np.min(logg_arr_2)]): - gravity_new = np.max([np.min(logg_arr_1), np.min(logg_arr_2)]) - - if verbose: - # Print out changes, if any - if temperature_new != temperature: - teff_msg = 'Changing to T={0:6.0f} for met={1:4.2f} T={2:6.0f} logg={3:4.2f}' - print( teff_msg.format(temperature_new, metallicity, temperature, gravity)) - - if gravity_new != gravity: - logg_msg = 'Changing to logg={0:4.2f} for met={1:4.2f} T={2:6.0f} logg={3:4.2f}' - print( logg_msg.format(gravity_new, metallicity, temperature, gravity)) - - if metallicity_new != metallicity: - logg_msg = 'Changing to met={0:4.2f} for met={1:4.2f} T={2:6.0f} logg={3:4.2f}' - print( logg_msg.format(metallicity_new, metallicity, temperature, gravity)) - - return (temperature_new, gravity_new, metallicity_new) - -def get_kurucz_atmosphere(metallicity=0, temperature=20000, gravity=4, rebin=False): - """ - Return atmosphere from the Kurucz pysnphot grid - (`Kurucz 1993 `_). - - Grid Range: - - * Teff: 3000 - 50000 K - * gravity: 0 - 5 cgs - * metallicity: -5.0 - 1.0 - - Parameters - ---------- - metallicity: float - The stellar metallicity, in terms of [Z] - - temperature: float - The stellar temperature, in units of K - - gravity: float - The stellar gravity, in cgs units - - rebin: boolean - Always false for this particular function - """ - try: - sp = pysynphot.Icat('k93models', temperature, metallicity, gravity) - except: - # Check atmosphere catalog bounds - (temperature, gravity, metallicity) = get_atmosphere_bounds('k93models', - metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - sp = pysynphot.Icat('k93models', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find Kurucz 1993 atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_castelli_atmosphere(metallicity=0, temperature=20000, gravity=4, rebin=False): - """ - Return atmospheres from the pysynphot ATLAS9 atlas - (`Castelli & Kurucz 2004 `_). - - Grid Range: - - * Teff: 3500 - 50000 K - * gravity: 0 - 5.0 cgs - * [M/H]: -2.5 - 0.2 - - Parameters - ---------- - metallicity: float - The stellar metallicity, in terms of [Z] - - temperature: float - The stellar temperature, in units of K - - gravity: float - The stellar gravity, in cgs units - - rebin: boolean - If true, rebins the atmospheres so that they are the same - resolution as the Castelli+04 atmospheres. Default is False, - which is often sufficient synthetic photometry in most cases. - - verbose: boolean - True for verbose output - """ - try: - sp = pysynphot.Icat('ck04models', temperature, metallicity, gravity) - except: - # Check atmosphere catalog bounds - (temperature, gravity, metallicity) = get_atmosphere_bounds('ck04models', - metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - sp = pysynphot.Icat('ck04models', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find Castelli and Kurucz 2004 atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_nextgen_atmosphere(metallicity=0, temperature=5000, gravity=4, rebin=False): - """ - metallicity = [M/H] (def = 0) - temperature = Kelvin (def = 5000) - gravity = log gravity (def = 4.0) - """ - try: - sp = pysynphot.Icat('nextgen', temperature, metallicity, gravity) - except: - # Check atmosphere catalog bounds - (temperature, gravity, metallicity) = get_atmosphere_bounds('nextgen', - metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - sp = pysynphot.Icat('nextgen', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find NextGen atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_amesdusty_atmosphere(metallicity=0, temperature=5000, gravity=4, rebin=False): - """ - metallicity = [M/H] (def = 0) - temperature = Kelvin (def = 5000) - gravity = log gravity (def = 4.0) - """ - sp = pysynphot.Icat('AMESdusty', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find AMESdusty Allard+ 2000 atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_phoenix_atmosphere(metallicity=0, temperature=5000, gravity=4, - rebin=False): - """ - Return atmosphere from the pysynphot - `PHOENIX atlas `_. - - Parameters - ---------- - metallicity: float - The stellar metallicity, in terms of [Z] - - temperature: float - The stellar temperature, in units of K - - gravity: float - The stellar gravity, in cgs units - - rebin: boolean - If true, rebins the atmospheres so that they are the same - resolution as the Castelli+04 atmospheres. Default is False, - which is often sufficient synthetic photometry in most cases. - - """ - try: - sp = pysynphot.Icat('phoenix', temperature, metallicity, gravity) - except: - # Check atmosphere catalog bounds - (temperature, gravity, metallicity) = get_atmosphere_bounds('phoenix', - metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - sp = pysynphot.Icat('phoenix', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find PHOENIX BT-Settl (Allard+ 2011 atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_cmfgenRot_atmosphere(metallicity=0, temperature=24000, gravity=4.3, rebin=True, verbose=False): - """ - metallicity = [M/H] (def = 0) - temperature = Kelvin (def = 24000) - gravity = log gravity (def = 4.3) - - rebin=True: pull from atmospheres at ck04model resolution. - """ - # Take care of atmospheres outside the catalog boundaries - logg_msg = 'Changing to logg={0:3.1f} for T={1:6.0f} logg={2:4.2f}' - if gravity > 4.3: - if verbose: - print( logg_msg.format(4.3, temperature, gravity)) - gravity = 4.3 - - if rebin: - sp = pysynphot.Icat('cmfgen_rot_rebin', temperature, metallicity, gravity) - else: - sp = pysynphot.Icat('cmfgen_rot', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find CMFGEN rotating atmosphere model (Fierro+15) for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_cmfgenRot_atmosphere_closest(metallicity=0, temperature=24000, gravity=4.3, rebin=True, - verbose=False): - """ - For a given stellar atmosphere, get extract the closest possible match in - Teff/logg space. Note that this is different from the normal routine - which interpolates along the input grid to get final spectrum. We can't - do this here because the Fierro+15 atmosphere grid is so sparse - - rebin=True: pull from atmospheres at ck04model resolution. - - If verbose, print out the parameters of the match - """ - # Set up the proper root directory - if rebin == True: - root_dir = os.environ['PYSYN_CDBS'] + '/cmfgen_rot_rebin/' - else: - root_dir = os.environ['PYSYN_CDBS'] + '/cmfgen_rot/' - - # Read in catalog, extract atmosphere info - cat = Table.read('{0}/catalog.fits'.format(root_dir), format='fits') - teff_arr = [] - z_arr = [] - logg_arr = [] - for ii in range(len(cat)): - index = cat['INDEX'][ii] - tmp = index.split(',') - teff_arr.append(float(tmp[0])) - z_arr.append(float(tmp[1])) - logg_arr.append(float(tmp[2])) - teff_arr = np.array(teff_arr) - z_arr = np.array(z_arr) - logg_arr = np.array(logg_arr) - - # Now find the closest atmosphere in parameter space to - # the one we want. We'll find the match with the lowest - # fractional difference - teff_diff = (teff_arr - temperature) / temperature - logg_diff = (logg_arr - gravity) / gravity - - diff_tot = abs(teff_diff) + abs(logg_diff) - idx_f = np.where(diff_tot == min(diff_tot))[0][0] - - # Extract the filename of the best-match model and read as - # pysynphot object - infile = cat[idx_f]['FILENAME'].split('.') - spec = Table.read('{0}/{1}.fits'.format(root_dir, infile[0])) - - # Now, the CMFGEN atmospheres assume a distance of 1 kpc, while the the - # ATLAS models are in FLAM at the surface. So, we need to multiply the - # CMFGEN atmospheres by (1000/R)**2. in order to convert to FLAM on surface. - # We'll calculate radius from Teff and logL, which is given in the Table_*.txt file - t = Table.read('{0}/Table_rot.txt'.format(root_dir), format='ascii') - tmp = np.where(t['col1'] == infile[0]) - - lum = t['col3'][tmp] * (3.839*10**33) # cgs - sigma = 5.6704 * 10**-5 # cgs - teff = teff_arr[idx_f] # cgs - - radius = np.sqrt( lum / (4.0 * np.pi * teff**4. * sigma) ) # in cm - radius /= 3.08*10**18 # in pc - - - # Make the pysynphot spectrum - w = spec['Wavelength'] - f = spec['Flux'] * (1000 / radius)**2. - sp = pysynphot.ArraySpectrum(w,f) - - #sp = pysynphot.FileSpectrum('{0}/{1}.fits'.format(root_dir, infile[0])) - - # Print out parameters of match, if desired - if verbose: - print('Teff match: Input: {0}, Output: {1}'.format(temperature, teff_arr[idx_f])) - print('logg match: Input: {0}, Output: {1}'.format(gravity, logg_arr[idx_f])) - - return sp - -def get_cmfgenNoRot_atmosphere(metallicity=0, temperature=22500, gravity=3.98, rebin=True): - """ - metallicity = [M/H] (def = 0) - temperature = Kelvin (def = 24000) - gravity = log gravity (def = 4.3) - - rebin=True: pull from atmospheres at ck04model resolution. - """ - if rebin: - sp = pysynphot.Icat('cmfgen_norot_rebin', temperature, metallicity, gravity) - else: - sp = pysynphot.Icat('cmfgen_norot', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find CMFGEN rotating atmosphere model (Fierro+15) for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_cmfgenNoRot_atmosphere(metallicity=0, temperature=30000, gravity=4.14): - """ - metallicity = [M/H] (def = 0) - temperature = Kelvin (def = 30000) - gravity = log gravity (def = 4.14) - """ - sp = pysynphot.Icat('cmfgenF15_noRot', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find CMFGEN non-rotating atmosphere model (Fierro+15) for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_phoenixv16_atmosphere(metallicity=0, temperature=4000, gravity=4, rebin=True): - """ - Return PHOENIX v16 atmospheres from - `Husser et al. 2013 `_. - - Models originally downloaded via `ftp `_. - Solar metallicity and [alpha/Fe] is used. - - Grid Range: - - * Teff: 2300 - 7000 K, steps of 100 K; 7000 - 12000 in steps of 200 K - * gravity: 0.0 - 6.0 cgs, steps of 0.5 - * [M/H]: -4.0 - 1.0 - - Parameters - ---------- - metallicity: float - The stellar metallicity, in terms of [Z] - - temperature: float - The stellar temperature, in units of K - - gravity: float - The stellar gravity, in cgs units - - rebin: boolean - If true, rebins the atmospheres so that they are the same - resolution as the Castelli+04 atmospheres. Default is False, - which is often sufficient synthetic photometry in most cases. - - """ - atm_model_name = 'phoenix_v16' - if rebin == True: - atm_model_name = 'phoenix_v16_rebin' - - - # Extract atmosphere. If that fails, then check bounds and try again - try: - sp = pysynphot.Icat(atm_model_name, temperature, metallicity, gravity) - except: - # Check atmosphere catalog bounds - (temperature, gravity, metallicity) = get_atmosphere_bounds(atm_model_name, - metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - sp = pysynphot.Icat(atm_model_name, temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find PHOENIXv16 (Husser+13) atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_BTSettl_2015_atmosphere(metallicity=0, temperature=2500, gravity=4, rebin=True): - """ - Return atmosphere from CIFIST2011_2015 grid - (`Allard et al. 2012 `_, - `Baraffe et al. 2015 `_ ) - - Grid originally downloaded from `website `_. - - Grid Range: - - * Teff: 1200 - 7000 K - * gravity: 2.5 - 5.5 cgs - * [M/H] = 0 - - Parameters - ---------- - metallicity: float - The stellar metallicity, in terms of [Z] - - temperature: float - The stellar temperature, in units of K - - gravity: float - The stellar gravity, in cgs units - - rebin: boolean - If true, rebins the atmospheres so that they are the same - resolution as the Castelli+04 atmospheres. Default is False, - which is often sufficient synthetic photometry in most cases. - """ - if rebin == True: - atm_name = 'BTSettl_2015_rebin' - else: - atm_name = 'BTSettl_2015' - - try: - sp = pysynphot.Icat(atm_name, temperature, metallicity, gravity) - except: - # Check atmosphere catalog bounds - (temperature, gravity, metallicity) = get_atmosphere_bounds(atm_name, - metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - sp = pysynphot.Icat(atm_name, temperature, metallicity, gravity) -<<<<<<< HEAD - #print(dir(obj)) - - -======= - - ->>>>>>> upstream/dev - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find BTSettl_2015 atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_BTSettl_atmosphere(metallicity=0, temperature=2500, gravity=4.5, rebin=True): - """ - Return atmosphere from CIFIST2011 grid - (`Allard et al. 2012 `_) - - Grid originally downloaded `here `_ - - Notes - ------ - Grid Range: - - * [M/H] = -2.5, -2.0, -1.5, -1.0, -0.5, 0, 0.5 - - Teff and gravity ranges depend on metallicity: - - [M/H] = -2.5 - - * Teff: 2600 - 4600 K - * gravity: 4.5 - 5.5 - - [M/H] = -2.0 - - * Teff: 2600 - 7000 - * gravity: 4.5 - 5.5 - - [M/H] = -1.5 - - * Teff: 2600 - 7000 - * gravity: 4.5 - 5.5 - - [M/H] = -1.0 - - * Teff: 2600 - 7000 - * gravity: Teff < 3200 --> 4.5 - 5.5; Teff > 3200 --> 2.5 - 5.5 - - [M/H] = -0.5 - - * Teff: 1000 -7000 - * gravity: Teff < 3000 --> 4.5 - 5.5; Teff > 3000 --> 3.0 - 6.0 - - [M/H] = 0 - - * Teff: 750 - 7000 - * gravity: Teff < 2500 --> 3.5 - 5.5; Teff > 2500 --> 0 - 5.5 - - [M/H] = 0.5 - - * Teff: 1000 - 5000 - * gravity: 3.5 - 5.0 - - - Alpha enhancement: - - * [M/H]= -0.0, +0.5 no anhancement - * [M/H]= -0.5 with [alpha/H]=+0.2 - * [M/H]= -1.0, -1.5, -2.0, -2.5 with [alpha/H]=+0.4 - - Parameters - ---------- - metallicity: float - The stellar metallicity, in terms of [Z] - - temperature: float - The stellar temperature, in units of K - - gravity: float - The stellar gravity, in cgs units - - rebin: boolean - If true, rebins the atmospheres so that they are the same - resolution as the Castelli+04 atmospheres. Default is False, - which is often sufficient synthetic photometry in most cases. - - **PRINT STATEMENTS TO DEBUG - **check get_atmosphere_bounds - **comment out try/except clause and check break - """ - if rebin == True: - atm_name = 'BTSettl_rebin' - else: - atm_name = 'BTSettl' - - try: - sp = pysynphot.Icat(atm_name, temperature, metallicity, gravity) - except: - # Check atmosphere catalog bounds - (temperature, gravity, metallicity) = get_atmosphere_bounds(atm_name, - metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - sp = pysynphot.Icat(atm_name, temperature, metallicity, gravity) -<<<<<<< HEAD - -def get_Meisner2023_atmosphere(metallicity=0, temperature=1000, gravity=4.5, rebin=True): - """ - Return atmosphere from Meisner2023 grid - (`Meisner et al. 2023 `_) - - Grid originally downloaded `here `_ - - Grid range: - * Teff = 250 - 1200 K - * gravity: 2.5 - 5.5 cgs (in steps of 0.5) - * [M/H] = -1.0, -0.5, 0, +0, +0.3 - - """ - if rebin == True: - atm_name = 'Meisner2023_rebin' - else: - atm_name = 'Meisner2023' - - try: - sp = pysynphot.Icat(atm_name, temperature, metallicity, gravity) - except: - # Check atmosphere catalog bounds - (temperature, gravity) = get_atmosphere_bounds(atm_name, - metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - sp = pysynphot.Icat(atm_name, temperature, metallicity, gravity) -======= - ->>>>>>> upstream/dev - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find Meisner2023 atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_Phillips2020_atmosphere(metallicity=0, temperature=1000, gravity=4.5, rebin=True): - """ - Return atmosphere from Phillips et al., 2020 using ATMO model - (`Phillips et al. 2020 `_) - - Grid originally downloaded `here `_ - - Grid Range: - * Teff: 200 - 3000 K - * gravity: 2.5 - 5.5 cgs - * [M/H] = 0 - """ - if rebin == True: - atm_name = 'Phillips2020_rebin' - else: - atm_name = 'Phillips2020' - - try: - sp = pysynphot.Icat(atm_name, temperature, metallicity, gravity) - except: - # Check atmosphere catalog bounds - (temperature, gravity) = get_atmosphere_bounds(atm_name, - metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - sp = pysynphot.Icat(atm_name, temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find Phillips2020 atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_wdKoester_atmosphere(metallicity=0, temperature=20000, gravity=7): - """ - Return white dwarf atmospheres from - `Koester et al. 2010 `_ - - Parameters - ---------- - metallicity: float - The stellar metallicity, in terms of [Z] - - temperature: float - The stellar temperature, in units of K - - gravity: float - The stellar gravity, in cgs units - - rebin: boolean - If true, rebins the atmospheres so that they are the same - resolution as the Castelli+04 atmospheres. Default is False, - which is often sufficient synthetic photometry in most cases. - """ - sp = pysynphot.Icat('wdKoester', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find WD Koester (Koester+ 2010 atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_atlas_phoenix_atmosphere(metallicity=0, temperature=5250, gravity=4): - """ - Return atmosphere that is a linear merge of atlas ck04 model and phoenixV16. - - Only valid for temps between 5000 - 5500K, gravity from 0 = 5.0 - """ - try: - sp = pysynphot.Icat('merged_atlas_phoenix', temperature, metallicity, gravity) - except: - # Check atmosphere catalog bounds - (temperature, gravity, metallicity) = get_atmosphere_bounds('merged_atlas_phoenix', - metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - sp = pysynphot.Icat('merged_atlas_phoenix', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find ATLAS-PHOENIX merge atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_BTSettl_phoenix_atmosphere(metallicity=0, temperature=5250, gravity=4): - """ - Return atmosphere that is a linear merge of BTSettl_CITFITS2011_2015 model - and phoenixV16. - - Only valid for temps between 3200 - 3800K, gravity from 2.5 - 5.5 - """ - try: - sp = pysynphot.Icat('merged_BTSettl_phoenix', temperature, metallicity, gravity) - except: - # Check atmosphere catalog bounds - (temperature, gravity, metallicity) = get_atmosphere_bounds('merged_BTSettl_phoenix', - metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - sp = pysynphot.Icat('merged_BTSettl_phoenix', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find ATLAS-PHOENIX merge atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_BTSettl_meisner_atmosphere(metallicity=0, temperature=5250, gravity=4): - """ - Return atmosphere that is a linear merge of BTSettl_CITFITS2011_2015 model - and Meisner2023. - - Only valid for temps between 1000 - 1200K, gravity from 3.5 - 5.5 - """ - try: - sp = pysynphot.Icat('merged_BTSettl_meisner', temperature, metallicity, gravity) - except: - # Check atmosphere catalog bounds - (temperature, gravity) = get_atmosphere_bounds('merged_BTSettl_meisner', - metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - sp = pysynphot.Icat('merged_BTSettl_meisner', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find BTSettl-Meisner merge atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -#---------------------------------------------------------------------# -def get_merged_atmosphere(metallicity=0, temperature=20000, gravity=4.5, verbose=False, - rebin=True): - """ - Return a stellar atmosphere from a suite of different model grids, - depending on the input temperature, (all values in K). - - Parameters - ---------- - metallicity: float - The stellar metallicity, in terms of [Z] - - temperature: float - The stellar temperature, in units of K - - gravity: float - The stellar gravity, in cgs units - - rebin: boolean - If true, rebins the atmospheres so that they are the same - resolution as the Castelli+04 atmospheres. Default is False, - which is often sufficient synthetic photometry in most cases. - - verbose: boolean - True for verbose output - - Notes - ----- - The underlying stellar model grid used changes as a function of - stellar temperature (in K): - - * T > 20,000: ATLAS - * 5500 <= T < 20,000: ATLAS - * 5000 <= T < 5500: ATLAS/PHOENIXv16 merge - * 3800 <= T < 5000: PHOENIXv16 - - For T < 3800, there is an additional gravity and metallicity - dependence: - - If T < 3800 and [M/H] = 0: - - * T < 3800, logg < 2.5: PHOENIX v16 - * 3200 <= T < 3800, logg > 2.5: BTSettl_CIFITS2011_2015/PHOENIXV16 merge - * 3200 < T <= 1200, logg > 2.5: BTSettl_CIFITS2011_2015 - * 1200 < T <= 1000, logg >= 3.5: BTSettl_CIFITS2011_2015/Meisner2023 merge - * 1000 < T <= 250, logg > 2.5: Meisner2023 - - Otherwise, if T < 3800 and [M/H] != 0: - - * T < 3800: PHOENIX v16 - - References: - - * ATLAS: ATLAS9 models (`Castelli & Kurucz 2004 `_) - * PHOENIXv16 (`Husser et al. 2013 `_) - * BTSettl_CIFITS2011_2015: Baraffee+15, Allard+ (https://phoenix.ens-lyon.fr/Grids/BT-Settl/CIFIST2011_2015/SPECTRA/) - * Meisner2023: ATMO 1D models (`Meisner et al. 2023 `_) - - LTE WARNING: - - The ATLAS atmospheres are calculated with LTE, and so they - are less accurate when non-LTE conditions apply (e.g. T > 20,000 - K). Ultimately we'd like to add a non-LTE atmosphere grid for - the hottest stars in the future. - - HOW BOUNDARIES BETWEEN MODELS ARE TREATED: - - At the boundary between two models grids a temperature range is defined - where the resulting atmosphere is a weighted average between the two - grids. Near one boundary one model - is weighted more heavily, while at the other boundary the other - model is weighted more heavily. These are calculated in the - temperature ranges where we switch between model grids, to - ensure a smooth transition. - """ - # For T < 3800, atmosphere depends on metallicity + gravity. - # If solar metallicity, use BTSettl 2015 grid. Only solar metallicity is - # currently available here, so if non-solar metallicity, just stick with - # the Phoenix grid - if (temperature < 1000): - if verbose: - print( 'Meisner2023 atmosphere') - return get_Meisner2023_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity, - rebin=rebin) - - if (temperature <= 1200) & (temperature >= 1000): - if (gravity >= 3.5): - if verbose: - print( 'BTSettl/Meisner2023 merged atmosphere') - return get_Meisner2023_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity, - rebin=rebin) - if (gravity < 3.5) & (gravity >=2.5): - if verbose: - print( 'Meisner2023 atmosphere') - return get_Meisner2023_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity, - rebin=rebin) - - if (temperature <= 3800) & (metallicity == 0): - # High gravity are in BTSettl regime - if (temperature <= 3200) & (gravity > 2.5): - if verbose: - print( 'BTSettl_2015 atmosphere') - return get_BTSettl_2015_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity, - rebin=rebin) - - if (temperature >= 3200) & (temperature < 3800) & (gravity > 2.5): - if verbose: - print( 'BTSettl/Phoenixv16 merged atmosphere') - return get_BTSettl_phoenix_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - # Low gravity is PHOENIX regime - if gravity <= 2.5: - if verbose: - print( 'Phoenixv16 atmosphere') - return get_phoenixv16_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity, - rebin=rebin) - - if (temperature <= 3800) & (metallicity != 0): - if verbose: - print( 'Phoenixv16 atmosphere') - return get_phoenixv16_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity, - rebin=rebin) - - # For T > 3800, no metallicity or gravity dependence - if (temperature >= 3800) & (temperature < 5000): - if verbose: - print( 'Phoenixv16 atmosphere') - return get_phoenixv16_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity, - rebin=rebin) - - if (temperature >= 5000) & (temperature < 5500): - if verbose: - print( 'ATLAS/Phoenix merged atmosphere') - return get_atlas_phoenix_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - if (temperature >= 5500) & (temperature < 20000): - if verbose: - print( 'ATLAS merged atmosphere') - return get_castelli_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - if temperature >= 20000: - if verbose: - print( 'Still ATLAS merged atmosphere') - return get_castelli_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - #print('CMFGEN') - #return get_cmfgenRot_atmosphere_closest(metallicity=metallicity, - # temperature=temperature, - # gravity=gravity) - - - - -def get_wd_atmosphere(metallicity=0, temperature=20000, gravity=4, verbose=False): - """ - Return the white dwarf atmosphere from - `Koester et al. 2010 `_. - If desired parameters are - outside of grid, return a blackbody spectrum instead - - Parameters - ---------- - metallicity: float - The stellar metallicity, in terms of [Z] - - temperature: float - The stellar temperature, in units of K - - gravity: float - The stellar gravity, in cgs units - - rebin: boolean - If true, rebins the atmospheres so that they are the same - resolution as the Castelli+04 atmospheres. Default is False, - which is often sufficient synthetic photometry in most cases. - - verbose: boolean - True for verbose output - """ - try: - if verbose: - print('wdKoester atmosphere') - - return get_wdKoester_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - except pysynphot.exceptions.ParameterOutOfBounds: - # Use a black-body atmosphere. - bbspec = get_bb_atmosphere(temperature=temperature, verbose=verbose) - return bbspec - - -def get_bd_atmosphere(metallicity=0, temperature=1000, gravity=4, verbose=False): - """ - Return the brown dwarf atmosphere from - `Meisner et al. 2023 `_. - If desired parameters are - outside of grid, return a blackbody spectrum instead - - Parameters - ---------- - metallicity: float - The stellar metallicity, in terms of [Z] - - temperature: float - The stellar temperature, in units of K - - gravity: float - The stellar gravity, in cgs units - - rebin: boolean - If true, rebins the atmospheres so that they are the same - resolution as the Castelli+04 atmospheres. Default is False, - which is often sufficient synthetic photometry in most cases. - - verbose: boolean - True for verbose output - """ - try: - if verbose: - print('Meisner2023 atmosphere') - - return get_Meisner2023_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - except pysynphot.exceptions.ParameterOutOfBounds: - # Use a black-body atmosphere - bbspec = get_bb_atmosphere(temperature=temperature, verbose=verbose) - return bbspec - -def get_bb_atmosphere(metallicity=None, temperature=20_000, gravity=None, - verbose=False, rebin=None, - wave_min=500, wave_max=50_000, wave_num=20_000): - """ - Return a blackbody spectrum - - Parameters - ---------- - temperature: float, default=20_000 - The stellar temperature, in units of K - wave_min: float, default=500 - Sets the minimum wavelength (in Angstroms) of the wavelength range - for the blackbody spectrum - wave_max: float, default=50_000 - Sets the maximum wavelength (in Angstroms) of the wavelength range - for the blackbody spectrum - wave_num: int, default=20_000 - Sets the number of wavelength points in the wavelength range - Note: the wavelength range is evenly spaced in log space - """ - if ((metallicity is not None) or (gravity is not None) or - (rebin is not None)): - warnings.warn( - 'Only `temperature` keyword is used for black-body atmosphere' - ) - - if verbose: - print('Black-body atmosphere') - - # Modify pysynphot's default waveset to specified bounds - pysynphot.refs.set_default_waveset( - minwave=wave_min, maxwave=wave_max, num=wave_num - ) - - # Get black-body atmosphere for specified temperature from pysynphot - bbspec = pysynphot.spectrum.BlackBody(temperature) - - # pysynphot `BlackBody` generates spectrum in `photlam`, need in `flam` - bbspec.convert('flam') - - # `BlackBody` spectrum is normalized to solar radius star at 1 kiloparsec. - # Need to remove this normalization for SPISEA by multiplying bbspec - # by (1000 * 1 parsec / 1 Rsun)**2 = (1000 * 3.08e18 cm / 6.957e10 cm)**2 - bbspec *= (1000 * 3.086e18 / 6.957e10)**2 - - return bbspec - - -#--------------------------------------# -# Atmosphere formatting functions -#--------------------------------------# - -def download_CMFGEN_atmospheres(Table_rot, Table_norot): - """ - Downloads CMFGEN models from - https://sites.google.com/site/fluxesandcontinuum/home; - these contain continuum as well as lines. - - Table_rot, Table_norot are tables with the file prefixes - and model atmosphere parameters, taken by hand from the - Fierro+15 paper - - Website addresses are hardcoded - - Puts downloaded models in the current working directory. - """ - print( 'WARNING: THIS DOES NOT COMPLETELY WORK') - print( '**********************') - t_rot = Table.read(Table_rot, format='ascii') - t_norot = Table.read(Table_norot, format='ascii') - - tables = [t_rot, t_norot] - filenames = [t_rot['col1'], t_norot['col1']] - - # Hardcoded list of webiste addresses - web_base1 = 'https://sites.google.com/site/fluxesandcontinuum/home/' - web_base2 = 'https://sites.google.com/site/modelsobmassivestars/' - web = [web_base1+'009-solar-masses/',web_base1+'012-solar-masses/', - web_base1+'015-solar-masses/',web_base1+'020-solar-masses/', - web_base1+'025-solar-masses/',web_base2+'009-solar-masses-tracks/', - web_base2+'040-solar-masses/',web_base2+'060-solar-masses/', - web_base1+'085-solar-masses/',web_base1+'120-solar-masses/'] - # Array of masses that matches the website addresses - mass_arr = np.array([9.,12.,15.,20.,25.,32.,40.,60.,85.,120.]) - - # Loop through rotating and unrotating case. First loop is rot, second unrot - for i in range(2): - # Extract masses from filenames - masses = [] - for j in filenames[i]: - tmp = j.split('m') - mass = float(tmp[1][:-1]) - masses.append(mass) - - # Download the models webpage by webpage. A bit tricky because masses - # change slightly within a particular website. THIS IS WHAT FAILS - for j in range(len(web)): - if j == 0: - good = np.where( (masses <= mass_arr[j]) ) - else: - g = j - 1 - good = np.where( (masses <= mass_arr[j]) & - (masses > mass_arr[g]) ) - # Use wget command to pull down the files, and unzip them - for k in good[0]: - full = web[j]+'{1:s}.flx.zip'.format(mass_arr[j],filenames[i][k]) - os.system('wget ' + full) - os.system('unzip '+ filenames[i][k] + '.flx.zip') - - return - -def organize_CMFGEN_atmospheres(path_to_dir): - """ - Organize CMFGEN grid from Fierro+15 - (http://www.astroscu.unam.mx/atlas/index.html) - into rot and noRot directories - - path_to_dir is from current working directory to directory - containing the downloaded models. Assumed that models - and tables describing parameters are in this directory. - - Tables describing parameters MUST be named Table_rot.txt, - Table_noRot.txt. Made by hand from Tables 3, 4 in Fierro+15. - These are located in same original directory as atmosphere files - - Will separate files into 2 subdirectories, one rotating and - the other non-rotating - - *Can't have any other files starting with "t" in model directory to start!* - """ - # First, record current working directory to return to later - start_dir = os.getcwd() - - # Enter atmosphere directory, collect rotating and non-rotating - # file names (assumed to all start with "t") - os.chdir(path_to_dir) - rot_models = glob.glob("t*r.flx*") - noRot_models = glob.glob("t*n.flx*") - - # Separate into different subdirectories - if os.path.exists('cmfgenF15_rot'): - pass - else: - os.mkdir('cmfgenF15_rot') - os.mkdir('cmfgenF15_noRot') - - for mod in rot_models: - cmd = 'mv {0:s} cmfgenF15_rot'.format(mod) - os.system(cmd) - - for mod in noRot_models: - cmd = 'mv {0:s} cmfgenF15_noRot'.format(mod) - os.system(cmd) - - # Also move Tables with model parameters into correct directory - os.system('mv Table_rot.txt cmfgenF15_rot') - os.system('mv Table_noRot.txt cmfgenF15_noRot') - - # Return to original directory - os.chdir(start_dir) - - return - -def make_CMFGEN_catalog(path_to_dir): - """ - Create cdbs catalog.fits of CMFGEN grid from Fierro+15 - (http://www.astroscu.unam.mx/atlas/index.html). - THIS IS STEP 2, after organize_CMFGEN_atmospheres has - been run. - - path_to_dir is from current working directory to directory - containing the rotating or non-rotating models (i.e. cmfgenF15_rot). Also, - needs to be a Table*.txt file which contains the parameters for all of the - original models, since params in filename are not precise enough - - Will create catalog.fits file in atmosphere directory with - description of each model - - *Can't have any other files starting with "t" in model directory to start!* - """ - # Record current working directory for later - start_dir = os.getcwd() - - # Enter atmosphere directory - os.chdir(path_to_dir) - - # Extract parameters for each atmosphere - # Note: can't rely on filename for this because not precise enough!! - - #---------OLD: GETTING PARAMS FROM FILENAME-------# - # Collect file names (assumed to all start with "t") - #files = glob.glob("t*") - #for name in files: - # tmp = name.split('l') - # temp = float(tmp[0][1:]) * 100.0 # In kelvin - - # lumtmp = tmp[1].split('_') - # lum = float(lumtmp[0][:-5]) * 1000.0 # In L_sun - - # mass = float(lumtmp[0][5:-1]) # In M_sun - - # Need to calculate log g from T and L (cgs) - # lum_sun = 3.846 * 10**33 # erg/s - # M_sun = 2 * 10**33 # g - # G_si = 6.67 * 10**(-8) # cgs - # sigma_si = 5.67 * 10**(-5) # cgs - - # g = (G_si * mass * M_sun * 4 * np.pi * sigma_si * temp**4) / \ - # (lum * lum_sun) - # logg = np.log10(g) - #---------------------------------------------------# - - # Read table with atmosphere params - table = glob.glob('Table_*') - t = Table.read(table[0], format = 'ascii') - names = t['col1'] - temps = t['col2'] - logg = t['col4'] - - # Create catalog.fits file - index_str = [] - name_str = [] - for i in range(len(names)): - index = '{0:5.0f},0.0,{1:3.2f}'.format(temps[i], logg[i]) - - #---NOTE: THE FOLLOWING DEPENDS ON FINAL LOCATION OF CATALOG FILE---# - #path = path_to_dir + '/' + names[i] - path = names[i] + '.fits[Flux]' - - index_str.append(index) - name_str.append(path) - - catalog = Table([index_str, name_str], names = ('INDEX', 'FILENAME')) - - # Create catalog.fits file in directory with the models - catalog.write('catalog.fits', format = 'fits') - - # Move back to original directory, create the catalog.fits file - os.chdir(start_dir) - - return - -def cdbs_cmfgen(path_to_dir, path_to_cdbs_dir): - """ - Code to put cmfgen models into cdbs format and adds proper unit keyword in - fits header. Save as fits file - - path_to_dir goes from current directory to cmfgen_rot or cmfgen_norot - directory with the *.flx models. Note that these files have already been - organized using organize_CMFGEN_atmospheres code. - - path_to_cdbs_dir goes from current directory to cdbs/grid/cmfgen_rot or - cmfgen_norot directory. Will copy new fits files to this directory. - This directory must already exist! - """ - # Save starting directory for later, move into path_to_dir directory - start_dir = os.getcwd() - os.chdir(path_to_dir) - - # Collect the filenames, make necessary changes to each one - files = glob.glob('*.flx') - - # Need to make brand-new fits tables with data we want. - counter = 0 - for i in files: - counter += 1 - # Open file, extract useful info - t = Table.read(i, format='ascii') - wave = t['col1'] - flux = t['col2'] # Flux is already in erg/cm^2/s/A - - # Need to eliminate duplicate entries (pysynphot crashes) - unique = np.unique(wave, return_index=True) - wave = wave[unique[1]] - flux = flux[unique[1]] - - # Make fits table from individual columns. - c0 = fits.Column(name='Wavelength', format='D', array=wave) - c1 = fits.Column(name='Flux', format='E', array=flux) - - cols = fits.ColDefs([c0, c1]) - tbhdu = fits.BinTableHDU.from_columns(cols) - - #Adding unit keywords - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - - prihdu = fits.PrimaryHDU() - - finalhdu = fits.HDUList([prihdu, tbhdu]) - finalhdu.writeto(i[:-4]+'.fits', overwrite=True) - - print( 'Done {0:2.0f} of {1:2.0f}'.format(counter, len(files))) - - # Return to original directory, copy over new .fits files to cdbs directory - os.chdir(start_dir) - cmd = 'mv {0:s}/*.fits {1:s}'.format(path_to_dir, path_to_cdbs_dir) - os.system(cmd) - - return - -def rebin_cmfgen(cdbs_path, rot=True): - """ - Rebin cmfgen_rot and cmfgen_norot models to atlas ck04 resolution; - this makes spectrophotometry MUCH faster - - cdbs_path: path to cdbs directory - rot=True for rotating models (cmfgen_rot), False for non-rotating models - - makes new directory in cdbs/grid: cmfgen_rot_rebin or cmfgen_norot_rebin - """ - # Get an atlas ck04 model, we will use this to set wavelength grid - sp_atlas = get_castelli_atmosphere() - - # Open a fits table for an existing cmfgen model; we will steal the header. - # Also define paths to new rebin directories - if rot == True: - tmp = cdbs_path+'/grid/cmfgen_rot/t0200l0008m009r.fits' - path = cdbs_path+'/grid/cmfgen_rot_rebin/' - orig_path = cdbs_path+'/grid/cmfgen_rot/' - else: - tmp = cdbs_path+'/grid/cmfgen_norot/t0200l0007m009n.fits' - path = cdbs_path+'/grid/cmfgen_norot_rebin/' - orig_path = cdbs_path+'/grid/cmfgen_norot/' - - cmfgen_hdu = fits.open(tmp) - header0 = cmfgen_hdu[0].header - # Create rebin directories if they don't already exist. Copy over - # catalog.fits file from original directory (will be the same) - if not os.path.exists(path): - os.mkdir(path) - cmd = 'cp {0:s}catalog.fits {1:s}'.format(orig_path, path) - os.system(cmd) - - # Read in the catalog.fits file - cat = fits.getdata(orig_path + 'catalog.fits') - files_all = [cat[ii][1].split('[')[0] for ii in range(len(cat))] - - # First column in new files will be for [atlas] wavelength - c0 = fits.Column(name='Wavelength', format='D', array=sp_atlas.wave) - - # For each catalog.fits entry, read the unbinned spectrum and rebin to - # the atlas resolution. Make a new fits file in rebin directory - count = 0 - for ff in range(len(files_all)): - count += 1 - # Extract the temp, Z, logg - vals = cat[ff][0].split(',') - temp = float(vals[0]) - metal = float(vals[1]) - grav = float(vals[2]) - - # Fetch the spectrum - if rot == True: - sp = pysynphot.Icat('cmfgen_rot', temp, metal, grav) - else: - sp = pysynphot.Icat('cmfgen_norot', temp, metal, grav) - - # Rebin - flux_rebin = rebin_spec(sp.wave, sp.flux, sp_atlas.wave) - c1 = fits.Column(name='Flux', format='E', array=flux_rebin) - - # Make the FITS file from the columns with header - cols = fits.ColDefs([c0,c1]) - tbhdu = fits.BinTableHDU.from_columns(cols) - prihdu = fits.PrimaryHDU(header=header0) - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - - # Write hdu to new directory with same filename - finalhdu = fits.HDUList([prihdu, tbhdu]) - finalhdu.writeto(path+files_all[ff]) - - print( 'Finished file {0} of {1}'.format(count, len(files_all)) ) - return - - -def organize_PHOENIXv16_atmospheres(path_to_dir, met_str='m00'): - """ - Construct the Phoenix Husser+13 atmopsheres for each model. Combines the - fluxes from the *HiRES.fits files and the wavelengths of the - WAVE_PHONEIX-ACES-AGSS-COND-2011.fits file. - - path_to_dir is the path to the directory containing all of the downloaded - files - - met_str is the name of the current metallicity - - Creates new fits files for each atmosphere: phoenix_.fits, - which contains columns for the log g (column header = g#.#). Puts - atmospheres in new directory phoenixm00 - """ - # Save current directory for return later, move into working dir - start_dir = os.getcwd() - os.chdir(path_to_dir) - - # If it doesn't already exist, create the current metallicity subdirectory - sub_dir = '../phoenix{0}'.format(met_str) - if os.path.exists(sub_dir): - pass - else: - os.mkdir(sub_dir) - - # Extract wavelength array, make column for later - wavefile = fits.open('WAVE_PHOENIX-ACES-AGSS-COND-2011.fits') - wave = wavefile[0].data - wavefile.close() - wave_col = Column(wave, name = 'WAVELENGTH') - - # Create temp array for Husser+13 grid (given in paper) - temp_arr = np.arange(2300, 7001, 100) - temp_arr = np.append(temp_arr, np.arange(7000, 12001, 200)) - - print( 'Looping though all temps') - # For each temp, build file containing the flux for all gravities - i = 0 - for temp in temp_arr: - files = glob.glob('lte{0:05d}-*-HiRes.fits'.format(temp)) - files.sort() - # Start the table with the wavelength column - t = Table() - t.add_column(wave_col) - for f in files: - # Extract the logg out of filename - logg = f[9:13] - - # Extract fluxes from file - spectrum = fits.open(f) - flux = spectrum[0].data - spectrum.close() - - # Make Column object with fluxes, add to table - col = Column(flux, name = 'g{0:2.1f}'.format(float(logg))) - t.add_column(col) - - # Now, construct final fits file for the given temp - outname = 'phoenix{0}_{1:05d}.fits'.format(met_str, temp) - t.write('{0}/{1}'.format(sub_dir, outname), format = 'fits', overwrite = True) - - # Progress counter for user - i += 1 - print( 'Done {0:d} of {1:d}'.format(i, len(temp_arr))) - - # Return to original directory - os.chdir(start_dir) - return - -def make_PHOENIXv16_catalog(path_to_dir, met_str='m00'): - """ - Makes catalog.fits file for Husser+13 phoenix models. Assumes that - organize_PHOENIXv16_atmospheres has been run already, and that the models lie - in subdirectory phoenix[met_str]. - - path_to_directory is the path to the directory with the reformatted - models (i.e. the output from construct_atmospheres, phoenix[met_str]) - - Puts catalog.fits file in directory the user starts in - """ - # Save starting directory for later, move into working directory - start_dir = os.getcwd() - os.chdir(path_to_dir) - - # Extract metallicity from metallicity string - met = float(met_str[1]) + (float(met_str[2]) * 0.1) - if 'm' in met_str: - met *= -1. - - # Collect the filenames. Each is a unique temp with many different log g's - files = glob.glob('phoenix*.fits') - files.sort() - - # Create the catalog.fits file, row by row - index_arr = [] - filename_arr = [] - for i in files: - # Get log g values from the column header the file - t = Table.read(i, format='fits') - keys = t.keys() - logg_vals = keys[1:] - - # Extract temp from filename - name = i.split('_') - temp = float(name[1][:-5]) - for j in logg_vals: - logg = float(j[1:]) - index = '{0:5.0f},{1:2.1f},{2:2.1f}'.format(temp, met, logg) - filename = path_to_dir + i + '[' + j + ']' - # Add row to table - index_arr.append(index) - filename_arr.append(filename) - - catalog = Table([index_arr, filename_arr], names=('INDEX', 'FILENAME')) - - # Return to starting directory, write catalog - os.chdir(start_dir) - - if os.path.exists('catalog.fits'): - from astropy.table import vstack - - prev_catalog = Table.read('catalog.fits', format='fits') - joined_catalog = vstack([prev_catalog, catalog]) - - joined_catalog.write('catalog.fits', format='fits', overwrite=True) - else: - catalog.write('catalog.fits', format='fits', overwrite=True) - - return - -def cdbs_PHOENIXv16(path_to_cdbs_dir): - """ - Put the PHOENIXv16 (Husser+13) fits files into cdbs format. This primarily - consists of adjusting the flux units from [erg/s/cm^2/cm] to [erg/s/cm^2/A] - and adding the appropriate keywords to the fits header. - - path_to_cdbs_dir goes from current working directory to phoenix[met] directory - in cdbs/grids/phoenix_v16. Note that these files have already been organized - using organize_PHOENIXv16_atmospheres code. - - Overwrites original files in directory - """ - # Save starting directory for later, move into working directory - start_dir = os.getcwd() - os.chdir(path_to_cdbs_dir) - - # Collect the filenames, make necessary changes to each one - files = glob.glob('phoenix*.fits') - - ## Need to sort filenames; glob doesn't always give them in order - files.sort() - - # Need to make brand-new fits tables with data we want. - counter = 0 - for i in files: - counter += 1 - - # Read in current FITS table - cur_table = Table.read(i, format='fits') - - cur_table.columns[0].name = 'Wavelength' - - num_cols = len(cur_table.colnames) - - # Multiplying each flux column by 10^-8 for conversion - for cur_col_index in range(1, num_cols, 1): - cur_col_name = cur_table.colnames[cur_col_index] - cur_table[cur_col_name] = cur_table[cur_col_name] * 10.**-8 - - - # Construct new FITS file based on old one - hdu = fits.open(i) - header_0 = hdu[0].header - header_1 = hdu[1].header - sci = hdu[1].data - - tbhdu = fits.table_to_hdu(cur_table) - - # Copying over the older headers, adding unit keywords - prihdu = fits.PrimaryHDU(header=header_0) - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - tbhdu.header['TUNIT3'] = 'FLAM' - tbhdu.header['TUNIT4'] = 'FLAM' - tbhdu.header['TUNIT5'] = 'FLAM' - tbhdu.header['TUNIT6'] = 'FLAM' - tbhdu.header['TUNIT7'] = 'FLAM' - tbhdu.header['TUNIT8'] = 'FLAM' - tbhdu.header['TUNIT9'] = 'FLAM' - tbhdu.header['TUNIT10'] = 'FLAM' - tbhdu.header['TUNIT11'] = 'FLAM' - tbhdu.header['TUNIT12'] = 'FLAM' - tbhdu.header['TUNIT13'] = 'FLAM' - tbhdu.header['TUNIT14'] = 'FLAM' - - # Construct and write out final FITS file - finalhdu = fits.HDUList([prihdu, tbhdu]) - finalhdu.writeto(i, overwrite=True) - - hdu.close() - print( 'Done {0:2.0f} of {1:2.0f}'.format(counter, len(files))) - - # Change back to starting directory - os.chdir(start_dir) - - return - -def rebin_phoenixV16(cdbs_path): - """ - Rebin phoenixV16 models to atlas ck04 resolution; this makes - spectrophotometry MUCH faster - - makes new directory in cdbs/grid: phoenix_v16_rebin - - cdbs_path: path to cdbs directory - """ - # Get an atlas ck04 model, we will use this to set wavelength grid - sp_atlas = get_castelli_atmosphere() - - # Open a fits table for an existing phoenix model; we will steal the header - ## (This assumes that at least 'm00' metallicity exists) - tmp = '{0}/grid/phoenix_v16/phoenix{1}/phoenix{1}_02400.fits'.format(cdbs_path, 'm00') - phoenix_hdu = fits.open(tmp) - header0 = phoenix_hdu[0].header - - # Create cdbs/grid directory for rebinned models - path = cdbs_path+'/grid/phoenix_v16_rebin/' - if not os.path.exists(path): - os.mkdir(path) - - - # Read in the existing catalog.fits file and rebin every spectrum. - cat = fits.getdata(cdbs_path + '/grid/phoenix_v16/catalog.fits') - files_all = [cat[ii][1].split('[')[0] for ii in range(len(cat))] - temp_arr = np.zeros(len(files_all), dtype=float) - logg_arr = np.zeros(len(files_all), dtype=float) - metal_arr = np.zeros(len(files_all), dtype=float) - - for ff in range(len(files_all)): - vals = cat[ff][0].split(',') - - temp_arr[ff] = float(vals[0]) - metal_arr[ff] = float(vals[1]) - logg_arr[ff] = float(vals[2]) - - - metal_uniq = np.unique(metal_arr) - temp_uniq = np.unique(temp_arr) - - for mm in range(len(metal_uniq)): - metal = metal_uniq[mm] # metallicity - - # Construct str for metallicity (for appropriate directory name) - met_str = str(int(np.abs(metal))) + str(int((metal % 1.0)*10)) - if metal > 0: - met_str = 'p' + met_str - else: - met_str = 'm' + met_str - - # Make directory for current metallicity if it does not exist yet - if not os.path.exists(path + 'phoenix' + met_str): - os.mkdir(path + 'phoenix' + met_str) - - for tt in range(len(temp_uniq)): - temp = temp_uniq[tt] # temperature - - # Pick out the list of gravities for this T, Z combo - idx = np.where((metal_arr == metal) & (temp_arr == temp))[0] - logg_exist = logg_arr[idx] - - # All gravities will go in one file. Here is the output - # file name. - outfile = path + files_all[idx[0]].split('[')[0] - - ## If the rebinned file already exists, continue - if os.path.exists(outfile): - continue - - # Build a columns array. One column for each gravity. - cols_arr = [] - - # Make the wavelength column, which is first in the cols array. - c0 = fits.Column(name='Wavelength', format='D', array=sp_atlas.wave) - cols_arr.append(c0) - - for gg in range(len(logg_exist)): - grav = logg_exist[gg] # gravity - - # Fetch the spectrum - sp = pysynphot.Icat('phoenix_v16', temp, metal, grav) - flux_rebin = rebin_spec(sp.wave, sp.flux, sp_atlas.wave) - - # Store the spectrum - name = 'g{0:3.1f}'.format(grav) - col = fits.Column(name=name, format='E', array=flux_rebin) - cols_arr.append(col) - - - # Make the FITS file from the columns with header. - cols = fits.ColDefs(cols_arr) - tbhdu = fits.BinTableHDU.from_columns(cols) - prihdu = fits.PrimaryHDU(header=header0) - tbhdu.header['TUNIT1'] = 'ANGSTROM' - for gg in range(len(logg_exist)): - tbhdu.header['TUNIT{0:d}'.format(gg+2)] = 'FLAM' - - # Write hdu - finalhdu = fits.HDUList([prihdu, tbhdu]) - # don't have overwrite to protect original files. - finalhdu.writeto(outfile) - - print( 'Finished file ' + outfile + ' with gravities: ', logg_exist) - - - return - - -def rebin_spec(wave, specin, wavnew): - """ - Helper routine to rebin spectra. TAKEN FROM ASTROBETTER BLOG FROM JESSICA: - http://www.astrobetter.com/blog/2013/08/12/ - python-tip-re-sampling-spectra-with-pysynphot/ - """ - spec = pysynphot.spectrum.ArraySourceSpectrum(wave=wave, flux=specin) - f = np.ones(len(wave)) - filt = pysynphot.spectrum.ArraySpectralElement(wave, f, waveunits='angstrom') - obs = pysynphot.observation.Observation(spec, filt, binset=wavnew, force='taper') - - return obs.binflux - -def organize_BTSettl_2015_atmospheres(path_to_dir): - """ - Construct cdbs-ready BTSettl_CIFITS_2011_2015 atmospheres for each model. - Will convert wavelength units to angstroms and flux units to [erg/s/cm^2/A] - - path_to_dir is the path to the directory containing all of the downloaded - files - - Saves cdbs-ready atmospheres into os.environ['PYSYN_CDBS']/grid/BTSettl_2015 - (assumes this directory exists) - """ - # Save current directory for return later, move into working dir - start_dir = os.getcwd() - os.chdir(path_to_dir) - - # If it doesn't already exist, create the BTSettl subdirectory - if not os.path.exists('BTSettl_2015'): - os.mkdir('BTSettl_2015') - - # Process each atmosphere file independently - print( 'Creating cdbs-ready files') - files = glob.glob('*.spec.fits') - - for i in files: - hdu = fits.open(i) - spec = hdu[1].data - header_0 = hdu[0].header - header_1 = hdu[1].header - - wave = spec.field(0) - flux = spec.field(1) - - # Get units right: convert wave from microns to Angstroms, - # flux from W /m^2/ micron to erg/s/cm^2/A - wave_new = wave * 10**4 - flux_new = flux * 10**(-1) - - # Make new fits table - c0 = fits.Column(name='Wavelength', format='D', array=wave_new) - c1 = fits.Column(name='Flux', format='E', array=flux_new) - - cols = fits.ColDefs([c0, c1]) - tbhdu = fits.BinTableHDU.from_columns(cols) - - # Copy over headers, update unit keywords - prihdu = fits.PrimaryHDU(header=header_0) - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - hdu_new = fits.HDUList([prihdu, tbhdu]) - - # Write new fits table in cdbs directory - hdu_new.writeto(os.environ['PYSYN_CDBS']+'grid/BTSettl_2015/'+i, overwrite=True) - - hdu.close() - hdu_new.close() - - # Return to original directory - os.chdir(start_dir) - return - -def make_BTSettl_2015_catalog(path_to_dir): - """ - Create cdbs catalog.fits of BTSettl_CIFITS2011_2015 grid. - THIS IS STEP 2, after organize_CMFGEN_atmospheres has - been run. - - path_to_dir is from current working directory to the cdbs directory. - Will create catalog.fits file in atmosphere directory with - description of each model - """ - # Record current working directory for later - start_dir = os.getcwd() - - # Enter atmosphere directory - os.chdir(path_to_dir) - - # Extract parameters for each atmosphere from the filename, - # construct columns for catalog file - files = glob.glob("*spec.fits") - index_str = [] - name_str = [] - for name in files: - tmp = name.split('-') - temp = float(tmp[0][3:]) * 100.0 # In kelvin - logg = float(tmp[1]) - - index_str.append('{0:5.0f},0.0,{1:3.2f}'.format(temp, logg)) - name_str.append('{0}[Flux]'.format(name)) - - # Make catalog - catalog = Table([index_str, name_str], names = ('INDEX', 'FILENAME')) - - # Create catalog.fits file in directory with the models - catalog.write('catalog.fits', format = 'fits', overwrite=True) - - # Move back to original directory, create the catalog.fits file - os.chdir(start_dir) - - return - -def rebin_BTSettl_2015(cdbs_path=os.environ['PYSYN_CDBS']): - """ - Rebin BTSettle_CIFITS2011_2015 models to atlas ck04 resolution; this makes - spectrophotometry MUCH faster - - makes new directory in cdbs/grid: BTSettl_2015_rebin - - cdbs_path: path to cdbs directory - """ - # Get an atlas ck04 model, we will use this to set wavelength grid - sp_atlas = get_castelli_atmosphere() - - # Open a fits table for an existing phoenix model; we will steal the header - tmp = cdbs_path+'/grid/phoenix_v16/phoenixm00/phoenixm00_02400.fits' - phoenix_hdu = fits.open(tmp) - header0 = phoenix_hdu[0].header - phoenix_hdu.close() - - # Create cdbs/grid directory for rebinned models - path = cdbs_path+'/grid/BTSettl_2015_rebin/' - if not os.path.exists(path): - os.mkdir(path) - - # Read in the existing catalog.fits file and rebin every spectrum. - cat = fits.getdata(cdbs_path + '/grid/BTSettl_2015/catalog.fits') - files_all = [cat[ii][1].split('[')[0] for ii in range(len(cat))] - - print( 'Rebinning BTSettl spectra') - for ff in range(len(files_all)): - vals = cat[ff][0].split(',') - temp = float(vals[0]) - metal = float(vals[1]) - logg = float(vals[2]) - - # Fetch the BTSettl spectrum, rebin flux - sp = pysynphot.Icat('BTSettl_2015', temp, metal, logg) - flux_rebin = rebin_spec(sp.wave, sp.flux, sp_atlas.wave) - - # Make new output - c0 = fits.Column(name='Wavelength', format='D', array=sp_atlas.wave) - c1 = fits.Column(name='Flux', format='E', array=flux_rebin) - - cols = fits.ColDefs([c0, c1]) - tbhdu = fits.BinTableHDU.from_columns(cols) - prihdu = fits.PrimaryHDU(header=header0) - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - - outfile = path + files_all[ff].split('[')[0] - finalhdu = fits.HDUList([prihdu, tbhdu]) - finalhdu.writeto(outfile, overwrite=True) - - return - -def make_wavelength_unique(files, dirname): - """ - Helper function to go through each BTSettl spectrum and ensure that - each wavelength point is unique. This is required for rebinning to work. - - - files: list of files to run this analysis on - """ - # Loop through each file, find fix repeated wavelength entries if necessary - for i in files: - t = Table.read('{0}/{1}'.format(dirname,i), format='fits') - test = np.unique(t['Wavelength'], return_index=True) - - if len(t) != len(test[0]): - t = t[test[1]] - - c0 = fits.Column(name='Wavelength', format='D', array=t['Wavelength']) - c1 = fits.Column(name='Flux', format='E', array=t['Flux']) - cols = fits.ColDefs([c0, c1]) - - tbhdu = fits.BinTableHDU.from_columns(cols) - prihdu = fits.PrimaryHDU() - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - finalhdu = fits.HDUList([prihdu, tbhdu]) - finalhdu.writeto('{0}/{1}'.format(dirname,i), overwrite=True) - - # Also make sure wavelength is monotonic. If it is not, then it is - # a sign that the wavelengths are out of order - diff = np.diff(t['Wavelength']) - bad = np.where(diff < 0) - if len(bad[0]) > 0: - t.sort('Wavelength') - - c0 = fits.Column(name='Wavelength', format='D', array=t['Wavelength']) - c1 = fits.Column(name='Flux', format='E', array=t['Flux']) - cols = fits.ColDefs([c0, c1]) - - tbhdu = fits.BinTableHDU.from_columns(cols) - prihdu = fits.PrimaryHDU() - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - finalhdu = fits.HDUList([prihdu, tbhdu]) - finalhdu.writeto('{0}/{1}'.format(dirname,i), overwrite=True) - - print('Done {0}'.format(i)) - - return - -def organize_BTSettl_atmospheres(): - """ - Construct cdbs-ready atmospheres for the BTSettl grid (CIFITS2011). - The code expects tp be run in cdbs/grid/BTSettl, and expects that the - individual model files have been downloaded from online - (https://phoenix.ens-lyon.fr/Grids/BT-Settl/CIFIST2011/SPECTRA/) - and processed into python-readable ascii files. - """ - orig_dir = os.getcwd() - dirs = ['btm25', 'btm20', 'btm15', 'btm10', 'btm05', 'btp00', 'btp05'] - #dirs = ['btm10', 'btm05', 'btp00', 'btp05'] - - - # Go through each directory, turning each spectrum into a cdbs-ready file. - # Will convert flux into Ergs/sec/cm**2/A (FLAM) units and save as a fits file, - # for faster access later - for ii in dirs: - print('Starting {0}'.format(ii)) - os.chdir(ii) - - files = glob.glob('*.txt') - count=0 - for jj in files: - t = Table.read(jj, format='ascii') - # First, trim the wavelengths to a more reasonable wavelength range - good = np.where( (t['col1'] > 1000) & (t['col1'] < 70000) ) - t = t[good] - - # Convert flux units to Flam (Ergs/sec/cm**2/A) - flux_new = 10**(t['col2'] - 8.0) - - # Save the file as a fits file - c0 = fits.Column(name='Wavelength', format='D', array=t['col1']) - c1 = fits.Column(name='Flux', format='E', array=flux_new) - - cols = fits.ColDefs([c0, c1]) - tbhdu = fits.BinTableHDU.from_columns(cols) - - # Add unit keywords - prihdu = fits.PrimaryHDU() - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - hdu_new = fits.HDUList([prihdu, tbhdu]) - - # Write new fits table in cdbs directory - hdu_new.writeto('{0}.fits'.format(jj[:-4]), overwrite=True) - hdu_new.close() - count += 1 - print('Done {0} of {1}'.format(count, len(files))) - - # Now, clean up all the files made when unzipping the spectra - cmd1 = 'rm *.bz2' - cmd2 = 'rm *.tmp' - #cmd3 = 'rm *.txt' - os.system(cmd1) - os.system(cmd2) - #os.system(cmd3) - print('==============================') - print('Done {0}'.format(ii)) - print('==============================') - - # Go back to original directory, move to next metallicity directory - os.chdir(orig_dir) - - return - -def make_BTSettl_catalog(): - """ - Create cdbs catalog.fits of BTSettl grid. - THIS IS STEP 2, after organize_BTSettl_atmospheres has - been run. - - Code expects to be run in cdbs/grid/BTSettl - Will create catalog.fits file in atmosphere directory with - description of each model - """ - # Record current working directory for later - start_dir = os.getcwd() - dirs = ['btm25', 'btm20', 'btm15', 'btm10', 'btm05', 'btp00', 'btp05'] - #dirs = ['btp05'] - - # Construct the catalog.fits file input. The input consists of - # and index string that specifies the stellar paramters, and a - # name string that points to the file - # Loop over all the metallicity directories to construct these inputs - index_str = [] - name_str = [] - for ii in dirs: - os.chdir(ii) - files = glob.glob('*.fits') - - # Construct the metallicity val - if 'm' in ii: - metal_flag = -1 * float(ii[3:])*0.1 - else: - metal_flag = float(ii[3:])*0.1 - - # Now collect the info from the files - for jj in files: - tmp = jj.split('-') - - if metal_flag >= 0: - temp = float(tmp[0].split('+')[0][3:]) * 100.0 # In kelvin - try: - logg = float(tmp[1]) - except: - logg = float(tmp[1].split('+')[0]) - else: - temp = float(tmp[0][3:]) * 100.0 # In kelvin - logg = float(tmp[1]) - - index_str.append('{0},{1},{2:3.2f}'.format(int(temp), metal_flag, logg)) - name_str.append('{0}/{1}[Flux]'.format(ii, jj)) - - # Go back to original directory to move to next metallicity - print('Done {0}'.format(ii)) - os.chdir(start_dir) - - # Make catalog - catalog = Table([index_str, name_str], names = ('INDEX', 'FILENAME')) - - # Create catalog.fits file in directory with the models - catalog.write('catalog.fits', format = 'fits', overwrite=True) - - # Move back to original directory, create the catalog.fits file - os.chdir(start_dir) - - return - -def rebin_BTSettl(make_unique=False): - """ - Rebin BTSettle models to atlas ck04 resolution; this makes - spectrophotometry MUCH faster - - makes new directory: BTSettl_rebin - - Code expects to be run in cdbs/grid directory - """ - # Get an atlas ck04 model, we will use this to set wavelength grid - sp_atlas = get_castelli_atmosphere() - - # Create cdbs/grid directory for rebinned models - path = 'BTSettl_rebin/' - if not os.path.exists(path): - os.mkdir(path) - - # Read in the existing catalog.fits file and rebin every spectrum. - cat = fits.getdata('BTSettl/catalog.fits') - files_all = [cat[ii][1].split('[')[0] for ii in range(len(cat))] - - #==============================# - #tmp = [] - #for ii in files_all: - # if ii.startswith('btp00'): - # tmp.append(ii) - #files_all = tmp - #=============================# - - print( 'Rebinning BTSettl spectra') - if make_unique: - print('Making unique') - make_wavelength_unique(files_all, 'BTSettl') - print('Done') - - for ff in range(len(files_all)): - vals = cat[ff][0].split(',') - temp = float(vals[0]) - metal = float(vals[1]) - logg = float(vals[2]) - - # Fetch the BTSettl spectrum, rebin flux - try: - sp = pysynphot.Icat('BTSettl', temp, metal, logg) - flux_rebin = rebin_spec(sp.wave, sp.flux, sp_atlas.wave) - - # Make new output - c0 = fits.Column(name='Wavelength', format='D', array=sp_atlas.wave) - c1 = fits.Column(name='Flux', format='E', array=flux_rebin) - - cols = fits.ColDefs([c0, c1]) - tbhdu = fits.BinTableHDU.from_columns(cols) - prihdu = fits.PrimaryHDU() - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - - outfile = path + files_all[ff].split('[')[0] - finalhdu = fits.HDUList([prihdu, tbhdu]) - finalhdu.writeto(outfile, overwrite=True) - except: - pdb.set_trace() - orig_file = '{0}/{1}'.format('BTSettl/', files_all[ff].split('[')[0]) - outfile = path + files_all[ff].split('[')[0] - cmd = 'cp {0} {1}'.format(orig_file, outfile) - os.system(cmd) - - print('Done {0} of {1}'.format(ff, len(files_all))) - - return - -def organize_all_Meisner2023_atmospheres(): - """ - Construct cdbs-ready atmospheres for the Meisner2023 grid. - The code expects tp be run in cdbs/grid/Meisner2023, and expects that the - individual model files have been downloaded from online - and processed into python-readable ascii files. - """ - orig_dir = os.getcwd() - dirs = ['mm10', 'mm05', 'mp00', 'mp03'] - - # Go through each directory, turning each spectrum into a cdbs-ready file. - # Save as a fits file, for faster access later - for ii in dirs: - print('Starting {0}'.format(ii)) - os.chdir(ii) - - files = glob.glob('*.fits') - count=0 - for jj in files: - # Open each .fits file and read the data - with fits.open(jj) as hdul: - data = hdul[1].data - wavelength = data['Wavelength'] - flux = data['Flux'] - - # Make flux independent of R&D - flux_new = flux / 5e-20 - - # Create new columns with desired format - c0 = fits.Column(name='Wavelength', format='D', array=wavelength) - c1 = fits.Column(name='Flux', format='E', array=flux_new) - - cols = fits.ColDefs([c0, c1]) - tbhdu = fits.BinTableHDU.from_columns(cols) - - # Add unit keywords - prihdu = fits.PrimaryHDU() - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - hdu_new = fits.HDUList([prihdu, tbhdu]) - - # Write the new fits table in the cdbs directory - output_filename = '{0}.fits'.format(jj[:-5]) # Removing the original .fits extension - hdu_new.writeto(output_filename, overwrite=True) - hdu_new.close() - count += 1 - print('Done {0} of {1}'.format(count, len(files))) - - # Go back to original directory, move to next metallicity directory - os.chdir(orig_dir) - - return - -def make_Meisner2023_catalog(): - """ - Create cdbs catalog.fits of Meisner2023 grid. - THIS IS STEP 2, after organize_Meisner2023_atmospheres has - been run. - - Code expects to be run in cdbs/grid/Meisner2023 - Will create catalog.fits file in atmosphere directory with - description of each model - """ - # Record current working directory for later - start_dir = os.getcwd() - dirs = ['mm10', 'mm05', 'mp00', 'mp03'] - - # Construct the catalog.fits file input. The input consists of - # and index string that specifies the stellar paramters, and a - # name string that points to the file - # Loop over all the metallicity directories to construct these inputs - index_str = [] - name_str = [] - for ii in dirs: - os.chdir(ii) - files = glob.glob('spec_jwst_*.fits') - - for jj in files: - # Parse temperature, log(g), and metallicity from filename - temp_str = jj.split('_')[2] - logg_str = jj.split('_')[3] - metal_str = jj.split('_')[4] - - # Extract temperature, surface gravity, and metallicity - temp = float(temp_str[1:]) # Temperature in Kelvin - logg = float(logg_str[1:]) # Surface gravity log(g) - - # Build metallicity value - if metal_str.startswith('m'): - metallicity = -1 * float(metal_str[1:]) - else: - metallicity = float(metal_str[1:]) - - # Construct index and filename strings - index_str.append('{0},{1},{2:3.2f}'.format(int(temp), metallicity, logg)) - name_str.append('{0}/{1}[Flux]'.format(ii, jj)) - - print('Processed directory:', ii) - os.chdir(start_dir) - - - # Make catalog - catalog = Table([index_str, name_str], names = ('INDEX', 'FILENAME')) - - # Create catalog.fits file in directory with the models - catalog.write('catalog.fits', format = 'fits', overwrite=True) - - # Move back to original directory, create the catalog.fits file - os.chdir(start_dir) - - return - -def rebin_Meisner2023(make_unique=False): - """ - Rebin Meisner2023 models to atlas ck04 resolution; this makes - spectrophotometry MUCH faster - - makes new directory: Meisner2023_rebin - - Code expects to be run in cdbs/grid directory - """ - # Get an atlas ck04 model, we will use this to set wavelength grid - sp_atlas = get_castelli_atmosphere() - - # Create a directory for rebinned Meisner2023 models - rebin_path = 'Meisner2023_rebin/' - if not os.path.exists(rebin_path): - os.mkdir(rebin_path) - - # Load the catalog.fits file and extract all spectra file paths - cat = Table.read('Meisner2023/catalog.fits') - files_all = [cat[ii]['FILENAME'].split('[')[0] for ii in range(len(cat))] - - print('Rebinning Meisner2023 spectra') - if make_unique: - print('Making unique') - make_wavelength_unique(files_all, 'Meisner2023') - print('Done') - - for ff, file in enumerate(files_all): - vals = cat[ff]['INDEX'].split(',') - temp = float(vals[0]) - metal = float(vals[1]) - logg = float(vals[2]) - - # Fetch the Meisner2023 spectrum and rebin its flux - try: - sp = pysynphot.Icat('Meisner2023', temp, metal, logg) - flux_rebin = rebin_spec(sp.wave, sp.flux, sp_atlas.wave) - - # Create the output FITS file - c0 = fits.Column(name='Wavelength', format='D', array=sp_atlas.wave) - c1 = fits.Column(name='Flux', format='E', array=flux_rebin) - - cols = fits.ColDefs([c0, c1]) - tbhdu = fits.BinTableHDU.from_columns(cols) - prihdu = fits.PrimaryHDU() - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - - # Write the new rebinned file in the Meisner2023_rebin directory - outfile = os.path.join(rebin_path, os.path.basename(file)) - finalhdu = fits.HDUList([prihdu, tbhdu]) - finalhdu.writeto(outfile, overwrite=True) - - except Exception as e: - print(f"Error processing {file}: {e}") - orig_file = os.path.join('Meisner2023', file) - outfile = os.path.join(rebin_path, os.path.basename(file)) - os.system(f'cp {orig_file} {outfile}') - - print('Done {0} of {1}'.format(ff + 1, len(files_all))) - - return - - - -def organize_WDKoester_atmospheres(path_to_dir): - """ - Construct cdbs-ready wdKoester WD atmospheres for each model. (from Koester 2010) - Will convert wavelength units to angstroms and flux units to [erg/s/cm^2/A] - - path_to_dir is the path to the directory containing all of the downloaded - files - - Saves cdbs-ready atmospheres into os.environ['PYSYN_CDBS']/wdKoeseter - (assumes this directory exists) - """ - # Save current directory for return later, move into working dir - start_dir = os.getcwd() - os.chdir(path_to_dir) - - # Process each atmosphere file independently - print( 'Creating cdbs-ready files') - files = glob.glob('*.dk.dat.txt') - - for i in files: - data = Table.read(i, format='ascii') - - wave = data['col1'] # angstrom - flux = data['col2'] # erg/s/cm^2/A - - # Make new fits table - c0 = fits.Column(name='Wavelength', format='D', array=wave) - c1 = fits.Column(name='Flux', format='E', array=flux) - - cols = fits.ColDefs([c0, c1]) - tbhdu = fits.BinTableHDU.from_columns(cols) - - # Copy over headers, update unit keywords - prihdu = fits.PrimaryHDU() - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - hdu_new = fits.HDUList([prihdu, tbhdu]) - - # Write new fits table in cdbs directory - hdu_new.writeto(os.environ['PYSYN_CDBS']+'/grid/wdKoester/'+i.replace('.txt', '.fits'), overwrite=True) - - hdu_new.close() - - # Return to original directory - os.chdir(start_dir) - return - -def make_WDKoester_catalog(path_to_dir): - """ - Create cdbs catalog.fits of wdKoester grid. - THIS IS STEP 2, after organize_WDKoester_atmospheres has - been run. - - path_to_dir is from current working directory to the cdbs directory. - Will create catalog.fits file in atmosphere directory with - description of each model - """ - # Record current working directory for later - start_dir = os.getcwd() - - # Enter atmosphere directory - os.chdir(path_to_dir) - - # Extract parameters for each atmosphere from the filename, - # construct columns for catalog file - files = glob.glob("*dk.dat.fits") - index_str = [] - name_str = [] - for name in files: - tmp = name.split('.') - tmp2 = tmp[0].split('_') - temp = float(tmp2[0][2:]) # Kelvin - logg = float(tmp2[1]) / 100.0 # log(g) - - index_str.append('{0:5.0f},0.0,{1:3.2f}'.format(temp, logg)) - name_str.append('{0}[Flux]'.format(name)) - - # Make catalog - catalog = Table([index_str, name_str], names = ('INDEX', 'FILENAME')) - - # Create catalog.fits file in directory with the models - catalog.write('catalog.fits', format = 'fits', overwrite=True) - - # Move back to original directory, create the catalog.fits file - os.chdir(start_dir) - - return - -def rebin_WDKoester(cdbs_path=os.environ['PYSYN_CDBS']): - """ - Rebin wdKoester models to atlas ck04 resolution; this makes - spectrophotometry MUCH faster - - makes new directory in cdbs/grid: wdKoester_rebin - - cdbs_path: path to cdbs directory - """ - # Get an atlas ck04 model, we will use this to set wavelength grid - sp_atlas = get_castelli_atmosphere() - - # Open a fits table for an existing model; we will steal the header - tmp = cdbs_path+'/grid/wdKoester/da70000_800.dk.dat.fits' - wdkoester_hdu = fits.open(tmp) - header0 = wdkoester_hdu[0].header - wdkoester_hdu.close() - - # Create cdbs/grid directory for rebinned models - path = cdbs_path+'/grid/wdKoester_rebin/' - if not os.path.exists(path): - os.mkdir(path) - - # Read in the existing catalog.fits file and rebin every spectrum. - cat = fits.getdata(cdbs_path + '/grid/wdKoester/catalog.fits') - files_all = [cat[ii][1].split('[')[0] for ii in range(len(cat))] - - print( 'Rebinning wdKoester spectra') - for ff in range(len(files_all)): - vals = cat[ff][0].split(',') - temp = float(vals[0]) - metal = float(vals[1]) - logg = float(vals[2]) - - # Fetch the wdKoester spectrum, rebin flux - sp = pysynphot.Icat('wdKoester', temp, metal, logg) - flux_rebin = rebin_spec(sp.wave, sp.flux, sp_atlas.wave) - - # Make new output - c0 = fits.Column(name='Wavelength', format='D', array=sp_atlas.wave) - c1 = fits.Column(name='Flux', format='E', array=flux_rebin) - - cols = fits.ColDefs([c0, c1]) - tbhdu = fits.BinTableHDU.from_columns(cols) - prihdu = fits.PrimaryHDU(header=header0) - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - - outfile = path + files_all[ff].split('[')[0] - finalhdu = fits.HDUList([prihdu, tbhdu]) - finalhdu.writeto(outfile, overwrite=True) - - return - - diff --git a/spisea/atmospheres_BACKUP_58456.py b/spisea/atmospheres_BACKUP_58456.py deleted file mode 100755 index e3d2233c..00000000 --- a/spisea/atmospheres_BACKUP_58456.py +++ /dev/null @@ -1,2524 +0,0 @@ -import logging -import numpy as np -import pysynphot -import os -import glob -from astropy.io import fits -from astropy.table import Table, Column -import pysynphot -import time -import pdb -import warnings - -log = logging.getLogger('atmospheres') - -def get_atmosphere_bounds(model_dir, metallicity=0, temperature=20000, gravity=4, verbose=False): - """ - Given atmosphere model, get temperature and gravity bounds - """ - # Open catalog fits file and break out row indices - catalog = Table.read('{0}/grid/{1}/catalog.fits'.format(os.environ['PYSYN_CDBS'], model_dir)) - - teff_arr = [] - z_arr = [] - logg_arr = [] - for cur_row_index in range(len(catalog)): - index = catalog['INDEX'][cur_row_index] - tmp = index.split(',') - teff_arr.append(float(tmp[0])) - z_arr.append(float(tmp[1])) - logg_arr.append(float(tmp[2])) - teff_arr = np.array(teff_arr) - z_arr = np.array(z_arr) - logg_arr = np.array(logg_arr) - - # Filter by metallicity. Will chose the closest metallicity to desired input - metal_list = np.unique(np.array(z_arr)) - metal_idx = np.argmin(np.abs(metal_list - metallicity)) - metallicity_new = metal_list[metal_idx] - - z_filt = np.where(z_arr == metal_list[metal_idx]) - teff_arr = teff_arr[z_filt] - logg_arr = logg_arr[z_filt] - - # # Now find the closest atmosphere in parameter space to - # # the one we want. We'll find the match with the lowest - # # fractional difference - # teff_diff = (teff_arr - temperature) / temperature - # logg_diff = (logg_arr - gravity) / gravity - # - # diff_tot = abs(teff_diff) + abs(logg_diff) - # idx_f = np.argmin(diff_tot) - # - # temperature_new = teff_arr[idx_f] - # gravity_new = logg_arr[idx_f] - - # First check if temperature within bounds - temperature_new = temperature - if temperature > np.max(teff_arr): - temperature_new = np.max(teff_arr) - if temperature < np.min(teff_arr): - temperature_new = np.min(teff_arr) - - # If temperature within bounds, then check if metallicity within bounds - teff_diff = np.abs(teff_arr - temperature) - sorted_min_diffs = np.unique(teff_diff) - - ## Find two closest temperatures - teff_close_1 = teff_arr[np.where(teff_diff == sorted_min_diffs[0])[0][0]] - teff_close_2 = teff_arr[np.where(teff_diff == sorted_min_diffs[1])[0][0]] - - logg_arr_1 = logg_arr[np.where(teff_arr == teff_close_1)] - logg_arr_2 = logg_arr[np.where(teff_arr == teff_close_2)] - - ## Switch to most conservative bound of logg out of two closest temps - gravity_new = gravity - if gravity > np.min([np.max(logg_arr_1), np.max(logg_arr_2)]): - gravity_new = np.min([np.max(logg_arr_1), np.max(logg_arr_2)]) - if gravity < np.max([np.min(logg_arr_1), np.min(logg_arr_2)]): - gravity_new = np.max([np.min(logg_arr_1), np.min(logg_arr_2)]) - - if verbose: - # Print out changes, if any - if temperature_new != temperature: - teff_msg = 'Changing to T={0:6.0f} for met={1:4.2f} T={2:6.0f} logg={3:4.2f}' - print( teff_msg.format(temperature_new, metallicity, temperature, gravity)) - - if gravity_new != gravity: - logg_msg = 'Changing to logg={0:4.2f} for met={1:4.2f} T={2:6.0f} logg={3:4.2f}' - print( logg_msg.format(gravity_new, metallicity, temperature, gravity)) - - if metallicity_new != metallicity: - logg_msg = 'Changing to met={0:4.2f} for met={1:4.2f} T={2:6.0f} logg={3:4.2f}' - print( logg_msg.format(metallicity_new, metallicity, temperature, gravity)) - - return (temperature_new, gravity_new, metallicity_new) - -def get_kurucz_atmosphere(metallicity=0, temperature=20000, gravity=4, rebin=False): - """ - Return atmosphere from the Kurucz pysnphot grid - (`Kurucz 1993 `_). - - Grid Range: - - * Teff: 3000 - 50000 K - * gravity: 0 - 5 cgs - * metallicity: -5.0 - 1.0 - - Parameters - ---------- - metallicity: float - The stellar metallicity, in terms of [Z] - - temperature: float - The stellar temperature, in units of K - - gravity: float - The stellar gravity, in cgs units - - rebin: boolean - Always false for this particular function - """ - try: - sp = pysynphot.Icat('k93models', temperature, metallicity, gravity) - except: - # Check atmosphere catalog bounds - (temperature, gravity, metallicity) = get_atmosphere_bounds('k93models', - metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - sp = pysynphot.Icat('k93models', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find Kurucz 1993 atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_castelli_atmosphere(metallicity=0, temperature=20000, gravity=4, rebin=False): - """ - Return atmospheres from the pysynphot ATLAS9 atlas - (`Castelli & Kurucz 2004 `_). - - Grid Range: - - * Teff: 3500 - 50000 K - * gravity: 0 - 5.0 cgs - * [M/H]: -2.5 - 0.2 - - Parameters - ---------- - metallicity: float - The stellar metallicity, in terms of [Z] - - temperature: float - The stellar temperature, in units of K - - gravity: float - The stellar gravity, in cgs units - - rebin: boolean - If true, rebins the atmospheres so that they are the same - resolution as the Castelli+04 atmospheres. Default is False, - which is often sufficient synthetic photometry in most cases. - - verbose: boolean - True for verbose output - """ - try: - sp = pysynphot.Icat('ck04models', temperature, metallicity, gravity) - except: - # Check atmosphere catalog bounds - (temperature, gravity, metallicity) = get_atmosphere_bounds('ck04models', - metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - sp = pysynphot.Icat('ck04models', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find Castelli and Kurucz 2004 atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_nextgen_atmosphere(metallicity=0, temperature=5000, gravity=4, rebin=False): - """ - metallicity = [M/H] (def = 0) - temperature = Kelvin (def = 5000) - gravity = log gravity (def = 4.0) - """ - try: - sp = pysynphot.Icat('nextgen', temperature, metallicity, gravity) - except: - # Check atmosphere catalog bounds - (temperature, gravity, metallicity) = get_atmosphere_bounds('nextgen', - metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - sp = pysynphot.Icat('nextgen', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find NextGen atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_amesdusty_atmosphere(metallicity=0, temperature=5000, gravity=4, rebin=False): - """ - metallicity = [M/H] (def = 0) - temperature = Kelvin (def = 5000) - gravity = log gravity (def = 4.0) - """ - sp = pysynphot.Icat('AMESdusty', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find AMESdusty Allard+ 2000 atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_phoenix_atmosphere(metallicity=0, temperature=5000, gravity=4, - rebin=False): - """ - Return atmosphere from the pysynphot - `PHOENIX atlas `_. - - Parameters - ---------- - metallicity: float - The stellar metallicity, in terms of [Z] - - temperature: float - The stellar temperature, in units of K - - gravity: float - The stellar gravity, in cgs units - - rebin: boolean - If true, rebins the atmospheres so that they are the same - resolution as the Castelli+04 atmospheres. Default is False, - which is often sufficient synthetic photometry in most cases. - - """ - try: - sp = pysynphot.Icat('phoenix', temperature, metallicity, gravity) - except: - # Check atmosphere catalog bounds - (temperature, gravity, metallicity) = get_atmosphere_bounds('phoenix', - metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - sp = pysynphot.Icat('phoenix', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find PHOENIX BT-Settl (Allard+ 2011 atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_cmfgenRot_atmosphere(metallicity=0, temperature=24000, gravity=4.3, rebin=True, verbose=False): - """ - metallicity = [M/H] (def = 0) - temperature = Kelvin (def = 24000) - gravity = log gravity (def = 4.3) - - rebin=True: pull from atmospheres at ck04model resolution. - """ - # Take care of atmospheres outside the catalog boundaries - logg_msg = 'Changing to logg={0:3.1f} for T={1:6.0f} logg={2:4.2f}' - if gravity > 4.3: - if verbose: - print( logg_msg.format(4.3, temperature, gravity)) - gravity = 4.3 - - if rebin: - sp = pysynphot.Icat('cmfgen_rot_rebin', temperature, metallicity, gravity) - else: - sp = pysynphot.Icat('cmfgen_rot', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find CMFGEN rotating atmosphere model (Fierro+15) for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_cmfgenRot_atmosphere_closest(metallicity=0, temperature=24000, gravity=4.3, rebin=True, - verbose=False): - """ - For a given stellar atmosphere, get extract the closest possible match in - Teff/logg space. Note that this is different from the normal routine - which interpolates along the input grid to get final spectrum. We can't - do this here because the Fierro+15 atmosphere grid is so sparse - - rebin=True: pull from atmospheres at ck04model resolution. - - If verbose, print out the parameters of the match - """ - # Set up the proper root directory - if rebin == True: - root_dir = os.environ['PYSYN_CDBS'] + '/cmfgen_rot_rebin/' - else: - root_dir = os.environ['PYSYN_CDBS'] + '/cmfgen_rot/' - - # Read in catalog, extract atmosphere info - cat = Table.read('{0}/catalog.fits'.format(root_dir), format='fits') - teff_arr = [] - z_arr = [] - logg_arr = [] - for ii in range(len(cat)): - index = cat['INDEX'][ii] - tmp = index.split(',') - teff_arr.append(float(tmp[0])) - z_arr.append(float(tmp[1])) - logg_arr.append(float(tmp[2])) - teff_arr = np.array(teff_arr) - z_arr = np.array(z_arr) - logg_arr = np.array(logg_arr) - - # Now find the closest atmosphere in parameter space to - # the one we want. We'll find the match with the lowest - # fractional difference - teff_diff = (teff_arr - temperature) / temperature - logg_diff = (logg_arr - gravity) / gravity - - diff_tot = abs(teff_diff) + abs(logg_diff) - idx_f = np.where(diff_tot == min(diff_tot))[0][0] - - # Extract the filename of the best-match model and read as - # pysynphot object - infile = cat[idx_f]['FILENAME'].split('.') - spec = Table.read('{0}/{1}.fits'.format(root_dir, infile[0])) - - # Now, the CMFGEN atmospheres assume a distance of 1 kpc, while the the - # ATLAS models are in FLAM at the surface. So, we need to multiply the - # CMFGEN atmospheres by (1000/R)**2. in order to convert to FLAM on surface. - # We'll calculate radius from Teff and logL, which is given in the Table_*.txt file - t = Table.read('{0}/Table_rot.txt'.format(root_dir), format='ascii') - tmp = np.where(t['col1'] == infile[0]) - - lum = t['col3'][tmp] * (3.839*10**33) # cgs - sigma = 5.6704 * 10**-5 # cgs - teff = teff_arr[idx_f] # cgs - - radius = np.sqrt( lum / (4.0 * np.pi * teff**4. * sigma) ) # in cm - radius /= 3.08*10**18 # in pc - - - # Make the pysynphot spectrum - w = spec['Wavelength'] - f = spec['Flux'] * (1000 / radius)**2. - sp = pysynphot.ArraySpectrum(w,f) - - #sp = pysynphot.FileSpectrum('{0}/{1}.fits'.format(root_dir, infile[0])) - - # Print out parameters of match, if desired - if verbose: - print('Teff match: Input: {0}, Output: {1}'.format(temperature, teff_arr[idx_f])) - print('logg match: Input: {0}, Output: {1}'.format(gravity, logg_arr[idx_f])) - - return sp - -def get_cmfgenNoRot_atmosphere(metallicity=0, temperature=22500, gravity=3.98, rebin=True): - """ - metallicity = [M/H] (def = 0) - temperature = Kelvin (def = 24000) - gravity = log gravity (def = 4.3) - - rebin=True: pull from atmospheres at ck04model resolution. - """ - if rebin: - sp = pysynphot.Icat('cmfgen_norot_rebin', temperature, metallicity, gravity) - else: - sp = pysynphot.Icat('cmfgen_norot', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find CMFGEN rotating atmosphere model (Fierro+15) for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_cmfgenNoRot_atmosphere(metallicity=0, temperature=30000, gravity=4.14): - """ - metallicity = [M/H] (def = 0) - temperature = Kelvin (def = 30000) - gravity = log gravity (def = 4.14) - """ - sp = pysynphot.Icat('cmfgenF15_noRot', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find CMFGEN non-rotating atmosphere model (Fierro+15) for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_phoenixv16_atmosphere(metallicity=0, temperature=4000, gravity=4, rebin=True): - """ - Return PHOENIX v16 atmospheres from - `Husser et al. 2013 `_. - - Models originally downloaded via `ftp `_. - Solar metallicity and [alpha/Fe] is used. - - Grid Range: - - * Teff: 2300 - 7000 K, steps of 100 K; 7000 - 12000 in steps of 200 K - * gravity: 0.0 - 6.0 cgs, steps of 0.5 - * [M/H]: -4.0 - 1.0 - - Parameters - ---------- - metallicity: float - The stellar metallicity, in terms of [Z] - - temperature: float - The stellar temperature, in units of K - - gravity: float - The stellar gravity, in cgs units - - rebin: boolean - If true, rebins the atmospheres so that they are the same - resolution as the Castelli+04 atmospheres. Default is False, - which is often sufficient synthetic photometry in most cases. - - """ - atm_model_name = 'phoenix_v16' - if rebin == True: - atm_model_name = 'phoenix_v16_rebin' - - - # Extract atmosphere. If that fails, then check bounds and try again - try: - sp = pysynphot.Icat(atm_model_name, temperature, metallicity, gravity) - except: - # Check atmosphere catalog bounds - (temperature, gravity, metallicity) = get_atmosphere_bounds(atm_model_name, - metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - sp = pysynphot.Icat(atm_model_name, temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find PHOENIXv16 (Husser+13) atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_BTSettl_2015_atmosphere(metallicity=0, temperature=2500, gravity=4, rebin=True): - """ - Return atmosphere from CIFIST2011_2015 grid - (`Allard et al. 2012 `_, - `Baraffe et al. 2015 `_ ) - - Grid originally downloaded from `website `_. - - Grid Range: - - * Teff: 1200 - 7000 K - * gravity: 2.5 - 5.5 cgs - * [M/H] = 0 - - Parameters - ---------- - metallicity: float - The stellar metallicity, in terms of [Z] - - temperature: float - The stellar temperature, in units of K - - gravity: float - The stellar gravity, in cgs units - - rebin: boolean - If true, rebins the atmospheres so that they are the same - resolution as the Castelli+04 atmospheres. Default is False, - which is often sufficient synthetic photometry in most cases. - """ - if rebin == True: - atm_name = 'BTSettl_2015_rebin' - else: - atm_name = 'BTSettl_2015' - - try: - sp = pysynphot.Icat(atm_name, temperature, metallicity, gravity) - except: - # Check atmosphere catalog bounds - (temperature, gravity, metallicity) = get_atmosphere_bounds(atm_name, - metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - sp = pysynphot.Icat(atm_name, temperature, metallicity, gravity) -<<<<<<< HEAD - #print(dir(obj)) - - -======= - - ->>>>>>> upstream/dev - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find BTSettl_2015 atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_BTSettl_atmosphere(metallicity=0, temperature=2500, gravity=4.5, rebin=True): - """ - Return atmosphere from CIFIST2011 grid - (`Allard et al. 2012 `_) - - Grid originally downloaded `here `_ - - Notes - ------ - Grid Range: - - * [M/H] = -2.5, -2.0, -1.5, -1.0, -0.5, 0, 0.5 - - Teff and gravity ranges depend on metallicity: - - [M/H] = -2.5 - - * Teff: 2600 - 4600 K - * gravity: 4.5 - 5.5 - - [M/H] = -2.0 - - * Teff: 2600 - 7000 - * gravity: 4.5 - 5.5 - - [M/H] = -1.5 - - * Teff: 2600 - 7000 - * gravity: 4.5 - 5.5 - - [M/H] = -1.0 - - * Teff: 2600 - 7000 - * gravity: Teff < 3200 --> 4.5 - 5.5; Teff > 3200 --> 2.5 - 5.5 - - [M/H] = -0.5 - - * Teff: 1000 -7000 - * gravity: Teff < 3000 --> 4.5 - 5.5; Teff > 3000 --> 3.0 - 6.0 - - [M/H] = 0 - - * Teff: 750 - 7000 - * gravity: Teff < 2500 --> 3.5 - 5.5; Teff > 2500 --> 0 - 5.5 - - [M/H] = 0.5 - - * Teff: 1000 - 5000 - * gravity: 3.5 - 5.0 - - - Alpha enhancement: - - * [M/H]= -0.0, +0.5 no anhancement - * [M/H]= -0.5 with [alpha/H]=+0.2 - * [M/H]= -1.0, -1.5, -2.0, -2.5 with [alpha/H]=+0.4 - - Parameters - ---------- - metallicity: float - The stellar metallicity, in terms of [Z] - - temperature: float - The stellar temperature, in units of K - - gravity: float - The stellar gravity, in cgs units - - rebin: boolean - If true, rebins the atmospheres so that they are the same - resolution as the Castelli+04 atmospheres. Default is False, - which is often sufficient synthetic photometry in most cases. - - **PRINT STATEMENTS TO DEBUG - **check get_atmosphere_bounds - **comment out try/except clause and check break - """ - if rebin == True: - atm_name = 'BTSettl_rebin' - else: - atm_name = 'BTSettl' - - try: - sp = pysynphot.Icat(atm_name, temperature, metallicity, gravity) - except: - # Check atmosphere catalog bounds - (temperature, gravity, metallicity) = get_atmosphere_bounds(atm_name, - metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - sp = pysynphot.Icat(atm_name, temperature, metallicity, gravity) -<<<<<<< HEAD - -def get_Meisner2023_atmosphere(metallicity=0, temperature=1000, gravity=4.5, rebin=True): - """ - Return atmosphere from Meisner2023 grid - (`Meisner et al. 2023 `_) - - Grid originally downloaded `here `_ - - Grid range: - * Teff = 250 - 1200 K - * gravity: 2.5 - 5.5 cgs (in steps of 0.5) - * [M/H] = -1.0, -0.5, 0, +0, +0.3 - - """ - if rebin == True: - atm_name = 'Meisner2023_rebin' - else: - atm_name = 'Meisner2023' - - try: - sp = pysynphot.Icat(atm_name, temperature, metallicity, gravity) - except: - # Check atmosphere catalog bounds - (temperature, gravity) = get_atmosphere_bounds(atm_name, - metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - sp = pysynphot.Icat(atm_name, temperature, metallicity, gravity) -======= - ->>>>>>> upstream/dev - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find Meisner2023 atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_Phillips2020_atmosphere(metallicity=0, temperature=1000, gravity=4.5, rebin=True): - """ - Return atmosphere from Phillips et al., 2020 using ATMO model - (`Phillips et al. 2020 `_) - - Grid originally downloaded `here `_ - - Grid Range: - * Teff: 200 - 3000 K - * gravity: 2.5 - 5.5 cgs - * [M/H] = 0 - """ - if rebin == True: - atm_name = 'Phillips2020_rebin' - else: - atm_name = 'Phillips2020' - - try: - sp = pysynphot.Icat(atm_name, temperature, metallicity, gravity) - except: - # Check atmosphere catalog bounds - (temperature, gravity) = get_atmosphere_bounds(atm_name, - metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - sp = pysynphot.Icat(atm_name, temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find Phillips2020 atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_wdKoester_atmosphere(metallicity=0, temperature=20000, gravity=7): - """ - Return white dwarf atmospheres from - `Koester et al. 2010 `_ - - Parameters - ---------- - metallicity: float - The stellar metallicity, in terms of [Z] - - temperature: float - The stellar temperature, in units of K - - gravity: float - The stellar gravity, in cgs units - - rebin: boolean - If true, rebins the atmospheres so that they are the same - resolution as the Castelli+04 atmospheres. Default is False, - which is often sufficient synthetic photometry in most cases. - """ - sp = pysynphot.Icat('wdKoester', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find WD Koester (Koester+ 2010 atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_atlas_phoenix_atmosphere(metallicity=0, temperature=5250, gravity=4): - """ - Return atmosphere that is a linear merge of atlas ck04 model and phoenixV16. - - Only valid for temps between 5000 - 5500K, gravity from 0 = 5.0 - """ - try: - sp = pysynphot.Icat('merged_atlas_phoenix', temperature, metallicity, gravity) - except: - # Check atmosphere catalog bounds - (temperature, gravity, metallicity) = get_atmosphere_bounds('merged_atlas_phoenix', - metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - sp = pysynphot.Icat('merged_atlas_phoenix', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find ATLAS-PHOENIX merge atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_BTSettl_phoenix_atmosphere(metallicity=0, temperature=5250, gravity=4): - """ - Return atmosphere that is a linear merge of BTSettl_CITFITS2011_2015 model - and phoenixV16. - - Only valid for temps between 3200 - 3800K, gravity from 2.5 - 5.5 - """ - try: - sp = pysynphot.Icat('merged_BTSettl_phoenix', temperature, metallicity, gravity) - except: - # Check atmosphere catalog bounds - (temperature, gravity, metallicity) = get_atmosphere_bounds('merged_BTSettl_phoenix', - metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - sp = pysynphot.Icat('merged_BTSettl_phoenix', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find ATLAS-PHOENIX merge atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_BTSettl_meisner_atmosphere(metallicity=0, temperature=5250, gravity=4): - """ - Return atmosphere that is a linear merge of BTSettl_CITFITS2011_2015 model - and Meisner2023. - - Only valid for temps between 1000 - 1200K, gravity from 3.5 - 5.5 - """ - try: - sp = pysynphot.Icat('merged_BTSettl_meisner', temperature, metallicity, gravity) - except: - # Check atmosphere catalog bounds - (temperature, gravity) = get_atmosphere_bounds('merged_BTSettl_meisner', - metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - sp = pysynphot.Icat('merged_BTSettl_meisner', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find BTSettl-Meisner merge atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -#---------------------------------------------------------------------# -def get_merged_atmosphere(metallicity=0, temperature=20000, gravity=4.5, verbose=False, - rebin=True): - """ - Return a stellar atmosphere from a suite of different model grids, - depending on the input temperature, (all values in K). - - Parameters - ---------- - metallicity: float - The stellar metallicity, in terms of [Z] - - temperature: float - The stellar temperature, in units of K - - gravity: float - The stellar gravity, in cgs units - - rebin: boolean - If true, rebins the atmospheres so that they are the same - resolution as the Castelli+04 atmospheres. Default is False, - which is often sufficient synthetic photometry in most cases. - - verbose: boolean - True for verbose output - - Notes - ----- - The underlying stellar model grid used changes as a function of - stellar temperature (in K): - - * T > 20,000: ATLAS - * 5500 <= T < 20,000: ATLAS - * 5000 <= T < 5500: ATLAS/PHOENIXv16 merge - * 3800 <= T < 5000: PHOENIXv16 - - For T < 3800, there is an additional gravity and metallicity - dependence: - - If T < 3800 and [M/H] = 0: - - * T < 3800, logg < 2.5: PHOENIX v16 - * 3200 <= T < 3800, logg > 2.5: BTSettl_CIFITS2011_2015/PHOENIXV16 merge - * 3200 < T <= 1200, logg > 2.5: BTSettl_CIFITS2011_2015 - * 1200 < T <= 1000, logg >= 3.5: BTSettl_CIFITS2011_2015/Meisner2023 merge - * 1000 < T <= 250, logg > 2.5: Meisner2023 - - Otherwise, if T < 3800 and [M/H] != 0: - - * T < 3800: PHOENIX v16 - - References: - - * ATLAS: ATLAS9 models (`Castelli & Kurucz 2004 `_) - * PHOENIXv16 (`Husser et al. 2013 `_) - * BTSettl_CIFITS2011_2015: Baraffee+15, Allard+ (https://phoenix.ens-lyon.fr/Grids/BT-Settl/CIFIST2011_2015/SPECTRA/) - * Meisner2023: ATMO 1D models (`Meisner et al. 2023 `_) - - LTE WARNING: - - The ATLAS atmospheres are calculated with LTE, and so they - are less accurate when non-LTE conditions apply (e.g. T > 20,000 - K). Ultimately we'd like to add a non-LTE atmosphere grid for - the hottest stars in the future. - - HOW BOUNDARIES BETWEEN MODELS ARE TREATED: - - At the boundary between two models grids a temperature range is defined - where the resulting atmosphere is a weighted average between the two - grids. Near one boundary one model - is weighted more heavily, while at the other boundary the other - model is weighted more heavily. These are calculated in the - temperature ranges where we switch between model grids, to - ensure a smooth transition. - """ - # For T < 3800, atmosphere depends on metallicity + gravity. - # If solar metallicity, use BTSettl 2015 grid. Only solar metallicity is - # currently available here, so if non-solar metallicity, just stick with - # the Phoenix grid - if (temperature < 1000): - if verbose: - print( 'Meisner2023 atmosphere') - return get_Meisner2023_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity, - rebin=rebin) - - if (temperature <= 1200) & (temperature >= 1000): - if (gravity >= 3.5): - if verbose: - print( 'BTSettl/Meisner2023 merged atmosphere') - return get_Meisner2023_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity, - rebin=rebin) - if (gravity < 3.5) & (gravity >=2.5): - if verbose: - print( 'Meisner2023 atmosphere') - return get_Meisner2023_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity, - rebin=rebin) - - if (temperature <= 3800) & (metallicity == 0): - # High gravity are in BTSettl regime - if (temperature <= 3200) & (gravity > 2.5): - if verbose: - print( 'BTSettl_2015 atmosphere') - return get_BTSettl_2015_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity, - rebin=rebin) - - if (temperature >= 3200) & (temperature < 3800) & (gravity > 2.5): - if verbose: - print( 'BTSettl/Phoenixv16 merged atmosphere') - return get_BTSettl_phoenix_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - # Low gravity is PHOENIX regime - if gravity <= 2.5: - if verbose: - print( 'Phoenixv16 atmosphere') - return get_phoenixv16_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity, - rebin=rebin) - - if (temperature <= 3800) & (metallicity != 0): - if verbose: - print( 'Phoenixv16 atmosphere') - return get_phoenixv16_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity, - rebin=rebin) - - # For T > 3800, no metallicity or gravity dependence - if (temperature >= 3800) & (temperature < 5000): - if verbose: - print( 'Phoenixv16 atmosphere') - return get_phoenixv16_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity, - rebin=rebin) - - if (temperature >= 5000) & (temperature < 5500): - if verbose: - print( 'ATLAS/Phoenix merged atmosphere') - return get_atlas_phoenix_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - if (temperature >= 5500) & (temperature < 20000): - if verbose: - print( 'ATLAS merged atmosphere') - return get_castelli_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - if temperature >= 20000: - if verbose: - print( 'Still ATLAS merged atmosphere') - return get_castelli_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - #print('CMFGEN') - #return get_cmfgenRot_atmosphere_closest(metallicity=metallicity, - # temperature=temperature, - # gravity=gravity) - - - - -def get_wd_atmosphere(metallicity=0, temperature=20000, gravity=4, verbose=False): - """ - Return the white dwarf atmosphere from - `Koester et al. 2010 `_. - If desired parameters are - outside of grid, return a blackbody spectrum instead - - Parameters - ---------- - metallicity: float - The stellar metallicity, in terms of [Z] - - temperature: float - The stellar temperature, in units of K - - gravity: float - The stellar gravity, in cgs units - - rebin: boolean - If true, rebins the atmospheres so that they are the same - resolution as the Castelli+04 atmospheres. Default is False, - which is often sufficient synthetic photometry in most cases. - - verbose: boolean - True for verbose output - """ - try: - if verbose: - print('wdKoester atmosphere') - - return get_wdKoester_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - except pysynphot.exceptions.ParameterOutOfBounds: - # Use a black-body atmosphere. - bbspec = get_bb_atmosphere(temperature=temperature, verbose=verbose) - return bbspec - - -def get_bd_atmosphere(metallicity=0, temperature=1000, gravity=4, verbose=False): - """ - Return the brown dwarf atmosphere from - `Meisner et al. 2023 `_. - If desired parameters are - outside of grid, return a blackbody spectrum instead - - Parameters - ---------- - metallicity: float - The stellar metallicity, in terms of [Z] - - temperature: float - The stellar temperature, in units of K - - gravity: float - The stellar gravity, in cgs units - - rebin: boolean - If true, rebins the atmospheres so that they are the same - resolution as the Castelli+04 atmospheres. Default is False, - which is often sufficient synthetic photometry in most cases. - - verbose: boolean - True for verbose output - """ - try: - if verbose: - print('Meisner2023 atmosphere') - - return get_Meisner2023_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - except pysynphot.exceptions.ParameterOutOfBounds: - # Use a black-body atmosphere - bbspec = get_bb_atmosphere(temperature=temperature, verbose=verbose) - return bbspec - -def get_bb_atmosphere(metallicity=None, temperature=20_000, gravity=None, - verbose=False, rebin=None, - wave_min=500, wave_max=50_000, wave_num=20_000): - """ - Return a blackbody spectrum - - Parameters - ---------- - temperature: float, default=20_000 - The stellar temperature, in units of K - wave_min: float, default=500 - Sets the minimum wavelength (in Angstroms) of the wavelength range - for the blackbody spectrum - wave_max: float, default=50_000 - Sets the maximum wavelength (in Angstroms) of the wavelength range - for the blackbody spectrum - wave_num: int, default=20_000 - Sets the number of wavelength points in the wavelength range - Note: the wavelength range is evenly spaced in log space - """ - if ((metallicity is not None) or (gravity is not None) or - (rebin is not None)): - warnings.warn( - 'Only `temperature` keyword is used for black-body atmosphere' - ) - - if verbose: - print('Black-body atmosphere') - - # Modify pysynphot's default waveset to specified bounds - pysynphot.refs.set_default_waveset( - minwave=wave_min, maxwave=wave_max, num=wave_num - ) - - # Get black-body atmosphere for specified temperature from pysynphot - bbspec = pysynphot.spectrum.BlackBody(temperature) - - # pysynphot `BlackBody` generates spectrum in `photlam`, need in `flam` - bbspec.convert('flam') - - # `BlackBody` spectrum is normalized to solar radius star at 1 kiloparsec. - # Need to remove this normalization for SPISEA by multiplying bbspec - # by (1000 * 1 parsec / 1 Rsun)**2 = (1000 * 3.08e18 cm / 6.957e10 cm)**2 - bbspec *= (1000 * 3.086e18 / 6.957e10)**2 - - return bbspec - - -#--------------------------------------# -# Atmosphere formatting functions -#--------------------------------------# - -def download_CMFGEN_atmospheres(Table_rot, Table_norot): - """ - Downloads CMFGEN models from - https://sites.google.com/site/fluxesandcontinuum/home; - these contain continuum as well as lines. - - Table_rot, Table_norot are tables with the file prefixes - and model atmosphere parameters, taken by hand from the - Fierro+15 paper - - Website addresses are hardcoded - - Puts downloaded models in the current working directory. - """ - print( 'WARNING: THIS DOES NOT COMPLETELY WORK') - print( '**********************') - t_rot = Table.read(Table_rot, format='ascii') - t_norot = Table.read(Table_norot, format='ascii') - - tables = [t_rot, t_norot] - filenames = [t_rot['col1'], t_norot['col1']] - - # Hardcoded list of webiste addresses - web_base1 = 'https://sites.google.com/site/fluxesandcontinuum/home/' - web_base2 = 'https://sites.google.com/site/modelsobmassivestars/' - web = [web_base1+'009-solar-masses/',web_base1+'012-solar-masses/', - web_base1+'015-solar-masses/',web_base1+'020-solar-masses/', - web_base1+'025-solar-masses/',web_base2+'009-solar-masses-tracks/', - web_base2+'040-solar-masses/',web_base2+'060-solar-masses/', - web_base1+'085-solar-masses/',web_base1+'120-solar-masses/'] - # Array of masses that matches the website addresses - mass_arr = np.array([9.,12.,15.,20.,25.,32.,40.,60.,85.,120.]) - - # Loop through rotating and unrotating case. First loop is rot, second unrot - for i in range(2): - # Extract masses from filenames - masses = [] - for j in filenames[i]: - tmp = j.split('m') - mass = float(tmp[1][:-1]) - masses.append(mass) - - # Download the models webpage by webpage. A bit tricky because masses - # change slightly within a particular website. THIS IS WHAT FAILS - for j in range(len(web)): - if j == 0: - good = np.where( (masses <= mass_arr[j]) ) - else: - g = j - 1 - good = np.where( (masses <= mass_arr[j]) & - (masses > mass_arr[g]) ) - # Use wget command to pull down the files, and unzip them - for k in good[0]: - full = web[j]+'{1:s}.flx.zip'.format(mass_arr[j],filenames[i][k]) - os.system('wget ' + full) - os.system('unzip '+ filenames[i][k] + '.flx.zip') - - return - -def organize_CMFGEN_atmospheres(path_to_dir): - """ - Organize CMFGEN grid from Fierro+15 - (http://www.astroscu.unam.mx/atlas/index.html) - into rot and noRot directories - - path_to_dir is from current working directory to directory - containing the downloaded models. Assumed that models - and tables describing parameters are in this directory. - - Tables describing parameters MUST be named Table_rot.txt, - Table_noRot.txt. Made by hand from Tables 3, 4 in Fierro+15. - These are located in same original directory as atmosphere files - - Will separate files into 2 subdirectories, one rotating and - the other non-rotating - - *Can't have any other files starting with "t" in model directory to start!* - """ - # First, record current working directory to return to later - start_dir = os.getcwd() - - # Enter atmosphere directory, collect rotating and non-rotating - # file names (assumed to all start with "t") - os.chdir(path_to_dir) - rot_models = glob.glob("t*r.flx*") - noRot_models = glob.glob("t*n.flx*") - - # Separate into different subdirectories - if os.path.exists('cmfgenF15_rot'): - pass - else: - os.mkdir('cmfgenF15_rot') - os.mkdir('cmfgenF15_noRot') - - for mod in rot_models: - cmd = 'mv {0:s} cmfgenF15_rot'.format(mod) - os.system(cmd) - - for mod in noRot_models: - cmd = 'mv {0:s} cmfgenF15_noRot'.format(mod) - os.system(cmd) - - # Also move Tables with model parameters into correct directory - os.system('mv Table_rot.txt cmfgenF15_rot') - os.system('mv Table_noRot.txt cmfgenF15_noRot') - - # Return to original directory - os.chdir(start_dir) - - return - -def make_CMFGEN_catalog(path_to_dir): - """ - Create cdbs catalog.fits of CMFGEN grid from Fierro+15 - (http://www.astroscu.unam.mx/atlas/index.html). - THIS IS STEP 2, after organize_CMFGEN_atmospheres has - been run. - - path_to_dir is from current working directory to directory - containing the rotating or non-rotating models (i.e. cmfgenF15_rot). Also, - needs to be a Table*.txt file which contains the parameters for all of the - original models, since params in filename are not precise enough - - Will create catalog.fits file in atmosphere directory with - description of each model - - *Can't have any other files starting with "t" in model directory to start!* - """ - # Record current working directory for later - start_dir = os.getcwd() - - # Enter atmosphere directory - os.chdir(path_to_dir) - - # Extract parameters for each atmosphere - # Note: can't rely on filename for this because not precise enough!! - - #---------OLD: GETTING PARAMS FROM FILENAME-------# - # Collect file names (assumed to all start with "t") - #files = glob.glob("t*") - #for name in files: - # tmp = name.split('l') - # temp = float(tmp[0][1:]) * 100.0 # In kelvin - - # lumtmp = tmp[1].split('_') - # lum = float(lumtmp[0][:-5]) * 1000.0 # In L_sun - - # mass = float(lumtmp[0][5:-1]) # In M_sun - - # Need to calculate log g from T and L (cgs) - # lum_sun = 3.846 * 10**33 # erg/s - # M_sun = 2 * 10**33 # g - # G_si = 6.67 * 10**(-8) # cgs - # sigma_si = 5.67 * 10**(-5) # cgs - - # g = (G_si * mass * M_sun * 4 * np.pi * sigma_si * temp**4) / \ - # (lum * lum_sun) - # logg = np.log10(g) - #---------------------------------------------------# - - # Read table with atmosphere params - table = glob.glob('Table_*') - t = Table.read(table[0], format = 'ascii') - names = t['col1'] - temps = t['col2'] - logg = t['col4'] - - # Create catalog.fits file - index_str = [] - name_str = [] - for i in range(len(names)): - index = '{0:5.0f},0.0,{1:3.2f}'.format(temps[i], logg[i]) - - #---NOTE: THE FOLLOWING DEPENDS ON FINAL LOCATION OF CATALOG FILE---# - #path = path_to_dir + '/' + names[i] - path = names[i] + '.fits[Flux]' - - index_str.append(index) - name_str.append(path) - - catalog = Table([index_str, name_str], names = ('INDEX', 'FILENAME')) - - # Create catalog.fits file in directory with the models - catalog.write('catalog.fits', format = 'fits') - - # Move back to original directory, create the catalog.fits file - os.chdir(start_dir) - - return - -def cdbs_cmfgen(path_to_dir, path_to_cdbs_dir): - """ - Code to put cmfgen models into cdbs format and adds proper unit keyword in - fits header. Save as fits file - - path_to_dir goes from current directory to cmfgen_rot or cmfgen_norot - directory with the *.flx models. Note that these files have already been - organized using organize_CMFGEN_atmospheres code. - - path_to_cdbs_dir goes from current directory to cdbs/grid/cmfgen_rot or - cmfgen_norot directory. Will copy new fits files to this directory. - This directory must already exist! - """ - # Save starting directory for later, move into path_to_dir directory - start_dir = os.getcwd() - os.chdir(path_to_dir) - - # Collect the filenames, make necessary changes to each one - files = glob.glob('*.flx') - - # Need to make brand-new fits tables with data we want. - counter = 0 - for i in files: - counter += 1 - # Open file, extract useful info - t = Table.read(i, format='ascii') - wave = t['col1'] - flux = t['col2'] # Flux is already in erg/cm^2/s/A - - # Need to eliminate duplicate entries (pysynphot crashes) - unique = np.unique(wave, return_index=True) - wave = wave[unique[1]] - flux = flux[unique[1]] - - # Make fits table from individual columns. - c0 = fits.Column(name='Wavelength', format='D', array=wave) - c1 = fits.Column(name='Flux', format='E', array=flux) - - cols = fits.ColDefs([c0, c1]) - tbhdu = fits.BinTableHDU.from_columns(cols) - - #Adding unit keywords - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - - prihdu = fits.PrimaryHDU() - - finalhdu = fits.HDUList([prihdu, tbhdu]) - finalhdu.writeto(i[:-4]+'.fits', overwrite=True) - - print( 'Done {0:2.0f} of {1:2.0f}'.format(counter, len(files))) - - # Return to original directory, copy over new .fits files to cdbs directory - os.chdir(start_dir) - cmd = 'mv {0:s}/*.fits {1:s}'.format(path_to_dir, path_to_cdbs_dir) - os.system(cmd) - - return - -def rebin_cmfgen(cdbs_path, rot=True): - """ - Rebin cmfgen_rot and cmfgen_norot models to atlas ck04 resolution; - this makes spectrophotometry MUCH faster - - cdbs_path: path to cdbs directory - rot=True for rotating models (cmfgen_rot), False for non-rotating models - - makes new directory in cdbs/grid: cmfgen_rot_rebin or cmfgen_norot_rebin - """ - # Get an atlas ck04 model, we will use this to set wavelength grid - sp_atlas = get_castelli_atmosphere() - - # Open a fits table for an existing cmfgen model; we will steal the header. - # Also define paths to new rebin directories - if rot == True: - tmp = cdbs_path+'/grid/cmfgen_rot/t0200l0008m009r.fits' - path = cdbs_path+'/grid/cmfgen_rot_rebin/' - orig_path = cdbs_path+'/grid/cmfgen_rot/' - else: - tmp = cdbs_path+'/grid/cmfgen_norot/t0200l0007m009n.fits' - path = cdbs_path+'/grid/cmfgen_norot_rebin/' - orig_path = cdbs_path+'/grid/cmfgen_norot/' - - cmfgen_hdu = fits.open(tmp) - header0 = cmfgen_hdu[0].header - # Create rebin directories if they don't already exist. Copy over - # catalog.fits file from original directory (will be the same) - if not os.path.exists(path): - os.mkdir(path) - cmd = 'cp {0:s}catalog.fits {1:s}'.format(orig_path, path) - os.system(cmd) - - # Read in the catalog.fits file - cat = fits.getdata(orig_path + 'catalog.fits') - files_all = [cat[ii][1].split('[')[0] for ii in range(len(cat))] - - # First column in new files will be for [atlas] wavelength - c0 = fits.Column(name='Wavelength', format='D', array=sp_atlas.wave) - - # For each catalog.fits entry, read the unbinned spectrum and rebin to - # the atlas resolution. Make a new fits file in rebin directory - count = 0 - for ff in range(len(files_all)): - count += 1 - # Extract the temp, Z, logg - vals = cat[ff][0].split(',') - temp = float(vals[0]) - metal = float(vals[1]) - grav = float(vals[2]) - - # Fetch the spectrum - if rot == True: - sp = pysynphot.Icat('cmfgen_rot', temp, metal, grav) - else: - sp = pysynphot.Icat('cmfgen_norot', temp, metal, grav) - - # Rebin - flux_rebin = rebin_spec(sp.wave, sp.flux, sp_atlas.wave) - c1 = fits.Column(name='Flux', format='E', array=flux_rebin) - - # Make the FITS file from the columns with header - cols = fits.ColDefs([c0,c1]) - tbhdu = fits.BinTableHDU.from_columns(cols) - prihdu = fits.PrimaryHDU(header=header0) - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - - # Write hdu to new directory with same filename - finalhdu = fits.HDUList([prihdu, tbhdu]) - finalhdu.writeto(path+files_all[ff]) - - print( 'Finished file {0} of {1}'.format(count, len(files_all)) ) - return - - -def organize_PHOENIXv16_atmospheres(path_to_dir, met_str='m00'): - """ - Construct the Phoenix Husser+13 atmopsheres for each model. Combines the - fluxes from the *HiRES.fits files and the wavelengths of the - WAVE_PHONEIX-ACES-AGSS-COND-2011.fits file. - - path_to_dir is the path to the directory containing all of the downloaded - files - - met_str is the name of the current metallicity - - Creates new fits files for each atmosphere: phoenix_.fits, - which contains columns for the log g (column header = g#.#). Puts - atmospheres in new directory phoenixm00 - """ - # Save current directory for return later, move into working dir - start_dir = os.getcwd() - os.chdir(path_to_dir) - - # If it doesn't already exist, create the current metallicity subdirectory - sub_dir = '../phoenix{0}'.format(met_str) - if os.path.exists(sub_dir): - pass - else: - os.mkdir(sub_dir) - - # Extract wavelength array, make column for later - wavefile = fits.open('WAVE_PHOENIX-ACES-AGSS-COND-2011.fits') - wave = wavefile[0].data - wavefile.close() - wave_col = Column(wave, name = 'WAVELENGTH') - - # Create temp array for Husser+13 grid (given in paper) - temp_arr = np.arange(2300, 7001, 100) - temp_arr = np.append(temp_arr, np.arange(7000, 12001, 200)) - - print( 'Looping though all temps') - # For each temp, build file containing the flux for all gravities - i = 0 - for temp in temp_arr: - files = glob.glob('lte{0:05d}-*-HiRes.fits'.format(temp)) - files.sort() - # Start the table with the wavelength column - t = Table() - t.add_column(wave_col) - for f in files: - # Extract the logg out of filename - logg = f[9:13] - - # Extract fluxes from file - spectrum = fits.open(f) - flux = spectrum[0].data - spectrum.close() - - # Make Column object with fluxes, add to table - col = Column(flux, name = 'g{0:2.1f}'.format(float(logg))) - t.add_column(col) - - # Now, construct final fits file for the given temp - outname = 'phoenix{0}_{1:05d}.fits'.format(met_str, temp) - t.write('{0}/{1}'.format(sub_dir, outname), format = 'fits', overwrite = True) - - # Progress counter for user - i += 1 - print( 'Done {0:d} of {1:d}'.format(i, len(temp_arr))) - - # Return to original directory - os.chdir(start_dir) - return - -def make_PHOENIXv16_catalog(path_to_dir, met_str='m00'): - """ - Makes catalog.fits file for Husser+13 phoenix models. Assumes that - organize_PHOENIXv16_atmospheres has been run already, and that the models lie - in subdirectory phoenix[met_str]. - - path_to_directory is the path to the directory with the reformatted - models (i.e. the output from construct_atmospheres, phoenix[met_str]) - - Puts catalog.fits file in directory the user starts in - """ - # Save starting directory for later, move into working directory - start_dir = os.getcwd() - os.chdir(path_to_dir) - - # Extract metallicity from metallicity string - met = float(met_str[1]) + (float(met_str[2]) * 0.1) - if 'm' in met_str: - met *= -1. - - # Collect the filenames. Each is a unique temp with many different log g's - files = glob.glob('phoenix*.fits') - files.sort() - - # Create the catalog.fits file, row by row - index_arr = [] - filename_arr = [] - for i in files: - # Get log g values from the column header the file - t = Table.read(i, format='fits') - keys = t.keys() - logg_vals = keys[1:] - - # Extract temp from filename - name = i.split('_') - temp = float(name[1][:-5]) - for j in logg_vals: - logg = float(j[1:]) - index = '{0:5.0f},{1:2.1f},{2:2.1f}'.format(temp, met, logg) - filename = path_to_dir + i + '[' + j + ']' - # Add row to table - index_arr.append(index) - filename_arr.append(filename) - - catalog = Table([index_arr, filename_arr], names=('INDEX', 'FILENAME')) - - # Return to starting directory, write catalog - os.chdir(start_dir) - - if os.path.exists('catalog.fits'): - from astropy.table import vstack - - prev_catalog = Table.read('catalog.fits', format='fits') - joined_catalog = vstack([prev_catalog, catalog]) - - joined_catalog.write('catalog.fits', format='fits', overwrite=True) - else: - catalog.write('catalog.fits', format='fits', overwrite=True) - - return - -def cdbs_PHOENIXv16(path_to_cdbs_dir): - """ - Put the PHOENIXv16 (Husser+13) fits files into cdbs format. This primarily - consists of adjusting the flux units from [erg/s/cm^2/cm] to [erg/s/cm^2/A] - and adding the appropriate keywords to the fits header. - - path_to_cdbs_dir goes from current working directory to phoenix[met] directory - in cdbs/grids/phoenix_v16. Note that these files have already been organized - using organize_PHOENIXv16_atmospheres code. - - Overwrites original files in directory - """ - # Save starting directory for later, move into working directory - start_dir = os.getcwd() - os.chdir(path_to_cdbs_dir) - - # Collect the filenames, make necessary changes to each one - files = glob.glob('phoenix*.fits') - - ## Need to sort filenames; glob doesn't always give them in order - files.sort() - - # Need to make brand-new fits tables with data we want. - counter = 0 - for i in files: - counter += 1 - - # Read in current FITS table - cur_table = Table.read(i, format='fits') - - cur_table.columns[0].name = 'Wavelength' - - num_cols = len(cur_table.colnames) - - # Multiplying each flux column by 10^-8 for conversion - for cur_col_index in range(1, num_cols, 1): - cur_col_name = cur_table.colnames[cur_col_index] - cur_table[cur_col_name] = cur_table[cur_col_name] * 10.**-8 - - - # Construct new FITS file based on old one - hdu = fits.open(i) - header_0 = hdu[0].header - header_1 = hdu[1].header - sci = hdu[1].data - - tbhdu = fits.table_to_hdu(cur_table) - - # Copying over the older headers, adding unit keywords - prihdu = fits.PrimaryHDU(header=header_0) - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - tbhdu.header['TUNIT3'] = 'FLAM' - tbhdu.header['TUNIT4'] = 'FLAM' - tbhdu.header['TUNIT5'] = 'FLAM' - tbhdu.header['TUNIT6'] = 'FLAM' - tbhdu.header['TUNIT7'] = 'FLAM' - tbhdu.header['TUNIT8'] = 'FLAM' - tbhdu.header['TUNIT9'] = 'FLAM' - tbhdu.header['TUNIT10'] = 'FLAM' - tbhdu.header['TUNIT11'] = 'FLAM' - tbhdu.header['TUNIT12'] = 'FLAM' - tbhdu.header['TUNIT13'] = 'FLAM' - tbhdu.header['TUNIT14'] = 'FLAM' - - # Construct and write out final FITS file - finalhdu = fits.HDUList([prihdu, tbhdu]) - finalhdu.writeto(i, overwrite=True) - - hdu.close() - print( 'Done {0:2.0f} of {1:2.0f}'.format(counter, len(files))) - - # Change back to starting directory - os.chdir(start_dir) - - return - -def rebin_phoenixV16(cdbs_path): - """ - Rebin phoenixV16 models to atlas ck04 resolution; this makes - spectrophotometry MUCH faster - - makes new directory in cdbs/grid: phoenix_v16_rebin - - cdbs_path: path to cdbs directory - """ - # Get an atlas ck04 model, we will use this to set wavelength grid - sp_atlas = get_castelli_atmosphere() - - # Open a fits table for an existing phoenix model; we will steal the header - ## (This assumes that at least 'm00' metallicity exists) - tmp = '{0}/grid/phoenix_v16/phoenix{1}/phoenix{1}_02400.fits'.format(cdbs_path, 'm00') - phoenix_hdu = fits.open(tmp) - header0 = phoenix_hdu[0].header - - # Create cdbs/grid directory for rebinned models - path = cdbs_path+'/grid/phoenix_v16_rebin/' - if not os.path.exists(path): - os.mkdir(path) - - - # Read in the existing catalog.fits file and rebin every spectrum. - cat = fits.getdata(cdbs_path + '/grid/phoenix_v16/catalog.fits') - files_all = [cat[ii][1].split('[')[0] for ii in range(len(cat))] - temp_arr = np.zeros(len(files_all), dtype=float) - logg_arr = np.zeros(len(files_all), dtype=float) - metal_arr = np.zeros(len(files_all), dtype=float) - - for ff in range(len(files_all)): - vals = cat[ff][0].split(',') - - temp_arr[ff] = float(vals[0]) - metal_arr[ff] = float(vals[1]) - logg_arr[ff] = float(vals[2]) - - - metal_uniq = np.unique(metal_arr) - temp_uniq = np.unique(temp_arr) - - for mm in range(len(metal_uniq)): - metal = metal_uniq[mm] # metallicity - - # Construct str for metallicity (for appropriate directory name) - met_str = str(int(np.abs(metal))) + str(int((metal % 1.0)*10)) - if metal > 0: - met_str = 'p' + met_str - else: - met_str = 'm' + met_str - - # Make directory for current metallicity if it does not exist yet - if not os.path.exists(path + 'phoenix' + met_str): - os.mkdir(path + 'phoenix' + met_str) - - for tt in range(len(temp_uniq)): - temp = temp_uniq[tt] # temperature - - # Pick out the list of gravities for this T, Z combo - idx = np.where((metal_arr == metal) & (temp_arr == temp))[0] - logg_exist = logg_arr[idx] - - # All gravities will go in one file. Here is the output - # file name. - outfile = path + files_all[idx[0]].split('[')[0] - - ## If the rebinned file already exists, continue - if os.path.exists(outfile): - continue - - # Build a columns array. One column for each gravity. - cols_arr = [] - - # Make the wavelength column, which is first in the cols array. - c0 = fits.Column(name='Wavelength', format='D', array=sp_atlas.wave) - cols_arr.append(c0) - - for gg in range(len(logg_exist)): - grav = logg_exist[gg] # gravity - - # Fetch the spectrum - sp = pysynphot.Icat('phoenix_v16', temp, metal, grav) - flux_rebin = rebin_spec(sp.wave, sp.flux, sp_atlas.wave) - - # Store the spectrum - name = 'g{0:3.1f}'.format(grav) - col = fits.Column(name=name, format='E', array=flux_rebin) - cols_arr.append(col) - - - # Make the FITS file from the columns with header. - cols = fits.ColDefs(cols_arr) - tbhdu = fits.BinTableHDU.from_columns(cols) - prihdu = fits.PrimaryHDU(header=header0) - tbhdu.header['TUNIT1'] = 'ANGSTROM' - for gg in range(len(logg_exist)): - tbhdu.header['TUNIT{0:d}'.format(gg+2)] = 'FLAM' - - # Write hdu - finalhdu = fits.HDUList([prihdu, tbhdu]) - # don't have overwrite to protect original files. - finalhdu.writeto(outfile) - - print( 'Finished file ' + outfile + ' with gravities: ', logg_exist) - - - return - - -def rebin_spec(wave, specin, wavnew): - """ - Helper routine to rebin spectra. TAKEN FROM ASTROBETTER BLOG FROM JESSICA: - http://www.astrobetter.com/blog/2013/08/12/ - python-tip-re-sampling-spectra-with-pysynphot/ - """ - spec = pysynphot.spectrum.ArraySourceSpectrum(wave=wave, flux=specin) - f = np.ones(len(wave)) - filt = pysynphot.spectrum.ArraySpectralElement(wave, f, waveunits='angstrom') - obs = pysynphot.observation.Observation(spec, filt, binset=wavnew, force='taper') - - return obs.binflux - -def organize_BTSettl_2015_atmospheres(path_to_dir): - """ - Construct cdbs-ready BTSettl_CIFITS_2011_2015 atmospheres for each model. - Will convert wavelength units to angstroms and flux units to [erg/s/cm^2/A] - - path_to_dir is the path to the directory containing all of the downloaded - files - - Saves cdbs-ready atmospheres into os.environ['PYSYN_CDBS']/grid/BTSettl_2015 - (assumes this directory exists) - """ - # Save current directory for return later, move into working dir - start_dir = os.getcwd() - os.chdir(path_to_dir) - - # If it doesn't already exist, create the BTSettl subdirectory - if not os.path.exists('BTSettl_2015'): - os.mkdir('BTSettl_2015') - - # Process each atmosphere file independently - print( 'Creating cdbs-ready files') - files = glob.glob('*.spec.fits') - - for i in files: - hdu = fits.open(i) - spec = hdu[1].data - header_0 = hdu[0].header - header_1 = hdu[1].header - - wave = spec.field(0) - flux = spec.field(1) - - # Get units right: convert wave from microns to Angstroms, - # flux from W /m^2/ micron to erg/s/cm^2/A - wave_new = wave * 10**4 - flux_new = flux * 10**(-1) - - # Make new fits table - c0 = fits.Column(name='Wavelength', format='D', array=wave_new) - c1 = fits.Column(name='Flux', format='E', array=flux_new) - - cols = fits.ColDefs([c0, c1]) - tbhdu = fits.BinTableHDU.from_columns(cols) - - # Copy over headers, update unit keywords - prihdu = fits.PrimaryHDU(header=header_0) - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - hdu_new = fits.HDUList([prihdu, tbhdu]) - - # Write new fits table in cdbs directory - hdu_new.writeto(os.environ['PYSYN_CDBS']+'grid/BTSettl_2015/'+i, overwrite=True) - - hdu.close() - hdu_new.close() - - # Return to original directory - os.chdir(start_dir) - return - -def make_BTSettl_2015_catalog(path_to_dir): - """ - Create cdbs catalog.fits of BTSettl_CIFITS2011_2015 grid. - THIS IS STEP 2, after organize_CMFGEN_atmospheres has - been run. - - path_to_dir is from current working directory to the cdbs directory. - Will create catalog.fits file in atmosphere directory with - description of each model - """ - # Record current working directory for later - start_dir = os.getcwd() - - # Enter atmosphere directory - os.chdir(path_to_dir) - - # Extract parameters for each atmosphere from the filename, - # construct columns for catalog file - files = glob.glob("*spec.fits") - index_str = [] - name_str = [] - for name in files: - tmp = name.split('-') - temp = float(tmp[0][3:]) * 100.0 # In kelvin - logg = float(tmp[1]) - - index_str.append('{0:5.0f},0.0,{1:3.2f}'.format(temp, logg)) - name_str.append('{0}[Flux]'.format(name)) - - # Make catalog - catalog = Table([index_str, name_str], names = ('INDEX', 'FILENAME')) - - # Create catalog.fits file in directory with the models - catalog.write('catalog.fits', format = 'fits', overwrite=True) - - # Move back to original directory, create the catalog.fits file - os.chdir(start_dir) - - return - -def rebin_BTSettl_2015(cdbs_path=os.environ['PYSYN_CDBS']): - """ - Rebin BTSettle_CIFITS2011_2015 models to atlas ck04 resolution; this makes - spectrophotometry MUCH faster - - makes new directory in cdbs/grid: BTSettl_2015_rebin - - cdbs_path: path to cdbs directory - """ - # Get an atlas ck04 model, we will use this to set wavelength grid - sp_atlas = get_castelli_atmosphere() - - # Open a fits table for an existing phoenix model; we will steal the header - tmp = cdbs_path+'/grid/phoenix_v16/phoenixm00/phoenixm00_02400.fits' - phoenix_hdu = fits.open(tmp) - header0 = phoenix_hdu[0].header - phoenix_hdu.close() - - # Create cdbs/grid directory for rebinned models - path = cdbs_path+'/grid/BTSettl_2015_rebin/' - if not os.path.exists(path): - os.mkdir(path) - - # Read in the existing catalog.fits file and rebin every spectrum. - cat = fits.getdata(cdbs_path + '/grid/BTSettl_2015/catalog.fits') - files_all = [cat[ii][1].split('[')[0] for ii in range(len(cat))] - - print( 'Rebinning BTSettl spectra') - for ff in range(len(files_all)): - vals = cat[ff][0].split(',') - temp = float(vals[0]) - metal = float(vals[1]) - logg = float(vals[2]) - - # Fetch the BTSettl spectrum, rebin flux - sp = pysynphot.Icat('BTSettl_2015', temp, metal, logg) - flux_rebin = rebin_spec(sp.wave, sp.flux, sp_atlas.wave) - - # Make new output - c0 = fits.Column(name='Wavelength', format='D', array=sp_atlas.wave) - c1 = fits.Column(name='Flux', format='E', array=flux_rebin) - - cols = fits.ColDefs([c0, c1]) - tbhdu = fits.BinTableHDU.from_columns(cols) - prihdu = fits.PrimaryHDU(header=header0) - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - - outfile = path + files_all[ff].split('[')[0] - finalhdu = fits.HDUList([prihdu, tbhdu]) - finalhdu.writeto(outfile, overwrite=True) - - return - -def make_wavelength_unique(files, dirname): - """ - Helper function to go through each BTSettl spectrum and ensure that - each wavelength point is unique. This is required for rebinning to work. - - - files: list of files to run this analysis on - """ - # Loop through each file, find fix repeated wavelength entries if necessary - for i in files: - t = Table.read('{0}/{1}'.format(dirname,i), format='fits') - test = np.unique(t['Wavelength'], return_index=True) - - if len(t) != len(test[0]): - t = t[test[1]] - - c0 = fits.Column(name='Wavelength', format='D', array=t['Wavelength']) - c1 = fits.Column(name='Flux', format='E', array=t['Flux']) - cols = fits.ColDefs([c0, c1]) - - tbhdu = fits.BinTableHDU.from_columns(cols) - prihdu = fits.PrimaryHDU() - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - finalhdu = fits.HDUList([prihdu, tbhdu]) - finalhdu.writeto('{0}/{1}'.format(dirname,i), overwrite=True) - - # Also make sure wavelength is monotonic. If it is not, then it is - # a sign that the wavelengths are out of order - diff = np.diff(t['Wavelength']) - bad = np.where(diff < 0) - if len(bad[0]) > 0: - t.sort('Wavelength') - - c0 = fits.Column(name='Wavelength', format='D', array=t['Wavelength']) - c1 = fits.Column(name='Flux', format='E', array=t['Flux']) - cols = fits.ColDefs([c0, c1]) - - tbhdu = fits.BinTableHDU.from_columns(cols) - prihdu = fits.PrimaryHDU() - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - finalhdu = fits.HDUList([prihdu, tbhdu]) - finalhdu.writeto('{0}/{1}'.format(dirname,i), overwrite=True) - - print('Done {0}'.format(i)) - - return - -def organize_BTSettl_atmospheres(): - """ - Construct cdbs-ready atmospheres for the BTSettl grid (CIFITS2011). - The code expects tp be run in cdbs/grid/BTSettl, and expects that the - individual model files have been downloaded from online - (https://phoenix.ens-lyon.fr/Grids/BT-Settl/CIFIST2011/SPECTRA/) - and processed into python-readable ascii files. - """ - orig_dir = os.getcwd() - dirs = ['btm25', 'btm20', 'btm15', 'btm10', 'btm05', 'btp00', 'btp05'] - #dirs = ['btm10', 'btm05', 'btp00', 'btp05'] - - - # Go through each directory, turning each spectrum into a cdbs-ready file. - # Will convert flux into Ergs/sec/cm**2/A (FLAM) units and save as a fits file, - # for faster access later - for ii in dirs: - print('Starting {0}'.format(ii)) - os.chdir(ii) - - files = glob.glob('*.txt') - count=0 - for jj in files: - t = Table.read(jj, format='ascii') - # First, trim the wavelengths to a more reasonable wavelength range - good = np.where( (t['col1'] > 1000) & (t['col1'] < 70000) ) - t = t[good] - - # Convert flux units to Flam (Ergs/sec/cm**2/A) - flux_new = 10**(t['col2'] - 8.0) - - # Save the file as a fits file - c0 = fits.Column(name='Wavelength', format='D', array=t['col1']) - c1 = fits.Column(name='Flux', format='E', array=flux_new) - - cols = fits.ColDefs([c0, c1]) - tbhdu = fits.BinTableHDU.from_columns(cols) - - # Add unit keywords - prihdu = fits.PrimaryHDU() - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - hdu_new = fits.HDUList([prihdu, tbhdu]) - - # Write new fits table in cdbs directory - hdu_new.writeto('{0}.fits'.format(jj[:-4]), overwrite=True) - hdu_new.close() - count += 1 - print('Done {0} of {1}'.format(count, len(files))) - - # Now, clean up all the files made when unzipping the spectra - cmd1 = 'rm *.bz2' - cmd2 = 'rm *.tmp' - #cmd3 = 'rm *.txt' - os.system(cmd1) - os.system(cmd2) - #os.system(cmd3) - print('==============================') - print('Done {0}'.format(ii)) - print('==============================') - - # Go back to original directory, move to next metallicity directory - os.chdir(orig_dir) - - return - -def make_BTSettl_catalog(): - """ - Create cdbs catalog.fits of BTSettl grid. - THIS IS STEP 2, after organize_BTSettl_atmospheres has - been run. - - Code expects to be run in cdbs/grid/BTSettl - Will create catalog.fits file in atmosphere directory with - description of each model - """ - # Record current working directory for later - start_dir = os.getcwd() - dirs = ['btm25', 'btm20', 'btm15', 'btm10', 'btm05', 'btp00', 'btp05'] - #dirs = ['btp05'] - - # Construct the catalog.fits file input. The input consists of - # and index string that specifies the stellar paramters, and a - # name string that points to the file - # Loop over all the metallicity directories to construct these inputs - index_str = [] - name_str = [] - for ii in dirs: - os.chdir(ii) - files = glob.glob('*.fits') - - # Construct the metallicity val - if 'm' in ii: - metal_flag = -1 * float(ii[3:])*0.1 - else: - metal_flag = float(ii[3:])*0.1 - - # Now collect the info from the files - for jj in files: - tmp = jj.split('-') - - if metal_flag >= 0: - temp = float(tmp[0].split('+')[0][3:]) * 100.0 # In kelvin - try: - logg = float(tmp[1]) - except: - logg = float(tmp[1].split('+')[0]) - else: - temp = float(tmp[0][3:]) * 100.0 # In kelvin - logg = float(tmp[1]) - - index_str.append('{0},{1},{2:3.2f}'.format(int(temp), metal_flag, logg)) - name_str.append('{0}/{1}[Flux]'.format(ii, jj)) - - # Go back to original directory to move to next metallicity - print('Done {0}'.format(ii)) - os.chdir(start_dir) - - # Make catalog - catalog = Table([index_str, name_str], names = ('INDEX', 'FILENAME')) - - # Create catalog.fits file in directory with the models - catalog.write('catalog.fits', format = 'fits', overwrite=True) - - # Move back to original directory, create the catalog.fits file - os.chdir(start_dir) - - return - -def rebin_BTSettl(make_unique=False): - """ - Rebin BTSettle models to atlas ck04 resolution; this makes - spectrophotometry MUCH faster - - makes new directory: BTSettl_rebin - - Code expects to be run in cdbs/grid directory - """ - # Get an atlas ck04 model, we will use this to set wavelength grid - sp_atlas = get_castelli_atmosphere() - - # Create cdbs/grid directory for rebinned models - path = 'BTSettl_rebin/' - if not os.path.exists(path): - os.mkdir(path) - - # Read in the existing catalog.fits file and rebin every spectrum. - cat = fits.getdata('BTSettl/catalog.fits') - files_all = [cat[ii][1].split('[')[0] for ii in range(len(cat))] - - #==============================# - #tmp = [] - #for ii in files_all: - # if ii.startswith('btp00'): - # tmp.append(ii) - #files_all = tmp - #=============================# - - print( 'Rebinning BTSettl spectra') - if make_unique: - print('Making unique') - make_wavelength_unique(files_all, 'BTSettl') - print('Done') - - for ff in range(len(files_all)): - vals = cat[ff][0].split(',') - temp = float(vals[0]) - metal = float(vals[1]) - logg = float(vals[2]) - - # Fetch the BTSettl spectrum, rebin flux - try: - sp = pysynphot.Icat('BTSettl', temp, metal, logg) - flux_rebin = rebin_spec(sp.wave, sp.flux, sp_atlas.wave) - - # Make new output - c0 = fits.Column(name='Wavelength', format='D', array=sp_atlas.wave) - c1 = fits.Column(name='Flux', format='E', array=flux_rebin) - - cols = fits.ColDefs([c0, c1]) - tbhdu = fits.BinTableHDU.from_columns(cols) - prihdu = fits.PrimaryHDU() - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - - outfile = path + files_all[ff].split('[')[0] - finalhdu = fits.HDUList([prihdu, tbhdu]) - finalhdu.writeto(outfile, overwrite=True) - except: - pdb.set_trace() - orig_file = '{0}/{1}'.format('BTSettl/', files_all[ff].split('[')[0]) - outfile = path + files_all[ff].split('[')[0] - cmd = 'cp {0} {1}'.format(orig_file, outfile) - os.system(cmd) - - print('Done {0} of {1}'.format(ff, len(files_all))) - - return - -def organize_all_Meisner2023_atmospheres(): - """ - Construct cdbs-ready atmospheres for the Meisner2023 grid. - The code expects tp be run in cdbs/grid/Meisner2023, and expects that the - individual model files have been downloaded from online - and processed into python-readable ascii files. - """ - orig_dir = os.getcwd() - dirs = ['mm10', 'mm05', 'mp00', 'mp03'] - - # Go through each directory, turning each spectrum into a cdbs-ready file. - # Save as a fits file, for faster access later - for ii in dirs: - print('Starting {0}'.format(ii)) - os.chdir(ii) - - files = glob.glob('*.fits') - count=0 - for jj in files: - # Open each .fits file and read the data - with fits.open(jj) as hdul: - data = hdul[1].data - wavelength = data['Wavelength'] - flux = data['Flux'] - - # Make flux independent of R&D - flux_new = flux / 5e-20 - - # Create new columns with desired format - c0 = fits.Column(name='Wavelength', format='D', array=wavelength) - c1 = fits.Column(name='Flux', format='E', array=flux_new) - - cols = fits.ColDefs([c0, c1]) - tbhdu = fits.BinTableHDU.from_columns(cols) - - # Add unit keywords - prihdu = fits.PrimaryHDU() - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - hdu_new = fits.HDUList([prihdu, tbhdu]) - - # Write the new fits table in the cdbs directory - output_filename = '{0}.fits'.format(jj[:-5]) # Removing the original .fits extension - hdu_new.writeto(output_filename, overwrite=True) - hdu_new.close() - count += 1 - print('Done {0} of {1}'.format(count, len(files))) - - # Go back to original directory, move to next metallicity directory - os.chdir(orig_dir) - - return - -def make_Meisner2023_catalog(): - """ - Create cdbs catalog.fits of Meisner2023 grid. - THIS IS STEP 2, after organize_Meisner2023_atmospheres has - been run. - - Code expects to be run in cdbs/grid/Meisner2023 - Will create catalog.fits file in atmosphere directory with - description of each model - """ - # Record current working directory for later - start_dir = os.getcwd() - dirs = ['mm10', 'mm05', 'mp00', 'mp03'] - - # Construct the catalog.fits file input. The input consists of - # and index string that specifies the stellar paramters, and a - # name string that points to the file - # Loop over all the metallicity directories to construct these inputs - index_str = [] - name_str = [] - for ii in dirs: - os.chdir(ii) - files = glob.glob('spec_jwst_*.fits') - - for jj in files: - # Parse temperature, log(g), and metallicity from filename - temp_str = jj.split('_')[2] - logg_str = jj.split('_')[3] - metal_str = jj.split('_')[4] - - # Extract temperature, surface gravity, and metallicity - temp = float(temp_str[1:]) # Temperature in Kelvin - logg = float(logg_str[1:]) # Surface gravity log(g) - - # Build metallicity value - if metal_str.startswith('m'): - metallicity = -1 * float(metal_str[1:]) - else: - metallicity = float(metal_str[1:]) - - # Construct index and filename strings - index_str.append('{0},{1},{2:3.2f}'.format(int(temp), metallicity, logg)) - name_str.append('{0}/{1}[Flux]'.format(ii, jj)) - - print('Processed directory:', ii) - os.chdir(start_dir) - - - # Make catalog - catalog = Table([index_str, name_str], names = ('INDEX', 'FILENAME')) - - # Create catalog.fits file in directory with the models - catalog.write('catalog.fits', format = 'fits', overwrite=True) - - # Move back to original directory, create the catalog.fits file - os.chdir(start_dir) - - return - -def rebin_Meisner2023(make_unique=False): - """ - Rebin Meisner2023 models to atlas ck04 resolution; this makes - spectrophotometry MUCH faster - - makes new directory: Meisner2023_rebin - - Code expects to be run in cdbs/grid directory - """ - # Get an atlas ck04 model, we will use this to set wavelength grid - sp_atlas = get_castelli_atmosphere() - - # Create a directory for rebinned Meisner2023 models - rebin_path = 'Meisner2023_rebin/' - if not os.path.exists(rebin_path): - os.mkdir(rebin_path) - - # Load the catalog.fits file and extract all spectra file paths - cat = Table.read('Meisner2023/catalog.fits') - files_all = [cat[ii]['FILENAME'].split('[')[0] for ii in range(len(cat))] - - print('Rebinning Meisner2023 spectra') - if make_unique: - print('Making unique') - make_wavelength_unique(files_all, 'Meisner2023') - print('Done') - - for ff, file in enumerate(files_all): - vals = cat[ff]['INDEX'].split(',') - temp = float(vals[0]) - metal = float(vals[1]) - logg = float(vals[2]) - - # Fetch the Meisner2023 spectrum and rebin its flux - try: - sp = pysynphot.Icat('Meisner2023', temp, metal, logg) - flux_rebin = rebin_spec(sp.wave, sp.flux, sp_atlas.wave) - - # Create the output FITS file - c0 = fits.Column(name='Wavelength', format='D', array=sp_atlas.wave) - c1 = fits.Column(name='Flux', format='E', array=flux_rebin) - - cols = fits.ColDefs([c0, c1]) - tbhdu = fits.BinTableHDU.from_columns(cols) - prihdu = fits.PrimaryHDU() - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - - # Write the new rebinned file in the Meisner2023_rebin directory - outfile = os.path.join(rebin_path, os.path.basename(file)) - finalhdu = fits.HDUList([prihdu, tbhdu]) - finalhdu.writeto(outfile, overwrite=True) - - except Exception as e: - print(f"Error processing {file}: {e}") - orig_file = os.path.join('Meisner2023', file) - outfile = os.path.join(rebin_path, os.path.basename(file)) - os.system(f'cp {orig_file} {outfile}') - - print('Done {0} of {1}'.format(ff + 1, len(files_all))) - - return - - - -def organize_WDKoester_atmospheres(path_to_dir): - """ - Construct cdbs-ready wdKoester WD atmospheres for each model. (from Koester 2010) - Will convert wavelength units to angstroms and flux units to [erg/s/cm^2/A] - - path_to_dir is the path to the directory containing all of the downloaded - files - - Saves cdbs-ready atmospheres into os.environ['PYSYN_CDBS']/wdKoeseter - (assumes this directory exists) - """ - # Save current directory for return later, move into working dir - start_dir = os.getcwd() - os.chdir(path_to_dir) - - # Process each atmosphere file independently - print( 'Creating cdbs-ready files') - files = glob.glob('*.dk.dat.txt') - - for i in files: - data = Table.read(i, format='ascii') - - wave = data['col1'] # angstrom - flux = data['col2'] # erg/s/cm^2/A - - # Make new fits table - c0 = fits.Column(name='Wavelength', format='D', array=wave) - c1 = fits.Column(name='Flux', format='E', array=flux) - - cols = fits.ColDefs([c0, c1]) - tbhdu = fits.BinTableHDU.from_columns(cols) - - # Copy over headers, update unit keywords - prihdu = fits.PrimaryHDU() - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - hdu_new = fits.HDUList([prihdu, tbhdu]) - - # Write new fits table in cdbs directory - hdu_new.writeto(os.environ['PYSYN_CDBS']+'/grid/wdKoester/'+i.replace('.txt', '.fits'), overwrite=True) - - hdu_new.close() - - # Return to original directory - os.chdir(start_dir) - return - -def make_WDKoester_catalog(path_to_dir): - """ - Create cdbs catalog.fits of wdKoester grid. - THIS IS STEP 2, after organize_WDKoester_atmospheres has - been run. - - path_to_dir is from current working directory to the cdbs directory. - Will create catalog.fits file in atmosphere directory with - description of each model - """ - # Record current working directory for later - start_dir = os.getcwd() - - # Enter atmosphere directory - os.chdir(path_to_dir) - - # Extract parameters for each atmosphere from the filename, - # construct columns for catalog file - files = glob.glob("*dk.dat.fits") - index_str = [] - name_str = [] - for name in files: - tmp = name.split('.') - tmp2 = tmp[0].split('_') - temp = float(tmp2[0][2:]) # Kelvin - logg = float(tmp2[1]) / 100.0 # log(g) - - index_str.append('{0:5.0f},0.0,{1:3.2f}'.format(temp, logg)) - name_str.append('{0}[Flux]'.format(name)) - - # Make catalog - catalog = Table([index_str, name_str], names = ('INDEX', 'FILENAME')) - - # Create catalog.fits file in directory with the models - catalog.write('catalog.fits', format = 'fits', overwrite=True) - - # Move back to original directory, create the catalog.fits file - os.chdir(start_dir) - - return - -def rebin_WDKoester(cdbs_path=os.environ['PYSYN_CDBS']): - """ - Rebin wdKoester models to atlas ck04 resolution; this makes - spectrophotometry MUCH faster - - makes new directory in cdbs/grid: wdKoester_rebin - - cdbs_path: path to cdbs directory - """ - # Get an atlas ck04 model, we will use this to set wavelength grid - sp_atlas = get_castelli_atmosphere() - - # Open a fits table for an existing model; we will steal the header - tmp = cdbs_path+'/grid/wdKoester/da70000_800.dk.dat.fits' - wdkoester_hdu = fits.open(tmp) - header0 = wdkoester_hdu[0].header - wdkoester_hdu.close() - - # Create cdbs/grid directory for rebinned models - path = cdbs_path+'/grid/wdKoester_rebin/' - if not os.path.exists(path): - os.mkdir(path) - - # Read in the existing catalog.fits file and rebin every spectrum. - cat = fits.getdata(cdbs_path + '/grid/wdKoester/catalog.fits') - files_all = [cat[ii][1].split('[')[0] for ii in range(len(cat))] - - print( 'Rebinning wdKoester spectra') - for ff in range(len(files_all)): - vals = cat[ff][0].split(',') - temp = float(vals[0]) - metal = float(vals[1]) - logg = float(vals[2]) - - # Fetch the wdKoester spectrum, rebin flux - sp = pysynphot.Icat('wdKoester', temp, metal, logg) - flux_rebin = rebin_spec(sp.wave, sp.flux, sp_atlas.wave) - - # Make new output - c0 = fits.Column(name='Wavelength', format='D', array=sp_atlas.wave) - c1 = fits.Column(name='Flux', format='E', array=flux_rebin) - - cols = fits.ColDefs([c0, c1]) - tbhdu = fits.BinTableHDU.from_columns(cols) - prihdu = fits.PrimaryHDU(header=header0) - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - - outfile = path + files_all[ff].split('[')[0] - finalhdu = fits.HDUList([prihdu, tbhdu]) - finalhdu.writeto(outfile, overwrite=True) - - return - - diff --git a/spisea/atmospheres_BASE_58456.py b/spisea/atmospheres_BASE_58456.py deleted file mode 100644 index 8df2fbe1..00000000 --- a/spisea/atmospheres_BASE_58456.py +++ /dev/null @@ -1,2165 +0,0 @@ -import logging -import numpy as np -import pysynphot -import os -import glob -from astropy.io import fits -from astropy.table import Table, Column -import pysynphot -import time -import pdb -import warnings - -log = logging.getLogger('atmospheres') - -def get_atmosphere_bounds(model_dir, metallicity=0, temperature=20000, gravity=4): - """ - Given atmosphere model, get temperature and gravity bounds - """ - # Open catalog fits file and break out row indices - catalog = Table.read('{0}/grid/{1}/catalog.fits'.format(os.environ['PYSYN_CDBS'], model_dir)) - - teff_arr = [] - z_arr = [] - logg_arr = [] - for cur_row_index in range(len(catalog)): - index = catalog['INDEX'][cur_row_index] - tmp = index.split(',') - teff_arr.append(float(tmp[0])) - z_arr.append(float(tmp[1])) - logg_arr.append(float(tmp[2])) - teff_arr = np.array(teff_arr) - z_arr = np.array(z_arr) - logg_arr = np.array(logg_arr) - - # Filter by metallicity. Will chose the closest metallicity to desired input - metal_list = np.unique(np.array(z_arr)) - metal_idx = np.argmin(np.abs(metal_list - metallicity)) - - z_filt = np.where(z_arr == metal_list[metal_idx]) - teff_arr = teff_arr[z_filt] - logg_arr = logg_arr[z_filt] - - # # Now find the closest atmosphere in parameter space to - # # the one we want. We'll find the match with the lowest - # # fractional difference - # teff_diff = (teff_arr - temperature) / temperature - # logg_diff = (logg_arr - gravity) / gravity - # - # diff_tot = abs(teff_diff) + abs(logg_diff) - # idx_f = np.argmin(diff_tot) - # - # temperature_new = teff_arr[idx_f] - # gravity_new = logg_arr[idx_f] - - # First check if temperature within bounds - temperature_new = temperature - if temperature > np.max(teff_arr): - temperature_new = np.max(teff_arr) - if temperature < np.min(teff_arr): - temperature_new = np.min(teff_arr) - - # If temperature within bounds, then check if metallicity within bounds - teff_diff = np.abs(teff_arr - temperature) - sorted_min_diffs = np.unique(teff_diff) - - ## Find two closest temperatures - teff_close_1 = teff_arr[np.where(teff_diff == sorted_min_diffs[0])[0][0]] - teff_close_2 = teff_arr[np.where(teff_diff == sorted_min_diffs[1])[0][0]] - - logg_arr_1 = logg_arr[np.where(teff_arr == teff_close_1)] - logg_arr_2 = logg_arr[np.where(teff_arr == teff_close_2)] - - ## Switch to most conservative bound of logg out of two closest temps - gravity_new = gravity - if gravity > np.min([np.max(logg_arr_1), np.max(logg_arr_2)]): - gravity_new = np.min([np.max(logg_arr_1), np.max(logg_arr_2)]) - if gravity < np.max([np.min(logg_arr_1), np.min(logg_arr_2)]): - gravity_new = np.max([np.min(logg_arr_1), np.min(logg_arr_2)]) - - # Print out changes, if any - if temperature_new != temperature: - teff_msg = 'Changing to T={0:6.0f} for T={1:6.0f} logg={2:4.2f}' - print( teff_msg.format(temperature_new, temperature, gravity)) - - if gravity_new != gravity: - logg_msg = 'Changing to logg={0:4.2f} for T={1:6.0f} logg={2:4.2f}' - print( logg_msg.format(gravity_new, temperature, gravity)) - - return (temperature_new, gravity_new) - -def get_kurucz_atmosphere(metallicity=0, temperature=20000, gravity=4, rebin=False): - """ - Return atmosphere from the Kurucz pysnphot grid - (`Kurucz 1993 `_). - - Grid Range: - - * Teff: 3000 - 50000 K - * gravity: 0 - 5 cgs - * metallicity: -5.0 - 1.0 - - Parameters - ---------- - metallicity: float - The stellar metallicity, in terms of [Z] - - temperature: float - The stellar temperature, in units of K - - gravity: float - The stellar gravity, in cgs units - - rebin: boolean - Always false for this particular function - """ - try: - sp = pysynphot.Icat('k93models', temperature, metallicity, gravity) - except: - # Check atmosphere catalog bounds - (temperature, gravity) = get_atmosphere_bounds('k93models', - metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - sp = pysynphot.Icat('k93models', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find Kurucz 1993 atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_castelli_atmosphere(metallicity=0, temperature=20000, gravity=4, rebin=False): - """ - Return atmospheres from the pysynphot ATLAS9 atlas - (`Castelli & Kurucz 2004 `_). - - Grid Range: - - * Teff: 3500 - 50000 K - * gravity: 0 - 5.0 cgs - * [M/H]: -2.5 - 0.2 - - Parameters - ---------- - metallicity: float - The stellar metallicity, in terms of [Z] - - temperature: float - The stellar temperature, in units of K - - gravity: float - The stellar gravity, in cgs units - - rebin: boolean - If true, rebins the atmospheres so that they are the same - resolution as the Castelli+04 atmospheres. Default is False, - which is often sufficient synthetic photometry in most cases. - - verbose: boolean - True for verbose output - """ - try: - sp = pysynphot.Icat('ck04models', temperature, metallicity, gravity) - except: - # Check atmosphere catalog bounds - (temperature, gravity) = get_atmosphere_bounds('ck04models', - metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - sp = pysynphot.Icat('ck04models', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find Castelli and Kurucz 2004 atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_nextgen_atmosphere(metallicity=0, temperature=5000, gravity=4, rebin=False): - """ - metallicity = [M/H] (def = 0) - temperature = Kelvin (def = 5000) - gravity = log gravity (def = 4.0) - """ - try: - sp = pysynphot.Icat('nextgen', temperature, metallicity, gravity) - except: - # Check atmosphere catalog bounds - (temperature, gravity) = get_atmosphere_bounds('nextgen', - metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - sp = pysynphot.Icat('nextgen', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find NextGen atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_amesdusty_atmosphere(metallicity=0, temperature=5000, gravity=4, rebin=False): - """ - metallicity = [M/H] (def = 0) - temperature = Kelvin (def = 5000) - gravity = log gravity (def = 4.0) - """ - sp = pysynphot.Icat('AMESdusty', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find AMESdusty Allard+ 2000 atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_phoenix_atmosphere(metallicity=0, temperature=5000, gravity=4, - rebin=False): - """ - Return atmosphere from the pysynphot - `PHOENIX atlas `_. - - Parameters - ---------- - metallicity: float - The stellar metallicity, in terms of [Z] - - temperature: float - The stellar temperature, in units of K - - gravity: float - The stellar gravity, in cgs units - - rebin: boolean - If true, rebins the atmospheres so that they are the same - resolution as the Castelli+04 atmospheres. Default is False, - which is often sufficient synthetic photometry in most cases. - - """ - try: - sp = pysynphot.Icat('phoenix', temperature, metallicity, gravity) - except: - # Check atmosphere catalog bounds - (temperature, gravity) = get_atmosphere_bounds('phoenix', - metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - sp = pysynphot.Icat('phoenix', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find PHOENIX BT-Settl (Allard+ 2011 atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_cmfgenRot_atmosphere(metallicity=0, temperature=24000, gravity=4.3, rebin=True): - """ - metallicity = [M/H] (def = 0) - temperature = Kelvin (def = 24000) - gravity = log gravity (def = 4.3) - - rebin=True: pull from atmospheres at ck04model resolution. - """ - # Take care of atmospheres outside the catalog boundaries - logg_msg = 'Changing to logg={0:3.1f} for T={1:6.0f} logg={2:4.2f}' - if gravity > 4.3: - print( logg_msg.format(4.3, temperature, gravity)) - gravity = 4.3 - - if rebin: - sp = pysynphot.Icat('cmfgen_rot_rebin', temperature, metallicity, gravity) - else: - sp = pysynphot.Icat('cmfgen_rot', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find CMFGEN rotating atmosphere model (Fierro+15) for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_cmfgenRot_atmosphere_closest(metallicity=0, temperature=24000, gravity=4.3, rebin=True, - verbose=False): - """ - For a given stellar atmosphere, get extract the closest possible match in - Teff/logg space. Note that this is different from the normal routine - which interpolates along the input grid to get final spectrum. We can't - do this here because the Fierro+15 atmosphere grid is so sparse - - rebin=True: pull from atmospheres at ck04model resolution. - - If verbose, print out the parameters of the match - """ - # Set up the proper root directory - if rebin == True: - root_dir = os.environ['PYSYN_CDBS'] + '/cmfgen_rot_rebin/' - else: - root_dir = os.environ['PYSYN_CDBS'] + '/cmfgen_rot/' - - # Read in catalog, extract atmosphere info - cat = Table.read('{0}/catalog.fits'.format(root_dir), format='fits') - teff_arr = [] - z_arr = [] - logg_arr = [] - for ii in range(len(cat)): - index = cat['INDEX'][ii] - tmp = index.split(',') - teff_arr.append(float(tmp[0])) - z_arr.append(float(tmp[1])) - logg_arr.append(float(tmp[2])) - teff_arr = np.array(teff_arr) - z_arr = np.array(z_arr) - logg_arr = np.array(logg_arr) - - # Now find the closest atmosphere in parameter space to - # the one we want. We'll find the match with the lowest - # fractional difference - teff_diff = (teff_arr - temperature) / temperature - logg_diff = (logg_arr - gravity) / gravity - - diff_tot = abs(teff_diff) + abs(logg_diff) - idx_f = np.where(diff_tot == min(diff_tot))[0][0] - - # Extract the filename of the best-match model and read as - # pysynphot object - infile = cat[idx_f]['FILENAME'].split('.') - spec = Table.read('{0}/{1}.fits'.format(root_dir, infile[0])) - - # Now, the CMFGEN atmospheres assume a distance of 1 kpc, while the the - # ATLAS models are in FLAM at the surface. So, we need to multiply the - # CMFGEN atmospheres by (1000/R)**2. in order to convert to FLAM on surface. - # We'll calculate radius from Teff and logL, which is given in the Table_*.txt file - t = Table.read('{0}/Table_rot.txt'.format(root_dir), format='ascii') - tmp = np.where(t['col1'] == infile[0]) - - lum = t['col3'][tmp] * (3.839*10**33) # cgs - sigma = 5.6704 * 10**-5 # cgs - teff = teff_arr[idx_f] # cgs - - radius = np.sqrt( lum / (4.0 * np.pi * teff**4. * sigma) ) # in cm - radius /= 3.08*10**18 # in pc - - - # Make the pysynphot spectrum - w = spec['Wavelength'] - f = spec['Flux'] * (1000 / radius)**2. - sp = pysynphot.ArraySpectrum(w,f) - - #sp = pysynphot.FileSpectrum('{0}/{1}.fits'.format(root_dir, infile[0])) - - # Print out parameters of match, if desired - if verbose: - print('Teff match: Input: {0}, Output: {1}'.format(temperature, teff_arr[idx_f])) - print('logg match: Input: {0}, Output: {1}'.format(gravity, logg_arr[idx_f])) - - return sp - -def get_cmfgenNoRot_atmosphere(metallicity=0, temperature=22500, gravity=3.98, rebin=True): - """ - metallicity = [M/H] (def = 0) - temperature = Kelvin (def = 24000) - gravity = log gravity (def = 4.3) - - rebin=True: pull from atmospheres at ck04model resolution. - """ - if rebin: - sp = pysynphot.Icat('cmfgen_norot_rebin', temperature, metallicity, gravity) - else: - sp = pysynphot.Icat('cmfgen_norot', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find CMFGEN rotating atmosphere model (Fierro+15) for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_cmfgenNoRot_atmosphere(metallicity=0, temperature=30000, gravity=4.14): - """ - metallicity = [M/H] (def = 0) - temperature = Kelvin (def = 30000) - gravity = log gravity (def = 4.14) - """ - sp = pysynphot.Icat('cmfgenF15_noRot', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find CMFGEN non-rotating atmosphere model (Fierro+15) for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_phoenixv16_atmosphere(metallicity=0, temperature=4000, gravity=4, rebin=True): - """ - Return PHOENIX v16 atmospheres from - `Husser et al. 2013 `_. - - Models originally downloaded via `ftp `_. - Solar metallicity and [alpha/Fe] is used. - - Grid Range: - - * Teff: 2300 - 7000 K, steps of 100 K; 7000 - 12000 in steps of 200 K - * gravity: 0.0 - 6.0 cgs, steps of 0.5 - * [M/H]: -4.0 - 1.0 - - Parameters - ---------- - metallicity: float - The stellar metallicity, in terms of [Z] - - temperature: float - The stellar temperature, in units of K - - gravity: float - The stellar gravity, in cgs units - - rebin: boolean - If true, rebins the atmospheres so that they are the same - resolution as the Castelli+04 atmospheres. Default is False, - which is often sufficient synthetic photometry in most cases. - - """ - atm_model_name = 'phoenix_v16' - if rebin == True: - atm_model_name = 'phoenix_v16_rebin' - - - # Extract atmosphere. If that fails, then check bounds and try again - try: - sp = pysynphot.Icat(atm_model_name, temperature, metallicity, gravity) - except: - # Check atmosphere catalog bounds - (temperature, gravity) = get_atmosphere_bounds(atm_model_name, - metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - sp = pysynphot.Icat(atm_model_name, temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find PHOENIXv16 (Husser+13) atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_BTSettl_2015_atmosphere(metallicity=0, temperature=2500, gravity=4, rebin=True): - """ - Return atmosphere from CIFIST2011_2015 grid - (`Allard et al. 2012 `_, - `Baraffe et al. 2015 `_ ) - - Grid originally downloaded from `website `_. - - Grid Range: - - * Teff: 1200 - 7000 K - * gravity: 2.5 - 5.5 cgs - * [M/H] = 0 - - Parameters - ---------- - metallicity: float - The stellar metallicity, in terms of [Z] - - temperature: float - The stellar temperature, in units of K - - gravity: float - The stellar gravity, in cgs units - - rebin: boolean - If true, rebins the atmospheres so that they are the same - resolution as the Castelli+04 atmospheres. Default is False, - which is often sufficient synthetic photometry in most cases. - """ - if rebin == True: - atm_name = 'BTSettl_2015_rebin' - else: - atm_name = 'BTSettl_2015' - - try: - sp = pysynphot.Icat(atm_name, temperature, metallicity, gravity) - except: - # Check atmosphere catalog bounds - (temperature, gravity) = get_atmosphere_bounds(atm_name, - metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - sp = pysynphot.Icat(atm_name, temperature, metallicity, gravity) - - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find BTSettl_2015 atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_BTSettl_atmosphere(metallicity=0, temperature=2500, gravity=4.5, rebin=True): - """ - Return atmosphere from CIFIST2011 grid - (`Allard et al. 2012 `_) - - Grid originally downloaded `here `_ - - Notes - ------ - Grid Range: - - * [M/H] = -2.5, -2.0, -1.5, -1.0, -0.5, 0, 0.5 - - Teff and gravity ranges depend on metallicity: - - [M/H] = -2.5 - - * Teff: 2600 - 4600 K - * gravity: 4.5 - 5.5 - - [M/H] = -2.0 - - * Teff: 2600 - 7000 - * gravity: 4.5 - 5.5 - - [M/H] = -1.5 - - * Teff: 2600 - 7000 - * gravity: 4.5 - 5.5 - - [M/H] = -1.0 - - * Teff: 2600 - 7000 - * gravity: Teff < 3200 --> 4.5 - 5.5; Teff > 3200 --> 2.5 - 5.5 - - [M/H] = -0.5 - - * Teff: 1000 -7000 - * gravity: Teff < 3000 --> 4.5 - 5.5; Teff > 3000 --> 3.0 - 6.0 - - [M/H] = 0 - - * Teff: 750 - 7000 - * gravity: Teff < 2500 --> 3.5 - 5.5; Teff > 2500 --> 0 - 5.5 - - [M/H] = 0.5 - - * Teff: 1000 - 5000 - * gravity: 3.5 - 5.0 - - - Alpha enhancement: - - * [M/H]= -0.0, +0.5 no anhancement - * [M/H]= -0.5 with [alpha/H]=+0.2 - * [M/H]= -1.0, -1.5, -2.0, -2.5 with [alpha/H]=+0.4 - - Parameters - ---------- - metallicity: float - The stellar metallicity, in terms of [Z] - - temperature: float - The stellar temperature, in units of K - - gravity: float - The stellar gravity, in cgs units - - rebin: boolean - If true, rebins the atmospheres so that they are the same - resolution as the Castelli+04 atmospheres. Default is False, - which is often sufficient synthetic photometry in most cases. - """ - if rebin == True: - atm_name = 'BTSettl_rebin' - else: - atm_name = 'BTSettl' - - try: - sp = pysynphot.Icat(atm_name, temperature, metallicity, gravity) - except: - # Check atmosphere catalog bounds - (temperature, gravity) = get_atmosphere_bounds(atm_name, - metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - sp = pysynphot.Icat(atm_name, temperature, metallicity, gravity) - - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find BTSettl_2015 atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_wdKoester_atmosphere(metallicity=0, temperature=20000, gravity=7): - """ - Return white dwarf atmospheres from - `Koester et al. 2010 `_ - - Parameters - ---------- - metallicity: float - The stellar metallicity, in terms of [Z] - - temperature: float - The stellar temperature, in units of K - - gravity: float - The stellar gravity, in cgs units - - rebin: boolean - If true, rebins the atmospheres so that they are the same - resolution as the Castelli+04 atmospheres. Default is False, - which is often sufficient synthetic photometry in most cases. - """ - sp = pysynphot.Icat('wdKoester', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find WD Koester (Koester+ 2010 atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_atlas_phoenix_atmosphere(metallicity=0, temperature=5250, gravity=4): - """ - Return atmosphere that is a linear merge of atlas ck04 model and phoenixV16. - - Only valid for temps between 5000 - 5500K, gravity from 0 = 5.0 - """ - try: - sp = pysynphot.Icat('merged_atlas_phoenix', temperature, metallicity, gravity) - except: - # Check atmosphere catalog bounds - (temperature, gravity) = get_atmosphere_bounds('merged_atlas_phoenix', - metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - sp = pysynphot.Icat('merged_atlas_phoenix', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find ATLAS-PHOENIX merge atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_BTSettl_phoenix_atmosphere(metallicity=0, temperature=5250, gravity=4): - """ - Return atmosphere that is a linear merge of BTSettl_CITFITS2011_2015 model - and phoenixV16. - - Only valid for temps between 3200 - 3800K, gravity from 2.5 - 5.5 - """ - try: - sp = pysynphot.Icat('merged_BTSettl_phoenix', temperature, metallicity, gravity) - except: - # Check atmosphere catalog bounds - (temperature, gravity) = get_atmosphere_bounds('merged_BTSettl_phoenix', - metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - sp = pysynphot.Icat('merged_BTSettl_phoenix', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find ATLAS-PHOENIX merge atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -#---------------------------------------------------------------------# -def get_merged_atmosphere(metallicity=0, temperature=20000, gravity=4.5, verbose=False, - rebin=True): - """ - Return a stellar atmosphere from a suite of different model grids, - depending on the input temperature, (all values in K). - - Parameters - ---------- - metallicity: float - The stellar metallicity, in terms of [Z] - - temperature: float - The stellar temperature, in units of K - - gravity: float - The stellar gravity, in cgs units - - rebin: boolean - If true, rebins the atmospheres so that they are the same - resolution as the Castelli+04 atmospheres. Default is False, - which is often sufficient synthetic photometry in most cases. - - verbose: boolean - True for verbose output - - Notes - ----- - The underlying stellar model grid used changes as a function of - stellar temperature (in K): - - * T > 20,000: ATLAS - * 5500 <= T < 20,000: ATLAS - * 5000 <= T < 5500: ATLAS/PHOENIXv16 merge - * 3800 <= T < 5000: PHOENIXv16 - - For T < 3800, there is an additional gravity and metallicity - dependence: - - If T < 3800 and [M/H] = 0: - - * T < 3800, logg < 2.5: PHOENIX v16 - * 3200 <= T < 3800, logg > 2.5: BTSettl_CIFITS2011_2015/PHOENIXV16 merge - * 3200 < T <= 1200, logg > 2.5: BTSettl_CIFITS2011_2015 - - Otherwise, if T < 3800 and [M/H] != 0: - - * T < 3800: PHOENIX v16 - - References: - - * ATLAS: ATLAS9 models (`Castelli & Kurucz 2004 `_) - * PHOENIXv16 (`Husser et al. 2013 `_) - * BTSettl_CIFITS2011_2015: Baraffee+15, Allard+ (https://phoenix.ens-lyon.fr/Grids/BT-Settl/CIFIST2011_2015/SPECTRA/) - - LTE WARNING: - - The ATLAS atmospheres are calculated with LTE, and so they - are less accurate when non-LTE conditions apply (e.g. T > 20,000 - K). Ultimately we'd like to add a non-LTE atmosphere grid for - the hottest stars in the future. - - HOW BOUNDARIES BETWEEN MODELS ARE TREATED: - - At the boundary between two models grids a temperature range is defined - where the resulting atmosphere is a weighted average between the two - grids. Near one boundary one model - is weighted more heavily, while at the other boundary the other - model is weighted more heavily. These are calculated in the - temperature ranges where we switch between model grids, to - ensure a smooth transition. - """ - # For T < 3800, atmosphere depends on metallicity + gravity. - # If solar metallicity, use BTSettl 2015 grid. Only solar metallicity is - # currently available here, so if non-solar metallicity, just stick with - # the Phoenix grid - if (temperature <= 3800) & (metallicity == 0): - # High gravity are in BTSettl regime - if (temperature <= 3200) & (gravity > 2.5): - if verbose: - print( 'BTSettl_2015 atmosphere') - return get_BTSettl_2015_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity, - rebin=rebin) - - if (temperature >= 3200) & (temperature < 3800) & (gravity > 2.5): - if verbose: - print( 'BTSettl/Phoenixv16 merged atmosphere') - return get_BTSettl_phoenix_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - # Low gravity is PHOENIX regime - if gravity <= 2.5: - if verbose: - print( 'Phoenixv16 atmosphere') - return get_phoenixv16_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity, - rebin=rebin) - - if (temperature <= 3800) & (metallicity != 0): - if verbose: - print( 'Phoenixv16 atmosphere') - return get_phoenixv16_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity, - rebin=rebin) - - # For T > 3800, no metallicity or gravity dependence - if (temperature >= 3800) & (temperature < 5000): - if verbose: - print( 'Phoenixv16 atmosphere') - return get_phoenixv16_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity, - rebin=rebin) - - if (temperature >= 5000) & (temperature < 5500): - if verbose: - print( 'ATLAS/Phoenix merged atmosphere') - return get_atlas_phoenix_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - if (temperature >= 5500) & (temperature < 20000): - if verbose: - print( 'ATLAS merged atmosphere') - return get_castelli_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - if temperature >= 20000: - if verbose: - print( 'Still ATLAS merged atmosphere') - return get_castelli_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - #print('CMFGEN') - #return get_cmfgenRot_atmosphere_closest(metallicity=metallicity, - # temperature=temperature, - # gravity=gravity) - - - - -def get_wd_atmosphere(metallicity=0, temperature=20000, gravity=4, verbose=False): - """ - Return the white dwarf atmosphere from - `Koester et al. 2010 `_. - If desired parameters are - outside of grid, return a blackbody spectrum instead - - Parameters - ---------- - metallicity: float - The stellar metallicity, in terms of [Z] - - temperature: float - The stellar temperature, in units of K - - gravity: float - The stellar gravity, in cgs units - - rebin: boolean - If true, rebins the atmospheres so that they are the same - resolution as the Castelli+04 atmospheres. Default is False, - which is often sufficient synthetic photometry in most cases. - - verbose: boolean - True for verbose output - """ - try: - if verbose: - print('wdKoester atmosphere') - - return get_wdKoester_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - except pysynphot.exceptions.ParameterOutOfBounds: - # Use a black-body atmosphere. - bbspec = get_bb_atmosphere(temperature=temperature, verbose=verbose) - return bbspec - -def get_bb_atmosphere(metallicity=None, temperature=20_000, gravity=None, - verbose=False, rebin=None, - wave_min=500, wave_max=50_000, wave_num=20_000): - """ - Return a blackbody spectrum - - Parameters - ---------- - temperature: float, default=20_000 - The stellar temperature, in units of K - wave_min: float, default=500 - Sets the minimum wavelength (in Angstroms) of the wavelength range - for the blackbody spectrum - wave_max: float, default=50_000 - Sets the maximum wavelength (in Angstroms) of the wavelength range - for the blackbody spectrum - wave_num: int, default=20_000 - Sets the number of wavelength points in the wavelength range - Note: the wavelength range is evenly spaced in log space - """ - if ((metallicity is not None) or (gravity is not None) or - (rebin is not None)): - warnings.warn( - 'Only `temperature` keyword is used for black-body atmosphere' - ) - - if verbose: - print('Black-body atmosphere') - - # Modify pysynphot's default waveset to specified bounds - pysynphot.refs.set_default_waveset( - minwave=wave_min, maxwave=wave_max, num=wave_num - ) - - # Get black-body atmosphere for specified temperature from pysynphot - bbspec = pysynphot.spectrum.BlackBody(temperature) - - # pysynphot `BlackBody` generates spectrum in `photlam`, need in `flam` - bbspec.convert('flam') - - # `BlackBody` spectrum is normalized to solar radius star at 1 kiloparsec. - # Need to remove this normalization for SPISEA by multiplying bbspec - # by (1000 * 1 parsec / 1 Rsun)**2 = (1000 * 3.08e18 cm / 6.957e10 cm)**2 - bbspec *= (1000 * 3.086e18 / 6.957e10)**2 - - return bbspec - - -#--------------------------------------# -# Atmosphere formatting functions -#--------------------------------------# - -def download_CMFGEN_atmospheres(Table_rot, Table_norot): - """ - Downloads CMFGEN models from - https://sites.google.com/site/fluxesandcontinuum/home; - these contain continuum as well as lines. - - Table_rot, Table_norot are tables with the file prefixes - and model atmosphere parameters, taken by hand from the - Fierro+15 paper - - Website addresses are hardcoded - - Puts downloaded models in the current working directory. - """ - print( 'WARNING: THIS DOES NOT COMPLETELY WORK') - print( '**********************') - t_rot = Table.read(Table_rot, format='ascii') - t_norot = Table.read(Table_norot, format='ascii') - - tables = [t_rot, t_norot] - filenames = [t_rot['col1'], t_norot['col1']] - - # Hardcoded list of webiste addresses - web_base1 = 'https://sites.google.com/site/fluxesandcontinuum/home/' - web_base2 = 'https://sites.google.com/site/modelsobmassivestars/' - web = [web_base1+'009-solar-masses/',web_base1+'012-solar-masses/', - web_base1+'015-solar-masses/',web_base1+'020-solar-masses/', - web_base1+'025-solar-masses/',web_base2+'009-solar-masses-tracks/', - web_base2+'040-solar-masses/',web_base2+'060-solar-masses/', - web_base1+'085-solar-masses/',web_base1+'120-solar-masses/'] - # Array of masses that matches the website addresses - mass_arr = np.array([9.,12.,15.,20.,25.,32.,40.,60.,85.,120.]) - - # Loop through rotating and unrotating case. First loop is rot, second unrot - for i in range(2): - # Extract masses from filenames - masses = [] - for j in filenames[i]: - tmp = j.split('m') - mass = float(tmp[1][:-1]) - masses.append(mass) - - # Download the models webpage by webpage. A bit tricky because masses - # change slightly within a particular website. THIS IS WHAT FAILS - for j in range(len(web)): - if j == 0: - good = np.where( (masses <= mass_arr[j]) ) - else: - g = j - 1 - good = np.where( (masses <= mass_arr[j]) & - (masses > mass_arr[g]) ) - # Use wget command to pull down the files, and unzip them - for k in good[0]: - full = web[j]+'{1:s}.flx.zip'.format(mass_arr[j],filenames[i][k]) - os.system('wget ' + full) - os.system('unzip '+ filenames[i][k] + '.flx.zip') - - return - -def organize_CMFGEN_atmospheres(path_to_dir): - """ - Organize CMFGEN grid from Fierro+15 - (http://www.astroscu.unam.mx/atlas/index.html) - into rot and noRot directories - - path_to_dir is from current working directory to directory - containing the downloaded models. Assumed that models - and tables describing parameters are in this directory. - - Tables describing parameters MUST be named Table_rot.txt, - Table_noRot.txt. Made by hand from Tables 3, 4 in Fierro+15. - These are located in same original directory as atmosphere files - - Will separate files into 2 subdirectories, one rotating and - the other non-rotating - - *Can't have any other files starting with "t" in model directory to start!* - """ - # First, record current working directory to return to later - start_dir = os.getcwd() - - # Enter atmosphere directory, collect rotating and non-rotating - # file names (assumed to all start with "t") - os.chdir(path_to_dir) - rot_models = glob.glob("t*r.flx*") - noRot_models = glob.glob("t*n.flx*") - - # Separate into different subdirectories - if os.path.exists('cmfgenF15_rot'): - pass - else: - os.mkdir('cmfgenF15_rot') - os.mkdir('cmfgenF15_noRot') - - for mod in rot_models: - cmd = 'mv {0:s} cmfgenF15_rot'.format(mod) - os.system(cmd) - - for mod in noRot_models: - cmd = 'mv {0:s} cmfgenF15_noRot'.format(mod) - os.system(cmd) - - # Also move Tables with model parameters into correct directory - os.system('mv Table_rot.txt cmfgenF15_rot') - os.system('mv Table_noRot.txt cmfgenF15_noRot') - - # Return to original directory - os.chdir(start_dir) - - return - -def make_CMFGEN_catalog(path_to_dir): - """ - Create cdbs catalog.fits of CMFGEN grid from Fierro+15 - (http://www.astroscu.unam.mx/atlas/index.html). - THIS IS STEP 2, after organize_CMFGEN_atmospheres has - been run. - - path_to_dir is from current working directory to directory - containing the rotating or non-rotating models (i.e. cmfgenF15_rot). Also, - needs to be a Table*.txt file which contains the parameters for all of the - original models, since params in filename are not precise enough - - Will create catalog.fits file in atmosphere directory with - description of each model - - *Can't have any other files starting with "t" in model directory to start!* - """ - # Record current working directory for later - start_dir = os.getcwd() - - # Enter atmosphere directory - os.chdir(path_to_dir) - - # Extract parameters for each atmosphere - # Note: can't rely on filename for this because not precise enough!! - - #---------OLD: GETTING PARAMS FROM FILENAME-------# - # Collect file names (assumed to all start with "t") - #files = glob.glob("t*") - #for name in files: - # tmp = name.split('l') - # temp = float(tmp[0][1:]) * 100.0 # In kelvin - - # lumtmp = tmp[1].split('_') - # lum = float(lumtmp[0][:-5]) * 1000.0 # In L_sun - - # mass = float(lumtmp[0][5:-1]) # In M_sun - - # Need to calculate log g from T and L (cgs) - # lum_sun = 3.846 * 10**33 # erg/s - # M_sun = 2 * 10**33 # g - # G_si = 6.67 * 10**(-8) # cgs - # sigma_si = 5.67 * 10**(-5) # cgs - - # g = (G_si * mass * M_sun * 4 * np.pi * sigma_si * temp**4) / \ - # (lum * lum_sun) - # logg = np.log10(g) - #---------------------------------------------------# - - # Read table with atmosphere params - table = glob.glob('Table_*') - t = Table.read(table[0], format = 'ascii') - names = t['col1'] - temps = t['col2'] - logg = t['col4'] - - # Create catalog.fits file - index_str = [] - name_str = [] - for i in range(len(names)): - index = '{0:5.0f},0.0,{1:3.2f}'.format(temps[i], logg[i]) - - #---NOTE: THE FOLLOWING DEPENDS ON FINAL LOCATION OF CATALOG FILE---# - #path = path_to_dir + '/' + names[i] - path = names[i] + '.fits[Flux]' - - index_str.append(index) - name_str.append(path) - - catalog = Table([index_str, name_str], names = ('INDEX', 'FILENAME')) - - # Create catalog.fits file in directory with the models - catalog.write('catalog.fits', format = 'fits') - - # Move back to original directory, create the catalog.fits file - os.chdir(start_dir) - - return - -def cdbs_cmfgen(path_to_dir, path_to_cdbs_dir): - """ - Code to put cmfgen models into cdbs format and adds proper unit keyword in - fits header. Save as fits file - - path_to_dir goes from current directory to cmfgen_rot or cmfgen_norot - directory with the *.flx models. Note that these files have already been - organized using organize_CMFGEN_atmospheres code. - - path_to_cdbs_dir goes from current directory to cdbs/grid/cmfgen_rot or - cmfgen_norot directory. Will copy new fits files to this directory. - This directory must already exist! - """ - # Save starting directory for later, move into path_to_dir directory - start_dir = os.getcwd() - os.chdir(path_to_dir) - - # Collect the filenames, make necessary changes to each one - files = glob.glob('*.flx') - - # Need to make brand-new fits tables with data we want. - counter = 0 - for i in files: - counter += 1 - # Open file, extract useful info - t = Table.read(i, format='ascii') - wave = t['col1'] - flux = t['col2'] # Flux is already in erg/cm^2/s/A - - # Need to eliminate duplicate entries (pysynphot crashes) - unique = np.unique(wave, return_index=True) - wave = wave[unique[1]] - flux = flux[unique[1]] - - # Make fits table from individual columns. - c0 = fits.Column(name='Wavelength', format='D', array=wave) - c1 = fits.Column(name='Flux', format='E', array=flux) - - cols = fits.ColDefs([c0, c1]) - tbhdu = fits.BinTableHDU.from_columns(cols) - - #Adding unit keywords - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - - prihdu = fits.PrimaryHDU() - - finalhdu = fits.HDUList([prihdu, tbhdu]) - finalhdu.writeto(i[:-4]+'.fits', overwrite=True) - - print( 'Done {0:2.0f} of {1:2.0f}'.format(counter, len(files))) - - # Return to original directory, copy over new .fits files to cdbs directory - os.chdir(start_dir) - cmd = 'mv {0:s}/*.fits {1:s}'.format(path_to_dir, path_to_cdbs_dir) - os.system(cmd) - - return - -def rebin_cmfgen(cdbs_path, rot=True): - """ - Rebin cmfgen_rot and cmfgen_norot models to atlas ck04 resolution; - this makes spectrophotometry MUCH faster - - cdbs_path: path to cdbs directory - rot=True for rotating models (cmfgen_rot), False for non-rotating models - - makes new directory in cdbs/grid: cmfgen_rot_rebin or cmfgen_norot_rebin - """ - # Get an atlas ck04 model, we will use this to set wavelength grid - sp_atlas = get_castelli_atmosphere() - - # Open a fits table for an existing cmfgen model; we will steal the header. - # Also define paths to new rebin directories - if rot == True: - tmp = cdbs_path+'/grid/cmfgen_rot/t0200l0008m009r.fits' - path = cdbs_path+'/grid/cmfgen_rot_rebin/' - orig_path = cdbs_path+'/grid/cmfgen_rot/' - else: - tmp = cdbs_path+'/grid/cmfgen_norot/t0200l0007m009n.fits' - path = cdbs_path+'/grid/cmfgen_norot_rebin/' - orig_path = cdbs_path+'/grid/cmfgen_norot/' - - cmfgen_hdu = fits.open(tmp) - header0 = cmfgen_hdu[0].header - # Create rebin directories if they don't already exist. Copy over - # catalog.fits file from original directory (will be the same) - if not os.path.exists(path): - os.mkdir(path) - cmd = 'cp {0:s}catalog.fits {1:s}'.format(orig_path, path) - os.system(cmd) - - # Read in the catalog.fits file - cat = fits.getdata(orig_path + 'catalog.fits') - files_all = [cat[ii][1].split('[')[0] for ii in range(len(cat))] - - # First column in new files will be for [atlas] wavelength - c0 = fits.Column(name='Wavelength', format='D', array=sp_atlas.wave) - - # For each catalog.fits entry, read the unbinned spectrum and rebin to - # the atlas resolution. Make a new fits file in rebin directory - count = 0 - for ff in range(len(files_all)): - count += 1 - # Extract the temp, Z, logg - vals = cat[ff][0].split(',') - temp = float(vals[0]) - metal = float(vals[1]) - grav = float(vals[2]) - - # Fetch the spectrum - if rot == True: - sp = pysynphot.Icat('cmfgen_rot', temp, metal, grav) - else: - sp = pysynphot.Icat('cmfgen_norot', temp, metal, grav) - - # Rebin - flux_rebin = rebin_spec(sp.wave, sp.flux, sp_atlas.wave) - c1 = fits.Column(name='Flux', format='E', array=flux_rebin) - - # Make the FITS file from the columns with header - cols = fits.ColDefs([c0,c1]) - tbhdu = fits.BinTableHDU.from_columns(cols) - prihdu = fits.PrimaryHDU(header=header0) - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - - # Write hdu to new directory with same filename - finalhdu = fits.HDUList([prihdu, tbhdu]) - finalhdu.writeto(path+files_all[ff]) - - print( 'Finished file {0} of {1}'.format(count, len(files_all)) ) - return - - -def organize_PHOENIXv16_atmospheres(path_to_dir, met_str='m00'): - """ - Construct the Phoenix Husser+13 atmopsheres for each model. Combines the - fluxes from the *HiRES.fits files and the wavelengths of the - WAVE_PHONEIX-ACES-AGSS-COND-2011.fits file. - - path_to_dir is the path to the directory containing all of the downloaded - files - - met_str is the name of the current metallicity - - Creates new fits files for each atmosphere: phoenix_.fits, - which contains columns for the log g (column header = g#.#). Puts - atmospheres in new directory phoenixm00 - """ - # Save current directory for return later, move into working dir - start_dir = os.getcwd() - os.chdir(path_to_dir) - - # If it doesn't already exist, create the current metallicity subdirectory - sub_dir = '../phoenix{0}'.format(met_str) - if os.path.exists(sub_dir): - pass - else: - os.mkdir(sub_dir) - - # Extract wavelength array, make column for later - wavefile = fits.open('WAVE_PHOENIX-ACES-AGSS-COND-2011.fits') - wave = wavefile[0].data - wavefile.close() - wave_col = Column(wave, name = 'WAVELENGTH') - - # Create temp array for Husser+13 grid (given in paper) - temp_arr = np.arange(2300, 7001, 100) - temp_arr = np.append(temp_arr, np.arange(7000, 12001, 200)) - - print( 'Looping though all temps') - # For each temp, build file containing the flux for all gravities - i = 0 - for temp in temp_arr: - files = glob.glob('lte{0:05d}-*-HiRes.fits'.format(temp)) - files.sort() - # Start the table with the wavelength column - t = Table() - t.add_column(wave_col) - for f in files: - # Extract the logg out of filename - logg = f[9:13] - - # Extract fluxes from file - spectrum = fits.open(f) - flux = spectrum[0].data - spectrum.close() - - # Make Column object with fluxes, add to table - col = Column(flux, name = 'g{0:2.1f}'.format(float(logg))) - t.add_column(col) - - # Now, construct final fits file for the given temp - outname = 'phoenix{0}_{1:05d}.fits'.format(met_str, temp) - t.write('{0}/{1}'.format(sub_dir, outname), format = 'fits', overwrite = True) - - # Progress counter for user - i += 1 - print( 'Done {0:d} of {1:d}'.format(i, len(temp_arr))) - - # Return to original directory - os.chdir(start_dir) - return - -def make_PHOENIXv16_catalog(path_to_dir, met_str='m00'): - """ - Makes catalog.fits file for Husser+13 phoenix models. Assumes that - organize_PHOENIXv16_atmospheres has been run already, and that the models lie - in subdirectory phoenix[met_str]. - - path_to_directory is the path to the directory with the reformatted - models (i.e. the output from construct_atmospheres, phoenix[met_str]) - - Puts catalog.fits file in directory the user starts in - """ - # Save starting directory for later, move into working directory - start_dir = os.getcwd() - os.chdir(path_to_dir) - - # Extract metallicity from metallicity string - met = float(met_str[1]) + (float(met_str[2]) * 0.1) - if 'm' in met_str: - met *= -1. - - # Collect the filenames. Each is a unique temp with many different log g's - files = glob.glob('phoenix*.fits') - files.sort() - - # Create the catalog.fits file, row by row - index_arr = [] - filename_arr = [] - for i in files: - # Get log g values from the column header the file - t = Table.read(i, format='fits') - keys = t.keys() - logg_vals = keys[1:] - - # Extract temp from filename - name = i.split('_') - temp = float(name[1][:-5]) - for j in logg_vals: - logg = float(j[1:]) - index = '{0:5.0f},{1:2.1f},{2:2.1f}'.format(temp, met, logg) - filename = path_to_dir + i + '[' + j + ']' - # Add row to table - index_arr.append(index) - filename_arr.append(filename) - - catalog = Table([index_arr, filename_arr], names=('INDEX', 'FILENAME')) - - # Return to starting directory, write catalog - os.chdir(start_dir) - - if os.path.exists('catalog.fits'): - from astropy.table import vstack - - prev_catalog = Table.read('catalog.fits', format='fits') - joined_catalog = vstack([prev_catalog, catalog]) - - joined_catalog.write('catalog.fits', format='fits', overwrite=True) - else: - catalog.write('catalog.fits', format='fits', overwrite=True) - - return - -def cdbs_PHOENIXv16(path_to_cdbs_dir): - """ - Put the PHOENIXv16 (Husser+13) fits files into cdbs format. This primarily - consists of adjusting the flux units from [erg/s/cm^2/cm] to [erg/s/cm^2/A] - and adding the appropriate keywords to the fits header. - - path_to_cdbs_dir goes from current working directory to phoenix[met] directory - in cdbs/grids/phoenix_v16. Note that these files have already been organized - using organize_PHOENIXv16_atmospheres code. - - Overwrites original files in directory - """ - # Save starting directory for later, move into working directory - start_dir = os.getcwd() - os.chdir(path_to_cdbs_dir) - - # Collect the filenames, make necessary changes to each one - files = glob.glob('phoenix*.fits') - - ## Need to sort filenames; glob doesn't always give them in order - files.sort() - - # Need to make brand-new fits tables with data we want. - counter = 0 - for i in files: - counter += 1 - - # Read in current FITS table - cur_table = Table.read(i, format='fits') - - cur_table.columns[0].name = 'Wavelength' - - num_cols = len(cur_table.colnames) - - # Multiplying each flux column by 10^-8 for conversion - for cur_col_index in range(1, num_cols, 1): - cur_col_name = cur_table.colnames[cur_col_index] - cur_table[cur_col_name] = cur_table[cur_col_name] * 10.**-8 - - - # Construct new FITS file based on old one - hdu = fits.open(i) - header_0 = hdu[0].header - header_1 = hdu[1].header - sci = hdu[1].data - - tbhdu = fits.table_to_hdu(cur_table) - - # Copying over the older headers, adding unit keywords - prihdu = fits.PrimaryHDU(header=header_0) - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - tbhdu.header['TUNIT3'] = 'FLAM' - tbhdu.header['TUNIT4'] = 'FLAM' - tbhdu.header['TUNIT5'] = 'FLAM' - tbhdu.header['TUNIT6'] = 'FLAM' - tbhdu.header['TUNIT7'] = 'FLAM' - tbhdu.header['TUNIT8'] = 'FLAM' - tbhdu.header['TUNIT9'] = 'FLAM' - tbhdu.header['TUNIT10'] = 'FLAM' - tbhdu.header['TUNIT11'] = 'FLAM' - tbhdu.header['TUNIT12'] = 'FLAM' - tbhdu.header['TUNIT13'] = 'FLAM' - tbhdu.header['TUNIT14'] = 'FLAM' - - # Construct and write out final FITS file - finalhdu = fits.HDUList([prihdu, tbhdu]) - finalhdu.writeto(i, overwrite=True) - - hdu.close() - print( 'Done {0:2.0f} of {1:2.0f}'.format(counter, len(files))) - - # Change back to starting directory - os.chdir(start_dir) - - return - -def rebin_phoenixV16(cdbs_path): - """ - Rebin phoenixV16 models to atlas ck04 resolution; this makes - spectrophotometry MUCH faster - - makes new directory in cdbs/grid: phoenix_v16_rebin - - cdbs_path: path to cdbs directory - """ - # Get an atlas ck04 model, we will use this to set wavelength grid - sp_atlas = get_castelli_atmosphere() - - # Open a fits table for an existing phoenix model; we will steal the header - ## (This assumes that at least 'm00' metallicity exists) - tmp = '{0}/grid/phoenix_v16/phoenix{1}/phoenix{1}_02400.fits'.format(cdbs_path, 'm00') - phoenix_hdu = fits.open(tmp) - header0 = phoenix_hdu[0].header - - # Create cdbs/grid directory for rebinned models - path = cdbs_path+'/grid/phoenix_v16_rebin/' - if not os.path.exists(path): - os.mkdir(path) - - - # Read in the existing catalog.fits file and rebin every spectrum. - cat = fits.getdata(cdbs_path + '/grid/phoenix_v16/catalog.fits') - files_all = [cat[ii][1].split('[')[0] for ii in range(len(cat))] - temp_arr = np.zeros(len(files_all), dtype=float) - logg_arr = np.zeros(len(files_all), dtype=float) - metal_arr = np.zeros(len(files_all), dtype=float) - - for ff in range(len(files_all)): - vals = cat[ff][0].split(',') - - temp_arr[ff] = float(vals[0]) - metal_arr[ff] = float(vals[1]) - logg_arr[ff] = float(vals[2]) - - - metal_uniq = np.unique(metal_arr) - temp_uniq = np.unique(temp_arr) - - for mm in range(len(metal_uniq)): - metal = metal_uniq[mm] # metallicity - - # Construct str for metallicity (for appropriate directory name) - met_str = str(int(np.abs(metal))) + str(int((metal % 1.0)*10)) - if metal > 0: - met_str = 'p' + met_str - else: - met_str = 'm' + met_str - - # Make directory for current metallicity if it does not exist yet - if not os.path.exists(path + 'phoenix' + met_str): - os.mkdir(path + 'phoenix' + met_str) - - for tt in range(len(temp_uniq)): - temp = temp_uniq[tt] # temperature - - # Pick out the list of gravities for this T, Z combo - idx = np.where((metal_arr == metal) & (temp_arr == temp))[0] - logg_exist = logg_arr[idx] - - # All gravities will go in one file. Here is the output - # file name. - outfile = path + files_all[idx[0]].split('[')[0] - - ## If the rebinned file already exists, continue - if os.path.exists(outfile): - continue - - # Build a columns array. One column for each gravity. - cols_arr = [] - - # Make the wavelength column, which is first in the cols array. - c0 = fits.Column(name='Wavelength', format='D', array=sp_atlas.wave) - cols_arr.append(c0) - - for gg in range(len(logg_exist)): - grav = logg_exist[gg] # gravity - - # Fetch the spectrum - sp = pysynphot.Icat('phoenix_v16', temp, metal, grav) - flux_rebin = rebin_spec(sp.wave, sp.flux, sp_atlas.wave) - - # Store the spectrum - name = 'g{0:3.1f}'.format(grav) - col = fits.Column(name=name, format='E', array=flux_rebin) - cols_arr.append(col) - - - # Make the FITS file from the columns with header. - cols = fits.ColDefs(cols_arr) - tbhdu = fits.BinTableHDU.from_columns(cols) - prihdu = fits.PrimaryHDU(header=header0) - tbhdu.header['TUNIT1'] = 'ANGSTROM' - for gg in range(len(logg_exist)): - tbhdu.header['TUNIT{0:d}'.format(gg+2)] = 'FLAM' - - # Write hdu - finalhdu = fits.HDUList([prihdu, tbhdu]) - # don't have overwrite to protect original files. - finalhdu.writeto(outfile) - - print( 'Finished file ' + outfile + ' with gravities: ', logg_exist) - - - return - - -def rebin_spec(wave, specin, wavnew): - """ - Helper routine to rebin spectra. TAKEN FROM ASTROBETTER BLOG FROM JESSICA: - http://www.astrobetter.com/blog/2013/08/12/ - python-tip-re-sampling-spectra-with-pysynphot/ - """ - spec = pysynphot.spectrum.ArraySourceSpectrum(wave=wave, flux=specin) - f = np.ones(len(wave)) - filt = pysynphot.spectrum.ArraySpectralElement(wave, f, waveunits='angstrom') - obs = pysynphot.observation.Observation(spec, filt, binset=wavnew, force='taper') - - return obs.binflux - -def organize_BTSettl_2015_atmospheres(path_to_dir): - """ - Construct cdbs-ready BTSettl_CIFITS_2011_2015 atmospheres for each model. - Will convert wavelength units to angstroms and flux units to [erg/s/cm^2/A] - - path_to_dir is the path to the directory containing all of the downloaded - files - - Saves cdbs-ready atmospheres into os.environ['PYSYN_CDBS']/grid/BTSettl_2015 - (assumes this directory exists) - """ - # Save current directory for return later, move into working dir - start_dir = os.getcwd() - os.chdir(path_to_dir) - - # If it doesn't already exist, create the BTSettl subdirectory - if not os.path.exists('BTSettl_2015'): - os.mkdir('BTSettl_2015') - - # Process each atmosphere file independently - print( 'Creating cdbs-ready files') - files = glob.glob('*.spec.fits') - - for i in files: - hdu = fits.open(i) - spec = hdu[1].data - header_0 = hdu[0].header - header_1 = hdu[1].header - - wave = spec.field(0) - flux = spec.field(1) - - # Get units right: convert wave from microns to Angstroms, - # flux from W /m^2/ micron to erg/s/cm^2/A - wave_new = wave * 10**4 - flux_new = flux * 10**(-1) - - # Make new fits table - c0 = fits.Column(name='Wavelength', format='D', array=wave_new) - c1 = fits.Column(name='Flux', format='E', array=flux_new) - - cols = fits.ColDefs([c0, c1]) - tbhdu = fits.BinTableHDU.from_columns(cols) - - # Copy over headers, update unit keywords - prihdu = fits.PrimaryHDU(header=header_0) - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - hdu_new = fits.HDUList([prihdu, tbhdu]) - - # Write new fits table in cdbs directory - hdu_new.writeto(os.environ['PYSYN_CDBS']+'grid/BTSettl_2015/'+i, overwrite=True) - - hdu.close() - hdu_new.close() - - # Return to original directory - os.chdir(start_dir) - return - -def make_BTSettl_2015_catalog(path_to_dir): - """ - Create cdbs catalog.fits of BTSettl_CIFITS2011_2015 grid. - THIS IS STEP 2, after organize_CMFGEN_atmospheres has - been run. - - path_to_dir is from current working directory to the cdbs directory. - Will create catalog.fits file in atmosphere directory with - description of each model - """ - # Record current working directory for later - start_dir = os.getcwd() - - # Enter atmosphere directory - os.chdir(path_to_dir) - - # Extract parameters for each atmosphere from the filename, - # construct columns for catalog file - files = glob.glob("*spec.fits") - index_str = [] - name_str = [] - for name in files: - tmp = name.split('-') - temp = float(tmp[0][3:]) * 100.0 # In kelvin - logg = float(tmp[1]) - - index_str.append('{0:5.0f},0.0,{1:3.2f}'.format(temp, logg)) - name_str.append('{0}[Flux]'.format(name)) - - # Make catalog - catalog = Table([index_str, name_str], names = ('INDEX', 'FILENAME')) - - # Create catalog.fits file in directory with the models - catalog.write('catalog.fits', format = 'fits', overwrite=True) - - # Move back to original directory, create the catalog.fits file - os.chdir(start_dir) - - return - -def rebin_BTSettl_2015(cdbs_path=os.environ['PYSYN_CDBS']): - """ - Rebin BTSettle_CIFITS2011_2015 models to atlas ck04 resolution; this makes - spectrophotometry MUCH faster - - makes new directory in cdbs/grid: BTSettl_2015_rebin - - cdbs_path: path to cdbs directory - """ - # Get an atlas ck04 model, we will use this to set wavelength grid - sp_atlas = get_castelli_atmosphere() - - # Open a fits table for an existing phoenix model; we will steal the header - tmp = cdbs_path+'/grid/phoenix_v16/phoenixm00/phoenixm00_02400.fits' - phoenix_hdu = fits.open(tmp) - header0 = phoenix_hdu[0].header - phoenix_hdu.close() - - # Create cdbs/grid directory for rebinned models - path = cdbs_path+'/grid/BTSettl_2015_rebin/' - if not os.path.exists(path): - os.mkdir(path) - - # Read in the existing catalog.fits file and rebin every spectrum. - cat = fits.getdata(cdbs_path + '/grid/BTSettl_2015/catalog.fits') - files_all = [cat[ii][1].split('[')[0] for ii in range(len(cat))] - - print( 'Rebinning BTSettl spectra') - for ff in range(len(files_all)): - vals = cat[ff][0].split(',') - temp = float(vals[0]) - metal = float(vals[1]) - logg = float(vals[2]) - - # Fetch the BTSettl spectrum, rebin flux - sp = pysynphot.Icat('BTSettl_2015', temp, metal, logg) - flux_rebin = rebin_spec(sp.wave, sp.flux, sp_atlas.wave) - - # Make new output - c0 = fits.Column(name='Wavelength', format='D', array=sp_atlas.wave) - c1 = fits.Column(name='Flux', format='E', array=flux_rebin) - - cols = fits.ColDefs([c0, c1]) - tbhdu = fits.BinTableHDU.from_columns(cols) - prihdu = fits.PrimaryHDU(header=header0) - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - - outfile = path + files_all[ff].split('[')[0] - finalhdu = fits.HDUList([prihdu, tbhdu]) - finalhdu.writeto(outfile, overwrite=True) - - return - -def make_wavelength_unique(files, dirname): - """ - Helper function to go through each BTSettl spectrum and ensure that - each wavelength point is unique. This is required for rebinning to work. - - - files: list of files to run this analysis on - """ - # Loop through each file, find fix repeated wavelength entries if necessary - for i in files: - t = Table.read('{0}/{1}'.format(dirname,i), format='fits') - test = np.unique(t['Wavelength'], return_index=True) - - if len(t) != len(test[0]): - t = t[test[1]] - - c0 = fits.Column(name='Wavelength', format='D', array=t['Wavelength']) - c1 = fits.Column(name='Flux', format='E', array=t['Flux']) - cols = fits.ColDefs([c0, c1]) - - tbhdu = fits.BinTableHDU.from_columns(cols) - prihdu = fits.PrimaryHDU() - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - finalhdu = fits.HDUList([prihdu, tbhdu]) - finalhdu.writeto('{0}/{1}'.format(dirname,i), overwrite=True) - - # Also make sure wavelength is monotonic. If it is not, then it is - # a sign that the wavelengths are out of order - diff = np.diff(t['Wavelength']) - bad = np.where(diff < 0) - if len(bad[0]) > 0: - t.sort('Wavelength') - - c0 = fits.Column(name='Wavelength', format='D', array=t['Wavelength']) - c1 = fits.Column(name='Flux', format='E', array=t['Flux']) - cols = fits.ColDefs([c0, c1]) - - tbhdu = fits.BinTableHDU.from_columns(cols) - prihdu = fits.PrimaryHDU() - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - finalhdu = fits.HDUList([prihdu, tbhdu]) - finalhdu.writeto('{0}/{1}'.format(dirname,i), overwrite=True) - - print('Done {0}'.format(i)) - - return - -def organize_BTSettl_atmospheres(): - """ - Construct cdbs-ready atmospheres for the BTSettl grid (CIFITS2011). - The code expects tp be run in cdbs/grid/BTSettl, and expects that the - individual model files have been downloaded from online - (https://phoenix.ens-lyon.fr/Grids/BT-Settl/CIFIST2011/SPECTRA/) - and processed into python-readable ascii files. - """ - orig_dir = os.getcwd() - dirs = ['btm25', 'btm20', 'btm15', 'btm10', 'btm05', 'btp00', 'btp05'] - #dirs = ['btm10', 'btm05', 'btp00', 'btp05'] - - - # Go through each directory, turning each spectrum into a cdbs-ready file. - # Will convert flux into Ergs/sec/cm**2/A (FLAM) units and save as a fits file, - # for faster access later - for ii in dirs: - print('Starting {0}'.format(ii)) - os.chdir(ii) - - files = glob.glob('*.txt') - count=0 - for jj in files: - t = Table.read(jj, format='ascii') - # First, trim the wavelengths to a more reasonable wavelength range - good = np.where( (t['col1'] > 1000) & (t['col1'] < 70000) ) - t = t[good] - - # Convert flux units to Flam (Ergs/sec/cm**2/A) - flux_new = 10**(t['col2'] - 8.0) - - # Save the file as a fits file - c0 = fits.Column(name='Wavelength', format='D', array=t['col1']) - c1 = fits.Column(name='Flux', format='E', array=flux_new) - - cols = fits.ColDefs([c0, c1]) - tbhdu = fits.BinTableHDU.from_columns(cols) - - # Add unit keywords - prihdu = fits.PrimaryHDU() - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - hdu_new = fits.HDUList([prihdu, tbhdu]) - - # Write new fits table in cdbs directory - hdu_new.writeto('{0}.fits'.format(jj[:-4]), overwrite=True) - hdu_new.close() - count += 1 - print('Done {0} of {1}'.format(count, len(files))) - - # Now, clean up all the files made when unzipping the spectra - cmd1 = 'rm *.bz2' - cmd2 = 'rm *.tmp' - #cmd3 = 'rm *.txt' - os.system(cmd1) - os.system(cmd2) - #os.system(cmd3) - print('==============================') - print('Done {0}'.format(ii)) - print('==============================') - - # Go back to original directory, move to next metallicity directory - os.chdir(orig_dir) - - return - -def make_BTSettl_catalog(): - """ - Create cdbs catalog.fits of BTSettl grid. - THIS IS STEP 2, after organize_BTSettl_atmospheres has - been run. - - Code expects to be run in cdbs/grid/BTSettl - Will create catalog.fits file in atmosphere directory with - description of each model - """ - # Record current working directory for later - start_dir = os.getcwd() - dirs = ['btm25', 'btm20', 'btm15', 'btm10', 'btm05', 'btp00', 'btp05'] - #dirs = ['btp05'] - - # Construct the catalog.fits file input. The input consists of - # and index string that specifies the stellar paramters, and a - # name string that points to the file - # Loop over all the metallicity directories to construct these inputs - index_str = [] - name_str = [] - for ii in dirs: - os.chdir(ii) - files = glob.glob('*.fits') - - # Construct the metallicity val - if 'm' in ii: - metal_flag = -1 * float(ii[3:])*0.1 - else: - metal_flag = float(ii[3:])*0.1 - - # Now collect the info from the files - for jj in files: - tmp = jj.split('-') - - if metal_flag >= 0: - temp = float(tmp[0].split('+')[0][3:]) * 100.0 # In kelvin - try: - logg = float(tmp[1]) - except: - logg = float(tmp[1].split('+')[0]) - else: - temp = float(tmp[0][3:]) * 100.0 # In kelvin - logg = float(tmp[1]) - - index_str.append('{0},{1},{2:3.2f}'.format(int(temp), metal_flag, logg)) - name_str.append('{0}/{1}[Flux]'.format(ii, jj)) - - # Go back to original directory to move to next metallicity - print('Done {0}'.format(ii)) - os.chdir(start_dir) - - # Make catalog - catalog = Table([index_str, name_str], names = ('INDEX', 'FILENAME')) - - # Create catalog.fits file in directory with the models - catalog.write('catalog.fits', format = 'fits', overwrite=True) - - # Move back to original directory, create the catalog.fits file - os.chdir(start_dir) - - return - -def rebin_BTSettl(make_unique=False): - """ - Rebin BTSettle models to atlas ck04 resolution; this makes - spectrophotometry MUCH faster - - makes new directory: BTSettl_rebin - - Code expects to be run in cdbs/grid directory - """ - # Get an atlas ck04 model, we will use this to set wavelength grid - sp_atlas = get_castelli_atmosphere() - - # Create cdbs/grid directory for rebinned models - path = 'BTSettl_rebin/' - if not os.path.exists(path): - os.mkdir(path) - - # Read in the existing catalog.fits file and rebin every spectrum. - cat = fits.getdata('BTSettl/catalog.fits') - files_all = [cat[ii][1].split('[')[0] for ii in range(len(cat))] - - #==============================# - #tmp = [] - #for ii in files_all: - # if ii.startswith('btp00'): - # tmp.append(ii) - #files_all = tmp - #=============================# - - print( 'Rebinning BTSettl spectra') - if make_unique: - print('Making unique') - make_wavelength_unique(files_all, 'BTSettl') - print('Done') - - for ff in range(len(files_all)): - vals = cat[ff][0].split(',') - temp = float(vals[0]) - metal = float(vals[1]) - logg = float(vals[2]) - - # Fetch the BTSettl spectrum, rebin flux - try: - sp = pysynphot.Icat('BTSettl', temp, metal, logg) - flux_rebin = rebin_spec(sp.wave, sp.flux, sp_atlas.wave) - - # Make new output - c0 = fits.Column(name='Wavelength', format='D', array=sp_atlas.wave) - c1 = fits.Column(name='Flux', format='E', array=flux_rebin) - - cols = fits.ColDefs([c0, c1]) - tbhdu = fits.BinTableHDU.from_columns(cols) - prihdu = fits.PrimaryHDU() - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - - outfile = path + files_all[ff].split('[')[0] - finalhdu = fits.HDUList([prihdu, tbhdu]) - finalhdu.writeto(outfile, overwrite=True) - except: - pdb.set_trace() - orig_file = '{0}/{1}'.format('BTSettl/', files_all[ff].split('[')[0]) - outfile = path + files_all[ff].split('[')[0] - cmd = 'cp {0} {1}'.format(orig_file, outfile) - os.system(cmd) - - print('Done {0} of {1}'.format(ff, len(files_all))) - - return - -def organize_WDKoester_atmospheres(path_to_dir): - """ - Construct cdbs-ready wdKoester WD atmospheres for each model. (from Koester 2010) - Will convert wavelength units to angstroms and flux units to [erg/s/cm^2/A] - - path_to_dir is the path to the directory containing all of the downloaded - files - - Saves cdbs-ready atmospheres into os.environ['PYSYN_CDBS']/wdKoeseter - (assumes this directory exists) - """ - # Save current directory for return later, move into working dir - start_dir = os.getcwd() - os.chdir(path_to_dir) - - # Process each atmosphere file independently - print( 'Creating cdbs-ready files') - files = glob.glob('*.dk.dat.txt') - - for i in files: - data = Table.read(i, format='ascii') - - wave = data['col1'] # angstrom - flux = data['col2'] # erg/s/cm^2/A - - # Make new fits table - c0 = fits.Column(name='Wavelength', format='D', array=wave) - c1 = fits.Column(name='Flux', format='E', array=flux) - - cols = fits.ColDefs([c0, c1]) - tbhdu = fits.BinTableHDU.from_columns(cols) - - # Copy over headers, update unit keywords - prihdu = fits.PrimaryHDU() - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - hdu_new = fits.HDUList([prihdu, tbhdu]) - - # Write new fits table in cdbs directory - hdu_new.writeto(os.environ['PYSYN_CDBS']+'/grid/wdKoester/'+i.replace('.txt', '.fits'), overwrite=True) - - hdu_new.close() - - # Return to original directory - os.chdir(start_dir) - return - -def make_WDKoester_catalog(path_to_dir): - """ - Create cdbs catalog.fits of wdKoester grid. - THIS IS STEP 2, after organize_WDKoester_atmospheres has - been run. - - path_to_dir is from current working directory to the cdbs directory. - Will create catalog.fits file in atmosphere directory with - description of each model - """ - # Record current working directory for later - start_dir = os.getcwd() - - # Enter atmosphere directory - os.chdir(path_to_dir) - - # Extract parameters for each atmosphere from the filename, - # construct columns for catalog file - files = glob.glob("*dk.dat.fits") - index_str = [] - name_str = [] - for name in files: - tmp = name.split('.') - tmp2 = tmp[0].split('_') - temp = float(tmp2[0][2:]) # Kelvin - logg = float(tmp2[1]) / 100.0 # log(g) - - index_str.append('{0:5.0f},0.0,{1:3.2f}'.format(temp, logg)) - name_str.append('{0}[Flux]'.format(name)) - - # Make catalog - catalog = Table([index_str, name_str], names = ('INDEX', 'FILENAME')) - - # Create catalog.fits file in directory with the models - catalog.write('catalog.fits', format = 'fits', overwrite=True) - - # Move back to original directory, create the catalog.fits file - os.chdir(start_dir) - - return - -def rebin_WDKoester(cdbs_path=os.environ['PYSYN_CDBS']): - """ - Rebin wdKoester models to atlas ck04 resolution; this makes - spectrophotometry MUCH faster - - makes new directory in cdbs/grid: wdKoester_rebin - - cdbs_path: path to cdbs directory - """ - # Get an atlas ck04 model, we will use this to set wavelength grid - sp_atlas = get_castelli_atmosphere() - - # Open a fits table for an existing model; we will steal the header - tmp = cdbs_path+'/grid/wdKoester/da70000_800.dk.dat.fits' - wdkoester_hdu = fits.open(tmp) - header0 = wdkoester_hdu[0].header - wdkoester_hdu.close() - - # Create cdbs/grid directory for rebinned models - path = cdbs_path+'/grid/wdKoester_rebin/' - if not os.path.exists(path): - os.mkdir(path) - - # Read in the existing catalog.fits file and rebin every spectrum. - cat = fits.getdata(cdbs_path + '/grid/wdKoester/catalog.fits') - files_all = [cat[ii][1].split('[')[0] for ii in range(len(cat))] - - print( 'Rebinning wdKoester spectra') - for ff in range(len(files_all)): - vals = cat[ff][0].split(',') - temp = float(vals[0]) - metal = float(vals[1]) - logg = float(vals[2]) - - # Fetch the wdKoester spectrum, rebin flux - sp = pysynphot.Icat('wdKoester', temp, metal, logg) - flux_rebin = rebin_spec(sp.wave, sp.flux, sp_atlas.wave) - - # Make new output - c0 = fits.Column(name='Wavelength', format='D', array=sp_atlas.wave) - c1 = fits.Column(name='Flux', format='E', array=flux_rebin) - - cols = fits.ColDefs([c0, c1]) - tbhdu = fits.BinTableHDU.from_columns(cols) - prihdu = fits.PrimaryHDU(header=header0) - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - - outfile = path + files_all[ff].split('[')[0] - finalhdu = fits.HDUList([prihdu, tbhdu]) - finalhdu.writeto(outfile, overwrite=True) - - return - - diff --git a/spisea/atmospheres_LOCAL_58456.py b/spisea/atmospheres_LOCAL_58456.py deleted file mode 100644 index 0f4c90e5..00000000 --- a/spisea/atmospheres_LOCAL_58456.py +++ /dev/null @@ -1,2508 +0,0 @@ -import logging -import numpy as np -import pysynphot -import os -import glob -from astropy.io import fits -from astropy.table import Table, Column -import pysynphot -import time -import pdb -import warnings - -log = logging.getLogger('atmospheres') - -def get_atmosphere_bounds(model_dir, metallicity=0, temperature=20000, gravity=4): - """ - Given atmosphere model, get temperature and gravity bounds - """ - # Open catalog fits file and break out row indices - catalog = Table.read('{0}/grid/{1}/catalog.fits'.format(os.environ['PYSYN_CDBS'], model_dir)) - - teff_arr = [] - z_arr = [] - logg_arr = [] - for cur_row_index in range(len(catalog)): - index = catalog['INDEX'][cur_row_index] - tmp = index.split(',') - teff_arr.append(float(tmp[0])) - z_arr.append(float(tmp[1])) - logg_arr.append(float(tmp[2])) - teff_arr = np.array(teff_arr) - z_arr = np.array(z_arr) - logg_arr = np.array(logg_arr) - - # Filter by metallicity. Will chose the closest metallicity to desired input - metal_list = np.unique(np.array(z_arr)) - metal_idx = np.argmin(np.abs(metal_list - metallicity)) - - z_filt = np.where(z_arr == metal_list[metal_idx]) - teff_arr = teff_arr[z_filt] - logg_arr = logg_arr[z_filt] - - # # Now find the closest atmosphere in parameter space to - # # the one we want. We'll find the match with the lowest - # # fractional difference - # teff_diff = (teff_arr - temperature) / temperature - # logg_diff = (logg_arr - gravity) / gravity - # - # diff_tot = abs(teff_diff) + abs(logg_diff) - # idx_f = np.argmin(diff_tot) - # - # temperature_new = teff_arr[idx_f] - # gravity_new = logg_arr[idx_f] - - # First check if temperature within bounds - temperature_new = temperature - if temperature > np.max(teff_arr): - temperature_new = np.max(teff_arr) - if temperature < np.min(teff_arr): - temperature_new = np.min(teff_arr) - - # If temperature within bounds, then check if metallicity within bounds - teff_diff = np.abs(teff_arr - temperature) - sorted_min_diffs = np.unique(teff_diff) - - ## Find two closest temperatures - teff_close_1 = teff_arr[np.where(teff_diff == sorted_min_diffs[0])[0][0]] - teff_close_2 = teff_arr[np.where(teff_diff == sorted_min_diffs[1])[0][0]] - - logg_arr_1 = logg_arr[np.where(teff_arr == teff_close_1)] - logg_arr_2 = logg_arr[np.where(teff_arr == teff_close_2)] - - ## Switch to most conservative bound of logg out of two closest temps - gravity_new = gravity - if gravity > np.min([np.max(logg_arr_1), np.max(logg_arr_2)]): - gravity_new = np.min([np.max(logg_arr_1), np.max(logg_arr_2)]) - if gravity < np.max([np.min(logg_arr_1), np.min(logg_arr_2)]): - gravity_new = np.max([np.min(logg_arr_1), np.min(logg_arr_2)]) - - # Print out changes, if any - if temperature_new != temperature: - teff_msg = 'Changing to T={0:6.0f} for T={1:6.0f} logg={2:4.2f}' - print( teff_msg.format(temperature_new, temperature, gravity)) - - if gravity_new != gravity: - logg_msg = 'Changing to logg={0:4.2f} for T={1:6.0f} logg={2:4.2f}' - print( logg_msg.format(gravity_new, temperature, gravity)) - - return (temperature_new, gravity_new) - -def get_kurucz_atmosphere(metallicity=0, temperature=20000, gravity=4, rebin=False): - """ - Return atmosphere from the Kurucz pysnphot grid - (`Kurucz 1993 `_). - - Grid Range: - - * Teff: 3000 - 50000 K - * gravity: 0 - 5 cgs - * metallicity: -5.0 - 1.0 - - Parameters - ---------- - metallicity: float - The stellar metallicity, in terms of [Z] - - temperature: float - The stellar temperature, in units of K - - gravity: float - The stellar gravity, in cgs units - - rebin: boolean - Always false for this particular function - """ - try: - sp = pysynphot.Icat('k93models', temperature, metallicity, gravity) - except: - # Check atmosphere catalog bounds - (temperature, gravity) = get_atmosphere_bounds('k93models', - metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - sp = pysynphot.Icat('k93models', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find Kurucz 1993 atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_castelli_atmosphere(metallicity=0, temperature=20000, gravity=4, rebin=False): - """ - Return atmospheres from the pysynphot ATLAS9 atlas - (`Castelli & Kurucz 2004 `_). - - Grid Range: - - * Teff: 3500 - 50000 K - * gravity: 0 - 5.0 cgs - * [M/H]: -2.5 - 0.2 - - Parameters - ---------- - metallicity: float - The stellar metallicity, in terms of [Z] - - temperature: float - The stellar temperature, in units of K - - gravity: float - The stellar gravity, in cgs units - - rebin: boolean - If true, rebins the atmospheres so that they are the same - resolution as the Castelli+04 atmospheres. Default is False, - which is often sufficient synthetic photometry in most cases. - - verbose: boolean - True for verbose output - """ - try: - sp = pysynphot.Icat('ck04models', temperature, metallicity, gravity) - except: - # Check atmosphere catalog bounds - (temperature, gravity) = get_atmosphere_bounds('ck04models', - metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - sp = pysynphot.Icat('ck04models', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find Castelli and Kurucz 2004 atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_nextgen_atmosphere(metallicity=0, temperature=5000, gravity=4, rebin=False): - """ - metallicity = [M/H] (def = 0) - temperature = Kelvin (def = 5000) - gravity = log gravity (def = 4.0) - """ - try: - sp = pysynphot.Icat('nextgen', temperature, metallicity, gravity) - except: - # Check atmosphere catalog bounds - (temperature, gravity) = get_atmosphere_bounds('nextgen', - metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - sp = pysynphot.Icat('nextgen', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find NextGen atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_amesdusty_atmosphere(metallicity=0, temperature=5000, gravity=4, rebin=False): - """ - metallicity = [M/H] (def = 0) - temperature = Kelvin (def = 5000) - gravity = log gravity (def = 4.0) - """ - sp = pysynphot.Icat('AMESdusty', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find AMESdusty Allard+ 2000 atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_phoenix_atmosphere(metallicity=0, temperature=5000, gravity=4, - rebin=False): - """ - Return atmosphere from the pysynphot - `PHOENIX atlas `_. - - Parameters - ---------- - metallicity: float - The stellar metallicity, in terms of [Z] - - temperature: float - The stellar temperature, in units of K - - gravity: float - The stellar gravity, in cgs units - - rebin: boolean - If true, rebins the atmospheres so that they are the same - resolution as the Castelli+04 atmospheres. Default is False, - which is often sufficient synthetic photometry in most cases. - - """ - try: - sp = pysynphot.Icat('phoenix', temperature, metallicity, gravity) - except: - # Check atmosphere catalog bounds - (temperature, gravity) = get_atmosphere_bounds('phoenix', - metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - sp = pysynphot.Icat('phoenix', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find PHOENIX BT-Settl (Allard+ 2011 atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_cmfgenRot_atmosphere(metallicity=0, temperature=24000, gravity=4.3, rebin=True): - """ - metallicity = [M/H] (def = 0) - temperature = Kelvin (def = 24000) - gravity = log gravity (def = 4.3) - - rebin=True: pull from atmospheres at ck04model resolution. - """ - # Take care of atmospheres outside the catalog boundaries - logg_msg = 'Changing to logg={0:3.1f} for T={1:6.0f} logg={2:4.2f}' - if gravity > 4.3: - print( logg_msg.format(4.3, temperature, gravity)) - gravity = 4.3 - - if rebin: - sp = pysynphot.Icat('cmfgen_rot_rebin', temperature, metallicity, gravity) - else: - sp = pysynphot.Icat('cmfgen_rot', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find CMFGEN rotating atmosphere model (Fierro+15) for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_cmfgenRot_atmosphere_closest(metallicity=0, temperature=24000, gravity=4.3, rebin=True, - verbose=False): - """ - For a given stellar atmosphere, get extract the closest possible match in - Teff/logg space. Note that this is different from the normal routine - which interpolates along the input grid to get final spectrum. We can't - do this here because the Fierro+15 atmosphere grid is so sparse - - rebin=True: pull from atmospheres at ck04model resolution. - - If verbose, print out the parameters of the match - """ - # Set up the proper root directory - if rebin == True: - root_dir = os.environ['PYSYN_CDBS'] + '/cmfgen_rot_rebin/' - else: - root_dir = os.environ['PYSYN_CDBS'] + '/cmfgen_rot/' - - # Read in catalog, extract atmosphere info - cat = Table.read('{0}/catalog.fits'.format(root_dir), format='fits') - teff_arr = [] - z_arr = [] - logg_arr = [] - for ii in range(len(cat)): - index = cat['INDEX'][ii] - tmp = index.split(',') - teff_arr.append(float(tmp[0])) - z_arr.append(float(tmp[1])) - logg_arr.append(float(tmp[2])) - teff_arr = np.array(teff_arr) - z_arr = np.array(z_arr) - logg_arr = np.array(logg_arr) - - # Now find the closest atmosphere in parameter space to - # the one we want. We'll find the match with the lowest - # fractional difference - teff_diff = (teff_arr - temperature) / temperature - logg_diff = (logg_arr - gravity) / gravity - - diff_tot = abs(teff_diff) + abs(logg_diff) - idx_f = np.where(diff_tot == min(diff_tot))[0][0] - - # Extract the filename of the best-match model and read as - # pysynphot object - infile = cat[idx_f]['FILENAME'].split('.') - spec = Table.read('{0}/{1}.fits'.format(root_dir, infile[0])) - - # Now, the CMFGEN atmospheres assume a distance of 1 kpc, while the the - # ATLAS models are in FLAM at the surface. So, we need to multiply the - # CMFGEN atmospheres by (1000/R)**2. in order to convert to FLAM on surface. - # We'll calculate radius from Teff and logL, which is given in the Table_*.txt file - t = Table.read('{0}/Table_rot.txt'.format(root_dir), format='ascii') - tmp = np.where(t['col1'] == infile[0]) - - lum = t['col3'][tmp] * (3.839*10**33) # cgs - sigma = 5.6704 * 10**-5 # cgs - teff = teff_arr[idx_f] # cgs - - radius = np.sqrt( lum / (4.0 * np.pi * teff**4. * sigma) ) # in cm - radius /= 3.08*10**18 # in pc - - - # Make the pysynphot spectrum - w = spec['Wavelength'] - f = spec['Flux'] * (1000 / radius)**2. - sp = pysynphot.ArraySpectrum(w,f) - - #sp = pysynphot.FileSpectrum('{0}/{1}.fits'.format(root_dir, infile[0])) - - # Print out parameters of match, if desired - if verbose: - print('Teff match: Input: {0}, Output: {1}'.format(temperature, teff_arr[idx_f])) - print('logg match: Input: {0}, Output: {1}'.format(gravity, logg_arr[idx_f])) - - return sp - -def get_cmfgenNoRot_atmosphere(metallicity=0, temperature=22500, gravity=3.98, rebin=True): - """ - metallicity = [M/H] (def = 0) - temperature = Kelvin (def = 24000) - gravity = log gravity (def = 4.3) - - rebin=True: pull from atmospheres at ck04model resolution. - """ - if rebin: - sp = pysynphot.Icat('cmfgen_norot_rebin', temperature, metallicity, gravity) - else: - sp = pysynphot.Icat('cmfgen_norot', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find CMFGEN rotating atmosphere model (Fierro+15) for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_cmfgenNoRot_atmosphere(metallicity=0, temperature=30000, gravity=4.14): - """ - metallicity = [M/H] (def = 0) - temperature = Kelvin (def = 30000) - gravity = log gravity (def = 4.14) - """ - sp = pysynphot.Icat('cmfgenF15_noRot', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find CMFGEN non-rotating atmosphere model (Fierro+15) for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_phoenixv16_atmosphere(metallicity=0, temperature=4000, gravity=4, rebin=True): - """ - Return PHOENIX v16 atmospheres from - `Husser et al. 2013 `_. - - Models originally downloaded via `ftp `_. - Solar metallicity and [alpha/Fe] is used. - - Grid Range: - - * Teff: 2300 - 7000 K, steps of 100 K; 7000 - 12000 in steps of 200 K - * gravity: 0.0 - 6.0 cgs, steps of 0.5 - * [M/H]: -4.0 - 1.0 - - Parameters - ---------- - metallicity: float - The stellar metallicity, in terms of [Z] - - temperature: float - The stellar temperature, in units of K - - gravity: float - The stellar gravity, in cgs units - - rebin: boolean - If true, rebins the atmospheres so that they are the same - resolution as the Castelli+04 atmospheres. Default is False, - which is often sufficient synthetic photometry in most cases. - - """ - atm_model_name = 'phoenix_v16' - if rebin == True: - atm_model_name = 'phoenix_v16_rebin' - - - # Extract atmosphere. If that fails, then check bounds and try again - try: - sp = pysynphot.Icat(atm_model_name, temperature, metallicity, gravity) - except: - # Check atmosphere catalog bounds - (temperature, gravity) = get_atmosphere_bounds(atm_model_name, - metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - sp = pysynphot.Icat(atm_model_name, temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find PHOENIXv16 (Husser+13) atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_BTSettl_2015_atmosphere(metallicity=0, temperature=2500, gravity=4, rebin=True): - """ - Return atmosphere from CIFIST2011_2015 grid - (`Allard et al. 2012 `_, - `Baraffe et al. 2015 `_ ) - - Grid originally downloaded from `website `_. - - Grid Range: - - * Teff: 1200 - 7000 K - * gravity: 2.5 - 5.5 cgs - * [M/H] = 0 - - Parameters - ---------- - metallicity: float - The stellar metallicity, in terms of [Z] - - temperature: float - The stellar temperature, in units of K - - gravity: float - The stellar gravity, in cgs units - - rebin: boolean - If true, rebins the atmospheres so that they are the same - resolution as the Castelli+04 atmospheres. Default is False, - which is often sufficient synthetic photometry in most cases. - """ - if rebin == True: - atm_name = 'BTSettl_2015_rebin' - else: - atm_name = 'BTSettl_2015' - - try: - sp = pysynphot.Icat(atm_name, temperature, metallicity, gravity) - except: - # Check atmosphere catalog bounds - (temperature, gravity) = get_atmosphere_bounds(atm_name, - metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - sp = pysynphot.Icat(atm_name, temperature, metallicity, gravity) - #print(dir(obj)) - - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find BTSettl_2015 atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_BTSettl_atmosphere(metallicity=0, temperature=2500, gravity=4.5, rebin=True): - """ - Return atmosphere from CIFIST2011 grid - (`Allard et al. 2012 `_) - - Grid originally downloaded `here `_ - - Notes - ------ - Grid Range: - - * [M/H] = -2.5, -2.0, -1.5, -1.0, -0.5, 0, 0.5 - - Teff and gravity ranges depend on metallicity: - - [M/H] = -2.5 - - * Teff: 2600 - 4600 K - * gravity: 4.5 - 5.5 - - [M/H] = -2.0 - - * Teff: 2600 - 7000 - * gravity: 4.5 - 5.5 - - [M/H] = -1.5 - - * Teff: 2600 - 7000 - * gravity: 4.5 - 5.5 - - [M/H] = -1.0 - - * Teff: 2600 - 7000 - * gravity: Teff < 3200 --> 4.5 - 5.5; Teff > 3200 --> 2.5 - 5.5 - - [M/H] = -0.5 - - * Teff: 1000 -7000 - * gravity: Teff < 3000 --> 4.5 - 5.5; Teff > 3000 --> 3.0 - 6.0 - - [M/H] = 0 - - * Teff: 750 - 7000 - * gravity: Teff < 2500 --> 3.5 - 5.5; Teff > 2500 --> 0 - 5.5 - - [M/H] = 0.5 - - * Teff: 1000 - 5000 - * gravity: 3.5 - 5.0 - - - Alpha enhancement: - - * [M/H]= -0.0, +0.5 no anhancement - * [M/H]= -0.5 with [alpha/H]=+0.2 - * [M/H]= -1.0, -1.5, -2.0, -2.5 with [alpha/H]=+0.4 - - Parameters - ---------- - metallicity: float - The stellar metallicity, in terms of [Z] - - temperature: float - The stellar temperature, in units of K - - gravity: float - The stellar gravity, in cgs units - - rebin: boolean - If true, rebins the atmospheres so that they are the same - resolution as the Castelli+04 atmospheres. Default is False, - which is often sufficient synthetic photometry in most cases. - - **PRINT STATEMENTS TO DEBUG - **check get_atmosphere_bounds - **comment out try/except clause and check break - """ - if rebin == True: - atm_name = 'BTSettl_rebin' - else: - atm_name = 'BTSettl' - - try: - sp = pysynphot.Icat(atm_name, temperature, metallicity, gravity) - except: - # Check atmosphere catalog bounds - (temperature, gravity) = get_atmosphere_bounds(atm_name, - metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - sp = pysynphot.Icat(atm_name, temperature, metallicity, gravity) - -def get_Meisner2023_atmosphere(metallicity=0, temperature=1000, gravity=4.5, rebin=True): - """ - Return atmosphere from Meisner2023 grid - (`Meisner et al. 2023 `_) - - Grid originally downloaded `here `_ - - Grid range: - * Teff = 250 - 1200 K - * gravity: 2.5 - 5.5 cgs (in steps of 0.5) - * [M/H] = -1.0, -0.5, 0, +0, +0.3 - - """ - if rebin == True: - atm_name = 'Meisner2023_rebin' - else: - atm_name = 'Meisner2023' - - try: - sp = pysynphot.Icat(atm_name, temperature, metallicity, gravity) - except: - # Check atmosphere catalog bounds - (temperature, gravity) = get_atmosphere_bounds(atm_name, - metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - sp = pysynphot.Icat(atm_name, temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find Meisner2023 atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_Phillips2020_atmosphere(metallicity=0, temperature=1000, gravity=4.5, rebin=True): - """ - Return atmosphere from Phillips et al., 2020 using ATMO model - (`Phillips et al. 2020 `_) - - Grid originally downloaded `here `_ - - Grid Range: - * Teff: 200 - 3000 K - * gravity: 2.5 - 5.5 cgs - * [M/H] = 0 - """ - if rebin == True: - atm_name = 'Phillips2020_rebin' - else: - atm_name = 'Phillips2020' - - try: - sp = pysynphot.Icat(atm_name, temperature, metallicity, gravity) - except: - # Check atmosphere catalog bounds - (temperature, gravity) = get_atmosphere_bounds(atm_name, - metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - sp = pysynphot.Icat(atm_name, temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find Phillips2020 atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_wdKoester_atmosphere(metallicity=0, temperature=20000, gravity=7): - """ - Return white dwarf atmospheres from - `Koester et al. 2010 `_ - - Parameters - ---------- - metallicity: float - The stellar metallicity, in terms of [Z] - - temperature: float - The stellar temperature, in units of K - - gravity: float - The stellar gravity, in cgs units - - rebin: boolean - If true, rebins the atmospheres so that they are the same - resolution as the Castelli+04 atmospheres. Default is False, - which is often sufficient synthetic photometry in most cases. - """ - sp = pysynphot.Icat('wdKoester', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find WD Koester (Koester+ 2010 atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_atlas_phoenix_atmosphere(metallicity=0, temperature=5250, gravity=4): - """ - Return atmosphere that is a linear merge of atlas ck04 model and phoenixV16. - - Only valid for temps between 5000 - 5500K, gravity from 0 = 5.0 - """ - try: - sp = pysynphot.Icat('merged_atlas_phoenix', temperature, metallicity, gravity) - except: - # Check atmosphere catalog bounds - (temperature, gravity) = get_atmosphere_bounds('merged_atlas_phoenix', - metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - sp = pysynphot.Icat('merged_atlas_phoenix', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find ATLAS-PHOENIX merge atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_BTSettl_phoenix_atmosphere(metallicity=0, temperature=5250, gravity=4): - """ - Return atmosphere that is a linear merge of BTSettl_CITFITS2011_2015 model - and phoenixV16. - - Only valid for temps between 3200 - 3800K, gravity from 2.5 - 5.5 - """ - try: - sp = pysynphot.Icat('merged_BTSettl_phoenix', temperature, metallicity, gravity) - except: - # Check atmosphere catalog bounds - (temperature, gravity) = get_atmosphere_bounds('merged_BTSettl_phoenix', - metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - sp = pysynphot.Icat('merged_BTSettl_phoenix', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find ATLAS-PHOENIX merge atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_BTSettl_meisner_atmosphere(metallicity=0, temperature=5250, gravity=4): - """ - Return atmosphere that is a linear merge of BTSettl_CITFITS2011_2015 model - and Meisner2023. - - Only valid for temps between 1000 - 1200K, gravity from 3.5 - 5.5 - """ - try: - sp = pysynphot.Icat('merged_BTSettl_meisner', temperature, metallicity, gravity) - except: - # Check atmosphere catalog bounds - (temperature, gravity) = get_atmosphere_bounds('merged_BTSettl_meisner', - metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - sp = pysynphot.Icat('merged_BTSettl_meisner', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find BTSettl-Meisner merge atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -#---------------------------------------------------------------------# -def get_merged_atmosphere(metallicity=0, temperature=20000, gravity=4.5, verbose=False, - rebin=True): - """ - Return a stellar atmosphere from a suite of different model grids, - depending on the input temperature, (all values in K). - - Parameters - ---------- - metallicity: float - The stellar metallicity, in terms of [Z] - - temperature: float - The stellar temperature, in units of K - - gravity: float - The stellar gravity, in cgs units - - rebin: boolean - If true, rebins the atmospheres so that they are the same - resolution as the Castelli+04 atmospheres. Default is False, - which is often sufficient synthetic photometry in most cases. - - verbose: boolean - True for verbose output - - Notes - ----- - The underlying stellar model grid used changes as a function of - stellar temperature (in K): - - * T > 20,000: ATLAS - * 5500 <= T < 20,000: ATLAS - * 5000 <= T < 5500: ATLAS/PHOENIXv16 merge - * 3800 <= T < 5000: PHOENIXv16 - - For T < 3800, there is an additional gravity and metallicity - dependence: - - If T < 3800 and [M/H] = 0: - - * T < 3800, logg < 2.5: PHOENIX v16 - * 3200 <= T < 3800, logg > 2.5: BTSettl_CIFITS2011_2015/PHOENIXV16 merge - * 3200 < T <= 1200, logg > 2.5: BTSettl_CIFITS2011_2015 - * 1200 < T <= 1000, logg >= 3.5: BTSettl_CIFITS2011_2015/Meisner2023 merge - * 1000 < T <= 250, logg > 2.5: Meisner2023 - - Otherwise, if T < 3800 and [M/H] != 0: - - * T < 3800: PHOENIX v16 - - References: - - * ATLAS: ATLAS9 models (`Castelli & Kurucz 2004 `_) - * PHOENIXv16 (`Husser et al. 2013 `_) - * BTSettl_CIFITS2011_2015: Baraffee+15, Allard+ (https://phoenix.ens-lyon.fr/Grids/BT-Settl/CIFIST2011_2015/SPECTRA/) - * Meisner2023: ATMO 1D models (`Meisner et al. 2023 `_) - - LTE WARNING: - - The ATLAS atmospheres are calculated with LTE, and so they - are less accurate when non-LTE conditions apply (e.g. T > 20,000 - K). Ultimately we'd like to add a non-LTE atmosphere grid for - the hottest stars in the future. - - HOW BOUNDARIES BETWEEN MODELS ARE TREATED: - - At the boundary between two models grids a temperature range is defined - where the resulting atmosphere is a weighted average between the two - grids. Near one boundary one model - is weighted more heavily, while at the other boundary the other - model is weighted more heavily. These are calculated in the - temperature ranges where we switch between model grids, to - ensure a smooth transition. - """ - # For T < 3800, atmosphere depends on metallicity + gravity. - # If solar metallicity, use BTSettl 2015 grid. Only solar metallicity is - # currently available here, so if non-solar metallicity, just stick with - # the Phoenix grid - if (temperature < 1000): - if verbose: - print( 'Meisner2023 atmosphere') - return get_Meisner2023_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity, - rebin=rebin) - - if (temperature <= 1200) & (temperature >= 1000): - if (gravity >= 3.5): - if verbose: - print( 'BTSettl/Meisner2023 merged atmosphere') - return get_Meisner2023_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity, - rebin=rebin) - if (gravity < 3.5) & (gravity >=2.5): - if verbose: - print( 'Meisner2023 atmosphere') - return get_Meisner2023_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity, - rebin=rebin) - - if (temperature <= 3800) & (metallicity == 0): - # High gravity are in BTSettl regime - if (temperature <= 3200) & (gravity > 2.5): - if verbose: - print( 'BTSettl_2015 atmosphere') - return get_BTSettl_2015_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity, - rebin=rebin) - - if (temperature >= 3200) & (temperature < 3800) & (gravity > 2.5): - if verbose: - print( 'BTSettl/Phoenixv16 merged atmosphere') - return get_BTSettl_phoenix_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - # Low gravity is PHOENIX regime - if gravity <= 2.5: - if verbose: - print( 'Phoenixv16 atmosphere') - return get_phoenixv16_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity, - rebin=rebin) - - if (temperature <= 3800) & (metallicity != 0): - if verbose: - print( 'Phoenixv16 atmosphere') - return get_phoenixv16_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity, - rebin=rebin) - - # For T > 3800, no metallicity or gravity dependence - if (temperature >= 3800) & (temperature < 5000): - if verbose: - print( 'Phoenixv16 atmosphere') - return get_phoenixv16_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity, - rebin=rebin) - - if (temperature >= 5000) & (temperature < 5500): - if verbose: - print( 'ATLAS/Phoenix merged atmosphere') - return get_atlas_phoenix_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - if (temperature >= 5500) & (temperature < 20000): - if verbose: - print( 'ATLAS merged atmosphere') - return get_castelli_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - if temperature >= 20000: - if verbose: - print( 'Still ATLAS merged atmosphere') - return get_castelli_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - #print('CMFGEN') - #return get_cmfgenRot_atmosphere_closest(metallicity=metallicity, - # temperature=temperature, - # gravity=gravity) - - - - -def get_wd_atmosphere(metallicity=0, temperature=20000, gravity=4, verbose=False): - """ - Return the white dwarf atmosphere from - `Koester et al. 2010 `_. - If desired parameters are - outside of grid, return a blackbody spectrum instead - - Parameters - ---------- - metallicity: float - The stellar metallicity, in terms of [Z] - - temperature: float - The stellar temperature, in units of K - - gravity: float - The stellar gravity, in cgs units - - rebin: boolean - If true, rebins the atmospheres so that they are the same - resolution as the Castelli+04 atmospheres. Default is False, - which is often sufficient synthetic photometry in most cases. - - verbose: boolean - True for verbose output - """ - try: - if verbose: - print('wdKoester atmosphere') - - return get_wdKoester_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - except pysynphot.exceptions.ParameterOutOfBounds: - # Use a black-body atmosphere. - bbspec = get_bb_atmosphere(temperature=temperature, verbose=verbose) - return bbspec - - -def get_bd_atmosphere(metallicity=0, temperature=1000, gravity=4, verbose=False): - """ - Return the brown dwarf atmosphere from - `Meisner et al. 2023 `_. - If desired parameters are - outside of grid, return a blackbody spectrum instead - - Parameters - ---------- - metallicity: float - The stellar metallicity, in terms of [Z] - - temperature: float - The stellar temperature, in units of K - - gravity: float - The stellar gravity, in cgs units - - rebin: boolean - If true, rebins the atmospheres so that they are the same - resolution as the Castelli+04 atmospheres. Default is False, - which is often sufficient synthetic photometry in most cases. - - verbose: boolean - True for verbose output - """ - try: - if verbose: - print('Meisner2023 atmosphere') - - return get_Meisner2023_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - except pysynphot.exceptions.ParameterOutOfBounds: - # Use a black-body atmosphere - bbspec = get_bb_atmosphere(temperature=temperature, verbose=verbose) - return bbspec - -def get_bb_atmosphere(metallicity=None, temperature=20_000, gravity=None, - verbose=False, rebin=None, - wave_min=500, wave_max=50_000, wave_num=20_000): - """ - Return a blackbody spectrum - - Parameters - ---------- - temperature: float, default=20_000 - The stellar temperature, in units of K - wave_min: float, default=500 - Sets the minimum wavelength (in Angstroms) of the wavelength range - for the blackbody spectrum - wave_max: float, default=50_000 - Sets the maximum wavelength (in Angstroms) of the wavelength range - for the blackbody spectrum - wave_num: int, default=20_000 - Sets the number of wavelength points in the wavelength range - Note: the wavelength range is evenly spaced in log space - """ - if ((metallicity is not None) or (gravity is not None) or - (rebin is not None)): - warnings.warn( - 'Only `temperature` keyword is used for black-body atmosphere' - ) - - if verbose: - print('Black-body atmosphere') - - # Modify pysynphot's default waveset to specified bounds - pysynphot.refs.set_default_waveset( - minwave=wave_min, maxwave=wave_max, num=wave_num - ) - - # Get black-body atmosphere for specified temperature from pysynphot - bbspec = pysynphot.spectrum.BlackBody(temperature) - - # pysynphot `BlackBody` generates spectrum in `photlam`, need in `flam` - bbspec.convert('flam') - - # `BlackBody` spectrum is normalized to solar radius star at 1 kiloparsec. - # Need to remove this normalization for SPISEA by multiplying bbspec - # by (1000 * 1 parsec / 1 Rsun)**2 = (1000 * 3.08e18 cm / 6.957e10 cm)**2 - bbspec *= (1000 * 3.086e18 / 6.957e10)**2 - - return bbspec - - -#--------------------------------------# -# Atmosphere formatting functions -#--------------------------------------# - -def download_CMFGEN_atmospheres(Table_rot, Table_norot): - """ - Downloads CMFGEN models from - https://sites.google.com/site/fluxesandcontinuum/home; - these contain continuum as well as lines. - - Table_rot, Table_norot are tables with the file prefixes - and model atmosphere parameters, taken by hand from the - Fierro+15 paper - - Website addresses are hardcoded - - Puts downloaded models in the current working directory. - """ - print( 'WARNING: THIS DOES NOT COMPLETELY WORK') - print( '**********************') - t_rot = Table.read(Table_rot, format='ascii') - t_norot = Table.read(Table_norot, format='ascii') - - tables = [t_rot, t_norot] - filenames = [t_rot['col1'], t_norot['col1']] - - # Hardcoded list of webiste addresses - web_base1 = 'https://sites.google.com/site/fluxesandcontinuum/home/' - web_base2 = 'https://sites.google.com/site/modelsobmassivestars/' - web = [web_base1+'009-solar-masses/',web_base1+'012-solar-masses/', - web_base1+'015-solar-masses/',web_base1+'020-solar-masses/', - web_base1+'025-solar-masses/',web_base2+'009-solar-masses-tracks/', - web_base2+'040-solar-masses/',web_base2+'060-solar-masses/', - web_base1+'085-solar-masses/',web_base1+'120-solar-masses/'] - # Array of masses that matches the website addresses - mass_arr = np.array([9.,12.,15.,20.,25.,32.,40.,60.,85.,120.]) - - # Loop through rotating and unrotating case. First loop is rot, second unrot - for i in range(2): - # Extract masses from filenames - masses = [] - for j in filenames[i]: - tmp = j.split('m') - mass = float(tmp[1][:-1]) - masses.append(mass) - - # Download the models webpage by webpage. A bit tricky because masses - # change slightly within a particular website. THIS IS WHAT FAILS - for j in range(len(web)): - if j == 0: - good = np.where( (masses <= mass_arr[j]) ) - else: - g = j - 1 - good = np.where( (masses <= mass_arr[j]) & - (masses > mass_arr[g]) ) - # Use wget command to pull down the files, and unzip them - for k in good[0]: - full = web[j]+'{1:s}.flx.zip'.format(mass_arr[j],filenames[i][k]) - os.system('wget ' + full) - os.system('unzip '+ filenames[i][k] + '.flx.zip') - - return - -def organize_CMFGEN_atmospheres(path_to_dir): - """ - Organize CMFGEN grid from Fierro+15 - (http://www.astroscu.unam.mx/atlas/index.html) - into rot and noRot directories - - path_to_dir is from current working directory to directory - containing the downloaded models. Assumed that models - and tables describing parameters are in this directory. - - Tables describing parameters MUST be named Table_rot.txt, - Table_noRot.txt. Made by hand from Tables 3, 4 in Fierro+15. - These are located in same original directory as atmosphere files - - Will separate files into 2 subdirectories, one rotating and - the other non-rotating - - *Can't have any other files starting with "t" in model directory to start!* - """ - # First, record current working directory to return to later - start_dir = os.getcwd() - - # Enter atmosphere directory, collect rotating and non-rotating - # file names (assumed to all start with "t") - os.chdir(path_to_dir) - rot_models = glob.glob("t*r.flx*") - noRot_models = glob.glob("t*n.flx*") - - # Separate into different subdirectories - if os.path.exists('cmfgenF15_rot'): - pass - else: - os.mkdir('cmfgenF15_rot') - os.mkdir('cmfgenF15_noRot') - - for mod in rot_models: - cmd = 'mv {0:s} cmfgenF15_rot'.format(mod) - os.system(cmd) - - for mod in noRot_models: - cmd = 'mv {0:s} cmfgenF15_noRot'.format(mod) - os.system(cmd) - - # Also move Tables with model parameters into correct directory - os.system('mv Table_rot.txt cmfgenF15_rot') - os.system('mv Table_noRot.txt cmfgenF15_noRot') - - # Return to original directory - os.chdir(start_dir) - - return - -def make_CMFGEN_catalog(path_to_dir): - """ - Create cdbs catalog.fits of CMFGEN grid from Fierro+15 - (http://www.astroscu.unam.mx/atlas/index.html). - THIS IS STEP 2, after organize_CMFGEN_atmospheres has - been run. - - path_to_dir is from current working directory to directory - containing the rotating or non-rotating models (i.e. cmfgenF15_rot). Also, - needs to be a Table*.txt file which contains the parameters for all of the - original models, since params in filename are not precise enough - - Will create catalog.fits file in atmosphere directory with - description of each model - - *Can't have any other files starting with "t" in model directory to start!* - """ - # Record current working directory for later - start_dir = os.getcwd() - - # Enter atmosphere directory - os.chdir(path_to_dir) - - # Extract parameters for each atmosphere - # Note: can't rely on filename for this because not precise enough!! - - #---------OLD: GETTING PARAMS FROM FILENAME-------# - # Collect file names (assumed to all start with "t") - #files = glob.glob("t*") - #for name in files: - # tmp = name.split('l') - # temp = float(tmp[0][1:]) * 100.0 # In kelvin - - # lumtmp = tmp[1].split('_') - # lum = float(lumtmp[0][:-5]) * 1000.0 # In L_sun - - # mass = float(lumtmp[0][5:-1]) # In M_sun - - # Need to calculate log g from T and L (cgs) - # lum_sun = 3.846 * 10**33 # erg/s - # M_sun = 2 * 10**33 # g - # G_si = 6.67 * 10**(-8) # cgs - # sigma_si = 5.67 * 10**(-5) # cgs - - # g = (G_si * mass * M_sun * 4 * np.pi * sigma_si * temp**4) / \ - # (lum * lum_sun) - # logg = np.log10(g) - #---------------------------------------------------# - - # Read table with atmosphere params - table = glob.glob('Table_*') - t = Table.read(table[0], format = 'ascii') - names = t['col1'] - temps = t['col2'] - logg = t['col4'] - - # Create catalog.fits file - index_str = [] - name_str = [] - for i in range(len(names)): - index = '{0:5.0f},0.0,{1:3.2f}'.format(temps[i], logg[i]) - - #---NOTE: THE FOLLOWING DEPENDS ON FINAL LOCATION OF CATALOG FILE---# - #path = path_to_dir + '/' + names[i] - path = names[i] + '.fits[Flux]' - - index_str.append(index) - name_str.append(path) - - catalog = Table([index_str, name_str], names = ('INDEX', 'FILENAME')) - - # Create catalog.fits file in directory with the models - catalog.write('catalog.fits', format = 'fits') - - # Move back to original directory, create the catalog.fits file - os.chdir(start_dir) - - return - -def cdbs_cmfgen(path_to_dir, path_to_cdbs_dir): - """ - Code to put cmfgen models into cdbs format and adds proper unit keyword in - fits header. Save as fits file - - path_to_dir goes from current directory to cmfgen_rot or cmfgen_norot - directory with the *.flx models. Note that these files have already been - organized using organize_CMFGEN_atmospheres code. - - path_to_cdbs_dir goes from current directory to cdbs/grid/cmfgen_rot or - cmfgen_norot directory. Will copy new fits files to this directory. - This directory must already exist! - """ - # Save starting directory for later, move into path_to_dir directory - start_dir = os.getcwd() - os.chdir(path_to_dir) - - # Collect the filenames, make necessary changes to each one - files = glob.glob('*.flx') - - # Need to make brand-new fits tables with data we want. - counter = 0 - for i in files: - counter += 1 - # Open file, extract useful info - t = Table.read(i, format='ascii') - wave = t['col1'] - flux = t['col2'] # Flux is already in erg/cm^2/s/A - - # Need to eliminate duplicate entries (pysynphot crashes) - unique = np.unique(wave, return_index=True) - wave = wave[unique[1]] - flux = flux[unique[1]] - - # Make fits table from individual columns. - c0 = fits.Column(name='Wavelength', format='D', array=wave) - c1 = fits.Column(name='Flux', format='E', array=flux) - - cols = fits.ColDefs([c0, c1]) - tbhdu = fits.BinTableHDU.from_columns(cols) - - #Adding unit keywords - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - - prihdu = fits.PrimaryHDU() - - finalhdu = fits.HDUList([prihdu, tbhdu]) - finalhdu.writeto(i[:-4]+'.fits', overwrite=True) - - print( 'Done {0:2.0f} of {1:2.0f}'.format(counter, len(files))) - - # Return to original directory, copy over new .fits files to cdbs directory - os.chdir(start_dir) - cmd = 'mv {0:s}/*.fits {1:s}'.format(path_to_dir, path_to_cdbs_dir) - os.system(cmd) - - return - -def rebin_cmfgen(cdbs_path, rot=True): - """ - Rebin cmfgen_rot and cmfgen_norot models to atlas ck04 resolution; - this makes spectrophotometry MUCH faster - - cdbs_path: path to cdbs directory - rot=True for rotating models (cmfgen_rot), False for non-rotating models - - makes new directory in cdbs/grid: cmfgen_rot_rebin or cmfgen_norot_rebin - """ - # Get an atlas ck04 model, we will use this to set wavelength grid - sp_atlas = get_castelli_atmosphere() - - # Open a fits table for an existing cmfgen model; we will steal the header. - # Also define paths to new rebin directories - if rot == True: - tmp = cdbs_path+'/grid/cmfgen_rot/t0200l0008m009r.fits' - path = cdbs_path+'/grid/cmfgen_rot_rebin/' - orig_path = cdbs_path+'/grid/cmfgen_rot/' - else: - tmp = cdbs_path+'/grid/cmfgen_norot/t0200l0007m009n.fits' - path = cdbs_path+'/grid/cmfgen_norot_rebin/' - orig_path = cdbs_path+'/grid/cmfgen_norot/' - - cmfgen_hdu = fits.open(tmp) - header0 = cmfgen_hdu[0].header - # Create rebin directories if they don't already exist. Copy over - # catalog.fits file from original directory (will be the same) - if not os.path.exists(path): - os.mkdir(path) - cmd = 'cp {0:s}catalog.fits {1:s}'.format(orig_path, path) - os.system(cmd) - - # Read in the catalog.fits file - cat = fits.getdata(orig_path + 'catalog.fits') - files_all = [cat[ii][1].split('[')[0] for ii in range(len(cat))] - - # First column in new files will be for [atlas] wavelength - c0 = fits.Column(name='Wavelength', format='D', array=sp_atlas.wave) - - # For each catalog.fits entry, read the unbinned spectrum and rebin to - # the atlas resolution. Make a new fits file in rebin directory - count = 0 - for ff in range(len(files_all)): - count += 1 - # Extract the temp, Z, logg - vals = cat[ff][0].split(',') - temp = float(vals[0]) - metal = float(vals[1]) - grav = float(vals[2]) - - # Fetch the spectrum - if rot == True: - sp = pysynphot.Icat('cmfgen_rot', temp, metal, grav) - else: - sp = pysynphot.Icat('cmfgen_norot', temp, metal, grav) - - # Rebin - flux_rebin = rebin_spec(sp.wave, sp.flux, sp_atlas.wave) - c1 = fits.Column(name='Flux', format='E', array=flux_rebin) - - # Make the FITS file from the columns with header - cols = fits.ColDefs([c0,c1]) - tbhdu = fits.BinTableHDU.from_columns(cols) - prihdu = fits.PrimaryHDU(header=header0) - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - - # Write hdu to new directory with same filename - finalhdu = fits.HDUList([prihdu, tbhdu]) - finalhdu.writeto(path+files_all[ff]) - - print( 'Finished file {0} of {1}'.format(count, len(files_all)) ) - return - - -def organize_PHOENIXv16_atmospheres(path_to_dir, met_str='m00'): - """ - Construct the Phoenix Husser+13 atmopsheres for each model. Combines the - fluxes from the *HiRES.fits files and the wavelengths of the - WAVE_PHONEIX-ACES-AGSS-COND-2011.fits file. - - path_to_dir is the path to the directory containing all of the downloaded - files - - met_str is the name of the current metallicity - - Creates new fits files for each atmosphere: phoenix_.fits, - which contains columns for the log g (column header = g#.#). Puts - atmospheres in new directory phoenixm00 - """ - # Save current directory for return later, move into working dir - start_dir = os.getcwd() - os.chdir(path_to_dir) - - # If it doesn't already exist, create the current metallicity subdirectory - sub_dir = '../phoenix{0}'.format(met_str) - if os.path.exists(sub_dir): - pass - else: - os.mkdir(sub_dir) - - # Extract wavelength array, make column for later - wavefile = fits.open('WAVE_PHOENIX-ACES-AGSS-COND-2011.fits') - wave = wavefile[0].data - wavefile.close() - wave_col = Column(wave, name = 'WAVELENGTH') - - # Create temp array for Husser+13 grid (given in paper) - temp_arr = np.arange(2300, 7001, 100) - temp_arr = np.append(temp_arr, np.arange(7000, 12001, 200)) - - print( 'Looping though all temps') - # For each temp, build file containing the flux for all gravities - i = 0 - for temp in temp_arr: - files = glob.glob('lte{0:05d}-*-HiRes.fits'.format(temp)) - files.sort() - # Start the table with the wavelength column - t = Table() - t.add_column(wave_col) - for f in files: - # Extract the logg out of filename - logg = f[9:13] - - # Extract fluxes from file - spectrum = fits.open(f) - flux = spectrum[0].data - spectrum.close() - - # Make Column object with fluxes, add to table - col = Column(flux, name = 'g{0:2.1f}'.format(float(logg))) - t.add_column(col) - - # Now, construct final fits file for the given temp - outname = 'phoenix{0}_{1:05d}.fits'.format(met_str, temp) - t.write('{0}/{1}'.format(sub_dir, outname), format = 'fits', overwrite = True) - - # Progress counter for user - i += 1 - print( 'Done {0:d} of {1:d}'.format(i, len(temp_arr))) - - # Return to original directory - os.chdir(start_dir) - return - -def make_PHOENIXv16_catalog(path_to_dir, met_str='m00'): - """ - Makes catalog.fits file for Husser+13 phoenix models. Assumes that - organize_PHOENIXv16_atmospheres has been run already, and that the models lie - in subdirectory phoenix[met_str]. - - path_to_directory is the path to the directory with the reformatted - models (i.e. the output from construct_atmospheres, phoenix[met_str]) - - Puts catalog.fits file in directory the user starts in - """ - # Save starting directory for later, move into working directory - start_dir = os.getcwd() - os.chdir(path_to_dir) - - # Extract metallicity from metallicity string - met = float(met_str[1]) + (float(met_str[2]) * 0.1) - if 'm' in met_str: - met *= -1. - - # Collect the filenames. Each is a unique temp with many different log g's - files = glob.glob('phoenix*.fits') - files.sort() - - # Create the catalog.fits file, row by row - index_arr = [] - filename_arr = [] - for i in files: - # Get log g values from the column header the file - t = Table.read(i, format='fits') - keys = t.keys() - logg_vals = keys[1:] - - # Extract temp from filename - name = i.split('_') - temp = float(name[1][:-5]) - for j in logg_vals: - logg = float(j[1:]) - index = '{0:5.0f},{1:2.1f},{2:2.1f}'.format(temp, met, logg) - filename = path_to_dir + i + '[' + j + ']' - # Add row to table - index_arr.append(index) - filename_arr.append(filename) - - catalog = Table([index_arr, filename_arr], names=('INDEX', 'FILENAME')) - - # Return to starting directory, write catalog - os.chdir(start_dir) - - if os.path.exists('catalog.fits'): - from astropy.table import vstack - - prev_catalog = Table.read('catalog.fits', format='fits') - joined_catalog = vstack([prev_catalog, catalog]) - - joined_catalog.write('catalog.fits', format='fits', overwrite=True) - else: - catalog.write('catalog.fits', format='fits', overwrite=True) - - return - -def cdbs_PHOENIXv16(path_to_cdbs_dir): - """ - Put the PHOENIXv16 (Husser+13) fits files into cdbs format. This primarily - consists of adjusting the flux units from [erg/s/cm^2/cm] to [erg/s/cm^2/A] - and adding the appropriate keywords to the fits header. - - path_to_cdbs_dir goes from current working directory to phoenix[met] directory - in cdbs/grids/phoenix_v16. Note that these files have already been organized - using organize_PHOENIXv16_atmospheres code. - - Overwrites original files in directory - """ - # Save starting directory for later, move into working directory - start_dir = os.getcwd() - os.chdir(path_to_cdbs_dir) - - # Collect the filenames, make necessary changes to each one - files = glob.glob('phoenix*.fits') - - ## Need to sort filenames; glob doesn't always give them in order - files.sort() - - # Need to make brand-new fits tables with data we want. - counter = 0 - for i in files: - counter += 1 - - # Read in current FITS table - cur_table = Table.read(i, format='fits') - - cur_table.columns[0].name = 'Wavelength' - - num_cols = len(cur_table.colnames) - - # Multiplying each flux column by 10^-8 for conversion - for cur_col_index in range(1, num_cols, 1): - cur_col_name = cur_table.colnames[cur_col_index] - cur_table[cur_col_name] = cur_table[cur_col_name] * 10.**-8 - - - # Construct new FITS file based on old one - hdu = fits.open(i) - header_0 = hdu[0].header - header_1 = hdu[1].header - sci = hdu[1].data - - tbhdu = fits.table_to_hdu(cur_table) - - # Copying over the older headers, adding unit keywords - prihdu = fits.PrimaryHDU(header=header_0) - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - tbhdu.header['TUNIT3'] = 'FLAM' - tbhdu.header['TUNIT4'] = 'FLAM' - tbhdu.header['TUNIT5'] = 'FLAM' - tbhdu.header['TUNIT6'] = 'FLAM' - tbhdu.header['TUNIT7'] = 'FLAM' - tbhdu.header['TUNIT8'] = 'FLAM' - tbhdu.header['TUNIT9'] = 'FLAM' - tbhdu.header['TUNIT10'] = 'FLAM' - tbhdu.header['TUNIT11'] = 'FLAM' - tbhdu.header['TUNIT12'] = 'FLAM' - tbhdu.header['TUNIT13'] = 'FLAM' - tbhdu.header['TUNIT14'] = 'FLAM' - - # Construct and write out final FITS file - finalhdu = fits.HDUList([prihdu, tbhdu]) - finalhdu.writeto(i, overwrite=True) - - hdu.close() - print( 'Done {0:2.0f} of {1:2.0f}'.format(counter, len(files))) - - # Change back to starting directory - os.chdir(start_dir) - - return - -def rebin_phoenixV16(cdbs_path): - """ - Rebin phoenixV16 models to atlas ck04 resolution; this makes - spectrophotometry MUCH faster - - makes new directory in cdbs/grid: phoenix_v16_rebin - - cdbs_path: path to cdbs directory - """ - # Get an atlas ck04 model, we will use this to set wavelength grid - sp_atlas = get_castelli_atmosphere() - - # Open a fits table for an existing phoenix model; we will steal the header - ## (This assumes that at least 'm00' metallicity exists) - tmp = '{0}/grid/phoenix_v16/phoenix{1}/phoenix{1}_02400.fits'.format(cdbs_path, 'm00') - phoenix_hdu = fits.open(tmp) - header0 = phoenix_hdu[0].header - - # Create cdbs/grid directory for rebinned models - path = cdbs_path+'/grid/phoenix_v16_rebin/' - if not os.path.exists(path): - os.mkdir(path) - - - # Read in the existing catalog.fits file and rebin every spectrum. - cat = fits.getdata(cdbs_path + '/grid/phoenix_v16/catalog.fits') - files_all = [cat[ii][1].split('[')[0] for ii in range(len(cat))] - temp_arr = np.zeros(len(files_all), dtype=float) - logg_arr = np.zeros(len(files_all), dtype=float) - metal_arr = np.zeros(len(files_all), dtype=float) - - for ff in range(len(files_all)): - vals = cat[ff][0].split(',') - - temp_arr[ff] = float(vals[0]) - metal_arr[ff] = float(vals[1]) - logg_arr[ff] = float(vals[2]) - - - metal_uniq = np.unique(metal_arr) - temp_uniq = np.unique(temp_arr) - - for mm in range(len(metal_uniq)): - metal = metal_uniq[mm] # metallicity - - # Construct str for metallicity (for appropriate directory name) - met_str = str(int(np.abs(metal))) + str(int((metal % 1.0)*10)) - if metal > 0: - met_str = 'p' + met_str - else: - met_str = 'm' + met_str - - # Make directory for current metallicity if it does not exist yet - if not os.path.exists(path + 'phoenix' + met_str): - os.mkdir(path + 'phoenix' + met_str) - - for tt in range(len(temp_uniq)): - temp = temp_uniq[tt] # temperature - - # Pick out the list of gravities for this T, Z combo - idx = np.where((metal_arr == metal) & (temp_arr == temp))[0] - logg_exist = logg_arr[idx] - - # All gravities will go in one file. Here is the output - # file name. - outfile = path + files_all[idx[0]].split('[')[0] - - ## If the rebinned file already exists, continue - if os.path.exists(outfile): - continue - - # Build a columns array. One column for each gravity. - cols_arr = [] - - # Make the wavelength column, which is first in the cols array. - c0 = fits.Column(name='Wavelength', format='D', array=sp_atlas.wave) - cols_arr.append(c0) - - for gg in range(len(logg_exist)): - grav = logg_exist[gg] # gravity - - # Fetch the spectrum - sp = pysynphot.Icat('phoenix_v16', temp, metal, grav) - flux_rebin = rebin_spec(sp.wave, sp.flux, sp_atlas.wave) - - # Store the spectrum - name = 'g{0:3.1f}'.format(grav) - col = fits.Column(name=name, format='E', array=flux_rebin) - cols_arr.append(col) - - - # Make the FITS file from the columns with header. - cols = fits.ColDefs(cols_arr) - tbhdu = fits.BinTableHDU.from_columns(cols) - prihdu = fits.PrimaryHDU(header=header0) - tbhdu.header['TUNIT1'] = 'ANGSTROM' - for gg in range(len(logg_exist)): - tbhdu.header['TUNIT{0:d}'.format(gg+2)] = 'FLAM' - - # Write hdu - finalhdu = fits.HDUList([prihdu, tbhdu]) - # don't have overwrite to protect original files. - finalhdu.writeto(outfile) - - print( 'Finished file ' + outfile + ' with gravities: ', logg_exist) - - - return - - -def rebin_spec(wave, specin, wavnew): - """ - Helper routine to rebin spectra. TAKEN FROM ASTROBETTER BLOG FROM JESSICA: - http://www.astrobetter.com/blog/2013/08/12/ - python-tip-re-sampling-spectra-with-pysynphot/ - """ - spec = pysynphot.spectrum.ArraySourceSpectrum(wave=wave, flux=specin) - f = np.ones(len(wave)) - filt = pysynphot.spectrum.ArraySpectralElement(wave, f, waveunits='angstrom') - obs = pysynphot.observation.Observation(spec, filt, binset=wavnew, force='taper') - - return obs.binflux - -def organize_BTSettl_2015_atmospheres(path_to_dir): - """ - Construct cdbs-ready BTSettl_CIFITS_2011_2015 atmospheres for each model. - Will convert wavelength units to angstroms and flux units to [erg/s/cm^2/A] - - path_to_dir is the path to the directory containing all of the downloaded - files - - Saves cdbs-ready atmospheres into os.environ['PYSYN_CDBS']/grid/BTSettl_2015 - (assumes this directory exists) - """ - # Save current directory for return later, move into working dir - start_dir = os.getcwd() - os.chdir(path_to_dir) - - # If it doesn't already exist, create the BTSettl subdirectory - if not os.path.exists('BTSettl_2015'): - os.mkdir('BTSettl_2015') - - # Process each atmosphere file independently - print( 'Creating cdbs-ready files') - files = glob.glob('*.spec.fits') - - for i in files: - hdu = fits.open(i) - spec = hdu[1].data - header_0 = hdu[0].header - header_1 = hdu[1].header - - wave = spec.field(0) - flux = spec.field(1) - - # Get units right: convert wave from microns to Angstroms, - # flux from W /m^2/ micron to erg/s/cm^2/A - wave_new = wave * 10**4 - flux_new = flux * 10**(-1) - - # Make new fits table - c0 = fits.Column(name='Wavelength', format='D', array=wave_new) - c1 = fits.Column(name='Flux', format='E', array=flux_new) - - cols = fits.ColDefs([c0, c1]) - tbhdu = fits.BinTableHDU.from_columns(cols) - - # Copy over headers, update unit keywords - prihdu = fits.PrimaryHDU(header=header_0) - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - hdu_new = fits.HDUList([prihdu, tbhdu]) - - # Write new fits table in cdbs directory - hdu_new.writeto(os.environ['PYSYN_CDBS']+'grid/BTSettl_2015/'+i, overwrite=True) - - hdu.close() - hdu_new.close() - - # Return to original directory - os.chdir(start_dir) - return - -def make_BTSettl_2015_catalog(path_to_dir): - """ - Create cdbs catalog.fits of BTSettl_CIFITS2011_2015 grid. - THIS IS STEP 2, after organize_CMFGEN_atmospheres has - been run. - - path_to_dir is from current working directory to the cdbs directory. - Will create catalog.fits file in atmosphere directory with - description of each model - """ - # Record current working directory for later - start_dir = os.getcwd() - - # Enter atmosphere directory - os.chdir(path_to_dir) - - # Extract parameters for each atmosphere from the filename, - # construct columns for catalog file - files = glob.glob("*spec.fits") - index_str = [] - name_str = [] - for name in files: - tmp = name.split('-') - temp = float(tmp[0][3:]) * 100.0 # In kelvin - logg = float(tmp[1]) - - index_str.append('{0:5.0f},0.0,{1:3.2f}'.format(temp, logg)) - name_str.append('{0}[Flux]'.format(name)) - - # Make catalog - catalog = Table([index_str, name_str], names = ('INDEX', 'FILENAME')) - - # Create catalog.fits file in directory with the models - catalog.write('catalog.fits', format = 'fits', overwrite=True) - - # Move back to original directory, create the catalog.fits file - os.chdir(start_dir) - - return - -def rebin_BTSettl_2015(cdbs_path=os.environ['PYSYN_CDBS']): - """ - Rebin BTSettle_CIFITS2011_2015 models to atlas ck04 resolution; this makes - spectrophotometry MUCH faster - - makes new directory in cdbs/grid: BTSettl_2015_rebin - - cdbs_path: path to cdbs directory - """ - # Get an atlas ck04 model, we will use this to set wavelength grid - sp_atlas = get_castelli_atmosphere() - - # Open a fits table for an existing phoenix model; we will steal the header - tmp = cdbs_path+'/grid/phoenix_v16/phoenixm00/phoenixm00_02400.fits' - phoenix_hdu = fits.open(tmp) - header0 = phoenix_hdu[0].header - phoenix_hdu.close() - - # Create cdbs/grid directory for rebinned models - path = cdbs_path+'/grid/BTSettl_2015_rebin/' - if not os.path.exists(path): - os.mkdir(path) - - # Read in the existing catalog.fits file and rebin every spectrum. - cat = fits.getdata(cdbs_path + '/grid/BTSettl_2015/catalog.fits') - files_all = [cat[ii][1].split('[')[0] for ii in range(len(cat))] - - print( 'Rebinning BTSettl spectra') - for ff in range(len(files_all)): - vals = cat[ff][0].split(',') - temp = float(vals[0]) - metal = float(vals[1]) - logg = float(vals[2]) - - # Fetch the BTSettl spectrum, rebin flux - sp = pysynphot.Icat('BTSettl_2015', temp, metal, logg) - flux_rebin = rebin_spec(sp.wave, sp.flux, sp_atlas.wave) - - # Make new output - c0 = fits.Column(name='Wavelength', format='D', array=sp_atlas.wave) - c1 = fits.Column(name='Flux', format='E', array=flux_rebin) - - cols = fits.ColDefs([c0, c1]) - tbhdu = fits.BinTableHDU.from_columns(cols) - prihdu = fits.PrimaryHDU(header=header0) - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - - outfile = path + files_all[ff].split('[')[0] - finalhdu = fits.HDUList([prihdu, tbhdu]) - finalhdu.writeto(outfile, overwrite=True) - - return - -def make_wavelength_unique(files, dirname): - """ - Helper function to go through each BTSettl spectrum and ensure that - each wavelength point is unique. This is required for rebinning to work. - - - files: list of files to run this analysis on - """ - # Loop through each file, find fix repeated wavelength entries if necessary - for i in files: - t = Table.read('{0}/{1}'.format(dirname,i), format='fits') - test = np.unique(t['Wavelength'], return_index=True) - - if len(t) != len(test[0]): - t = t[test[1]] - - c0 = fits.Column(name='Wavelength', format='D', array=t['Wavelength']) - c1 = fits.Column(name='Flux', format='E', array=t['Flux']) - cols = fits.ColDefs([c0, c1]) - - tbhdu = fits.BinTableHDU.from_columns(cols) - prihdu = fits.PrimaryHDU() - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - finalhdu = fits.HDUList([prihdu, tbhdu]) - finalhdu.writeto('{0}/{1}'.format(dirname,i), overwrite=True) - - # Also make sure wavelength is monotonic. If it is not, then it is - # a sign that the wavelengths are out of order - diff = np.diff(t['Wavelength']) - bad = np.where(diff < 0) - if len(bad[0]) > 0: - t.sort('Wavelength') - - c0 = fits.Column(name='Wavelength', format='D', array=t['Wavelength']) - c1 = fits.Column(name='Flux', format='E', array=t['Flux']) - cols = fits.ColDefs([c0, c1]) - - tbhdu = fits.BinTableHDU.from_columns(cols) - prihdu = fits.PrimaryHDU() - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - finalhdu = fits.HDUList([prihdu, tbhdu]) - finalhdu.writeto('{0}/{1}'.format(dirname,i), overwrite=True) - - print('Done {0}'.format(i)) - - return - -def organize_BTSettl_atmospheres(): - """ - Construct cdbs-ready atmospheres for the BTSettl grid (CIFITS2011). - The code expects tp be run in cdbs/grid/BTSettl, and expects that the - individual model files have been downloaded from online - (https://phoenix.ens-lyon.fr/Grids/BT-Settl/CIFIST2011/SPECTRA/) - and processed into python-readable ascii files. - """ - orig_dir = os.getcwd() - dirs = ['btm25', 'btm20', 'btm15', 'btm10', 'btm05', 'btp00', 'btp05'] - #dirs = ['btm10', 'btm05', 'btp00', 'btp05'] - - - # Go through each directory, turning each spectrum into a cdbs-ready file. - # Will convert flux into Ergs/sec/cm**2/A (FLAM) units and save as a fits file, - # for faster access later - for ii in dirs: - print('Starting {0}'.format(ii)) - os.chdir(ii) - - files = glob.glob('*.txt') - count=0 - for jj in files: - t = Table.read(jj, format='ascii') - # First, trim the wavelengths to a more reasonable wavelength range - good = np.where( (t['col1'] > 1000) & (t['col1'] < 70000) ) - t = t[good] - - # Convert flux units to Flam (Ergs/sec/cm**2/A) - flux_new = 10**(t['col2'] - 8.0) - - # Save the file as a fits file - c0 = fits.Column(name='Wavelength', format='D', array=t['col1']) - c1 = fits.Column(name='Flux', format='E', array=flux_new) - - cols = fits.ColDefs([c0, c1]) - tbhdu = fits.BinTableHDU.from_columns(cols) - - # Add unit keywords - prihdu = fits.PrimaryHDU() - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - hdu_new = fits.HDUList([prihdu, tbhdu]) - - # Write new fits table in cdbs directory - hdu_new.writeto('{0}.fits'.format(jj[:-4]), overwrite=True) - hdu_new.close() - count += 1 - print('Done {0} of {1}'.format(count, len(files))) - - # Now, clean up all the files made when unzipping the spectra - cmd1 = 'rm *.bz2' - cmd2 = 'rm *.tmp' - #cmd3 = 'rm *.txt' - os.system(cmd1) - os.system(cmd2) - #os.system(cmd3) - print('==============================') - print('Done {0}'.format(ii)) - print('==============================') - - # Go back to original directory, move to next metallicity directory - os.chdir(orig_dir) - - return - -def make_BTSettl_catalog(): - """ - Create cdbs catalog.fits of BTSettl grid. - THIS IS STEP 2, after organize_BTSettl_atmospheres has - been run. - - Code expects to be run in cdbs/grid/BTSettl - Will create catalog.fits file in atmosphere directory with - description of each model - """ - # Record current working directory for later - start_dir = os.getcwd() - dirs = ['btm25', 'btm20', 'btm15', 'btm10', 'btm05', 'btp00', 'btp05'] - #dirs = ['btp05'] - - # Construct the catalog.fits file input. The input consists of - # and index string that specifies the stellar paramters, and a - # name string that points to the file - # Loop over all the metallicity directories to construct these inputs - index_str = [] - name_str = [] - for ii in dirs: - os.chdir(ii) - files = glob.glob('*.fits') - - # Construct the metallicity val - if 'm' in ii: - metal_flag = -1 * float(ii[3:])*0.1 - else: - metal_flag = float(ii[3:])*0.1 - - # Now collect the info from the files - for jj in files: - tmp = jj.split('-') - - if metal_flag >= 0: - temp = float(tmp[0].split('+')[0][3:]) * 100.0 # In kelvin - try: - logg = float(tmp[1]) - except: - logg = float(tmp[1].split('+')[0]) - else: - temp = float(tmp[0][3:]) * 100.0 # In kelvin - logg = float(tmp[1]) - - index_str.append('{0},{1},{2:3.2f}'.format(int(temp), metal_flag, logg)) - name_str.append('{0}/{1}[Flux]'.format(ii, jj)) - - # Go back to original directory to move to next metallicity - print('Done {0}'.format(ii)) - os.chdir(start_dir) - - # Make catalog - catalog = Table([index_str, name_str], names = ('INDEX', 'FILENAME')) - - # Create catalog.fits file in directory with the models - catalog.write('catalog.fits', format = 'fits', overwrite=True) - - # Move back to original directory, create the catalog.fits file - os.chdir(start_dir) - - return - -def rebin_BTSettl(make_unique=False): - """ - Rebin BTSettle models to atlas ck04 resolution; this makes - spectrophotometry MUCH faster - - makes new directory: BTSettl_rebin - - Code expects to be run in cdbs/grid directory - """ - # Get an atlas ck04 model, we will use this to set wavelength grid - sp_atlas = get_castelli_atmosphere() - - # Create cdbs/grid directory for rebinned models - path = 'BTSettl_rebin/' - if not os.path.exists(path): - os.mkdir(path) - - # Read in the existing catalog.fits file and rebin every spectrum. - cat = fits.getdata('BTSettl/catalog.fits') - files_all = [cat[ii][1].split('[')[0] for ii in range(len(cat))] - - #==============================# - #tmp = [] - #for ii in files_all: - # if ii.startswith('btp00'): - # tmp.append(ii) - #files_all = tmp - #=============================# - - print( 'Rebinning BTSettl spectra') - if make_unique: - print('Making unique') - make_wavelength_unique(files_all, 'BTSettl') - print('Done') - - for ff in range(len(files_all)): - vals = cat[ff][0].split(',') - temp = float(vals[0]) - metal = float(vals[1]) - logg = float(vals[2]) - - # Fetch the BTSettl spectrum, rebin flux - try: - sp = pysynphot.Icat('BTSettl', temp, metal, logg) - flux_rebin = rebin_spec(sp.wave, sp.flux, sp_atlas.wave) - - # Make new output - c0 = fits.Column(name='Wavelength', format='D', array=sp_atlas.wave) - c1 = fits.Column(name='Flux', format='E', array=flux_rebin) - - cols = fits.ColDefs([c0, c1]) - tbhdu = fits.BinTableHDU.from_columns(cols) - prihdu = fits.PrimaryHDU() - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - - outfile = path + files_all[ff].split('[')[0] - finalhdu = fits.HDUList([prihdu, tbhdu]) - finalhdu.writeto(outfile, overwrite=True) - except: - pdb.set_trace() - orig_file = '{0}/{1}'.format('BTSettl/', files_all[ff].split('[')[0]) - outfile = path + files_all[ff].split('[')[0] - cmd = 'cp {0} {1}'.format(orig_file, outfile) - os.system(cmd) - - print('Done {0} of {1}'.format(ff, len(files_all))) - - return - -def organize_all_Meisner2023_atmospheres(): - """ - Construct cdbs-ready atmospheres for the Meisner2023 grid. - The code expects tp be run in cdbs/grid/Meisner2023, and expects that the - individual model files have been downloaded from online - and processed into python-readable ascii files. - """ - orig_dir = os.getcwd() - dirs = ['mm10', 'mm05', 'mp00', 'mp03'] - - # Go through each directory, turning each spectrum into a cdbs-ready file. - # Save as a fits file, for faster access later - for ii in dirs: - print('Starting {0}'.format(ii)) - os.chdir(ii) - - files = glob.glob('*.fits') - count=0 - for jj in files: - # Open each .fits file and read the data - with fits.open(jj) as hdul: - data = hdul[1].data - wavelength = data['Wavelength'] - flux = data['Flux'] - - # Make flux independent of R&D - flux_new = flux / 5e-20 - - # Create new columns with desired format - c0 = fits.Column(name='Wavelength', format='D', array=wavelength) - c1 = fits.Column(name='Flux', format='E', array=flux_new) - - cols = fits.ColDefs([c0, c1]) - tbhdu = fits.BinTableHDU.from_columns(cols) - - # Add unit keywords - prihdu = fits.PrimaryHDU() - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - hdu_new = fits.HDUList([prihdu, tbhdu]) - - # Write the new fits table in the cdbs directory - output_filename = '{0}.fits'.format(jj[:-5]) # Removing the original .fits extension - hdu_new.writeto(output_filename, overwrite=True) - hdu_new.close() - count += 1 - print('Done {0} of {1}'.format(count, len(files))) - - # Go back to original directory, move to next metallicity directory - os.chdir(orig_dir) - - return - -def make_Meisner2023_catalog(): - """ - Create cdbs catalog.fits of Meisner2023 grid. - THIS IS STEP 2, after organize_Meisner2023_atmospheres has - been run. - - Code expects to be run in cdbs/grid/Meisner2023 - Will create catalog.fits file in atmosphere directory with - description of each model - """ - # Record current working directory for later - start_dir = os.getcwd() - dirs = ['mm10', 'mm05', 'mp00', 'mp03'] - - # Construct the catalog.fits file input. The input consists of - # and index string that specifies the stellar paramters, and a - # name string that points to the file - # Loop over all the metallicity directories to construct these inputs - index_str = [] - name_str = [] - for ii in dirs: - os.chdir(ii) - files = glob.glob('spec_jwst_*.fits') - - for jj in files: - # Parse temperature, log(g), and metallicity from filename - temp_str = jj.split('_')[2] - logg_str = jj.split('_')[3] - metal_str = jj.split('_')[4] - - # Extract temperature, surface gravity, and metallicity - temp = float(temp_str[1:]) # Temperature in Kelvin - logg = float(logg_str[1:]) # Surface gravity log(g) - - # Build metallicity value - if metal_str.startswith('m'): - metallicity = -1 * float(metal_str[1:]) - else: - metallicity = float(metal_str[1:]) - - # Construct index and filename strings - index_str.append('{0},{1},{2:3.2f}'.format(int(temp), metallicity, logg)) - name_str.append('{0}/{1}[Flux]'.format(ii, jj)) - - print('Processed directory:', ii) - os.chdir(start_dir) - - - # Make catalog - catalog = Table([index_str, name_str], names = ('INDEX', 'FILENAME')) - - # Create catalog.fits file in directory with the models - catalog.write('catalog.fits', format = 'fits', overwrite=True) - - # Move back to original directory, create the catalog.fits file - os.chdir(start_dir) - - return - -def rebin_Meisner2023(make_unique=False): - """ - Rebin Meisner2023 models to atlas ck04 resolution; this makes - spectrophotometry MUCH faster - - makes new directory: Meisner2023_rebin - - Code expects to be run in cdbs/grid directory - """ - # Get an atlas ck04 model, we will use this to set wavelength grid - sp_atlas = get_castelli_atmosphere() - - # Create a directory for rebinned Meisner2023 models - rebin_path = 'Meisner2023_rebin/' - if not os.path.exists(rebin_path): - os.mkdir(rebin_path) - - # Load the catalog.fits file and extract all spectra file paths - cat = Table.read('Meisner2023/catalog.fits') - files_all = [cat[ii]['FILENAME'].split('[')[0] for ii in range(len(cat))] - - print('Rebinning Meisner2023 spectra') - if make_unique: - print('Making unique') - make_wavelength_unique(files_all, 'Meisner2023') - print('Done') - - for ff, file in enumerate(files_all): - vals = cat[ff]['INDEX'].split(',') - temp = float(vals[0]) - metal = float(vals[1]) - logg = float(vals[2]) - - # Fetch the Meisner2023 spectrum and rebin its flux - try: - sp = pysynphot.Icat('Meisner2023', temp, metal, logg) - flux_rebin = rebin_spec(sp.wave, sp.flux, sp_atlas.wave) - - # Create the output FITS file - c0 = fits.Column(name='Wavelength', format='D', array=sp_atlas.wave) - c1 = fits.Column(name='Flux', format='E', array=flux_rebin) - - cols = fits.ColDefs([c0, c1]) - tbhdu = fits.BinTableHDU.from_columns(cols) - prihdu = fits.PrimaryHDU() - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - - # Write the new rebinned file in the Meisner2023_rebin directory - outfile = os.path.join(rebin_path, os.path.basename(file)) - finalhdu = fits.HDUList([prihdu, tbhdu]) - finalhdu.writeto(outfile, overwrite=True) - - except Exception as e: - print(f"Error processing {file}: {e}") - orig_file = os.path.join('Meisner2023', file) - outfile = os.path.join(rebin_path, os.path.basename(file)) - os.system(f'cp {orig_file} {outfile}') - - print('Done {0} of {1}'.format(ff + 1, len(files_all))) - - return - - - -def organize_WDKoester_atmospheres(path_to_dir): - """ - Construct cdbs-ready wdKoester WD atmospheres for each model. (from Koester 2010) - Will convert wavelength units to angstroms and flux units to [erg/s/cm^2/A] - - path_to_dir is the path to the directory containing all of the downloaded - files - - Saves cdbs-ready atmospheres into os.environ['PYSYN_CDBS']/wdKoeseter - (assumes this directory exists) - """ - # Save current directory for return later, move into working dir - start_dir = os.getcwd() - os.chdir(path_to_dir) - - # Process each atmosphere file independently - print( 'Creating cdbs-ready files') - files = glob.glob('*.dk.dat.txt') - - for i in files: - data = Table.read(i, format='ascii') - - wave = data['col1'] # angstrom - flux = data['col2'] # erg/s/cm^2/A - - # Make new fits table - c0 = fits.Column(name='Wavelength', format='D', array=wave) - c1 = fits.Column(name='Flux', format='E', array=flux) - - cols = fits.ColDefs([c0, c1]) - tbhdu = fits.BinTableHDU.from_columns(cols) - - # Copy over headers, update unit keywords - prihdu = fits.PrimaryHDU() - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - hdu_new = fits.HDUList([prihdu, tbhdu]) - - # Write new fits table in cdbs directory - hdu_new.writeto(os.environ['PYSYN_CDBS']+'/grid/wdKoester/'+i.replace('.txt', '.fits'), overwrite=True) - - hdu_new.close() - - # Return to original directory - os.chdir(start_dir) - return - -def make_WDKoester_catalog(path_to_dir): - """ - Create cdbs catalog.fits of wdKoester grid. - THIS IS STEP 2, after organize_WDKoester_atmospheres has - been run. - - path_to_dir is from current working directory to the cdbs directory. - Will create catalog.fits file in atmosphere directory with - description of each model - """ - # Record current working directory for later - start_dir = os.getcwd() - - # Enter atmosphere directory - os.chdir(path_to_dir) - - # Extract parameters for each atmosphere from the filename, - # construct columns for catalog file - files = glob.glob("*dk.dat.fits") - index_str = [] - name_str = [] - for name in files: - tmp = name.split('.') - tmp2 = tmp[0].split('_') - temp = float(tmp2[0][2:]) # Kelvin - logg = float(tmp2[1]) / 100.0 # log(g) - - index_str.append('{0:5.0f},0.0,{1:3.2f}'.format(temp, logg)) - name_str.append('{0}[Flux]'.format(name)) - - # Make catalog - catalog = Table([index_str, name_str], names = ('INDEX', 'FILENAME')) - - # Create catalog.fits file in directory with the models - catalog.write('catalog.fits', format = 'fits', overwrite=True) - - # Move back to original directory, create the catalog.fits file - os.chdir(start_dir) - - return - -def rebin_WDKoester(cdbs_path=os.environ['PYSYN_CDBS']): - """ - Rebin wdKoester models to atlas ck04 resolution; this makes - spectrophotometry MUCH faster - - makes new directory in cdbs/grid: wdKoester_rebin - - cdbs_path: path to cdbs directory - """ - # Get an atlas ck04 model, we will use this to set wavelength grid - sp_atlas = get_castelli_atmosphere() - - # Open a fits table for an existing model; we will steal the header - tmp = cdbs_path+'/grid/wdKoester/da70000_800.dk.dat.fits' - wdkoester_hdu = fits.open(tmp) - header0 = wdkoester_hdu[0].header - wdkoester_hdu.close() - - # Create cdbs/grid directory for rebinned models - path = cdbs_path+'/grid/wdKoester_rebin/' - if not os.path.exists(path): - os.mkdir(path) - - # Read in the existing catalog.fits file and rebin every spectrum. - cat = fits.getdata(cdbs_path + '/grid/wdKoester/catalog.fits') - files_all = [cat[ii][1].split('[')[0] for ii in range(len(cat))] - - print( 'Rebinning wdKoester spectra') - for ff in range(len(files_all)): - vals = cat[ff][0].split(',') - temp = float(vals[0]) - metal = float(vals[1]) - logg = float(vals[2]) - - # Fetch the wdKoester spectrum, rebin flux - sp = pysynphot.Icat('wdKoester', temp, metal, logg) - flux_rebin = rebin_spec(sp.wave, sp.flux, sp_atlas.wave) - - # Make new output - c0 = fits.Column(name='Wavelength', format='D', array=sp_atlas.wave) - c1 = fits.Column(name='Flux', format='E', array=flux_rebin) - - cols = fits.ColDefs([c0, c1]) - tbhdu = fits.BinTableHDU.from_columns(cols) - prihdu = fits.PrimaryHDU(header=header0) - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - - outfile = path + files_all[ff].split('[')[0] - finalhdu = fits.HDUList([prihdu, tbhdu]) - finalhdu.writeto(outfile, overwrite=True) - - return - - diff --git a/spisea/atmospheres_REMOTE_58456.py b/spisea/atmospheres_REMOTE_58456.py deleted file mode 100644 index 9867db81..00000000 --- a/spisea/atmospheres_REMOTE_58456.py +++ /dev/null @@ -1,2172 +0,0 @@ -import logging -import numpy as np -import pysynphot -import os -import glob -from astropy.io import fits -from astropy.table import Table, Column -import pysynphot -import time -import pdb -import warnings - -log = logging.getLogger('atmospheres') - -def get_atmosphere_bounds(model_dir, metallicity=0, temperature=20000, gravity=4, verbose=False): - """ - Given atmosphere model, get temperature and gravity bounds - """ - # Open catalog fits file and break out row indices - catalog = Table.read('{0}/grid/{1}/catalog.fits'.format(os.environ['PYSYN_CDBS'], model_dir)) - - teff_arr = [] - z_arr = [] - logg_arr = [] - for cur_row_index in range(len(catalog)): - index = catalog['INDEX'][cur_row_index] - tmp = index.split(',') - teff_arr.append(float(tmp[0])) - z_arr.append(float(tmp[1])) - logg_arr.append(float(tmp[2])) - teff_arr = np.array(teff_arr) - z_arr = np.array(z_arr) - logg_arr = np.array(logg_arr) - - # Filter by metallicity. Will chose the closest metallicity to desired input - metal_list = np.unique(np.array(z_arr)) - metal_idx = np.argmin(np.abs(metal_list - metallicity)) - metallicity_new = metal_list[metal_idx] - - z_filt = np.where(z_arr == metal_list[metal_idx]) - teff_arr = teff_arr[z_filt] - logg_arr = logg_arr[z_filt] - - # # Now find the closest atmosphere in parameter space to - # # the one we want. We'll find the match with the lowest - # # fractional difference - # teff_diff = (teff_arr - temperature) / temperature - # logg_diff = (logg_arr - gravity) / gravity - # - # diff_tot = abs(teff_diff) + abs(logg_diff) - # idx_f = np.argmin(diff_tot) - # - # temperature_new = teff_arr[idx_f] - # gravity_new = logg_arr[idx_f] - - # First check if temperature within bounds - temperature_new = temperature - if temperature > np.max(teff_arr): - temperature_new = np.max(teff_arr) - if temperature < np.min(teff_arr): - temperature_new = np.min(teff_arr) - - # If temperature within bounds, then check if metallicity within bounds - teff_diff = np.abs(teff_arr - temperature) - sorted_min_diffs = np.unique(teff_diff) - - ## Find two closest temperatures - teff_close_1 = teff_arr[np.where(teff_diff == sorted_min_diffs[0])[0][0]] - teff_close_2 = teff_arr[np.where(teff_diff == sorted_min_diffs[1])[0][0]] - - logg_arr_1 = logg_arr[np.where(teff_arr == teff_close_1)] - logg_arr_2 = logg_arr[np.where(teff_arr == teff_close_2)] - - ## Switch to most conservative bound of logg out of two closest temps - gravity_new = gravity - if gravity > np.min([np.max(logg_arr_1), np.max(logg_arr_2)]): - gravity_new = np.min([np.max(logg_arr_1), np.max(logg_arr_2)]) - if gravity < np.max([np.min(logg_arr_1), np.min(logg_arr_2)]): - gravity_new = np.max([np.min(logg_arr_1), np.min(logg_arr_2)]) - - if verbose: - # Print out changes, if any - if temperature_new != temperature: - teff_msg = 'Changing to T={0:6.0f} for met={1:4.2f} T={2:6.0f} logg={3:4.2f}' - print( teff_msg.format(temperature_new, metallicity, temperature, gravity)) - - if gravity_new != gravity: - logg_msg = 'Changing to logg={0:4.2f} for met={1:4.2f} T={2:6.0f} logg={3:4.2f}' - print( logg_msg.format(gravity_new, metallicity, temperature, gravity)) - - if metallicity_new != metallicity: - logg_msg = 'Changing to met={0:4.2f} for met={1:4.2f} T={2:6.0f} logg={3:4.2f}' - print( logg_msg.format(metallicity_new, metallicity, temperature, gravity)) - - return (temperature_new, gravity_new, metallicity_new) - -def get_kurucz_atmosphere(metallicity=0, temperature=20000, gravity=4, rebin=False): - """ - Return atmosphere from the Kurucz pysnphot grid - (`Kurucz 1993 `_). - - Grid Range: - - * Teff: 3000 - 50000 K - * gravity: 0 - 5 cgs - * metallicity: -5.0 - 1.0 - - Parameters - ---------- - metallicity: float - The stellar metallicity, in terms of [Z] - - temperature: float - The stellar temperature, in units of K - - gravity: float - The stellar gravity, in cgs units - - rebin: boolean - Always false for this particular function - """ - try: - sp = pysynphot.Icat('k93models', temperature, metallicity, gravity) - except: - # Check atmosphere catalog bounds - (temperature, gravity, metallicity) = get_atmosphere_bounds('k93models', - metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - sp = pysynphot.Icat('k93models', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find Kurucz 1993 atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_castelli_atmosphere(metallicity=0, temperature=20000, gravity=4, rebin=False): - """ - Return atmospheres from the pysynphot ATLAS9 atlas - (`Castelli & Kurucz 2004 `_). - - Grid Range: - - * Teff: 3500 - 50000 K - * gravity: 0 - 5.0 cgs - * [M/H]: -2.5 - 0.2 - - Parameters - ---------- - metallicity: float - The stellar metallicity, in terms of [Z] - - temperature: float - The stellar temperature, in units of K - - gravity: float - The stellar gravity, in cgs units - - rebin: boolean - If true, rebins the atmospheres so that they are the same - resolution as the Castelli+04 atmospheres. Default is False, - which is often sufficient synthetic photometry in most cases. - - verbose: boolean - True for verbose output - """ - try: - sp = pysynphot.Icat('ck04models', temperature, metallicity, gravity) - except: - # Check atmosphere catalog bounds - (temperature, gravity, metallicity) = get_atmosphere_bounds('ck04models', - metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - sp = pysynphot.Icat('ck04models', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find Castelli and Kurucz 2004 atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_nextgen_atmosphere(metallicity=0, temperature=5000, gravity=4, rebin=False): - """ - metallicity = [M/H] (def = 0) - temperature = Kelvin (def = 5000) - gravity = log gravity (def = 4.0) - """ - try: - sp = pysynphot.Icat('nextgen', temperature, metallicity, gravity) - except: - # Check atmosphere catalog bounds - (temperature, gravity, metallicity) = get_atmosphere_bounds('nextgen', - metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - sp = pysynphot.Icat('nextgen', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find NextGen atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_amesdusty_atmosphere(metallicity=0, temperature=5000, gravity=4, rebin=False): - """ - metallicity = [M/H] (def = 0) - temperature = Kelvin (def = 5000) - gravity = log gravity (def = 4.0) - """ - sp = pysynphot.Icat('AMESdusty', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find AMESdusty Allard+ 2000 atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_phoenix_atmosphere(metallicity=0, temperature=5000, gravity=4, - rebin=False): - """ - Return atmosphere from the pysynphot - `PHOENIX atlas `_. - - Parameters - ---------- - metallicity: float - The stellar metallicity, in terms of [Z] - - temperature: float - The stellar temperature, in units of K - - gravity: float - The stellar gravity, in cgs units - - rebin: boolean - If true, rebins the atmospheres so that they are the same - resolution as the Castelli+04 atmospheres. Default is False, - which is often sufficient synthetic photometry in most cases. - - """ - try: - sp = pysynphot.Icat('phoenix', temperature, metallicity, gravity) - except: - # Check atmosphere catalog bounds - (temperature, gravity, metallicity) = get_atmosphere_bounds('phoenix', - metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - sp = pysynphot.Icat('phoenix', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find PHOENIX BT-Settl (Allard+ 2011 atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_cmfgenRot_atmosphere(metallicity=0, temperature=24000, gravity=4.3, rebin=True, verbose=False): - """ - metallicity = [M/H] (def = 0) - temperature = Kelvin (def = 24000) - gravity = log gravity (def = 4.3) - - rebin=True: pull from atmospheres at ck04model resolution. - """ - # Take care of atmospheres outside the catalog boundaries - logg_msg = 'Changing to logg={0:3.1f} for T={1:6.0f} logg={2:4.2f}' - if gravity > 4.3: - if verbose: - print( logg_msg.format(4.3, temperature, gravity)) - gravity = 4.3 - - if rebin: - sp = pysynphot.Icat('cmfgen_rot_rebin', temperature, metallicity, gravity) - else: - sp = pysynphot.Icat('cmfgen_rot', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find CMFGEN rotating atmosphere model (Fierro+15) for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_cmfgenRot_atmosphere_closest(metallicity=0, temperature=24000, gravity=4.3, rebin=True, - verbose=False): - """ - For a given stellar atmosphere, get extract the closest possible match in - Teff/logg space. Note that this is different from the normal routine - which interpolates along the input grid to get final spectrum. We can't - do this here because the Fierro+15 atmosphere grid is so sparse - - rebin=True: pull from atmospheres at ck04model resolution. - - If verbose, print out the parameters of the match - """ - # Set up the proper root directory - if rebin == True: - root_dir = os.environ['PYSYN_CDBS'] + '/cmfgen_rot_rebin/' - else: - root_dir = os.environ['PYSYN_CDBS'] + '/cmfgen_rot/' - - # Read in catalog, extract atmosphere info - cat = Table.read('{0}/catalog.fits'.format(root_dir), format='fits') - teff_arr = [] - z_arr = [] - logg_arr = [] - for ii in range(len(cat)): - index = cat['INDEX'][ii] - tmp = index.split(',') - teff_arr.append(float(tmp[0])) - z_arr.append(float(tmp[1])) - logg_arr.append(float(tmp[2])) - teff_arr = np.array(teff_arr) - z_arr = np.array(z_arr) - logg_arr = np.array(logg_arr) - - # Now find the closest atmosphere in parameter space to - # the one we want. We'll find the match with the lowest - # fractional difference - teff_diff = (teff_arr - temperature) / temperature - logg_diff = (logg_arr - gravity) / gravity - - diff_tot = abs(teff_diff) + abs(logg_diff) - idx_f = np.where(diff_tot == min(diff_tot))[0][0] - - # Extract the filename of the best-match model and read as - # pysynphot object - infile = cat[idx_f]['FILENAME'].split('.') - spec = Table.read('{0}/{1}.fits'.format(root_dir, infile[0])) - - # Now, the CMFGEN atmospheres assume a distance of 1 kpc, while the the - # ATLAS models are in FLAM at the surface. So, we need to multiply the - # CMFGEN atmospheres by (1000/R)**2. in order to convert to FLAM on surface. - # We'll calculate radius from Teff and logL, which is given in the Table_*.txt file - t = Table.read('{0}/Table_rot.txt'.format(root_dir), format='ascii') - tmp = np.where(t['col1'] == infile[0]) - - lum = t['col3'][tmp] * (3.839*10**33) # cgs - sigma = 5.6704 * 10**-5 # cgs - teff = teff_arr[idx_f] # cgs - - radius = np.sqrt( lum / (4.0 * np.pi * teff**4. * sigma) ) # in cm - radius /= 3.08*10**18 # in pc - - - # Make the pysynphot spectrum - w = spec['Wavelength'] - f = spec['Flux'] * (1000 / radius)**2. - sp = pysynphot.ArraySpectrum(w,f) - - #sp = pysynphot.FileSpectrum('{0}/{1}.fits'.format(root_dir, infile[0])) - - # Print out parameters of match, if desired - if verbose: - print('Teff match: Input: {0}, Output: {1}'.format(temperature, teff_arr[idx_f])) - print('logg match: Input: {0}, Output: {1}'.format(gravity, logg_arr[idx_f])) - - return sp - -def get_cmfgenNoRot_atmosphere(metallicity=0, temperature=22500, gravity=3.98, rebin=True): - """ - metallicity = [M/H] (def = 0) - temperature = Kelvin (def = 24000) - gravity = log gravity (def = 4.3) - - rebin=True: pull from atmospheres at ck04model resolution. - """ - if rebin: - sp = pysynphot.Icat('cmfgen_norot_rebin', temperature, metallicity, gravity) - else: - sp = pysynphot.Icat('cmfgen_norot', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find CMFGEN rotating atmosphere model (Fierro+15) for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_cmfgenNoRot_atmosphere(metallicity=0, temperature=30000, gravity=4.14): - """ - metallicity = [M/H] (def = 0) - temperature = Kelvin (def = 30000) - gravity = log gravity (def = 4.14) - """ - sp = pysynphot.Icat('cmfgenF15_noRot', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find CMFGEN non-rotating atmosphere model (Fierro+15) for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_phoenixv16_atmosphere(metallicity=0, temperature=4000, gravity=4, rebin=True): - """ - Return PHOENIX v16 atmospheres from - `Husser et al. 2013 `_. - - Models originally downloaded via `ftp `_. - Solar metallicity and [alpha/Fe] is used. - - Grid Range: - - * Teff: 2300 - 7000 K, steps of 100 K; 7000 - 12000 in steps of 200 K - * gravity: 0.0 - 6.0 cgs, steps of 0.5 - * [M/H]: -4.0 - 1.0 - - Parameters - ---------- - metallicity: float - The stellar metallicity, in terms of [Z] - - temperature: float - The stellar temperature, in units of K - - gravity: float - The stellar gravity, in cgs units - - rebin: boolean - If true, rebins the atmospheres so that they are the same - resolution as the Castelli+04 atmospheres. Default is False, - which is often sufficient synthetic photometry in most cases. - - """ - atm_model_name = 'phoenix_v16' - if rebin == True: - atm_model_name = 'phoenix_v16_rebin' - - - # Extract atmosphere. If that fails, then check bounds and try again - try: - sp = pysynphot.Icat(atm_model_name, temperature, metallicity, gravity) - except: - # Check atmosphere catalog bounds - (temperature, gravity, metallicity) = get_atmosphere_bounds(atm_model_name, - metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - sp = pysynphot.Icat(atm_model_name, temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find PHOENIXv16 (Husser+13) atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_BTSettl_2015_atmosphere(metallicity=0, temperature=2500, gravity=4, rebin=True): - """ - Return atmosphere from CIFIST2011_2015 grid - (`Allard et al. 2012 `_, - `Baraffe et al. 2015 `_ ) - - Grid originally downloaded from `website `_. - - Grid Range: - - * Teff: 1200 - 7000 K - * gravity: 2.5 - 5.5 cgs - * [M/H] = 0 - - Parameters - ---------- - metallicity: float - The stellar metallicity, in terms of [Z] - - temperature: float - The stellar temperature, in units of K - - gravity: float - The stellar gravity, in cgs units - - rebin: boolean - If true, rebins the atmospheres so that they are the same - resolution as the Castelli+04 atmospheres. Default is False, - which is often sufficient synthetic photometry in most cases. - """ - if rebin == True: - atm_name = 'BTSettl_2015_rebin' - else: - atm_name = 'BTSettl_2015' - - try: - sp = pysynphot.Icat(atm_name, temperature, metallicity, gravity) - except: - # Check atmosphere catalog bounds - (temperature, gravity, metallicity) = get_atmosphere_bounds(atm_name, - metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - sp = pysynphot.Icat(atm_name, temperature, metallicity, gravity) - - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find BTSettl_2015 atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_BTSettl_atmosphere(metallicity=0, temperature=2500, gravity=4.5, rebin=True): - """ - Return atmosphere from CIFIST2011 grid - (`Allard et al. 2012 `_) - - Grid originally downloaded `here `_ - - Notes - ------ - Grid Range: - - * [M/H] = -2.5, -2.0, -1.5, -1.0, -0.5, 0, 0.5 - - Teff and gravity ranges depend on metallicity: - - [M/H] = -2.5 - - * Teff: 2600 - 4600 K - * gravity: 4.5 - 5.5 - - [M/H] = -2.0 - - * Teff: 2600 - 7000 - * gravity: 4.5 - 5.5 - - [M/H] = -1.5 - - * Teff: 2600 - 7000 - * gravity: 4.5 - 5.5 - - [M/H] = -1.0 - - * Teff: 2600 - 7000 - * gravity: Teff < 3200 --> 4.5 - 5.5; Teff > 3200 --> 2.5 - 5.5 - - [M/H] = -0.5 - - * Teff: 1000 -7000 - * gravity: Teff < 3000 --> 4.5 - 5.5; Teff > 3000 --> 3.0 - 6.0 - - [M/H] = 0 - - * Teff: 750 - 7000 - * gravity: Teff < 2500 --> 3.5 - 5.5; Teff > 2500 --> 0 - 5.5 - - [M/H] = 0.5 - - * Teff: 1000 - 5000 - * gravity: 3.5 - 5.0 - - - Alpha enhancement: - - * [M/H]= -0.0, +0.5 no anhancement - * [M/H]= -0.5 with [alpha/H]=+0.2 - * [M/H]= -1.0, -1.5, -2.0, -2.5 with [alpha/H]=+0.4 - - Parameters - ---------- - metallicity: float - The stellar metallicity, in terms of [Z] - - temperature: float - The stellar temperature, in units of K - - gravity: float - The stellar gravity, in cgs units - - rebin: boolean - If true, rebins the atmospheres so that they are the same - resolution as the Castelli+04 atmospheres. Default is False, - which is often sufficient synthetic photometry in most cases. - """ - if rebin == True: - atm_name = 'BTSettl_rebin' - else: - atm_name = 'BTSettl' - - try: - sp = pysynphot.Icat(atm_name, temperature, metallicity, gravity) - except: - # Check atmosphere catalog bounds - (temperature, gravity, metallicity) = get_atmosphere_bounds(atm_name, - metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - sp = pysynphot.Icat(atm_name, temperature, metallicity, gravity) - - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find BTSettl_2015 atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_wdKoester_atmosphere(metallicity=0, temperature=20000, gravity=7): - """ - Return white dwarf atmospheres from - `Koester et al. 2010 `_ - - Parameters - ---------- - metallicity: float - The stellar metallicity, in terms of [Z] - - temperature: float - The stellar temperature, in units of K - - gravity: float - The stellar gravity, in cgs units - - rebin: boolean - If true, rebins the atmospheres so that they are the same - resolution as the Castelli+04 atmospheres. Default is False, - which is often sufficient synthetic photometry in most cases. - """ - sp = pysynphot.Icat('wdKoester', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find WD Koester (Koester+ 2010 atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_atlas_phoenix_atmosphere(metallicity=0, temperature=5250, gravity=4): - """ - Return atmosphere that is a linear merge of atlas ck04 model and phoenixV16. - - Only valid for temps between 5000 - 5500K, gravity from 0 = 5.0 - """ - try: - sp = pysynphot.Icat('merged_atlas_phoenix', temperature, metallicity, gravity) - except: - # Check atmosphere catalog bounds - (temperature, gravity, metallicity) = get_atmosphere_bounds('merged_atlas_phoenix', - metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - sp = pysynphot.Icat('merged_atlas_phoenix', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find ATLAS-PHOENIX merge atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -def get_BTSettl_phoenix_atmosphere(metallicity=0, temperature=5250, gravity=4): - """ - Return atmosphere that is a linear merge of BTSettl_CITFITS2011_2015 model - and phoenixV16. - - Only valid for temps between 3200 - 3800K, gravity from 2.5 - 5.5 - """ - try: - sp = pysynphot.Icat('merged_BTSettl_phoenix', temperature, metallicity, gravity) - except: - # Check atmosphere catalog bounds - (temperature, gravity, metallicity) = get_atmosphere_bounds('merged_BTSettl_phoenix', - metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - sp = pysynphot.Icat('merged_BTSettl_phoenix', temperature, metallicity, gravity) - - # Do some error checking - idx = np.where(sp.flux != 0)[0] - if len(idx) == 0: - print( 'Could not find ATLAS-PHOENIX merge atmosphere model for') - print( ' temperature = %d' % temperature) - print( ' metallicity = %.1f' % metallicity) - print( ' log gravity = %.1f' % gravity) - - return sp - -#---------------------------------------------------------------------# -def get_merged_atmosphere(metallicity=0, temperature=20000, gravity=4.5, verbose=False, - rebin=True): - """ - Return a stellar atmosphere from a suite of different model grids, - depending on the input temperature, (all values in K). - - Parameters - ---------- - metallicity: float - The stellar metallicity, in terms of [Z] - - temperature: float - The stellar temperature, in units of K - - gravity: float - The stellar gravity, in cgs units - - rebin: boolean - If true, rebins the atmospheres so that they are the same - resolution as the Castelli+04 atmospheres. Default is False, - which is often sufficient synthetic photometry in most cases. - - verbose: boolean - True for verbose output - - Notes - ----- - The underlying stellar model grid used changes as a function of - stellar temperature (in K): - - * T > 20,000: ATLAS - * 5500 <= T < 20,000: ATLAS - * 5000 <= T < 5500: ATLAS/PHOENIXv16 merge - * 3800 <= T < 5000: PHOENIXv16 - - For T < 3800, there is an additional gravity and metallicity - dependence: - - If T < 3800 and [M/H] = 0: - - * T < 3800, logg < 2.5: PHOENIX v16 - * 3200 <= T < 3800, logg > 2.5: BTSettl_CIFITS2011_2015/PHOENIXV16 merge - * 3200 < T <= 1200, logg > 2.5: BTSettl_CIFITS2011_2015 - - Otherwise, if T < 3800 and [M/H] != 0: - - * T < 3800: PHOENIX v16 - - References: - - * ATLAS: ATLAS9 models (`Castelli & Kurucz 2004 `_) - * PHOENIXv16 (`Husser et al. 2013 `_) - * BTSettl_CIFITS2011_2015: Baraffee+15, Allard+ (https://phoenix.ens-lyon.fr/Grids/BT-Settl/CIFIST2011_2015/SPECTRA/) - - LTE WARNING: - - The ATLAS atmospheres are calculated with LTE, and so they - are less accurate when non-LTE conditions apply (e.g. T > 20,000 - K). Ultimately we'd like to add a non-LTE atmosphere grid for - the hottest stars in the future. - - HOW BOUNDARIES BETWEEN MODELS ARE TREATED: - - At the boundary between two models grids a temperature range is defined - where the resulting atmosphere is a weighted average between the two - grids. Near one boundary one model - is weighted more heavily, while at the other boundary the other - model is weighted more heavily. These are calculated in the - temperature ranges where we switch between model grids, to - ensure a smooth transition. - """ - # For T < 3800, atmosphere depends on metallicity + gravity. - # If solar metallicity, use BTSettl 2015 grid. Only solar metallicity is - # currently available here, so if non-solar metallicity, just stick with - # the Phoenix grid - if (temperature <= 3800) & (metallicity == 0): - # High gravity are in BTSettl regime - if (temperature <= 3200) & (gravity > 2.5): - if verbose: - print( 'BTSettl_2015 atmosphere') - return get_BTSettl_2015_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity, - rebin=rebin) - - if (temperature >= 3200) & (temperature < 3800) & (gravity > 2.5): - if verbose: - print( 'BTSettl/Phoenixv16 merged atmosphere') - return get_BTSettl_phoenix_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - # Low gravity is PHOENIX regime - if gravity <= 2.5: - if verbose: - print( 'Phoenixv16 atmosphere') - return get_phoenixv16_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity, - rebin=rebin) - - if (temperature <= 3800) & (metallicity != 0): - if verbose: - print( 'Phoenixv16 atmosphere') - return get_phoenixv16_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity, - rebin=rebin) - - # For T > 3800, no metallicity or gravity dependence - if (temperature >= 3800) & (temperature < 5000): - if verbose: - print( 'Phoenixv16 atmosphere') - return get_phoenixv16_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity, - rebin=rebin) - - if (temperature >= 5000) & (temperature < 5500): - if verbose: - print( 'ATLAS/Phoenix merged atmosphere') - return get_atlas_phoenix_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - if (temperature >= 5500) & (temperature < 20000): - if verbose: - print( 'ATLAS merged atmosphere') - return get_castelli_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - if temperature >= 20000: - if verbose: - print( 'Still ATLAS merged atmosphere') - return get_castelli_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - #print('CMFGEN') - #return get_cmfgenRot_atmosphere_closest(metallicity=metallicity, - # temperature=temperature, - # gravity=gravity) - - - - -def get_wd_atmosphere(metallicity=0, temperature=20000, gravity=4, verbose=False): - """ - Return the white dwarf atmosphere from - `Koester et al. 2010 `_. - If desired parameters are - outside of grid, return a blackbody spectrum instead - - Parameters - ---------- - metallicity: float - The stellar metallicity, in terms of [Z] - - temperature: float - The stellar temperature, in units of K - - gravity: float - The stellar gravity, in cgs units - - rebin: boolean - If true, rebins the atmospheres so that they are the same - resolution as the Castelli+04 atmospheres. Default is False, - which is often sufficient synthetic photometry in most cases. - - verbose: boolean - True for verbose output - """ - try: - if verbose: - print('wdKoester atmosphere') - - return get_wdKoester_atmosphere(metallicity=metallicity, - temperature=temperature, - gravity=gravity) - - except pysynphot.exceptions.ParameterOutOfBounds: - # Use a black-body atmosphere. - bbspec = get_bb_atmosphere(temperature=temperature, verbose=verbose) - return bbspec - -def get_bb_atmosphere(metallicity=None, temperature=20_000, gravity=None, - verbose=False, rebin=None, - wave_min=500, wave_max=50_000, wave_num=20_000): - """ - Return a blackbody spectrum - - Parameters - ---------- - temperature: float, default=20_000 - The stellar temperature, in units of K - wave_min: float, default=500 - Sets the minimum wavelength (in Angstroms) of the wavelength range - for the blackbody spectrum - wave_max: float, default=50_000 - Sets the maximum wavelength (in Angstroms) of the wavelength range - for the blackbody spectrum - wave_num: int, default=20_000 - Sets the number of wavelength points in the wavelength range - Note: the wavelength range is evenly spaced in log space - """ - if ((metallicity is not None) or (gravity is not None) or - (rebin is not None)): - warnings.warn( - 'Only `temperature` keyword is used for black-body atmosphere' - ) - - if verbose: - print('Black-body atmosphere') - - # Modify pysynphot's default waveset to specified bounds - pysynphot.refs.set_default_waveset( - minwave=wave_min, maxwave=wave_max, num=wave_num - ) - - # Get black-body atmosphere for specified temperature from pysynphot - bbspec = pysynphot.spectrum.BlackBody(temperature) - - # pysynphot `BlackBody` generates spectrum in `photlam`, need in `flam` - bbspec.convert('flam') - - # `BlackBody` spectrum is normalized to solar radius star at 1 kiloparsec. - # Need to remove this normalization for SPISEA by multiplying bbspec - # by (1000 * 1 parsec / 1 Rsun)**2 = (1000 * 3.08e18 cm / 6.957e10 cm)**2 - bbspec *= (1000 * 3.086e18 / 6.957e10)**2 - - return bbspec - - -#--------------------------------------# -# Atmosphere formatting functions -#--------------------------------------# - -def download_CMFGEN_atmospheres(Table_rot, Table_norot): - """ - Downloads CMFGEN models from - https://sites.google.com/site/fluxesandcontinuum/home; - these contain continuum as well as lines. - - Table_rot, Table_norot are tables with the file prefixes - and model atmosphere parameters, taken by hand from the - Fierro+15 paper - - Website addresses are hardcoded - - Puts downloaded models in the current working directory. - """ - print( 'WARNING: THIS DOES NOT COMPLETELY WORK') - print( '**********************') - t_rot = Table.read(Table_rot, format='ascii') - t_norot = Table.read(Table_norot, format='ascii') - - tables = [t_rot, t_norot] - filenames = [t_rot['col1'], t_norot['col1']] - - # Hardcoded list of webiste addresses - web_base1 = 'https://sites.google.com/site/fluxesandcontinuum/home/' - web_base2 = 'https://sites.google.com/site/modelsobmassivestars/' - web = [web_base1+'009-solar-masses/',web_base1+'012-solar-masses/', - web_base1+'015-solar-masses/',web_base1+'020-solar-masses/', - web_base1+'025-solar-masses/',web_base2+'009-solar-masses-tracks/', - web_base2+'040-solar-masses/',web_base2+'060-solar-masses/', - web_base1+'085-solar-masses/',web_base1+'120-solar-masses/'] - # Array of masses that matches the website addresses - mass_arr = np.array([9.,12.,15.,20.,25.,32.,40.,60.,85.,120.]) - - # Loop through rotating and unrotating case. First loop is rot, second unrot - for i in range(2): - # Extract masses from filenames - masses = [] - for j in filenames[i]: - tmp = j.split('m') - mass = float(tmp[1][:-1]) - masses.append(mass) - - # Download the models webpage by webpage. A bit tricky because masses - # change slightly within a particular website. THIS IS WHAT FAILS - for j in range(len(web)): - if j == 0: - good = np.where( (masses <= mass_arr[j]) ) - else: - g = j - 1 - good = np.where( (masses <= mass_arr[j]) & - (masses > mass_arr[g]) ) - # Use wget command to pull down the files, and unzip them - for k in good[0]: - full = web[j]+'{1:s}.flx.zip'.format(mass_arr[j],filenames[i][k]) - os.system('wget ' + full) - os.system('unzip '+ filenames[i][k] + '.flx.zip') - - return - -def organize_CMFGEN_atmospheres(path_to_dir): - """ - Organize CMFGEN grid from Fierro+15 - (http://www.astroscu.unam.mx/atlas/index.html) - into rot and noRot directories - - path_to_dir is from current working directory to directory - containing the downloaded models. Assumed that models - and tables describing parameters are in this directory. - - Tables describing parameters MUST be named Table_rot.txt, - Table_noRot.txt. Made by hand from Tables 3, 4 in Fierro+15. - These are located in same original directory as atmosphere files - - Will separate files into 2 subdirectories, one rotating and - the other non-rotating - - *Can't have any other files starting with "t" in model directory to start!* - """ - # First, record current working directory to return to later - start_dir = os.getcwd() - - # Enter atmosphere directory, collect rotating and non-rotating - # file names (assumed to all start with "t") - os.chdir(path_to_dir) - rot_models = glob.glob("t*r.flx*") - noRot_models = glob.glob("t*n.flx*") - - # Separate into different subdirectories - if os.path.exists('cmfgenF15_rot'): - pass - else: - os.mkdir('cmfgenF15_rot') - os.mkdir('cmfgenF15_noRot') - - for mod in rot_models: - cmd = 'mv {0:s} cmfgenF15_rot'.format(mod) - os.system(cmd) - - for mod in noRot_models: - cmd = 'mv {0:s} cmfgenF15_noRot'.format(mod) - os.system(cmd) - - # Also move Tables with model parameters into correct directory - os.system('mv Table_rot.txt cmfgenF15_rot') - os.system('mv Table_noRot.txt cmfgenF15_noRot') - - # Return to original directory - os.chdir(start_dir) - - return - -def make_CMFGEN_catalog(path_to_dir): - """ - Create cdbs catalog.fits of CMFGEN grid from Fierro+15 - (http://www.astroscu.unam.mx/atlas/index.html). - THIS IS STEP 2, after organize_CMFGEN_atmospheres has - been run. - - path_to_dir is from current working directory to directory - containing the rotating or non-rotating models (i.e. cmfgenF15_rot). Also, - needs to be a Table*.txt file which contains the parameters for all of the - original models, since params in filename are not precise enough - - Will create catalog.fits file in atmosphere directory with - description of each model - - *Can't have any other files starting with "t" in model directory to start!* - """ - # Record current working directory for later - start_dir = os.getcwd() - - # Enter atmosphere directory - os.chdir(path_to_dir) - - # Extract parameters for each atmosphere - # Note: can't rely on filename for this because not precise enough!! - - #---------OLD: GETTING PARAMS FROM FILENAME-------# - # Collect file names (assumed to all start with "t") - #files = glob.glob("t*") - #for name in files: - # tmp = name.split('l') - # temp = float(tmp[0][1:]) * 100.0 # In kelvin - - # lumtmp = tmp[1].split('_') - # lum = float(lumtmp[0][:-5]) * 1000.0 # In L_sun - - # mass = float(lumtmp[0][5:-1]) # In M_sun - - # Need to calculate log g from T and L (cgs) - # lum_sun = 3.846 * 10**33 # erg/s - # M_sun = 2 * 10**33 # g - # G_si = 6.67 * 10**(-8) # cgs - # sigma_si = 5.67 * 10**(-5) # cgs - - # g = (G_si * mass * M_sun * 4 * np.pi * sigma_si * temp**4) / \ - # (lum * lum_sun) - # logg = np.log10(g) - #---------------------------------------------------# - - # Read table with atmosphere params - table = glob.glob('Table_*') - t = Table.read(table[0], format = 'ascii') - names = t['col1'] - temps = t['col2'] - logg = t['col4'] - - # Create catalog.fits file - index_str = [] - name_str = [] - for i in range(len(names)): - index = '{0:5.0f},0.0,{1:3.2f}'.format(temps[i], logg[i]) - - #---NOTE: THE FOLLOWING DEPENDS ON FINAL LOCATION OF CATALOG FILE---# - #path = path_to_dir + '/' + names[i] - path = names[i] + '.fits[Flux]' - - index_str.append(index) - name_str.append(path) - - catalog = Table([index_str, name_str], names = ('INDEX', 'FILENAME')) - - # Create catalog.fits file in directory with the models - catalog.write('catalog.fits', format = 'fits') - - # Move back to original directory, create the catalog.fits file - os.chdir(start_dir) - - return - -def cdbs_cmfgen(path_to_dir, path_to_cdbs_dir): - """ - Code to put cmfgen models into cdbs format and adds proper unit keyword in - fits header. Save as fits file - - path_to_dir goes from current directory to cmfgen_rot or cmfgen_norot - directory with the *.flx models. Note that these files have already been - organized using organize_CMFGEN_atmospheres code. - - path_to_cdbs_dir goes from current directory to cdbs/grid/cmfgen_rot or - cmfgen_norot directory. Will copy new fits files to this directory. - This directory must already exist! - """ - # Save starting directory for later, move into path_to_dir directory - start_dir = os.getcwd() - os.chdir(path_to_dir) - - # Collect the filenames, make necessary changes to each one - files = glob.glob('*.flx') - - # Need to make brand-new fits tables with data we want. - counter = 0 - for i in files: - counter += 1 - # Open file, extract useful info - t = Table.read(i, format='ascii') - wave = t['col1'] - flux = t['col2'] # Flux is already in erg/cm^2/s/A - - # Need to eliminate duplicate entries (pysynphot crashes) - unique = np.unique(wave, return_index=True) - wave = wave[unique[1]] - flux = flux[unique[1]] - - # Make fits table from individual columns. - c0 = fits.Column(name='Wavelength', format='D', array=wave) - c1 = fits.Column(name='Flux', format='E', array=flux) - - cols = fits.ColDefs([c0, c1]) - tbhdu = fits.BinTableHDU.from_columns(cols) - - #Adding unit keywords - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - - prihdu = fits.PrimaryHDU() - - finalhdu = fits.HDUList([prihdu, tbhdu]) - finalhdu.writeto(i[:-4]+'.fits', overwrite=True) - - print( 'Done {0:2.0f} of {1:2.0f}'.format(counter, len(files))) - - # Return to original directory, copy over new .fits files to cdbs directory - os.chdir(start_dir) - cmd = 'mv {0:s}/*.fits {1:s}'.format(path_to_dir, path_to_cdbs_dir) - os.system(cmd) - - return - -def rebin_cmfgen(cdbs_path, rot=True): - """ - Rebin cmfgen_rot and cmfgen_norot models to atlas ck04 resolution; - this makes spectrophotometry MUCH faster - - cdbs_path: path to cdbs directory - rot=True for rotating models (cmfgen_rot), False for non-rotating models - - makes new directory in cdbs/grid: cmfgen_rot_rebin or cmfgen_norot_rebin - """ - # Get an atlas ck04 model, we will use this to set wavelength grid - sp_atlas = get_castelli_atmosphere() - - # Open a fits table for an existing cmfgen model; we will steal the header. - # Also define paths to new rebin directories - if rot == True: - tmp = cdbs_path+'/grid/cmfgen_rot/t0200l0008m009r.fits' - path = cdbs_path+'/grid/cmfgen_rot_rebin/' - orig_path = cdbs_path+'/grid/cmfgen_rot/' - else: - tmp = cdbs_path+'/grid/cmfgen_norot/t0200l0007m009n.fits' - path = cdbs_path+'/grid/cmfgen_norot_rebin/' - orig_path = cdbs_path+'/grid/cmfgen_norot/' - - cmfgen_hdu = fits.open(tmp) - header0 = cmfgen_hdu[0].header - # Create rebin directories if they don't already exist. Copy over - # catalog.fits file from original directory (will be the same) - if not os.path.exists(path): - os.mkdir(path) - cmd = 'cp {0:s}catalog.fits {1:s}'.format(orig_path, path) - os.system(cmd) - - # Read in the catalog.fits file - cat = fits.getdata(orig_path + 'catalog.fits') - files_all = [cat[ii][1].split('[')[0] for ii in range(len(cat))] - - # First column in new files will be for [atlas] wavelength - c0 = fits.Column(name='Wavelength', format='D', array=sp_atlas.wave) - - # For each catalog.fits entry, read the unbinned spectrum and rebin to - # the atlas resolution. Make a new fits file in rebin directory - count = 0 - for ff in range(len(files_all)): - count += 1 - # Extract the temp, Z, logg - vals = cat[ff][0].split(',') - temp = float(vals[0]) - metal = float(vals[1]) - grav = float(vals[2]) - - # Fetch the spectrum - if rot == True: - sp = pysynphot.Icat('cmfgen_rot', temp, metal, grav) - else: - sp = pysynphot.Icat('cmfgen_norot', temp, metal, grav) - - # Rebin - flux_rebin = rebin_spec(sp.wave, sp.flux, sp_atlas.wave) - c1 = fits.Column(name='Flux', format='E', array=flux_rebin) - - # Make the FITS file from the columns with header - cols = fits.ColDefs([c0,c1]) - tbhdu = fits.BinTableHDU.from_columns(cols) - prihdu = fits.PrimaryHDU(header=header0) - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - - # Write hdu to new directory with same filename - finalhdu = fits.HDUList([prihdu, tbhdu]) - finalhdu.writeto(path+files_all[ff]) - - print( 'Finished file {0} of {1}'.format(count, len(files_all)) ) - return - - -def organize_PHOENIXv16_atmospheres(path_to_dir, met_str='m00'): - """ - Construct the Phoenix Husser+13 atmopsheres for each model. Combines the - fluxes from the *HiRES.fits files and the wavelengths of the - WAVE_PHONEIX-ACES-AGSS-COND-2011.fits file. - - path_to_dir is the path to the directory containing all of the downloaded - files - - met_str is the name of the current metallicity - - Creates new fits files for each atmosphere: phoenix_.fits, - which contains columns for the log g (column header = g#.#). Puts - atmospheres in new directory phoenixm00 - """ - # Save current directory for return later, move into working dir - start_dir = os.getcwd() - os.chdir(path_to_dir) - - # If it doesn't already exist, create the current metallicity subdirectory - sub_dir = '../phoenix{0}'.format(met_str) - if os.path.exists(sub_dir): - pass - else: - os.mkdir(sub_dir) - - # Extract wavelength array, make column for later - wavefile = fits.open('WAVE_PHOENIX-ACES-AGSS-COND-2011.fits') - wave = wavefile[0].data - wavefile.close() - wave_col = Column(wave, name = 'WAVELENGTH') - - # Create temp array for Husser+13 grid (given in paper) - temp_arr = np.arange(2300, 7001, 100) - temp_arr = np.append(temp_arr, np.arange(7000, 12001, 200)) - - print( 'Looping though all temps') - # For each temp, build file containing the flux for all gravities - i = 0 - for temp in temp_arr: - files = glob.glob('lte{0:05d}-*-HiRes.fits'.format(temp)) - files.sort() - # Start the table with the wavelength column - t = Table() - t.add_column(wave_col) - for f in files: - # Extract the logg out of filename - logg = f[9:13] - - # Extract fluxes from file - spectrum = fits.open(f) - flux = spectrum[0].data - spectrum.close() - - # Make Column object with fluxes, add to table - col = Column(flux, name = 'g{0:2.1f}'.format(float(logg))) - t.add_column(col) - - # Now, construct final fits file for the given temp - outname = 'phoenix{0}_{1:05d}.fits'.format(met_str, temp) - t.write('{0}/{1}'.format(sub_dir, outname), format = 'fits', overwrite = True) - - # Progress counter for user - i += 1 - print( 'Done {0:d} of {1:d}'.format(i, len(temp_arr))) - - # Return to original directory - os.chdir(start_dir) - return - -def make_PHOENIXv16_catalog(path_to_dir, met_str='m00'): - """ - Makes catalog.fits file for Husser+13 phoenix models. Assumes that - organize_PHOENIXv16_atmospheres has been run already, and that the models lie - in subdirectory phoenix[met_str]. - - path_to_directory is the path to the directory with the reformatted - models (i.e. the output from construct_atmospheres, phoenix[met_str]) - - Puts catalog.fits file in directory the user starts in - """ - # Save starting directory for later, move into working directory - start_dir = os.getcwd() - os.chdir(path_to_dir) - - # Extract metallicity from metallicity string - met = float(met_str[1]) + (float(met_str[2]) * 0.1) - if 'm' in met_str: - met *= -1. - - # Collect the filenames. Each is a unique temp with many different log g's - files = glob.glob('phoenix*.fits') - files.sort() - - # Create the catalog.fits file, row by row - index_arr = [] - filename_arr = [] - for i in files: - # Get log g values from the column header the file - t = Table.read(i, format='fits') - keys = t.keys() - logg_vals = keys[1:] - - # Extract temp from filename - name = i.split('_') - temp = float(name[1][:-5]) - for j in logg_vals: - logg = float(j[1:]) - index = '{0:5.0f},{1:2.1f},{2:2.1f}'.format(temp, met, logg) - filename = path_to_dir + i + '[' + j + ']' - # Add row to table - index_arr.append(index) - filename_arr.append(filename) - - catalog = Table([index_arr, filename_arr], names=('INDEX', 'FILENAME')) - - # Return to starting directory, write catalog - os.chdir(start_dir) - - if os.path.exists('catalog.fits'): - from astropy.table import vstack - - prev_catalog = Table.read('catalog.fits', format='fits') - joined_catalog = vstack([prev_catalog, catalog]) - - joined_catalog.write('catalog.fits', format='fits', overwrite=True) - else: - catalog.write('catalog.fits', format='fits', overwrite=True) - - return - -def cdbs_PHOENIXv16(path_to_cdbs_dir): - """ - Put the PHOENIXv16 (Husser+13) fits files into cdbs format. This primarily - consists of adjusting the flux units from [erg/s/cm^2/cm] to [erg/s/cm^2/A] - and adding the appropriate keywords to the fits header. - - path_to_cdbs_dir goes from current working directory to phoenix[met] directory - in cdbs/grids/phoenix_v16. Note that these files have already been organized - using organize_PHOENIXv16_atmospheres code. - - Overwrites original files in directory - """ - # Save starting directory for later, move into working directory - start_dir = os.getcwd() - os.chdir(path_to_cdbs_dir) - - # Collect the filenames, make necessary changes to each one - files = glob.glob('phoenix*.fits') - - ## Need to sort filenames; glob doesn't always give them in order - files.sort() - - # Need to make brand-new fits tables with data we want. - counter = 0 - for i in files: - counter += 1 - - # Read in current FITS table - cur_table = Table.read(i, format='fits') - - cur_table.columns[0].name = 'Wavelength' - - num_cols = len(cur_table.colnames) - - # Multiplying each flux column by 10^-8 for conversion - for cur_col_index in range(1, num_cols, 1): - cur_col_name = cur_table.colnames[cur_col_index] - cur_table[cur_col_name] = cur_table[cur_col_name] * 10.**-8 - - - # Construct new FITS file based on old one - hdu = fits.open(i) - header_0 = hdu[0].header - header_1 = hdu[1].header - sci = hdu[1].data - - tbhdu = fits.table_to_hdu(cur_table) - - # Copying over the older headers, adding unit keywords - prihdu = fits.PrimaryHDU(header=header_0) - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - tbhdu.header['TUNIT3'] = 'FLAM' - tbhdu.header['TUNIT4'] = 'FLAM' - tbhdu.header['TUNIT5'] = 'FLAM' - tbhdu.header['TUNIT6'] = 'FLAM' - tbhdu.header['TUNIT7'] = 'FLAM' - tbhdu.header['TUNIT8'] = 'FLAM' - tbhdu.header['TUNIT9'] = 'FLAM' - tbhdu.header['TUNIT10'] = 'FLAM' - tbhdu.header['TUNIT11'] = 'FLAM' - tbhdu.header['TUNIT12'] = 'FLAM' - tbhdu.header['TUNIT13'] = 'FLAM' - tbhdu.header['TUNIT14'] = 'FLAM' - - # Construct and write out final FITS file - finalhdu = fits.HDUList([prihdu, tbhdu]) - finalhdu.writeto(i, overwrite=True) - - hdu.close() - print( 'Done {0:2.0f} of {1:2.0f}'.format(counter, len(files))) - - # Change back to starting directory - os.chdir(start_dir) - - return - -def rebin_phoenixV16(cdbs_path): - """ - Rebin phoenixV16 models to atlas ck04 resolution; this makes - spectrophotometry MUCH faster - - makes new directory in cdbs/grid: phoenix_v16_rebin - - cdbs_path: path to cdbs directory - """ - # Get an atlas ck04 model, we will use this to set wavelength grid - sp_atlas = get_castelli_atmosphere() - - # Open a fits table for an existing phoenix model; we will steal the header - ## (This assumes that at least 'm00' metallicity exists) - tmp = '{0}/grid/phoenix_v16/phoenix{1}/phoenix{1}_02400.fits'.format(cdbs_path, 'm00') - phoenix_hdu = fits.open(tmp) - header0 = phoenix_hdu[0].header - - # Create cdbs/grid directory for rebinned models - path = cdbs_path+'/grid/phoenix_v16_rebin/' - if not os.path.exists(path): - os.mkdir(path) - - - # Read in the existing catalog.fits file and rebin every spectrum. - cat = fits.getdata(cdbs_path + '/grid/phoenix_v16/catalog.fits') - files_all = [cat[ii][1].split('[')[0] for ii in range(len(cat))] - temp_arr = np.zeros(len(files_all), dtype=float) - logg_arr = np.zeros(len(files_all), dtype=float) - metal_arr = np.zeros(len(files_all), dtype=float) - - for ff in range(len(files_all)): - vals = cat[ff][0].split(',') - - temp_arr[ff] = float(vals[0]) - metal_arr[ff] = float(vals[1]) - logg_arr[ff] = float(vals[2]) - - - metal_uniq = np.unique(metal_arr) - temp_uniq = np.unique(temp_arr) - - for mm in range(len(metal_uniq)): - metal = metal_uniq[mm] # metallicity - - # Construct str for metallicity (for appropriate directory name) - met_str = str(int(np.abs(metal))) + str(int((metal % 1.0)*10)) - if metal > 0: - met_str = 'p' + met_str - else: - met_str = 'm' + met_str - - # Make directory for current metallicity if it does not exist yet - if not os.path.exists(path + 'phoenix' + met_str): - os.mkdir(path + 'phoenix' + met_str) - - for tt in range(len(temp_uniq)): - temp = temp_uniq[tt] # temperature - - # Pick out the list of gravities for this T, Z combo - idx = np.where((metal_arr == metal) & (temp_arr == temp))[0] - logg_exist = logg_arr[idx] - - # All gravities will go in one file. Here is the output - # file name. - outfile = path + files_all[idx[0]].split('[')[0] - - ## If the rebinned file already exists, continue - if os.path.exists(outfile): - continue - - # Build a columns array. One column for each gravity. - cols_arr = [] - - # Make the wavelength column, which is first in the cols array. - c0 = fits.Column(name='Wavelength', format='D', array=sp_atlas.wave) - cols_arr.append(c0) - - for gg in range(len(logg_exist)): - grav = logg_exist[gg] # gravity - - # Fetch the spectrum - sp = pysynphot.Icat('phoenix_v16', temp, metal, grav) - flux_rebin = rebin_spec(sp.wave, sp.flux, sp_atlas.wave) - - # Store the spectrum - name = 'g{0:3.1f}'.format(grav) - col = fits.Column(name=name, format='E', array=flux_rebin) - cols_arr.append(col) - - - # Make the FITS file from the columns with header. - cols = fits.ColDefs(cols_arr) - tbhdu = fits.BinTableHDU.from_columns(cols) - prihdu = fits.PrimaryHDU(header=header0) - tbhdu.header['TUNIT1'] = 'ANGSTROM' - for gg in range(len(logg_exist)): - tbhdu.header['TUNIT{0:d}'.format(gg+2)] = 'FLAM' - - # Write hdu - finalhdu = fits.HDUList([prihdu, tbhdu]) - # don't have overwrite to protect original files. - finalhdu.writeto(outfile) - - print( 'Finished file ' + outfile + ' with gravities: ', logg_exist) - - - return - - -def rebin_spec(wave, specin, wavnew): - """ - Helper routine to rebin spectra. TAKEN FROM ASTROBETTER BLOG FROM JESSICA: - http://www.astrobetter.com/blog/2013/08/12/ - python-tip-re-sampling-spectra-with-pysynphot/ - """ - spec = pysynphot.spectrum.ArraySourceSpectrum(wave=wave, flux=specin) - f = np.ones(len(wave)) - filt = pysynphot.spectrum.ArraySpectralElement(wave, f, waveunits='angstrom') - obs = pysynphot.observation.Observation(spec, filt, binset=wavnew, force='taper') - - return obs.binflux - -def organize_BTSettl_2015_atmospheres(path_to_dir): - """ - Construct cdbs-ready BTSettl_CIFITS_2011_2015 atmospheres for each model. - Will convert wavelength units to angstroms and flux units to [erg/s/cm^2/A] - - path_to_dir is the path to the directory containing all of the downloaded - files - - Saves cdbs-ready atmospheres into os.environ['PYSYN_CDBS']/grid/BTSettl_2015 - (assumes this directory exists) - """ - # Save current directory for return later, move into working dir - start_dir = os.getcwd() - os.chdir(path_to_dir) - - # If it doesn't already exist, create the BTSettl subdirectory - if not os.path.exists('BTSettl_2015'): - os.mkdir('BTSettl_2015') - - # Process each atmosphere file independently - print( 'Creating cdbs-ready files') - files = glob.glob('*.spec.fits') - - for i in files: - hdu = fits.open(i) - spec = hdu[1].data - header_0 = hdu[0].header - header_1 = hdu[1].header - - wave = spec.field(0) - flux = spec.field(1) - - # Get units right: convert wave from microns to Angstroms, - # flux from W /m^2/ micron to erg/s/cm^2/A - wave_new = wave * 10**4 - flux_new = flux * 10**(-1) - - # Make new fits table - c0 = fits.Column(name='Wavelength', format='D', array=wave_new) - c1 = fits.Column(name='Flux', format='E', array=flux_new) - - cols = fits.ColDefs([c0, c1]) - tbhdu = fits.BinTableHDU.from_columns(cols) - - # Copy over headers, update unit keywords - prihdu = fits.PrimaryHDU(header=header_0) - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - hdu_new = fits.HDUList([prihdu, tbhdu]) - - # Write new fits table in cdbs directory - hdu_new.writeto(os.environ['PYSYN_CDBS']+'grid/BTSettl_2015/'+i, overwrite=True) - - hdu.close() - hdu_new.close() - - # Return to original directory - os.chdir(start_dir) - return - -def make_BTSettl_2015_catalog(path_to_dir): - """ - Create cdbs catalog.fits of BTSettl_CIFITS2011_2015 grid. - THIS IS STEP 2, after organize_CMFGEN_atmospheres has - been run. - - path_to_dir is from current working directory to the cdbs directory. - Will create catalog.fits file in atmosphere directory with - description of each model - """ - # Record current working directory for later - start_dir = os.getcwd() - - # Enter atmosphere directory - os.chdir(path_to_dir) - - # Extract parameters for each atmosphere from the filename, - # construct columns for catalog file - files = glob.glob("*spec.fits") - index_str = [] - name_str = [] - for name in files: - tmp = name.split('-') - temp = float(tmp[0][3:]) * 100.0 # In kelvin - logg = float(tmp[1]) - - index_str.append('{0:5.0f},0.0,{1:3.2f}'.format(temp, logg)) - name_str.append('{0}[Flux]'.format(name)) - - # Make catalog - catalog = Table([index_str, name_str], names = ('INDEX', 'FILENAME')) - - # Create catalog.fits file in directory with the models - catalog.write('catalog.fits', format = 'fits', overwrite=True) - - # Move back to original directory, create the catalog.fits file - os.chdir(start_dir) - - return - -def rebin_BTSettl_2015(cdbs_path=os.environ['PYSYN_CDBS']): - """ - Rebin BTSettle_CIFITS2011_2015 models to atlas ck04 resolution; this makes - spectrophotometry MUCH faster - - makes new directory in cdbs/grid: BTSettl_2015_rebin - - cdbs_path: path to cdbs directory - """ - # Get an atlas ck04 model, we will use this to set wavelength grid - sp_atlas = get_castelli_atmosphere() - - # Open a fits table for an existing phoenix model; we will steal the header - tmp = cdbs_path+'/grid/phoenix_v16/phoenixm00/phoenixm00_02400.fits' - phoenix_hdu = fits.open(tmp) - header0 = phoenix_hdu[0].header - phoenix_hdu.close() - - # Create cdbs/grid directory for rebinned models - path = cdbs_path+'/grid/BTSettl_2015_rebin/' - if not os.path.exists(path): - os.mkdir(path) - - # Read in the existing catalog.fits file and rebin every spectrum. - cat = fits.getdata(cdbs_path + '/grid/BTSettl_2015/catalog.fits') - files_all = [cat[ii][1].split('[')[0] for ii in range(len(cat))] - - print( 'Rebinning BTSettl spectra') - for ff in range(len(files_all)): - vals = cat[ff][0].split(',') - temp = float(vals[0]) - metal = float(vals[1]) - logg = float(vals[2]) - - # Fetch the BTSettl spectrum, rebin flux - sp = pysynphot.Icat('BTSettl_2015', temp, metal, logg) - flux_rebin = rebin_spec(sp.wave, sp.flux, sp_atlas.wave) - - # Make new output - c0 = fits.Column(name='Wavelength', format='D', array=sp_atlas.wave) - c1 = fits.Column(name='Flux', format='E', array=flux_rebin) - - cols = fits.ColDefs([c0, c1]) - tbhdu = fits.BinTableHDU.from_columns(cols) - prihdu = fits.PrimaryHDU(header=header0) - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - - outfile = path + files_all[ff].split('[')[0] - finalhdu = fits.HDUList([prihdu, tbhdu]) - finalhdu.writeto(outfile, overwrite=True) - - return - -def make_wavelength_unique(files, dirname): - """ - Helper function to go through each BTSettl spectrum and ensure that - each wavelength point is unique. This is required for rebinning to work. - - - files: list of files to run this analysis on - """ - # Loop through each file, find fix repeated wavelength entries if necessary - for i in files: - t = Table.read('{0}/{1}'.format(dirname,i), format='fits') - test = np.unique(t['Wavelength'], return_index=True) - - if len(t) != len(test[0]): - t = t[test[1]] - - c0 = fits.Column(name='Wavelength', format='D', array=t['Wavelength']) - c1 = fits.Column(name='Flux', format='E', array=t['Flux']) - cols = fits.ColDefs([c0, c1]) - - tbhdu = fits.BinTableHDU.from_columns(cols) - prihdu = fits.PrimaryHDU() - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - finalhdu = fits.HDUList([prihdu, tbhdu]) - finalhdu.writeto('{0}/{1}'.format(dirname,i), overwrite=True) - - # Also make sure wavelength is monotonic. If it is not, then it is - # a sign that the wavelengths are out of order - diff = np.diff(t['Wavelength']) - bad = np.where(diff < 0) - if len(bad[0]) > 0: - t.sort('Wavelength') - - c0 = fits.Column(name='Wavelength', format='D', array=t['Wavelength']) - c1 = fits.Column(name='Flux', format='E', array=t['Flux']) - cols = fits.ColDefs([c0, c1]) - - tbhdu = fits.BinTableHDU.from_columns(cols) - prihdu = fits.PrimaryHDU() - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - finalhdu = fits.HDUList([prihdu, tbhdu]) - finalhdu.writeto('{0}/{1}'.format(dirname,i), overwrite=True) - - print('Done {0}'.format(i)) - - return - -def organize_BTSettl_atmospheres(): - """ - Construct cdbs-ready atmospheres for the BTSettl grid (CIFITS2011). - The code expects tp be run in cdbs/grid/BTSettl, and expects that the - individual model files have been downloaded from online - (https://phoenix.ens-lyon.fr/Grids/BT-Settl/CIFIST2011/SPECTRA/) - and processed into python-readable ascii files. - """ - orig_dir = os.getcwd() - dirs = ['btm25', 'btm20', 'btm15', 'btm10', 'btm05', 'btp00', 'btp05'] - #dirs = ['btm10', 'btm05', 'btp00', 'btp05'] - - - # Go through each directory, turning each spectrum into a cdbs-ready file. - # Will convert flux into Ergs/sec/cm**2/A (FLAM) units and save as a fits file, - # for faster access later - for ii in dirs: - print('Starting {0}'.format(ii)) - os.chdir(ii) - - files = glob.glob('*.txt') - count=0 - for jj in files: - t = Table.read(jj, format='ascii') - # First, trim the wavelengths to a more reasonable wavelength range - good = np.where( (t['col1'] > 1000) & (t['col1'] < 70000) ) - t = t[good] - - # Convert flux units to Flam (Ergs/sec/cm**2/A) - flux_new = 10**(t['col2'] - 8.0) - - # Save the file as a fits file - c0 = fits.Column(name='Wavelength', format='D', array=t['col1']) - c1 = fits.Column(name='Flux', format='E', array=flux_new) - - cols = fits.ColDefs([c0, c1]) - tbhdu = fits.BinTableHDU.from_columns(cols) - - # Add unit keywords - prihdu = fits.PrimaryHDU() - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - hdu_new = fits.HDUList([prihdu, tbhdu]) - - # Write new fits table in cdbs directory - hdu_new.writeto('{0}.fits'.format(jj[:-4]), overwrite=True) - hdu_new.close() - count += 1 - print('Done {0} of {1}'.format(count, len(files))) - - # Now, clean up all the files made when unzipping the spectra - cmd1 = 'rm *.bz2' - cmd2 = 'rm *.tmp' - #cmd3 = 'rm *.txt' - os.system(cmd1) - os.system(cmd2) - #os.system(cmd3) - print('==============================') - print('Done {0}'.format(ii)) - print('==============================') - - # Go back to original directory, move to next metallicity directory - os.chdir(orig_dir) - - return - -def make_BTSettl_catalog(): - """ - Create cdbs catalog.fits of BTSettl grid. - THIS IS STEP 2, after organize_BTSettl_atmospheres has - been run. - - Code expects to be run in cdbs/grid/BTSettl - Will create catalog.fits file in atmosphere directory with - description of each model - """ - # Record current working directory for later - start_dir = os.getcwd() - dirs = ['btm25', 'btm20', 'btm15', 'btm10', 'btm05', 'btp00', 'btp05'] - #dirs = ['btp05'] - - # Construct the catalog.fits file input. The input consists of - # and index string that specifies the stellar paramters, and a - # name string that points to the file - # Loop over all the metallicity directories to construct these inputs - index_str = [] - name_str = [] - for ii in dirs: - os.chdir(ii) - files = glob.glob('*.fits') - - # Construct the metallicity val - if 'm' in ii: - metal_flag = -1 * float(ii[3:])*0.1 - else: - metal_flag = float(ii[3:])*0.1 - - # Now collect the info from the files - for jj in files: - tmp = jj.split('-') - - if metal_flag >= 0: - temp = float(tmp[0].split('+')[0][3:]) * 100.0 # In kelvin - try: - logg = float(tmp[1]) - except: - logg = float(tmp[1].split('+')[0]) - else: - temp = float(tmp[0][3:]) * 100.0 # In kelvin - logg = float(tmp[1]) - - index_str.append('{0},{1},{2:3.2f}'.format(int(temp), metal_flag, logg)) - name_str.append('{0}/{1}[Flux]'.format(ii, jj)) - - # Go back to original directory to move to next metallicity - print('Done {0}'.format(ii)) - os.chdir(start_dir) - - # Make catalog - catalog = Table([index_str, name_str], names = ('INDEX', 'FILENAME')) - - # Create catalog.fits file in directory with the models - catalog.write('catalog.fits', format = 'fits', overwrite=True) - - # Move back to original directory, create the catalog.fits file - os.chdir(start_dir) - - return - -def rebin_BTSettl(make_unique=False): - """ - Rebin BTSettle models to atlas ck04 resolution; this makes - spectrophotometry MUCH faster - - makes new directory: BTSettl_rebin - - Code expects to be run in cdbs/grid directory - """ - # Get an atlas ck04 model, we will use this to set wavelength grid - sp_atlas = get_castelli_atmosphere() - - # Create cdbs/grid directory for rebinned models - path = 'BTSettl_rebin/' - if not os.path.exists(path): - os.mkdir(path) - - # Read in the existing catalog.fits file and rebin every spectrum. - cat = fits.getdata('BTSettl/catalog.fits') - files_all = [cat[ii][1].split('[')[0] for ii in range(len(cat))] - - #==============================# - #tmp = [] - #for ii in files_all: - # if ii.startswith('btp00'): - # tmp.append(ii) - #files_all = tmp - #=============================# - - print( 'Rebinning BTSettl spectra') - if make_unique: - print('Making unique') - make_wavelength_unique(files_all, 'BTSettl') - print('Done') - - for ff in range(len(files_all)): - vals = cat[ff][0].split(',') - temp = float(vals[0]) - metal = float(vals[1]) - logg = float(vals[2]) - - # Fetch the BTSettl spectrum, rebin flux - try: - sp = pysynphot.Icat('BTSettl', temp, metal, logg) - flux_rebin = rebin_spec(sp.wave, sp.flux, sp_atlas.wave) - - # Make new output - c0 = fits.Column(name='Wavelength', format='D', array=sp_atlas.wave) - c1 = fits.Column(name='Flux', format='E', array=flux_rebin) - - cols = fits.ColDefs([c0, c1]) - tbhdu = fits.BinTableHDU.from_columns(cols) - prihdu = fits.PrimaryHDU() - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - - outfile = path + files_all[ff].split('[')[0] - finalhdu = fits.HDUList([prihdu, tbhdu]) - finalhdu.writeto(outfile, overwrite=True) - except: - pdb.set_trace() - orig_file = '{0}/{1}'.format('BTSettl/', files_all[ff].split('[')[0]) - outfile = path + files_all[ff].split('[')[0] - cmd = 'cp {0} {1}'.format(orig_file, outfile) - os.system(cmd) - - print('Done {0} of {1}'.format(ff, len(files_all))) - - return - -def organize_WDKoester_atmospheres(path_to_dir): - """ - Construct cdbs-ready wdKoester WD atmospheres for each model. (from Koester 2010) - Will convert wavelength units to angstroms and flux units to [erg/s/cm^2/A] - - path_to_dir is the path to the directory containing all of the downloaded - files - - Saves cdbs-ready atmospheres into os.environ['PYSYN_CDBS']/wdKoeseter - (assumes this directory exists) - """ - # Save current directory for return later, move into working dir - start_dir = os.getcwd() - os.chdir(path_to_dir) - - # Process each atmosphere file independently - print( 'Creating cdbs-ready files') - files = glob.glob('*.dk.dat.txt') - - for i in files: - data = Table.read(i, format='ascii') - - wave = data['col1'] # angstrom - flux = data['col2'] # erg/s/cm^2/A - - # Make new fits table - c0 = fits.Column(name='Wavelength', format='D', array=wave) - c1 = fits.Column(name='Flux', format='E', array=flux) - - cols = fits.ColDefs([c0, c1]) - tbhdu = fits.BinTableHDU.from_columns(cols) - - # Copy over headers, update unit keywords - prihdu = fits.PrimaryHDU() - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - hdu_new = fits.HDUList([prihdu, tbhdu]) - - # Write new fits table in cdbs directory - hdu_new.writeto(os.environ['PYSYN_CDBS']+'/grid/wdKoester/'+i.replace('.txt', '.fits'), overwrite=True) - - hdu_new.close() - - # Return to original directory - os.chdir(start_dir) - return - -def make_WDKoester_catalog(path_to_dir): - """ - Create cdbs catalog.fits of wdKoester grid. - THIS IS STEP 2, after organize_WDKoester_atmospheres has - been run. - - path_to_dir is from current working directory to the cdbs directory. - Will create catalog.fits file in atmosphere directory with - description of each model - """ - # Record current working directory for later - start_dir = os.getcwd() - - # Enter atmosphere directory - os.chdir(path_to_dir) - - # Extract parameters for each atmosphere from the filename, - # construct columns for catalog file - files = glob.glob("*dk.dat.fits") - index_str = [] - name_str = [] - for name in files: - tmp = name.split('.') - tmp2 = tmp[0].split('_') - temp = float(tmp2[0][2:]) # Kelvin - logg = float(tmp2[1]) / 100.0 # log(g) - - index_str.append('{0:5.0f},0.0,{1:3.2f}'.format(temp, logg)) - name_str.append('{0}[Flux]'.format(name)) - - # Make catalog - catalog = Table([index_str, name_str], names = ('INDEX', 'FILENAME')) - - # Create catalog.fits file in directory with the models - catalog.write('catalog.fits', format = 'fits', overwrite=True) - - # Move back to original directory, create the catalog.fits file - os.chdir(start_dir) - - return - -def rebin_WDKoester(cdbs_path=os.environ['PYSYN_CDBS']): - """ - Rebin wdKoester models to atlas ck04 resolution; this makes - spectrophotometry MUCH faster - - makes new directory in cdbs/grid: wdKoester_rebin - - cdbs_path: path to cdbs directory - """ - # Get an atlas ck04 model, we will use this to set wavelength grid - sp_atlas = get_castelli_atmosphere() - - # Open a fits table for an existing model; we will steal the header - tmp = cdbs_path+'/grid/wdKoester/da70000_800.dk.dat.fits' - wdkoester_hdu = fits.open(tmp) - header0 = wdkoester_hdu[0].header - wdkoester_hdu.close() - - # Create cdbs/grid directory for rebinned models - path = cdbs_path+'/grid/wdKoester_rebin/' - if not os.path.exists(path): - os.mkdir(path) - - # Read in the existing catalog.fits file and rebin every spectrum. - cat = fits.getdata(cdbs_path + '/grid/wdKoester/catalog.fits') - files_all = [cat[ii][1].split('[')[0] for ii in range(len(cat))] - - print( 'Rebinning wdKoester spectra') - for ff in range(len(files_all)): - vals = cat[ff][0].split(',') - temp = float(vals[0]) - metal = float(vals[1]) - logg = float(vals[2]) - - # Fetch the wdKoester spectrum, rebin flux - sp = pysynphot.Icat('wdKoester', temp, metal, logg) - flux_rebin = rebin_spec(sp.wave, sp.flux, sp_atlas.wave) - - # Make new output - c0 = fits.Column(name='Wavelength', format='D', array=sp_atlas.wave) - c1 = fits.Column(name='Flux', format='E', array=flux_rebin) - - cols = fits.ColDefs([c0, c1]) - tbhdu = fits.BinTableHDU.from_columns(cols) - prihdu = fits.PrimaryHDU(header=header0) - tbhdu.header['TUNIT1'] = 'ANGSTROM' - tbhdu.header['TUNIT2'] = 'FLAM' - - outfile = path + files_all[ff].split('[')[0] - finalhdu = fits.HDUList([prihdu, tbhdu]) - finalhdu.writeto(outfile, overwrite=True) - - return - - From 1293ea8ecf531e5f8ebe6f258ee940abc524fece Mon Sep 17 00:00:00 2001 From: nsabrams Date: Wed, 17 Jun 2026 14:43:44 -0700 Subject: [PATCH 26/28] updated contributors file --- docs/contributors.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/contributors.rst b/docs/contributors.rst index c3b51bdf..9cb44a45 100644 --- a/docs/contributors.rst +++ b/docs/contributors.rst @@ -19,7 +19,7 @@ Dongwon Kim -- code testing/debugging Siyao Jia -- helped with early code and documentation development Natasha Abrams -- developed resolved multiplicity capabilities -(ResolvedMultiplicityDK class) +(ResolvedMultiplicityDK class) and added COSMIC support. Michael Medford -- developed resolved multiplicity capabilities (ResolvedMultiplicityDK class) @@ -49,4 +49,4 @@ files, Vega mag to ST mag conversion function (v2.4) Anna Pusack -- Added IRTF L-band filter support -Caitlin Begbie -- added brown dwarf physics and capabilities \ No newline at end of file +Caitlin Begbie -- added brown dwarf physics and capabilities From 9b39f7ddcde637b84e31a24b0f02acd03151e981 Mon Sep 17 00:00:00 2001 From: nsabrams Date: Wed, 17 Jun 2026 15:04:34 -0700 Subject: [PATCH 27/28] fixed tiny path typo in docs --- docs/atmo_models.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/atmo_models.rst b/docs/atmo_models.rst index fda94778..b54056bc 100644 --- a/docs/atmo_models.rst +++ b/docs/atmo_models.rst @@ -4,7 +4,7 @@ Atmosphere Model Object ======================================== Stellar atmosphere models are defined as functions in -``popstar/atmospheres.py``. These can be called by:: +``spisea/atmospheres.py``. These can be called by:: from popstar import atmospheres atmo = atmospheres. From 1548f21f9d9724d56a746e1e3a29f78609985ca9 Mon Sep 17 00:00:00 2001 From: nsabrams Date: Thu, 18 Jun 2026 15:22:08 -0700 Subject: [PATCH 28/28] edited test to make sure cluster mass within 2 percent rather than specific number --- spisea/tests/test_imf.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spisea/tests/test_imf.py b/spisea/tests/test_imf.py index 969e550d..943dc0a1 100755 --- a/spisea/tests/test_imf.py +++ b/spisea/tests/test_imf.py @@ -19,8 +19,8 @@ def test_generate_cluster(): mass, isMulti, compMass, sysMass = my_imf.generate_cluster(M_cl) # Make sure that the total mass is always within the expected - # range of the requested mass. - assert np.abs(M_cl - sysMass.sum()) < 120.0 + # range of the requested mass (2%). + assert np.abs(M_cl - sysMass.sum()) < M_cl*0.02 # Check that enough companions were generated. # Should be greater than 25% of the stars with companions.