-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathstellar_model.py
executable file
·254 lines (216 loc) · 8.74 KB
/
stellar_model.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
""""
Stellar Model representing a star.
Notes:
- Flux Unit - W/m^2
"""
import numpy as np
from enum import Enum
LY_IN_PARSEC = 3.26
METERS_IN_LY = 9.461e15
SOLAR_LUMINOSITY = 3.827e26
WIENS_DISPLACEMENT_NM_K = 2897768.5
MASS_CONSTANT = 0.2857
RADIUS_CONSTANT = 5800
LIFETIME_CONSTANT = 1e10
MILION_YEAR = 1e6
# Giant luminosity class identifier limits
GIANT_MIN_TEMP = 3000
GIANT_MAX_TEMP = 4000
GIANT_MIN_LUMINOSITY_SOLAR = 50
GIANT_MAX_LUMINOSITY_SOLAR = 1000
SUPER_GIANT_MIN_TEMP = 3000
SUPER_GIANT_MAX_TEMP = 8000
SUPER_GIANT_MIN_LUMINOSITY_SOLAR = 1e4
SUPER_GIANT_MAX_LUMINOSITY_SOLAR = 1e6
# Spectral Classes
O_CLASS_MAX_TEMP = int(6e4)
O_CLASS_MIN_TEMP = int(3e4)
B_CLASS_MAX_TEMP = int(3e4)
B_CLASS_MIN_TEMP = int(1e4)
A_CLASS_MAX_TEMP = int(1e4)
A_CLASS_MIN_TEMP = int(7500)
F_CLASS_MAX_TEMP = int(7500)
F_CLASS_MIN_TEMP = int(6000)
G_CLASS_MAX_TEMP = int(6000)
G_CLASS_MIN_TEMP = int(5000)
K_CLASS_MAX_TEMP = int(5000)
K_CLASS_MIN_TEMP = int(3500)
M_CLASS_MAX_TEMP = int(3500)
M_CLASS_MIN_TEMP = int(2500)
L_CLASS_MAX_TEMP = int(2500)
L_CLASS_MIN_TEMP = int(1200)
T_CLASS_MAX_TEMP = int(1200)
T_CLASS_MIN_TEMP = int(500)
Y_CLASS_MAX_TEMP = int(500)
Y_CLASS_MIN_TEMP = int(0)
class Spectral_Class(Enum):
O = 0
B = 1
A = 2
F = 3
G = 4
K = 5
M = 6
L = 7
T = 8
Y = 9
class Luminosity_Class(Enum):
SUPER_GIANT = 0
BRIGHT_GIANT = 1
GIANT = 2
MAIN_SEQUENCE = 3
SUB_DWARF = 4
WHITE_DWARF = 5
UNKNOWN = 6
class EM_Wave(Enum):
UV = 0
VIOLET = 1
BLUE = 2
CYAN = 3
GREEN = 4
YELLOW = 5
ORANGE = 6
RED = 7
IR = 8
class Stellar_Model:
def analyze_stellar_data(self, name, parallax_arcseconds, peak_wavelength_nm, flux, metallicity):
"""Analyzes the stellar data and makes calculations about the star based on provided user info"""
self.name = name
self.parallax = parallax_arcseconds
self.peak_weavelength_nm = peak_wavelength_nm
self.flux = flux
self.metallicity = metallicity
self.spectral_class = None
self.luminosity_class = None
self.mass_solar = None
self.radius_solar = None
self.lifetime_myr = None
self.em_wave = None
self.habitablity_check = False
# Calculated parameters
(self.distance_ly, self.distance_m) = self.calculate_distance()
(self.luminasity_w, self.luminosity_solar) = self.calculate_luminosity()
self.temperature_k = self.calculate_temperature()
# Spectral analysis
self.identify_luminosity_classes()
self.identify_EM_wave()
self.identify_spectral_classes()
self.is_star_worth_checking_for_habitability()
def calculate_distance(self):
"""Distance in Light Years is calculated by dividing 3.26 by parallax in arc-seconds"""
ly = (LY_IN_PARSEC / self.parallax)
meters = ly * METERS_IN_LY
return (ly, meters)
def calculate_luminosity(self):
"""Luminosity is calculated using Flux and distance. L = Flux x 4 x PI x Distance^2"""
l = self.flux * 4 * np.pi * pow(self.distance_m, 2)
l_solar = (l / SOLAR_LUMINOSITY)
return (l, l_solar)
def calculate_temperature(self):
"""Calculate the stellar temperature using Wien's Law Lambda = b / T"""
temperature_k = WIENS_DISPLACEMENT_NM_K / self.peak_weavelength_nm
return int(temperature_k)
def identify_EM_wave(self):
"""Identify the EM Wave type based on its length in nm"""
if self.peak_weavelength_nm < 400:
self.em_wave = EM_Wave.UV
elif self.peak_weavelength_nm >= 400 and self.peak_weavelength_nm < 450:
self.em_wave = EM_Wave.VIOLET
elif self.peak_weavelength_nm >= 450 and self.peak_weavelength_nm < 475:
self.em_wave = EM_Wave.BLUE
elif self.peak_weavelength_nm >= 475 and self.peak_weavelength_nm < 495:
self.em_wave = EM_Wave.CYAN
elif self.peak_weavelength_nm >= 495 and self.peak_weavelength_nm < 570:
self.em_wave = EM_Wave.GREEN
elif self.peak_weavelength_nm >= 570 and self.peak_weavelength_nm < 590:
self.em_wave = EM_Wave.YELLOW
elif self.peak_weavelength_nm >= 590 and self.peak_weavelength_nm < 620:
self.em_wave = EM_Wave.ORANGE
elif self.peak_weavelength_nm >= 620 and self.peak_weavelength_nm < 750:
self.em_wave = EM_Wave.RED
elif self.peak_weavelength_nm >= 750:
self.em_wave = EM_Wave.IR
def identify_luminosity_classes(self):
"""Identify Luminosity class."""
if (
self.temperature_k > GIANT_MIN_TEMP
and self.temperature_k < GIANT_MAX_TEMP
and self.luminosity_solar > GIANT_MIN_LUMINOSITY_SOLAR
and self.luminosity_solar < GIANT_MAX_LUMINOSITY_SOLAR
):
self.luminosity_class = Luminosity_Class.GIANT
elif (
self.temperature_k > SUPER_GIANT_MIN_TEMP
and self.temperature_k < SUPER_GIANT_MAX_TEMP
and self.luminosity_solar > SUPER_GIANT_MIN_LUMINOSITY_SOLAR
and self.luminosity_solar < SUPER_GIANT_MAX_LUMINOSITY_SOLAR
):
self.luminosity_class = Luminosity_Class.SUPER_GIANT
else:
self.luminosity_class = Luminosity_Class.UNKNOWN
def identify_spectral_classes(self):
"""Identify Spectral Class"""
if self.temperature_k in range(O_CLASS_MIN_TEMP, O_CLASS_MAX_TEMP):
self.spectral_class = Spectral_Class.O
elif self.temperature_k in range(B_CLASS_MIN_TEMP, B_CLASS_MAX_TEMP):
self.spectral_class = Spectral_Class.B
elif self.temperature_k in range(A_CLASS_MIN_TEMP, A_CLASS_MAX_TEMP):
self.spectral_class = Spectral_Class.A
elif self.temperature_k in range(F_CLASS_MIN_TEMP, F_CLASS_MAX_TEMP):
self.spectral_class = Spectral_Class.F
elif self.temperature_k in range(G_CLASS_MIN_TEMP, G_CLASS_MAX_TEMP):
self.spectral_class = Spectral_Class.B
elif self.temperature_k in range(K_CLASS_MIN_TEMP, K_CLASS_MAX_TEMP):
self.spectral_class = Spectral_Class.K
elif self.temperature_k in range(M_CLASS_MIN_TEMP, M_CLASS_MAX_TEMP):
self.spectral_class = Spectral_Class.M
elif self.temperature_k in range(L_CLASS_MIN_TEMP, L_CLASS_MAX_TEMP):
self.spectral_class = Spectral_Class.L
elif self.temperature_k in range(T_CLASS_MIN_TEMP, T_CLASS_MAX_TEMP):
self.spectral_class = Spectral_Class.T
elif self.temperature_k in range(Y_CLASS_MIN_TEMP, Y_CLASS_MAX_TEMP):
self.spectral_class = Spectral_Class.Y
def calculate_main_sequence_mass_radius_lifetime(self):
"""Calculate mass, radius, and lifetime of star if it is a main sequence star"""
# Calculate stellar mass in solar masses
self.mass_solar = pow(self.luminosity_solar, MASS_CONSTANT)
# Calculate stellar radius in solar radius
self.radius_solar = (pow(self.luminosity_solar, 0.5)) / pow((self.temperature_k / RADIUS_CONSTANT), 2)
# Calculate stellar lifetime in million years (Ma)
self.lifetime_myr = (LIFETIME_CONSTANT * pow(self.mass_solar, -2.5)) / MILION_YEAR
return (self.mass_solar, self.radius_solar, self.lifetime_myr)
def is_star_worth_checking_for_habitability(self):
"""Check if it is worth to check for habitable planets around the star"""
if self.luminosity_class == Luminosity_Class.MAIN_SEQUENCE:
if (
self.spectral_class is Spectral_Class.A
or self.spectral_class is Spectral_Class.F
or self.spectral_class is Spectral_Class.G
):
self.habitablity_check = True
def return_stellar_data(self):
"""Dump all stellar model information based on calculations"""
print(f"=========== {self.name}===========")
print(f"Distance_LY: {self.distance_ly}")
print(f"L_Solar: {self.luminosity_solar}")
print(f"T_K: {self.temperature_k}")
print(f"M_Solar: {self.mass_solar}")
print(f"R_Solar: {self.radius_solar}")
print(f"Lifetime_Ma: {self.lifetime_myr}")
print(f"Luminosity Class: {self.luminosity_class.name}")
print(f"Spectral Class: {self.spectral_class.name}")
print(f"EM Wave Type: {self.em_wave.name}")
print(f"Check for Habitable Worlds: {self.habitablity_check}")
return [
self.name,
self.parallax,
self.peak_weavelength_nm,
self.flux,
self.metallicity,
self.spectral_class,
self.luminosity_class,
self.mass_solar,
self.radius_solar,
self.lifetime_myr,
self.em_wave,
]