sedlib 1.0.0__py3-none-any.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.
- sedlib/__init__.py +47 -0
- sedlib/bol2rad.py +552 -0
- sedlib/catalog.py +1141 -0
- sedlib/core.py +6059 -0
- sedlib/data/__init__.py +2 -0
- sedlib/data/temp_to_bc_coefficients.yaml +62 -0
- sedlib/filter/__init__.py +5 -0
- sedlib/filter/core.py +1064 -0
- sedlib/filter/data/__init__.py +2 -0
- sedlib/filter/data/svo_all_filter_database.pickle +0 -0
- sedlib/filter/data/svo_filter_catalog.pickle +0 -0
- sedlib/filter/data/svo_meta_data.xml +1282 -0
- sedlib/filter/utils.py +71 -0
- sedlib/helper.py +361 -0
- sedlib/utils.py +789 -0
- sedlib/version.py +12 -0
- sedlib-1.0.0.dist-info/METADATA +611 -0
- sedlib-1.0.0.dist-info/RECORD +21 -0
- sedlib-1.0.0.dist-info/WHEEL +5 -0
- sedlib-1.0.0.dist-info/licenses/LICENSE +201 -0
- sedlib-1.0.0.dist-info/top_level.txt +1 -0
sedlib/__init__.py
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
|
3
|
+
"""
|
4
|
+
sedlib: A Python library for Spectral Energy Distribution (SED) analysis
|
5
|
+
|
6
|
+
This module provides tools for managing photometric data, performing SED analysis,
|
7
|
+
and modeling stellar energy distributions with interstellar extinction correction.
|
8
|
+
|
9
|
+
Features:
|
10
|
+
- Catalog class for organizing photometric data
|
11
|
+
- Filter class for managing photometric filters
|
12
|
+
- SED class for SED analysis and fitting
|
13
|
+
- Integration with astronomical libraries like astropy and dust_extinction
|
14
|
+
- Advanced optimization tools for interstellar extinction correction
|
15
|
+
- BolometricCorrection class for computing bolometric corrections and radii
|
16
|
+
|
17
|
+
Author:
|
18
|
+
Oğuzhan OKUYAN
|
19
|
+
ookuyan@gmail.com, oguzhan.okuyan@tubitak.gov.tr
|
20
|
+
|
21
|
+
Version:
|
22
|
+
1.0.0
|
23
|
+
|
24
|
+
License:
|
25
|
+
Apache License 2.0
|
26
|
+
"""
|
27
|
+
|
28
|
+
__author__ = 'Oğuzhan OKUYAN'
|
29
|
+
__license__ = 'Apache License 2.0'
|
30
|
+
__version__ = '1.0.0'
|
31
|
+
__maintainer__ = 'Oğuzhan OKUYAN'
|
32
|
+
__email__ = 'ookuyan@gmail.com, oguzhan.okuyan@tubitak.gov.tr'
|
33
|
+
__description__ = "A Python library for Spectral Energy Distribution analysis"
|
34
|
+
__url__ = "https://github.com/ookuyan/sedlib"
|
35
|
+
|
36
|
+
|
37
|
+
__all__ = [
|
38
|
+
'Filter',
|
39
|
+
'Catalog',
|
40
|
+
'SED',
|
41
|
+
'BolometricCorrection'
|
42
|
+
]
|
43
|
+
|
44
|
+
from .filter import Filter
|
45
|
+
from .catalog import Catalog
|
46
|
+
from .core import SED
|
47
|
+
from .bol2rad import BolometricCorrection
|
sedlib/bol2rad.py
ADDED
@@ -0,0 +1,552 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
|
3
|
+
__all__ = ['BolometricCorrection']
|
4
|
+
|
5
|
+
import math
|
6
|
+
from typing import Optional, Tuple
|
7
|
+
from importlib import resources
|
8
|
+
|
9
|
+
import yaml
|
10
|
+
|
11
|
+
import numpy as np
|
12
|
+
|
13
|
+
import astropy.units as u
|
14
|
+
|
15
|
+
|
16
|
+
class BolometricCorrection(object):
|
17
|
+
"""
|
18
|
+
Class for computing bolometric corrections (BC) for stars based on their
|
19
|
+
effective temperature and for inferring stellar properties such as the weighted
|
20
|
+
bolometric magnitude and the stellar radius (expressed in solar units).
|
21
|
+
|
22
|
+
This class performs a full analysis pipeline that includes the following steps:
|
23
|
+
1. **Loading Coefficients:** Reads temperature-to-bolometric correction
|
24
|
+
polynomial coefficients from a YAML file. These coefficients (with their
|
25
|
+
fixed uncertainties) allow the calculation of bolometric corrections using
|
26
|
+
a 4th-degree polynomial.
|
27
|
+
2. **Filter Selection:** From the available photometric filters in the star's
|
28
|
+
SED, the class selects the preferred filters (e.g., Johnson B, V; GAIA G,
|
29
|
+
GBP, GRP, etc.) based on a pre-defined priority order.
|
30
|
+
3. **Bolometric Correction Computation:** For each selected filter, it
|
31
|
+
computes the bolometric correction for the target star's effective
|
32
|
+
temperature.
|
33
|
+
4. **Absolute Bolometric Magnitude Determination:** The computed corrections
|
34
|
+
are applied to the observed absolute magnitudes, and a weighted average is
|
35
|
+
obtained using inverse-variance weighting. This yields the star's absolute
|
36
|
+
bolometric magnitude and its associated uncertainty.
|
37
|
+
5. **Stellar Radius Estimation:** Using the relation between luminosity,
|
38
|
+
radius, and effective temperature (i.e., L = 4πR²σT⁴) along with the
|
39
|
+
bolometric magnitude definition (M_Bol = -2.5 log L + constant), the
|
40
|
+
stellar radius is determined relative to the Sun. The target star's radius
|
41
|
+
(in R_sun) is computed via:
|
42
|
+
R_star / R_sun = 10^((M_bol,☉ - M_bol,star)/5) * (T_☉ / T_star)²,
|
43
|
+
and the uncertainty is propagated accordingly.
|
44
|
+
|
45
|
+
The full analysis pipeline can be executed in one go using the `run` method.
|
46
|
+
|
47
|
+
Example
|
48
|
+
-------
|
49
|
+
>>> from sedlib import SED, BolometricCorrection
|
50
|
+
>>> from astropy import units as u
|
51
|
+
>>>
|
52
|
+
>>> sed = SED(name='Vega')
|
53
|
+
>>> sed.teff = 10070 * u.K
|
54
|
+
>>> sed.radius = 2.766 * u.Rsun
|
55
|
+
>>> sed.distance = 7.68 * u.pc
|
56
|
+
>>>
|
57
|
+
>>> sed.estimate_ebv()
|
58
|
+
>>> sed.compute_A_lambda()
|
59
|
+
>>> sed.compute_absolute_magnitudes()
|
60
|
+
>>>
|
61
|
+
>>> bc = BolometricCorrection(sed=sed)
|
62
|
+
>>> bc.run()
|
63
|
+
>>> print(f"Stellar radius: {bc.radius:.2f} ± {bc.radius_error:.2f} R_sun")
|
64
|
+
"""
|
65
|
+
|
66
|
+
def __init__(
|
67
|
+
self,
|
68
|
+
sed: Optional[object] = None,
|
69
|
+
coeff_file: Optional[str] = None,
|
70
|
+
accept_radius: bool = False
|
71
|
+
):
|
72
|
+
"""
|
73
|
+
Initialize the BolometricCorrection instance.
|
74
|
+
|
75
|
+
Parameters
|
76
|
+
----------
|
77
|
+
sed : sedlib.SED, optional
|
78
|
+
SED object containing catalog and stellar parameters. Must have
|
79
|
+
computed absolute magnitudes and effective temperature.
|
80
|
+
coeff_file : str, optional
|
81
|
+
Path to the YAML file containing the coefficient data. If None, the
|
82
|
+
default 'temp_to_bc_coefficients.yaml' file is used.
|
83
|
+
accept_radius : bool, optional
|
84
|
+
If True, the computed radius will be stored in sed.radius and
|
85
|
+
sed.radius_error. Default is False.
|
86
|
+
|
87
|
+
Raises
|
88
|
+
------
|
89
|
+
ValueError
|
90
|
+
If sed object is provided but lacks required attributes.
|
91
|
+
FileNotFoundError
|
92
|
+
If coefficient file cannot be found.
|
93
|
+
yaml.YAMLError
|
94
|
+
If coefficient file cannot be parsed.
|
95
|
+
|
96
|
+
Notes
|
97
|
+
-----
|
98
|
+
The bolometric correction analysis requires:
|
99
|
+
- Effective temperature (sed.teff)
|
100
|
+
- Absolute magnitudes for preferred filters
|
101
|
+
- Distance information for magnitude calculations
|
102
|
+
|
103
|
+
The preferred filters are selected automatically based on availability
|
104
|
+
and priority: Johnson B,V; GAIA G, GBP, GRP; etc.
|
105
|
+
"""
|
106
|
+
self._sed = sed
|
107
|
+
self._coefficients = {}
|
108
|
+
self._bolometric_corrections = {}
|
109
|
+
self._bolometric_mags = {}
|
110
|
+
self._abs_mags = {}
|
111
|
+
|
112
|
+
self._abs_bol_mag = None
|
113
|
+
self._abs_bol_mag_err = None
|
114
|
+
|
115
|
+
self._sun_bol_mag = 4.74
|
116
|
+
self._sun_teff = 5772 * u.K
|
117
|
+
|
118
|
+
self._radius = None
|
119
|
+
self._radius_error = None
|
120
|
+
|
121
|
+
self._accept_radius = accept_radius
|
122
|
+
|
123
|
+
if sed is not None:
|
124
|
+
self._sed = sed
|
125
|
+
self._abs_mags = self._select_preferred_filters()
|
126
|
+
|
127
|
+
self._load_coefficients(coeff_file)
|
128
|
+
|
129
|
+
@property
|
130
|
+
def abs_bol_mag(self) -> float:
|
131
|
+
return self._abs_bol_mag
|
132
|
+
|
133
|
+
@property
|
134
|
+
def abs_bol_mag_err(self) -> float:
|
135
|
+
return self._abs_bol_mag_err
|
136
|
+
|
137
|
+
@property
|
138
|
+
def radius(self) -> u.Quantity:
|
139
|
+
return self._radius
|
140
|
+
|
141
|
+
@property
|
142
|
+
def radius_error(self) -> u.Quantity:
|
143
|
+
return self._radius_error
|
144
|
+
|
145
|
+
def _load_coefficients(self, coeff_file: Optional[str] = None) -> dict:
|
146
|
+
"""
|
147
|
+
Internal method to load polynomial coefficients from a YAML file and store
|
148
|
+
each as a tuple (value, error). Additionally, if a filter block contains
|
149
|
+
an "RMS" key, that value is removed and stored as the fixed error for
|
150
|
+
that filter.
|
151
|
+
|
152
|
+
Parameters
|
153
|
+
----------
|
154
|
+
coeff_file : str, optional
|
155
|
+
Path to the YAML file containing coefficient data.
|
156
|
+
"""
|
157
|
+
self._coefficients = {}
|
158
|
+
|
159
|
+
try:
|
160
|
+
if coeff_file is None:
|
161
|
+
file_obj = resources.open_text(
|
162
|
+
'sedlib.data',
|
163
|
+
'temp_to_bc_coefficients.yaml'
|
164
|
+
)
|
165
|
+
else:
|
166
|
+
file_obj = open(coeff_file, 'r')
|
167
|
+
with file_obj as file:
|
168
|
+
self._coefficients = yaml.safe_load(file)
|
169
|
+
except Exception as e:
|
170
|
+
source = ("package resources" if coeff_file is None
|
171
|
+
else f"file '{coeff_file}'")
|
172
|
+
raise IOError(f"Error loading coefficients from {source}: {e}")
|
173
|
+
|
174
|
+
def _select_preferred_filters(self) -> dict:
|
175
|
+
"""
|
176
|
+
The allowed filters and their priority are defined as follows:
|
177
|
+
|
178
|
+
- Johnson:B
|
179
|
+
- Johnson:V
|
180
|
+
- GAIA/GAIA3:G
|
181
|
+
- GAIA/GAIA3:Gbp
|
182
|
+
- GAIA/GAIA3:Grp
|
183
|
+
- GAIA/GAIA2:G
|
184
|
+
- GAIA/GAIA2:Gbp
|
185
|
+
- GAIA/GAIA2:Grp
|
186
|
+
- Gaia:G
|
187
|
+
- TESS/TESS:Red
|
188
|
+
|
189
|
+
Returns
|
190
|
+
-------
|
191
|
+
dict
|
192
|
+
Dictionary where keys are the selected filter names and values are
|
193
|
+
tuples (abs_mag, abs_mag_err).
|
194
|
+
"""
|
195
|
+
# allowed filters in order
|
196
|
+
allowed_filters = [
|
197
|
+
'Johnson:B',
|
198
|
+
'Johnson:V',
|
199
|
+
'GAIA/GAIA3:G',
|
200
|
+
'GAIA/GAIA3:Grp',
|
201
|
+
'GAIA/GAIA3:Gbp',
|
202
|
+
'GAIA/GAIA2:G',
|
203
|
+
'GAIA/GAIA2:Grp',
|
204
|
+
'GAIA/GAIA2:Gbp',
|
205
|
+
'Gaia:G',
|
206
|
+
'TESS/TESS:Red',
|
207
|
+
]
|
208
|
+
|
209
|
+
result = {}
|
210
|
+
chosen_bands = {}
|
211
|
+
|
212
|
+
for filt in allowed_filters:
|
213
|
+
mask = self._sed.catalog.table['vizier_filter'] == filt
|
214
|
+
if not mask.any():
|
215
|
+
continue
|
216
|
+
|
217
|
+
row = self._sed.catalog.table[mask][0]
|
218
|
+
mag = row['abs_mag']
|
219
|
+
mag_err = row['abs_mag_err']
|
220
|
+
|
221
|
+
band = filt.split(":")[-1]
|
222
|
+
if band not in chosen_bands:
|
223
|
+
if band == 'Red':
|
224
|
+
band = 'TESS'
|
225
|
+
result[band.upper()] = (mag, mag_err)
|
226
|
+
chosen_bands[band] = filt
|
227
|
+
|
228
|
+
return result
|
229
|
+
|
230
|
+
@staticmethod
|
231
|
+
def _compute_bc_and_error(
|
232
|
+
T: float,
|
233
|
+
T_err: float,
|
234
|
+
coeffs: dict
|
235
|
+
) -> Tuple[float, float]:
|
236
|
+
"""
|
237
|
+
Internal method to compute the bolometric correction (BC) for a given
|
238
|
+
effective temperature (in Kelvin) using the 4th-degree polynomial. (The
|
239
|
+
propagated uncertainty computed here will later be replaced by the fixed
|
240
|
+
value from the YAML file.)
|
241
|
+
|
242
|
+
Parameters
|
243
|
+
----------
|
244
|
+
T : float
|
245
|
+
Effective temperature in Kelvin (nominal value).
|
246
|
+
T_err : float
|
247
|
+
Effective temperature error in Kelvin.
|
248
|
+
coeffs : dict
|
249
|
+
Dictionary of coefficients for a specific filter with keys 'a', 'b',
|
250
|
+
'c', 'd', 'e'. Each coefficient is a tuple: (value, error).
|
251
|
+
|
252
|
+
Returns
|
253
|
+
-------
|
254
|
+
tuple of float
|
255
|
+
(BC, sigma_BC) where sigma_BC is computed but will later be replaced
|
256
|
+
by a fixed value.
|
257
|
+
"""
|
258
|
+
# Compute L = log10(T)
|
259
|
+
L = math.log10(T)
|
260
|
+
# Propagate error from T to L: σ_L = T_err / (T ln(10))
|
261
|
+
sigma_L = T_err / (T * math.log(10))
|
262
|
+
|
263
|
+
# Unpack coefficients
|
264
|
+
a, sigma_a = coeffs["a"]
|
265
|
+
b, sigma_b = coeffs["b"]
|
266
|
+
c, sigma_c = coeffs["c"]
|
267
|
+
d, sigma_d = coeffs["d"]
|
268
|
+
e, sigma_e = coeffs["e"]
|
269
|
+
|
270
|
+
# Compute nominal BC:
|
271
|
+
BC = a + L * b + (L**2) * c + (L**3) * d + (L**4) * e
|
272
|
+
|
273
|
+
# Compute propagated uncertainty (to be replaced)
|
274
|
+
dfdL = b + 2 * L * c + 3 * (L**2) * d + 4 * (L**3) * e
|
275
|
+
sigma_BC = np.sqrt(
|
276
|
+
sigma_a**2 +
|
277
|
+
(L * sigma_b)**2 +
|
278
|
+
((L**2) * sigma_c)**2 +
|
279
|
+
((L**3) * sigma_d)**2 +
|
280
|
+
((L**4) * sigma_e)**2 +
|
281
|
+
(dfdL * sigma_L)**2
|
282
|
+
)
|
283
|
+
return BC, sigma_BC
|
284
|
+
|
285
|
+
def compute_bolometric_corrections(
|
286
|
+
self,
|
287
|
+
filter_name: Optional[str] = None,
|
288
|
+
return_results: bool = False
|
289
|
+
) -> dict:
|
290
|
+
"""
|
291
|
+
Compute bolometric corrections (BC) for either a single filter or all
|
292
|
+
available filters.
|
293
|
+
|
294
|
+
Parameters
|
295
|
+
----------
|
296
|
+
filter_name : str, optional
|
297
|
+
Filter name (e.g., 'B', 'V', 'G', 'GBP', 'GRP', 'TESS').
|
298
|
+
If None, computes BCs for all available filters.
|
299
|
+
return_results : bool, optional
|
300
|
+
If True, returns the computed BCs as a dictionary.
|
301
|
+
If False, updates the instance variables and returns None.
|
302
|
+
|
303
|
+
Returns
|
304
|
+
-------
|
305
|
+
dict
|
306
|
+
Dictionary mapping filter names to tuples of (BC, fixed_error).
|
307
|
+
For a single filter, returns a dictionary with one entry.
|
308
|
+
|
309
|
+
Raises
|
310
|
+
------
|
311
|
+
ValueError
|
312
|
+
If specified filter_name is not valid.
|
313
|
+
"""
|
314
|
+
results = {}
|
315
|
+
|
316
|
+
if filter_name is not None:
|
317
|
+
# Single filter case
|
318
|
+
if filter_name not in self._coefficients:
|
319
|
+
raise ValueError(
|
320
|
+
"Invalid filter name. Choose from: " +
|
321
|
+
", ".join(self._coefficients.keys())
|
322
|
+
)
|
323
|
+
filters_to_process = [filter_name]
|
324
|
+
else:
|
325
|
+
# All filters case
|
326
|
+
filters_to_process = self._coefficients.keys()
|
327
|
+
|
328
|
+
T = self._sed.teff.to(u.K).value
|
329
|
+
T_err = self._sed.teff_error.to(u.K).value
|
330
|
+
|
331
|
+
for filt in filters_to_process:
|
332
|
+
coeffs = self._coefficients[filt]
|
333
|
+
|
334
|
+
bc_result = self._compute_bc_and_error(T, T_err, coeffs)
|
335
|
+
fixed_err = coeffs['RMS']
|
336
|
+
|
337
|
+
results[filt] = (bc_result[0], fixed_err)
|
338
|
+
|
339
|
+
self._bolometric_corrections = results
|
340
|
+
|
341
|
+
return self._bolometric_corrections if return_results else None
|
342
|
+
|
343
|
+
def apply_correction(self):
|
344
|
+
"""
|
345
|
+
Apply the bolometric correction to a set of absolute magnitudes.
|
346
|
+
"""
|
347
|
+
for filt in self._abs_mags.keys():
|
348
|
+
mag, mag_err = self._abs_mags[filt]
|
349
|
+
bc, bc_err = self._bolometric_corrections[filt]
|
350
|
+
|
351
|
+
self._bolometric_mags[filt] = (
|
352
|
+
mag + bc,
|
353
|
+
np.sqrt(mag_err**2 + bc_err**2)
|
354
|
+
)
|
355
|
+
|
356
|
+
def compute_weighted_abs_bol_mag(
|
357
|
+
self,
|
358
|
+
return_results: bool = False
|
359
|
+
) -> Tuple[float, float]:
|
360
|
+
"""
|
361
|
+
Compute a weighted average of the bolometric magnitudes from different
|
362
|
+
filters.
|
363
|
+
|
364
|
+
The weighted average is computed using inverse-variance weighting:
|
365
|
+
|
366
|
+
weighted_mag = sum(m_i / sigma_i^2) / sum(1 / sigma_i^2)
|
367
|
+
weighted_error = sqrt(1 / sum(1 / sigma_i^2))
|
368
|
+
|
369
|
+
Parameters
|
370
|
+
----------
|
371
|
+
return_results : bool, optional
|
372
|
+
If True, returns the computed weighted average as a tuple.
|
373
|
+
If False, updates the instance variables and returns None.
|
374
|
+
|
375
|
+
Returns
|
376
|
+
-------
|
377
|
+
tuple of float
|
378
|
+
(weighted_bolometric_magnitude, weighted_error)
|
379
|
+
|
380
|
+
Raises
|
381
|
+
------
|
382
|
+
ValueError
|
383
|
+
If no bolometric magnitudes have been computed.
|
384
|
+
"""
|
385
|
+
if not self._bolometric_mags:
|
386
|
+
raise ValueError(
|
387
|
+
"No bolometric magnitudes available. "
|
388
|
+
"Run apply_correction() first."
|
389
|
+
)
|
390
|
+
|
391
|
+
mags = []
|
392
|
+
errors = []
|
393
|
+
for filt in self._bolometric_mags:
|
394
|
+
mag, err = self._bolometric_mags[filt]
|
395
|
+
mags.append(float(mag))
|
396
|
+
errors.append(err)
|
397
|
+
|
398
|
+
mags = np.array(mags)
|
399
|
+
errors = np.array(errors)
|
400
|
+
weights = 1 / errors**2
|
401
|
+
|
402
|
+
self._abs_bol_mag = np.sum(mags * weights) / np.sum(weights)
|
403
|
+
self._abs_bol_mag_err = np.sqrt(1 / np.sum(weights))
|
404
|
+
|
405
|
+
if return_results:
|
406
|
+
return (self._abs_bol_mag, self._abs_bol_mag_err)
|
407
|
+
return None
|
408
|
+
|
409
|
+
def compute_normalized_radius(
|
410
|
+
self,
|
411
|
+
return_results: bool = False
|
412
|
+
) -> Tuple[u.Quantity, u.Quantity]:
|
413
|
+
"""
|
414
|
+
The radius ratio is calculated as:
|
415
|
+
R_star / R_sun = 10^((M_bol,sun - M_bol,star)/5) * (T_sun / T_star)^2
|
416
|
+
|
417
|
+
Uncertainty propagation (via logarithmic differentiation):
|
418
|
+
(delta R_star / R_star)^2 = ( (ln10/5 * delta M_bol,star)^2 +
|
419
|
+
(2 * delta T_star / T_star)^2 )
|
420
|
+
|
421
|
+
Parameters
|
422
|
+
----------
|
423
|
+
return_results : bool, optional
|
424
|
+
If True, return the radius ratio and its error as a tuple.
|
425
|
+
If False, update the instance variables and return None.
|
426
|
+
|
427
|
+
Returns
|
428
|
+
-------
|
429
|
+
tuple of astropy.units.Quantity
|
430
|
+
A tuple (radius_ratio, radius_ratio_err) where:
|
431
|
+
- radius_ratio is the target star's radius in units of the Sun's
|
432
|
+
radius.
|
433
|
+
- radius_ratio_err is the corresponding uncertainty.
|
434
|
+
|
435
|
+
Raises
|
436
|
+
------
|
437
|
+
ValueError
|
438
|
+
If the target star's bolometric magnitude (or its error) has not been
|
439
|
+
computed, or if the Sun's parameters are not defined.
|
440
|
+
"""
|
441
|
+
# Ensure that the target star's bolometric magnitude and error are
|
442
|
+
# available.
|
443
|
+
if self._abs_bol_mag is None or self._abs_bol_mag_err is None:
|
444
|
+
raise ValueError(
|
445
|
+
"Target star's bolometric magnitude and/or its error have not "
|
446
|
+
"been computed. Please run compute_weighted_abs_bol_mag() first."
|
447
|
+
)
|
448
|
+
|
449
|
+
# Retrieve target star parameters.
|
450
|
+
target_mbol = self._abs_bol_mag
|
451
|
+
target_mbol_err = self._abs_bol_mag_err
|
452
|
+
target_teff = self._sed.teff.to(u.K).value
|
453
|
+
target_teff_err = self._sed.teff_error.to(u.K).value
|
454
|
+
|
455
|
+
# Retrieve Sun parameters.
|
456
|
+
sun_bol_mag = self._sun_bol_mag
|
457
|
+
sun_teff = self._sun_teff.value
|
458
|
+
|
459
|
+
# Compute the radius ratio using the relation:
|
460
|
+
# R_star / R_sun = 10^((M_bol,sun - M_bol,star)/5) * (T_sun / T_star)^2
|
461
|
+
radius_ratio = (10 ** ((sun_bol_mag - target_mbol) / 5.0) *
|
462
|
+
(sun_teff / target_teff) ** 2)
|
463
|
+
|
464
|
+
# Propagate uncertainties.
|
465
|
+
# The logarithmic derivative of R_ratio is:
|
466
|
+
# d(ln(R_ratio)) = -(ln10/5)*dM_bol,star - 2*(dT_star/T_star)
|
467
|
+
# Thus, the relative uncertainty is:
|
468
|
+
# (delta R_ratio / R_ratio)^2 = ( (ln10/5 * delta M_bol,star)^2 +
|
469
|
+
# (2 * delta T_star/T_star)^2 )
|
470
|
+
rel_error = np.sqrt(
|
471
|
+
(np.log(10) / 5 * target_mbol_err) ** 2 +
|
472
|
+
(2 * target_teff_err / target_teff) ** 2
|
473
|
+
)
|
474
|
+
radius_ratio_err = radius_ratio * rel_error
|
475
|
+
|
476
|
+
self._radius = radius_ratio * u.R_sun
|
477
|
+
self._radius_error = radius_ratio_err * u.R_sun
|
478
|
+
|
479
|
+
if return_results:
|
480
|
+
return self._radius, self._radius_error
|
481
|
+
return None
|
482
|
+
|
483
|
+
def run(self, verbose: bool = False) -> None:
|
484
|
+
"""
|
485
|
+
Execute the complete bolometric correction analysis pipeline.
|
486
|
+
|
487
|
+
The pipeline performs the following steps:
|
488
|
+
1. Compute bolometric corrections for available filters.
|
489
|
+
2. Apply the bolometric corrections to the target star's absolute
|
490
|
+
magnitudes.
|
491
|
+
3. Compute a weighted average of the corrected bolometric magnitudes.
|
492
|
+
4. Compute the target star's radius in units of the Sun's radius by
|
493
|
+
comparing the target's bolometric magnitude and effective temperature
|
494
|
+
with solar values.
|
495
|
+
|
496
|
+
Parameters
|
497
|
+
----------
|
498
|
+
verbose : bool, optional
|
499
|
+
If True, print verbose output.
|
500
|
+
|
501
|
+
Returns
|
502
|
+
-------
|
503
|
+
tuple of astropy.units.Quantity
|
504
|
+
A tuple (radius, radius_error)
|
505
|
+
|
506
|
+
Example
|
507
|
+
-------
|
508
|
+
>>> from sedlib import SED, BolometricCorrection
|
509
|
+
>>> from astropy import units as u
|
510
|
+
>>>
|
511
|
+
>>> sed = SED(name='Vega')
|
512
|
+
>>> sed.teff = 10070 * u.K
|
513
|
+
>>> sed.radius = 2.766 * u.Rsun
|
514
|
+
>>> sed.distance = 7.68 * u.pc
|
515
|
+
>>>
|
516
|
+
>>> sed.estimate_ebv()
|
517
|
+
>>> sed.compute_A_lambda()
|
518
|
+
>>> sed.compute_absolute_magnitudes()
|
519
|
+
>>>
|
520
|
+
>>> bc = BolometricCorrection(sed=sed)
|
521
|
+
>>> bc.run()
|
522
|
+
>>> print(
|
523
|
+
... f"Stellar radius: {bc.radius:.2f} ± {bc.radius_error:.2f} R_sun"
|
524
|
+
... )
|
525
|
+
"""
|
526
|
+
# Execute pipeline sequentially
|
527
|
+
self.compute_bolometric_corrections()
|
528
|
+
self.apply_correction()
|
529
|
+
self.compute_weighted_abs_bol_mag()
|
530
|
+
self.compute_normalized_radius()
|
531
|
+
|
532
|
+
if verbose:
|
533
|
+
print(
|
534
|
+
f"Stellar radius: {self._radius:.2f} ± "
|
535
|
+
f"{self._radius_error:.2f} R_sun"
|
536
|
+
)
|
537
|
+
|
538
|
+
if self._accept_radius:
|
539
|
+
self._sed._radius = self._radius
|
540
|
+
self._sed._radius_error = self._radius_error
|
541
|
+
|
542
|
+
self._result = {
|
543
|
+
'abs_mags': self._abs_mags,
|
544
|
+
'bolometric_corrections': self._bolometric_corrections,
|
545
|
+
'bol_mags': self._bolometric_mags,
|
546
|
+
'abs_bol_mag': self._abs_bol_mag,
|
547
|
+
'abs_bol_mag_err': self._abs_bol_mag_err,
|
548
|
+
'radius': self._radius,
|
549
|
+
'radius_error': self._radius_error
|
550
|
+
}
|
551
|
+
|
552
|
+
return self._radius, self._radius_error
|