cosmic-popsynth 3.6.2__cp313-cp313-macosx_14_0_arm64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cosmic/.dylibs/libgcc_s.1.1.dylib +0 -0
- cosmic/.dylibs/libgfortran.5.dylib +0 -0
- cosmic/.dylibs/libquadmath.0.dylib +0 -0
- cosmic/Match.py +191 -0
- cosmic/__init__.py +32 -0
- cosmic/_commit_hash.py +1 -0
- cosmic/_evolvebin.cpython-313-darwin.so +0 -0
- cosmic/_version.py +1 -0
- cosmic/bse_utils/__init__.py +18 -0
- cosmic/bse_utils/zcnsts.py +570 -0
- cosmic/bse_utils/zdata.py +596 -0
- cosmic/checkstate.py +128 -0
- cosmic/data/cosmic-settings.json +1635 -0
- cosmic/evolve.py +607 -0
- cosmic/filter.py +214 -0
- cosmic/get_commit_hash.py +15 -0
- cosmic/output.py +466 -0
- cosmic/plotting.py +680 -0
- cosmic/sample/__init__.py +26 -0
- cosmic/sample/cmc/__init__.py +18 -0
- cosmic/sample/cmc/elson.py +411 -0
- cosmic/sample/cmc/king.py +260 -0
- cosmic/sample/initialbinarytable.py +251 -0
- cosmic/sample/initialcmctable.py +449 -0
- cosmic/sample/sampler/__init__.py +25 -0
- cosmic/sample/sampler/cmc.py +418 -0
- cosmic/sample/sampler/independent.py +1252 -0
- cosmic/sample/sampler/multidim.py +882 -0
- cosmic/sample/sampler/sampler.py +130 -0
- cosmic/test_evolve.py +108 -0
- cosmic/test_match.py +30 -0
- cosmic/test_sample.py +580 -0
- cosmic/test_utils.py +198 -0
- cosmic/utils.py +1574 -0
- cosmic_popsynth-3.6.2.data/scripts/cosmic-pop +544 -0
- cosmic_popsynth-3.6.2.dist-info/METADATA +55 -0
- cosmic_popsynth-3.6.2.dist-info/RECORD +38 -0
- cosmic_popsynth-3.6.2.dist-info/WHEEL +6 -0
cosmic/plotting.py
ADDED
|
@@ -0,0 +1,680 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright (C) Katelyn Breivik (2017 - 2021)
|
|
3
|
+
#
|
|
4
|
+
# This file is part of cosmic.
|
|
5
|
+
#
|
|
6
|
+
# cosmic is free software: you can redistribute it and/or modify
|
|
7
|
+
# it under the terms of the GNU General Public License as published by
|
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
9
|
+
# (at your option) any later version.
|
|
10
|
+
#
|
|
11
|
+
# cosmic is distributed in the hope that it will be useful,
|
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14
|
+
# GNU General Public License for more details.
|
|
15
|
+
#
|
|
16
|
+
# You should have received a copy of the GNU General Public License
|
|
17
|
+
# along with cosmic. If not, see <http://www.gnu.org/licenses/>.
|
|
18
|
+
|
|
19
|
+
"""`plotting`
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
import numpy as np
|
|
23
|
+
import pandas as pd
|
|
24
|
+
import matplotlib.pyplot as plt
|
|
25
|
+
import matplotlib.gridspec as gridspec
|
|
26
|
+
import matplotlib.patches as mpatches
|
|
27
|
+
|
|
28
|
+
from matplotlib.lines import Line2D
|
|
29
|
+
from .utils import a_from_p, calc_Roche_radius
|
|
30
|
+
from .evolve import Evolve
|
|
31
|
+
|
|
32
|
+
__author__ = "Jeff Andrews <andrews.jeff@gmail.com>"
|
|
33
|
+
__all__ = [
|
|
34
|
+
"evolve_binary",
|
|
35
|
+
"plot_k_type",
|
|
36
|
+
"plot_radius",
|
|
37
|
+
"plot_mass",
|
|
38
|
+
"plot_Teff",
|
|
39
|
+
"plot_Mdot",
|
|
40
|
+
"plot_P_orb",
|
|
41
|
+
"plot_ecc",
|
|
42
|
+
"plot_HR_diagram",
|
|
43
|
+
"plot_binary_evol",
|
|
44
|
+
"evolve_and_plot",
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
# Colors
|
|
48
|
+
primary_color = "C0"
|
|
49
|
+
secondary_color = "C1"
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def evolve_binary(initC, t_min=None, t_max=None, BSEDict={}):
|
|
53
|
+
"""
|
|
54
|
+
Evolves a single binary with all timesteps written
|
|
55
|
+
to the bcm array for plotting
|
|
56
|
+
|
|
57
|
+
Parameters
|
|
58
|
+
----------
|
|
59
|
+
initC : `pandas.DataFrame`
|
|
60
|
+
initial conditions for binary to evolve
|
|
61
|
+
|
|
62
|
+
t_min : `float`
|
|
63
|
+
starting time for plot in Myr
|
|
64
|
+
|
|
65
|
+
t_max : `float`
|
|
66
|
+
ending time for plot in Myr
|
|
67
|
+
|
|
68
|
+
BSEDict : `Dict`
|
|
69
|
+
Dictionary containing all BSE flags needed
|
|
70
|
+
|
|
71
|
+
Returns
|
|
72
|
+
-------
|
|
73
|
+
bcm : `pandas.DataFrame`
|
|
74
|
+
binary evolution data form BSE's bcm dict
|
|
75
|
+
"""
|
|
76
|
+
|
|
77
|
+
# Disable chained warning for now which throws
|
|
78
|
+
# a warning for setting dtp and tphysf
|
|
79
|
+
pd.options.mode.chained_assignment = None
|
|
80
|
+
|
|
81
|
+
# Get highest BSE temporal resolution
|
|
82
|
+
BSEDict["dtp"] = 0.01
|
|
83
|
+
|
|
84
|
+
# To deal with the limited size of the bcm array, we need to reduce
|
|
85
|
+
# the time resolution if we are evolving a binary for more than 100 Myr
|
|
86
|
+
if t_max is not None:
|
|
87
|
+
if t_min is not None:
|
|
88
|
+
if t_max - t_min > 100:
|
|
89
|
+
BSEDict["dtp"] = (t_max - t_min) / 10000
|
|
90
|
+
else:
|
|
91
|
+
if t_max > 100:
|
|
92
|
+
BSEDict["dtp"] = t_max / 10000
|
|
93
|
+
|
|
94
|
+
# Set maximum time for evolution
|
|
95
|
+
if t_max is not None:
|
|
96
|
+
initC["tphysf"] = t_max
|
|
97
|
+
|
|
98
|
+
# Call evolution scripts
|
|
99
|
+
bpp, bcm, initC, kick_info = Evolve.evolve(
|
|
100
|
+
initialbinarytable=initC, BSEDict=BSEDict
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
# In case minimum and maximum times are not supplied by user
|
|
104
|
+
if t_min is None:
|
|
105
|
+
# BUG HERE - BSE sets first value to weird float
|
|
106
|
+
# HACKED FIX
|
|
107
|
+
t_phys = np.array(bcm.tphys)
|
|
108
|
+
t_phys[0] = 0.0
|
|
109
|
+
bcm.at[0, "tphys"] = t_phys
|
|
110
|
+
t_min = bcm.tphys.min()
|
|
111
|
+
if t_max is None:
|
|
112
|
+
t_max = bcm.tphys.max()
|
|
113
|
+
|
|
114
|
+
# Select for temporal range
|
|
115
|
+
bcm = bcm.loc[(bcm.tphys <= t_max) & (bcm.tphys >= t_min)]
|
|
116
|
+
|
|
117
|
+
return bcm
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def plot_k_type(ax_1, ax_2, ax_k_type_list, times, k1_out, k2_out,
|
|
121
|
+
k_type_colors=None, k_type_labels=None):
|
|
122
|
+
"""Plots the stellar types as a function of time
|
|
123
|
+
|
|
124
|
+
Parameters
|
|
125
|
+
----------
|
|
126
|
+
ax_1 : `matplotlib.Axes`
|
|
127
|
+
Axis instance for kstar 1
|
|
128
|
+
|
|
129
|
+
ax_2 : `matplotlib.Axes`
|
|
130
|
+
Axis instance for kstar 2
|
|
131
|
+
|
|
132
|
+
ax_k_type_list : `list`
|
|
133
|
+
List of ktypes for the legend of the ktype bar plots
|
|
134
|
+
|
|
135
|
+
times : `pandas.Series`
|
|
136
|
+
Series of times at each binary evolution time step in Myr
|
|
137
|
+
|
|
138
|
+
k1_out : `pandas.Series`
|
|
139
|
+
Series of kstar 1 type at each binary evolution time step in Myr
|
|
140
|
+
|
|
141
|
+
k2_out : `pandas.Series`
|
|
142
|
+
Series of kstar 2 type at each binary evolution time step in Myr
|
|
143
|
+
|
|
144
|
+
k_type_colors : `list`
|
|
145
|
+
List of colors for each ktype
|
|
146
|
+
|
|
147
|
+
k_type_labels : `list`
|
|
148
|
+
List of labels for each ktype
|
|
149
|
+
|
|
150
|
+
Returns
|
|
151
|
+
-------
|
|
152
|
+
Null
|
|
153
|
+
"""
|
|
154
|
+
|
|
155
|
+
k_type_colors = [
|
|
156
|
+
"plum",
|
|
157
|
+
"sandybrown",
|
|
158
|
+
"lightseagreen",
|
|
159
|
+
"moccasin",
|
|
160
|
+
"chartreuse",
|
|
161
|
+
"deepskyblue",
|
|
162
|
+
"gold",
|
|
163
|
+
"rosybrown",
|
|
164
|
+
"m",
|
|
165
|
+
"darkgreen",
|
|
166
|
+
"grey",
|
|
167
|
+
"sienna",
|
|
168
|
+
"palevioletred",
|
|
169
|
+
"navy",
|
|
170
|
+
"tan",
|
|
171
|
+
"black",
|
|
172
|
+
] if k_type_colors is None else k_type_colors
|
|
173
|
+
k_type = [
|
|
174
|
+
"MS conv",
|
|
175
|
+
"MS",
|
|
176
|
+
"HG",
|
|
177
|
+
"GB",
|
|
178
|
+
"CHeB",
|
|
179
|
+
"EAGB",
|
|
180
|
+
"TPAGB",
|
|
181
|
+
"HeMS",
|
|
182
|
+
"HeHG",
|
|
183
|
+
"HeGB",
|
|
184
|
+
"HeWD",
|
|
185
|
+
"COWD",
|
|
186
|
+
"ONeWD",
|
|
187
|
+
"NS",
|
|
188
|
+
"BH",
|
|
189
|
+
"no remnant",
|
|
190
|
+
] if k_type_labels is None else k_type_labels
|
|
191
|
+
|
|
192
|
+
# k-type plots
|
|
193
|
+
for a in [ax_1, ax_2]:
|
|
194
|
+
|
|
195
|
+
a.axis("off")
|
|
196
|
+
|
|
197
|
+
for j, k in enumerate(np.unique(k1_out)):
|
|
198
|
+
a.fill_between(times[k1_out == k], 0.7, 0.9, color=k_type_colors[k])
|
|
199
|
+
for j, k in enumerate(np.unique(k2_out)):
|
|
200
|
+
a.fill_between(times[k2_out == k], 0.4, 0.6, color=k_type_colors[k])
|
|
201
|
+
|
|
202
|
+
a.set_title("Stellar Type")
|
|
203
|
+
|
|
204
|
+
a.set_xlim(np.min(times), np.max(times))
|
|
205
|
+
|
|
206
|
+
# Add legend
|
|
207
|
+
ax_k_type_list.axis("off")
|
|
208
|
+
k_type_all = np.unique(np.array([k1_out, k2_out]))
|
|
209
|
+
patches = [
|
|
210
|
+
mpatches.Patch(color=k_type_colors[k], label=k_type[k]) for k in k_type_all
|
|
211
|
+
]
|
|
212
|
+
leg = ax_k_type_list.legend(handles=patches, mode="expand", ncol=len(k_type_all))
|
|
213
|
+
leg.get_frame().set_alpha(0.0)
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
def plot_radius(
|
|
217
|
+
ax, times, R1_out, R2_out, M1_out, M2_out, P_orb_out, ecc_out, sys_obs, legend=True
|
|
218
|
+
):
|
|
219
|
+
"""Plots the stellar radii as a function of time
|
|
220
|
+
|
|
221
|
+
Parameters
|
|
222
|
+
----------
|
|
223
|
+
ax : `matplotlib.Axes`
|
|
224
|
+
Axis instance for the plot
|
|
225
|
+
|
|
226
|
+
times : `pandas.Series`
|
|
227
|
+
Series of times at each binary evolution time step in Myr
|
|
228
|
+
|
|
229
|
+
R1_out : `pandas.Series`
|
|
230
|
+
Series of primary radius at each binary evolution time step in Rsun
|
|
231
|
+
|
|
232
|
+
R2_out : `pandas.Series`
|
|
233
|
+
Series of secondary radius at each binary evolution time step in Rsun
|
|
234
|
+
|
|
235
|
+
M1_out : `pandas.Series`
|
|
236
|
+
Series of primary mass at each binary evolution time step in Msun
|
|
237
|
+
|
|
238
|
+
M2_out : `pandas.Series`
|
|
239
|
+
Series of secondary mass at each binary evolution time step in Msun
|
|
240
|
+
|
|
241
|
+
P_orb_out : `pandas.Series`
|
|
242
|
+
Series of orbital periods at each binary evolution time step in days
|
|
243
|
+
|
|
244
|
+
ecc_out : `pandas.Series`
|
|
245
|
+
Series of eccentricities at each binary evolution time step
|
|
246
|
+
|
|
247
|
+
sys_obs : `Dict`
|
|
248
|
+
Dictionary containing keys for binary parameters with values to plot
|
|
249
|
+
as vertical lines for each stellar component
|
|
250
|
+
|
|
251
|
+
Returns
|
|
252
|
+
-------
|
|
253
|
+
Null
|
|
254
|
+
"""
|
|
255
|
+
# Radius
|
|
256
|
+
ax.plot(times, R1_out, color=primary_color)
|
|
257
|
+
ax.plot(times, R2_out, color=secondary_color)
|
|
258
|
+
|
|
259
|
+
# Plot Roche radii - at periastron
|
|
260
|
+
A_out = a_from_p(M1_out, M2_out, P_orb_out) # in Rsun
|
|
261
|
+
R1_Roche = calc_Roche_radius(M1_out, M2_out, A_out * (1.0 - ecc_out)) # in Rsun
|
|
262
|
+
R2_Roche = calc_Roche_radius(M2_out, M1_out, A_out * (1.0 - ecc_out)) # in Rsun
|
|
263
|
+
ax.plot(times, R1_Roche, color=primary_color, linestyle="--")
|
|
264
|
+
ax.plot(times, R2_Roche, color=secondary_color, linestyle="--")
|
|
265
|
+
|
|
266
|
+
for key, value in sys_obs.items():
|
|
267
|
+
if key == "R1":
|
|
268
|
+
ax.axhline(value, color=primary_color, linestyle="dashed")
|
|
269
|
+
if key == "R2":
|
|
270
|
+
ax.axhline(value, color=secondary_color, linestyle="dashed")
|
|
271
|
+
|
|
272
|
+
ax.set_yscale("log")
|
|
273
|
+
ax.set_ylim(0.5, ax.get_ylim()[1])
|
|
274
|
+
|
|
275
|
+
ax.set_ylabel(r"Radius ($R_{\odot}$)")
|
|
276
|
+
|
|
277
|
+
ax.set_xlim(np.min(times), np.max(times))
|
|
278
|
+
|
|
279
|
+
if legend:
|
|
280
|
+
custom_lines = [
|
|
281
|
+
Line2D([0], [0], color="k", linestyle="solid"),
|
|
282
|
+
Line2D([0], [0], color="k", linestyle="dashed"),
|
|
283
|
+
]
|
|
284
|
+
ax.legend(custom_lines, ["Stellar Radius", "Roche Radius"], frameon=False)
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
def plot_mass(ax, times, M1_out, M2_out, sys_obs):
|
|
288
|
+
"""Plots the stellar mass as a function of time
|
|
289
|
+
|
|
290
|
+
Parameters
|
|
291
|
+
----------
|
|
292
|
+
ax : `matplotlib.Axes`
|
|
293
|
+
Axis instance for the plot
|
|
294
|
+
|
|
295
|
+
times : `pandas.Series`
|
|
296
|
+
Series of times at each binary evolution time step in Myr
|
|
297
|
+
|
|
298
|
+
M1_out : `pandas.Series`
|
|
299
|
+
Series of primary mass at each binary evolution time step in Msun
|
|
300
|
+
|
|
301
|
+
M2_out : `pandas.Series`
|
|
302
|
+
Series of secondary mass at each binary evolution time step in Msun
|
|
303
|
+
|
|
304
|
+
sys_obs : `Dict`
|
|
305
|
+
Dictionary containing keys for binary parameters with values to plot
|
|
306
|
+
as vertical lines for each stellar component
|
|
307
|
+
|
|
308
|
+
Returns
|
|
309
|
+
-------
|
|
310
|
+
Null
|
|
311
|
+
"""
|
|
312
|
+
|
|
313
|
+
# Mass
|
|
314
|
+
ax.plot(times, M1_out, color=primary_color)
|
|
315
|
+
ax.plot(times, M2_out, color=secondary_color)
|
|
316
|
+
|
|
317
|
+
for key, value in sys_obs.items():
|
|
318
|
+
if key == "M1":
|
|
319
|
+
ax.axhline(value, color=primary_color, linestyle="dashed")
|
|
320
|
+
if key == "M2":
|
|
321
|
+
ax.axhline(value, color=secondary_color, linestyle="dashed")
|
|
322
|
+
|
|
323
|
+
ax.set_ylabel(r"Mass ($M_{\odot}$)")
|
|
324
|
+
ax.set_xlim(np.min(times), np.max(times))
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
def plot_Teff(ax, times, Teff1_out, Teff2_out, sys_obs):
|
|
328
|
+
"""Plots the stellar effectvie temperature as a function of time
|
|
329
|
+
|
|
330
|
+
Parameters
|
|
331
|
+
----------
|
|
332
|
+
ax : `matplotlib.Axes`
|
|
333
|
+
Axis instance for the plot
|
|
334
|
+
|
|
335
|
+
times : `pandas.Series`
|
|
336
|
+
Series of times at each binary evolution time step in Myr
|
|
337
|
+
|
|
338
|
+
Teff1_out : `pandas.Series`
|
|
339
|
+
Series of primary effective temperature at each binary evolution time step in K
|
|
340
|
+
|
|
341
|
+
Teff2_out : `pandas.Series`
|
|
342
|
+
Series of secondary effective temperature at each binary evolution time step in K
|
|
343
|
+
|
|
344
|
+
sys_obs : `Dict`
|
|
345
|
+
Dictionary containing keys for binary parameters with values to plot
|
|
346
|
+
as vertical lines for each stellar component
|
|
347
|
+
|
|
348
|
+
Returns
|
|
349
|
+
-------
|
|
350
|
+
Null
|
|
351
|
+
"""
|
|
352
|
+
|
|
353
|
+
# Effective temperature
|
|
354
|
+
ax.plot(times, Teff1_out, color=primary_color)
|
|
355
|
+
ax.plot(times, Teff2_out, color=secondary_color)
|
|
356
|
+
|
|
357
|
+
for key, value in sys_obs.items():
|
|
358
|
+
if key == "T1":
|
|
359
|
+
ax.axhline(value, color=primary_color, linestyle="dashed")
|
|
360
|
+
if key == "T2":
|
|
361
|
+
ax.axhline(value, color=secondary_color, linestyle="dashed")
|
|
362
|
+
|
|
363
|
+
ax.set_yscale("log")
|
|
364
|
+
ax.set_ylabel(r"T$_{\rm eff}$ (K)")
|
|
365
|
+
ax.set_xlim(np.min(times), np.max(times))
|
|
366
|
+
ax.set_xlabel("Time (Myr)")
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
def plot_Mdot(ax, times, Mdot1_out, Mdot2_out, legend=True):
|
|
370
|
+
"""Plots the stellar effectvie temperature as a function of time
|
|
371
|
+
|
|
372
|
+
Parameters
|
|
373
|
+
----------
|
|
374
|
+
ax : `matplotlib.Axes`
|
|
375
|
+
Axis instance for the plot
|
|
376
|
+
|
|
377
|
+
times : `pandas.Series`
|
|
378
|
+
Series of times at each binary evolution time step in Myr
|
|
379
|
+
|
|
380
|
+
Mdot1_out : `pandas.Series`
|
|
381
|
+
Series of primary mass transfer rate at each binary evolution time step in Msun/yr
|
|
382
|
+
|
|
383
|
+
Mdot2_out : `pandas.Series`
|
|
384
|
+
Series of secondary mass transfer rate at each binary evolution time step in Msun/yr
|
|
385
|
+
|
|
386
|
+
sys_obs : `Dict`
|
|
387
|
+
Dictionary containing keys for binary parameters with values to plot
|
|
388
|
+
as vertical lines for each stellar component
|
|
389
|
+
|
|
390
|
+
Returns
|
|
391
|
+
-------
|
|
392
|
+
Null
|
|
393
|
+
"""
|
|
394
|
+
|
|
395
|
+
# Mass accretion rate
|
|
396
|
+
ax.plot(times, np.log10(np.clip(Mdot1_out, 1.0e-16, None)), color=primary_color)
|
|
397
|
+
ax.plot(times, np.log10(np.clip(Mdot2_out, 1.0e-16, None)), color=secondary_color)
|
|
398
|
+
ax.set_ylabel(r"Mass Accretion Rate ($M_{\odot}$ yr$^{-1}$)")
|
|
399
|
+
|
|
400
|
+
ax.set_ylim(-14, ax.get_ylim()[1])
|
|
401
|
+
ax.set_xlim(np.min(times), np.max(times))
|
|
402
|
+
|
|
403
|
+
if legend:
|
|
404
|
+
custom_lines = [
|
|
405
|
+
Line2D([0], [0], color="C0", linestyle="solid"),
|
|
406
|
+
Line2D([0], [0], color="C1", linestyle="solid"),
|
|
407
|
+
]
|
|
408
|
+
ax.legend(custom_lines, ["Primary", "Secondary"], loc=2, frameon=False)
|
|
409
|
+
|
|
410
|
+
|
|
411
|
+
def plot_P_orb(ax, times, P_orb_out, t_max, sys_obs):
|
|
412
|
+
"""Plots the orbital period as a function of time
|
|
413
|
+
|
|
414
|
+
Parameters
|
|
415
|
+
----------
|
|
416
|
+
ax : `matplotlib.Axes`
|
|
417
|
+
Axis instance for the plot
|
|
418
|
+
|
|
419
|
+
times : `pandas.Series`
|
|
420
|
+
Series of times at each binary evolution time step in Myr
|
|
421
|
+
|
|
422
|
+
P_orb_out : `pandas.Series`
|
|
423
|
+
Series of orbital periods at each binary evolution time step in days
|
|
424
|
+
|
|
425
|
+
t_max : `float`
|
|
426
|
+
ending time for plot in Myr
|
|
427
|
+
|
|
428
|
+
sys_obs : `Dict`
|
|
429
|
+
Dictionary containing keys for binary parameters with values to plot
|
|
430
|
+
as vertical lines for each stellar component
|
|
431
|
+
|
|
432
|
+
Returns
|
|
433
|
+
-------
|
|
434
|
+
Null
|
|
435
|
+
"""
|
|
436
|
+
|
|
437
|
+
ax.plot(times, P_orb_out, color="k")
|
|
438
|
+
|
|
439
|
+
for key, value in sys_obs.items():
|
|
440
|
+
if key == "P_orb":
|
|
441
|
+
ax.axhline(value, color="k", linestyle="dashed")
|
|
442
|
+
|
|
443
|
+
ax.set_xlim(np.min(times), t_max)
|
|
444
|
+
|
|
445
|
+
ax.set_ylabel(r"P$_{\rm orb}$ (days)")
|
|
446
|
+
ax.set_yscale("log")
|
|
447
|
+
|
|
448
|
+
|
|
449
|
+
def plot_ecc(ax, times, ecc_out, t_max, sys_obs):
|
|
450
|
+
"""Plots the eccentricity as a function of time
|
|
451
|
+
|
|
452
|
+
Parameters
|
|
453
|
+
----------
|
|
454
|
+
ax : `matplotlib.Axes`
|
|
455
|
+
Axis instance for the plot
|
|
456
|
+
|
|
457
|
+
times : `pandas.Series`
|
|
458
|
+
Series of times at each binary evolution time step in Myr
|
|
459
|
+
|
|
460
|
+
ecc_out : `pandas.Series`
|
|
461
|
+
Series of eccentricities at each binary evolution time step
|
|
462
|
+
|
|
463
|
+
t_max : `float`
|
|
464
|
+
ending time for plot in Myr
|
|
465
|
+
|
|
466
|
+
sys_obs : `Dict`
|
|
467
|
+
Dictionary containing keys for binary parameters with values to plot
|
|
468
|
+
as vertical lines for each stellar component
|
|
469
|
+
|
|
470
|
+
Returns
|
|
471
|
+
-------
|
|
472
|
+
Null
|
|
473
|
+
"""
|
|
474
|
+
|
|
475
|
+
ax.plot(times, ecc_out, color="k")
|
|
476
|
+
|
|
477
|
+
for key, value in sys_obs.items():
|
|
478
|
+
if key == "ecc":
|
|
479
|
+
ax.axhline(value, color="k", linestyle="dashed")
|
|
480
|
+
|
|
481
|
+
ax.set_xlim(np.min(times), t_max)
|
|
482
|
+
|
|
483
|
+
ax.set_ylabel("Eccentricity")
|
|
484
|
+
ax.set_xlabel("Time (Myr)")
|
|
485
|
+
|
|
486
|
+
|
|
487
|
+
def plot_HR_diagram(ax, L1_out, L2_out, Teff1_out, Teff2_out):
|
|
488
|
+
"""Plots the eccentricity as a function of time
|
|
489
|
+
|
|
490
|
+
Parameters
|
|
491
|
+
----------
|
|
492
|
+
ax : `matplotlib.Axes`
|
|
493
|
+
Axis instance for the plot
|
|
494
|
+
|
|
495
|
+
times : `pandas.Series`
|
|
496
|
+
Series of times at each binary evolution time step in Myr
|
|
497
|
+
|
|
498
|
+
L1_out : `pandas.Series`
|
|
499
|
+
Series of primary luminosities at each binary evolution time step in Lsun
|
|
500
|
+
|
|
501
|
+
L2_out : `pandas.Series`
|
|
502
|
+
Series of secondary luminosities at each binary evolution time step in Lsun
|
|
503
|
+
|
|
504
|
+
Teff1_out : `pandas.Series`
|
|
505
|
+
Series of primary effective temperature at each binary evolution time step in K
|
|
506
|
+
|
|
507
|
+
Teff2_out : `pandas.Series`
|
|
508
|
+
Series of secondary effective temperature at each binary evolution time step in K
|
|
509
|
+
|
|
510
|
+
sys_obs : `Dict`
|
|
511
|
+
Dictionary containing keys for binary parameters with values to plot
|
|
512
|
+
as vertical lines for each stellar component
|
|
513
|
+
|
|
514
|
+
Returns
|
|
515
|
+
-------
|
|
516
|
+
Null
|
|
517
|
+
"""
|
|
518
|
+
|
|
519
|
+
ax.plot(Teff1_out, L1_out, color=primary_color)
|
|
520
|
+
ax.plot(Teff2_out, L2_out, color=secondary_color)
|
|
521
|
+
|
|
522
|
+
ax.set_xscale("log")
|
|
523
|
+
ax.set_yscale("log")
|
|
524
|
+
ax.set_xlim(40000, 2000)
|
|
525
|
+
|
|
526
|
+
ax.set_xlabel(r"log T$_{\rm eff}$ (K)")
|
|
527
|
+
ax.set_ylabel("log L (erg/s)")
|
|
528
|
+
|
|
529
|
+
ax.set_xticks([2000, 5000, 10000, 20000, 40000])
|
|
530
|
+
|
|
531
|
+
|
|
532
|
+
def plot_binary_evol(bcm, sys_obs={}, ktype_kwargs={}, t_min=None, t_max=None):
|
|
533
|
+
"""Plots the full set of plots and kstar bar plots
|
|
534
|
+
|
|
535
|
+
Parameters
|
|
536
|
+
----------
|
|
537
|
+
bcm : `pandas.DataFrame`
|
|
538
|
+
binary evolution data form BSE's bcm dict
|
|
539
|
+
|
|
540
|
+
sys_obs : `Dict`
|
|
541
|
+
Dictionary containing keys for binary parameters with values to plot
|
|
542
|
+
as vertical lines for each stellar component
|
|
543
|
+
|
|
544
|
+
Returns
|
|
545
|
+
-------
|
|
546
|
+
fig : `matplotlib.figure`
|
|
547
|
+
Figure containing all the plots!
|
|
548
|
+
"""
|
|
549
|
+
|
|
550
|
+
fig = plt.figure(figsize=(10, 10), layout="tight")
|
|
551
|
+
|
|
552
|
+
gs = fig.add_gridspec(2, 1, height_ratios=[1.3, 6], hspace=0.0)
|
|
553
|
+
gs_top = gs[0].subgridspec(2, 2, width_ratios=[1, 1], height_ratios=[1, 1.3], hspace=0.15)
|
|
554
|
+
gs_bottom = gs[1].subgridspec(3, 2, width_ratios=[1, 1], height_ratios=[2, 2, 2], hspace=0.15)
|
|
555
|
+
|
|
556
|
+
if t_min is not None:
|
|
557
|
+
bcm = bcm.loc[bcm.tphys >= t_min]
|
|
558
|
+
if t_max is not None:
|
|
559
|
+
bcm = bcm.loc[bcm.tphys <= t_max]
|
|
560
|
+
|
|
561
|
+
# k-type panels
|
|
562
|
+
plot_k_type(
|
|
563
|
+
fig.add_subplot(gs_top[0, 0]),
|
|
564
|
+
fig.add_subplot(gs_top[0, 1]),
|
|
565
|
+
fig.add_subplot(gs_top[1, :]),
|
|
566
|
+
bcm.tphys,
|
|
567
|
+
bcm.kstar_1.astype(int),
|
|
568
|
+
bcm.kstar_2.astype(int),
|
|
569
|
+
**ktype_kwargs
|
|
570
|
+
)
|
|
571
|
+
|
|
572
|
+
# Radius panel
|
|
573
|
+
plot_radius(
|
|
574
|
+
fig.add_subplot(gs_bottom[0, 0]),
|
|
575
|
+
bcm.tphys,
|
|
576
|
+
bcm.rad_1,
|
|
577
|
+
bcm.rad_2,
|
|
578
|
+
bcm.mass_1,
|
|
579
|
+
bcm.mass_2,
|
|
580
|
+
bcm.porb,
|
|
581
|
+
bcm.ecc,
|
|
582
|
+
sys_obs,
|
|
583
|
+
)
|
|
584
|
+
|
|
585
|
+
# Mass panel
|
|
586
|
+
plot_mass(fig.add_subplot(gs_bottom[1, 0]), bcm.tphys, bcm.mass_1, bcm.mass_2, sys_obs)
|
|
587
|
+
|
|
588
|
+
# Teff panel
|
|
589
|
+
plot_Teff(fig.add_subplot(gs_bottom[2, 0]), bcm.tphys, bcm.teff_1, bcm.teff_2, sys_obs)
|
|
590
|
+
|
|
591
|
+
# Mass accretion rate panel
|
|
592
|
+
plot_Mdot(fig.add_subplot(gs_bottom[0, 1]), bcm.tphys, bcm.deltam_1, bcm.deltam_2)
|
|
593
|
+
|
|
594
|
+
# Orbital period panel
|
|
595
|
+
plot_P_orb(
|
|
596
|
+
fig.add_subplot(gs_bottom[1, 1]),
|
|
597
|
+
bcm.loc[bcm.kstar_2 < 15].tphys,
|
|
598
|
+
bcm.loc[bcm.kstar_2 < 15].porb,
|
|
599
|
+
np.max(bcm.tphys),
|
|
600
|
+
sys_obs,
|
|
601
|
+
)
|
|
602
|
+
|
|
603
|
+
# Plot eccentricity panel
|
|
604
|
+
plot_ecc(
|
|
605
|
+
fig.add_subplot(gs_bottom[2, 1]),
|
|
606
|
+
bcm.loc[bcm.kstar_2 < 15].tphys,
|
|
607
|
+
bcm.loc[bcm.kstar_2 < 15].ecc,
|
|
608
|
+
np.max(bcm.tphys),
|
|
609
|
+
sys_obs,
|
|
610
|
+
)
|
|
611
|
+
|
|
612
|
+
# Plot HR diagram
|
|
613
|
+
# idx_1 = np.where(k1_out < 10)[0]
|
|
614
|
+
# idx_2 = np.where(k2_out < 10)[0]
|
|
615
|
+
# plot_HR_diagram(ax[7], L1_out[k1_out<10], L2_out[k2_out<10], Teff1_out[k1_out<10], Teff2_out[k2_out<10])
|
|
616
|
+
|
|
617
|
+
return fig
|
|
618
|
+
|
|
619
|
+
|
|
620
|
+
def evolve_and_plot(initC, t_min=None, t_max=None, BSEDict=None, sys_obs={}):
|
|
621
|
+
"""
|
|
622
|
+
Evolve and plot binaries as a function of time
|
|
623
|
+
|
|
624
|
+
Parameters
|
|
625
|
+
----------
|
|
626
|
+
initC : `pandas.DataFrame`
|
|
627
|
+
initial conditions for binary to evolve
|
|
628
|
+
|
|
629
|
+
t_min : `float or list`
|
|
630
|
+
starting time for plot in Myr
|
|
631
|
+
|
|
632
|
+
t_max : `float or list`
|
|
633
|
+
ending time for plot in Myr
|
|
634
|
+
|
|
635
|
+
BSEDict : `Dict`
|
|
636
|
+
Dictionary containing all BSE flags needed
|
|
637
|
+
|
|
638
|
+
sys_obs : `Dict`
|
|
639
|
+
Dictionary containing keys for binary parameters with values to plot
|
|
640
|
+
as vertical lines for each stellar component
|
|
641
|
+
|
|
642
|
+
Returns
|
|
643
|
+
-------
|
|
644
|
+
all_figs : `list`
|
|
645
|
+
list of all figures created
|
|
646
|
+
"""
|
|
647
|
+
|
|
648
|
+
# Throw an error if user is plotting more than 10 binaries
|
|
649
|
+
if len(initC) > 10:
|
|
650
|
+
raise ValueError(
|
|
651
|
+
"You have asked to plot more than 10 separate binaries. This could cause problems..."
|
|
652
|
+
)
|
|
653
|
+
|
|
654
|
+
# Iterate over all binaries in initC
|
|
655
|
+
all_figs = []
|
|
656
|
+
for i in range(len(initC)):
|
|
657
|
+
|
|
658
|
+
# Check if t_min and t_max are lists
|
|
659
|
+
if isinstance(t_min, list):
|
|
660
|
+
t_min_tmp = t_min[i]
|
|
661
|
+
else:
|
|
662
|
+
t_min_tmp = t_min
|
|
663
|
+
if isinstance(t_max, list):
|
|
664
|
+
t_max_tmp = t_max[i]
|
|
665
|
+
else:
|
|
666
|
+
t_max_tmp = t_max
|
|
667
|
+
|
|
668
|
+
# Evolve binary
|
|
669
|
+
bcm = evolve_binary(
|
|
670
|
+
initC.iloc[i: i + 1], t_min=t_min_tmp, t_max=t_max_tmp, BSEDict=BSEDict
|
|
671
|
+
)
|
|
672
|
+
|
|
673
|
+
# Plot binary
|
|
674
|
+
fig = plot_binary_evol(bcm, sys_obs=sys_obs)
|
|
675
|
+
|
|
676
|
+
# Add to list of figs
|
|
677
|
+
all_figs.append(fig)
|
|
678
|
+
|
|
679
|
+
# Return list of figs
|
|
680
|
+
return all_figs
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# Copyright (C) Katie Breivik (2017 - 2020)
|
|
4
|
+
#
|
|
5
|
+
# This file is part of COSMIC
|
|
6
|
+
#
|
|
7
|
+
# COSMIC is free software: you can redistribute it and/or modify
|
|
8
|
+
# it under the terms of the GNU General Public License as published by
|
|
9
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
10
|
+
# (at your option) any later version.
|
|
11
|
+
#
|
|
12
|
+
# COSMIC is distributed in the hope that it will be useful,
|
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15
|
+
# GNU General Public License for more details.
|
|
16
|
+
#
|
|
17
|
+
# You should have received a copy of the GNU General Public License
|
|
18
|
+
# along with COSMIC. If not, see <http://www.gnu.org/licenses/>
|
|
19
|
+
|
|
20
|
+
# load tables
|
|
21
|
+
from astropy.table import Column, Table
|
|
22
|
+
from .initialbinarytable import InitialBinaryTable
|
|
23
|
+
from .initialcmctable import InitialCMCTable
|
|
24
|
+
|
|
25
|
+
# attach unified I/O
|
|
26
|
+
from . import sampler
|