File:Colours and temperatures of main sequence stars 1.svg

From Wikimedia Commons, the free media repository
Jump to navigation Jump to search

Original file(SVG file, nominally 1,333 × 819 pixels, file size: 44 KB)

Captions

Captions

Colours and surface temperatures of main sequence stars

Summary

[edit]
Description
English: Colours and surface temperatures of main sequence stars
Date
Source Own work
Author Merikanto

Source of main sequence data

https://en.wikipedia.org/wiki/Main_sequence

Source of CIE data

https://github.com/jrr1984/Prototipo0_S-D_SpectralGUI/blob/master/spectral_gui/cie-cmf.txt

Python code

    1. star spectral type and temperature interpolate
    2. view star colours in filled circles
    3. needs predefined table of staller tspectral types, masses, temperatures ...
    4. python 3 code
    5. 13.2.2023 v 0000.0002


import numpy as np

    1. import scipy as sp

import matplotlib.pyplot as plt import math import pandas as pd

from sklearn import metrics from sklearn.linear_model import LinearRegression from sklearn.ensemble import RandomForestRegressor from sklearn.metrics import r2_score from pygam import GAM, s, te from pygam import LinearGAM from pygam import PoissonGAM

    1. from pygam import LogisticGAM

from scipy import interpolate


from scipy.constants import h, c, k from matplotlib.patches import Circle

from colour_system import cs_hdtv cs = cs_hdtv

def planck(lam, T):

   lam_m = lam / 1.e9
   fac = h*c/lam_m/k/T
   B = 2*h*c**2/lam_m**5 / (np.exp(fac) - 1)
   return B

def linear_log_predict1(x,y): logx=np.log10(x).reshape(-1, 1) logy=np.log10(y).reshape(-1, 1) logmodel= LinearRegression().fit(logx, logy) logk=logmodel.coef_ logb=logmodel.intercept_ #print(logmodel) logpre=logmodel.predict(logx) pre=np.power(10, logpre) return(pre, logk, logb)


def linear_log_predict2(x,y, x2): logx=np.log10(x).reshape(-1, 1) logy=np.log10(y).reshape(-1, 1) logx2=np.log10(x2).reshape(-1, 1) logmodel= LinearRegression().fit(logx, logy) logk=logmodel.coef_ logb=logmodel.intercept_ #print(loglums_model) logpre=logmodel.predict(logx2) pre=np.power(10, logpre) return(pre)

def linear_log_predict_point(x,y, px): logx=np.log10(x).reshape(-1, 1) logy=np.log10(y).reshape(-1, 1) logmodel= LinearRegression().fit(logx, logy) logk=logmodel.coef_ logb=logmodel.intercept_ logpx=math.log10(px) logpy=logb+logpx*logk py=math.pow(10,logpy) return(py)

def gamma_log_predict2(x,y, x2): logx=np.log10(x).reshape(-1, 1) logy=np.log10(y).reshape(-1, 1) logx2=np.log10(x2).reshape(-1, 1) gam = LinearGAM(s(0, n_splines=10)).fit(logx,logy) #gam = PoissonGAM(s(0, n_splines=10)).fit(logx,logy) logpre = gam.predict(logx2) pre=np.power(10, logpre) return(pre)

def gamma_predict3(x,y, x2): ex=x.reshape(-1, 1) ey=y.reshape(-1, 1) ex2=x2.reshape(-1, 1) gam = LogisticGAM(s(0, n_splines=10)).fit(ex,ey) pre = gam.predict(ex2) return(pre)

def rf_log_predict2(x,y, x2): logx=np.log10(x).reshape(-1, 1) logy=np.log10(y).reshape(-1, 1) logx2=np.log10(x2).reshape(-1, 1) regressor = RandomForestRegressor(n_estimators=10000, random_state=0) regressor.fit(logx,logy) logpre = regressor.predict(logx2) pre=np.power(10, logpre) return(pre)


def interpolate1(x,y, x2): f = interpolate.interp1d(x, y) y2 = f(x2) return(y2)

def interpolate_point(x,y, px): f = interpolate.interp1d(x, y) y2 = f(px) return(y2)


def interpolate2(x,y, x2): logx=np.log10(x).reshape(-1, 1) logy=np.log10(y).reshape(-1, 1) logx2=np.log10(x2).reshape(-1, 1) f = interpolate.interp1d(logx, logy) y2 = f(logx2) pre=np.power(10,y2) return(y2)


def speknum(spt): spe=spt spe=spe.replace('O', '1') spe=spe.replace('B', '2') spe=spe.replace('A', '3') spe=spe.replace('F', '4') spe=spe.replace('G', '5') spe=spe.replace('K', '6') spe=spe.replace('M', '7') spe=spe.replace('L', '8') return(int(spe))

    1. load main sequence star data, edited from wiki 2023
    2. https://en.wikipedia.org/wiki/Main_sequence


arrname1="mainseq1.txt"


starr1 = np.loadtxt(arrname1,skiprows=1,dtype="float",delimiter=",",usecols =(1,2,3,4)) print(starr1)

masses1=starr1[:,1] lums1=starr1[:,2] temps1=starr1[:,3] radiuses1=starr1[:,0]


print (masses1) print (lums1) print (temps1)


df00 = pd.read_csv(arrname1, sep=",")


  1. print(df00)

spek1=df00['spectral']

  1. print(spek1)

classes="OBAFGKML"


spek2=spek1.tolist()


  1. print(spek2)


spek3 = [sub.replace('O', '1') for sub in spek2] spek3 = [sub.replace('B', '2') for sub in spek3] spek3 = [sub.replace('A', '3') for sub in spek3] spek3 = [sub.replace('F', '4') for sub in spek3] spek3 = [sub.replace('G', '5') for sub in spek3] spek3 = [sub.replace('K', '6') for sub in spek3] spek3 = [sub.replace('M', '7') for sub in spek3] spek3 = [sub.replace('L', '8') for sub in spek3]

  1. print(spek3)

spek4=np.array(spek3).astype(float)

  1. print(spek4)

speg1=np.arange(12,82,1)

  1. print(speg1)

speg2=speg1.astype(int)

  1. print(speg2)

speg3=speg2.tolist()


  1. print(speg3)

speg4 = [str(x) for x in speg3]

  1. print(speg4)


speg5=[]

first1=0

for sx in speg4:

sy=sx print(sy) chari1=sy[0] if(sy[0]=='1'): sy=sy.replace(sy[0],"O",1) if(sy[0]=='2'): sy=sy.replace(sy[0],"B",1) if(sy[0]=='3'): sy=sy.replace(sy[0],"A",1) if(sy[0]=='4'): sy=sy.replace(sy[0],"F",1) if(sy[0]=='5'): sy=sy.replace(sy[0],"G",1) if(sy[0]=='6'): sy=sy.replace(sy[0],"K",1) if(sy[0]=='7'): sy=sy.replace(sy[0],"M",1) if(sy[0]=='8'): sy=sy.replace(sy[0],"L",1) speg5.append(sy)

  1. print("speg5")
  1. print(spek4)
  2. print(speg1)
  3. print(speg5)


spektr1=spek4 spektr2=speg1

sally1=spek2 sally2=speg5


print(sally1) print(sally2)

print(spektr1) print(spektr2)


masses2=interpolate1(spektr1, masses1, spektr2) radiuses2=interpolate1(spektr1, radiuses1, spektr2) lums2=interpolate1(spektr1, lums1, spektr2) temps2=interpolate1(spektr1, temps1, spektr2)


spt1="G2"

spnum1=speknum(spt1)

teff1=interpolate_point(spektr1,temps1, spnum1)

print(spt1, spnum1,teff1)

  1. lum1=interpolate_point(masses1, lums1, m1)


  1. plt.xlim(0.1, 1.5)
  2. plt.ylim(0.0, 3)

font = {'family' : 'DejaVu Sans',

       'weight' : 'normal',
       'size'   : 18}
  1. plt.rc('font', **font)
  1. plt.title ("Main sequence spectral class - surface temperature", size=20)
  2. plt.plot(spektr1, temps1, "o", lw=6)
  1. plt.plot(spektr2, temps2, "-", color="r", lw=10)
  1. plt.grid(color='b', linestyle=':', linewidth=1)
  1. plt.xticks(spektr1, sally1)
  1. plt.plot(spnum1, teff1, "x")
  1. plt.show()



fig, ax = plt.subplots()

  1. The grid of visible wavelengths corresponding to the grid of colour-matching
  2. functions used by the ColourSystem instance.

lam = np.arange(380., 781., 5)

for i in range(len(spektr1)):

   # T = 500 to 12000 K
   #T = 500*i + 500
   T=int(temps1[i])
   sp1=sally1[i]
   # Calculate the black body spectrum and the HTML hex RGB colour string
   # it looks like
   spec = planck(lam, T)
   html_rgb = cs.spec_to_rgb(spec, out_fmt='html')
   # Place and label a circle with the colour of a black body at temperature T
   x, y = i % 5, -(i // 5)
   circle = Circle(xy=(x, y*1.2), radius=0.4, fc=html_rgb)
   ax.add_patch(circle)
   ax.annotate('{:4d} K'.format(T), xy=(x, y*1.2-0.6), va='center',
               ha='center', color=html_rgb, fontsize=15)
   ax.annotate('{:4s}'.format(sp1), xy=(x, y*1.2), va='center',
               ha='center', color='k', fontsize=18)   
               
  1. Set the limits and background colour; remove the ticks

ax.set_xlim(-0.5,5.0) ax.set_ylim(-4.35, 0.5) ax.set_xticks([]) ax.set_yticks([]) ax.set_facecolor('k')

  1. Make sure our circles are circular!

ax.set_aspect("equal") plt.title("Colours and temperatures of main sequence stars", size=22) plt.show()







CIE colour system code

  1. colour_system.py

import numpy as np

def xyz_from_xy(x, y):

   """Return the vector (x, y, 1-x-y)."""
   return np.array((x, y, 1-x-y))

class ColourSystem:

   """A class representing a colour system.
   A colour system defined by the CIE x, y and z=1-x-y coordinates of
   its three primary illuminants and its "white point".
   TODO: Implement gamma correction
   """
   # The CIE colour matching function for 380 - 780 nm in 5 nm intervals
   cmf = np.loadtxt('cie-cmf.txt', usecols=(1,2,3))
   def __init__(self, red, green, blue, white):
       """Initialise the ColourSystem object.
       Pass vectors (ie NumPy arrays of shape (3,)) for each of the
       red, green, blue  chromaticities and the white illuminant
       defining the colour system.
       """
       # Chromaticities
       self.red, self.green, self.blue = red, green, blue
       self.white = white
       # The chromaticity matrix (rgb -> xyz) and its inverse
       self.M = np.vstack((self.red, self.green, self.blue)).T 
       self.MI = np.linalg.inv(self.M)
       # White scaling array
       self.wscale = self.MI.dot(self.white)
       # xyz -> rgb transformation matrix
       self.T = self.MI / self.wscale[:, np.newaxis]
   def xyz_to_rgb(self, xyz, out_fmt=None):
       """Transform from xyz to rgb representation of colour.
       The output rgb components are normalized on their maximum
       value. If xyz is out the rgb gamut, it is desaturated until it
       comes into gamut.
       By default, fractional rgb components are returned; if
       out_fmt='html', the HTML hex string '#rrggbb' is returned.
       """
       rgb = self.T.dot(xyz)
       if np.any(rgb < 0):
           # We're not in the RGB gamut: approximate by desaturating
           w = - np.min(rgb)
           rgb += w
       if not np.all(rgb==0):
           # Normalize the rgb vector
           rgb /= np.max(rgb)
       if out_fmt == 'html':
           return self.rgb_to_hex(rgb)
       return rgb
   def rgb_to_hex(self, rgb):
       """Convert from fractional rgb values to HTML-style hex string."""
       hex_rgb = (255 * rgb).astype(int)
       return '#{:02x}{:02x}{:02x}'.format(*hex_rgb)
   def spec_to_xyz(self, spec):
       """Convert a spectrum to an xyz point.
       The spectrum must be on the same grid of points as the colour-matching
       function, self.cmf: 380-780 nm in 5 nm steps.
       """
       XYZ = np.sum(spec[:, np.newaxis] * self.cmf, axis=0)
       den = np.sum(XYZ)
       if den == 0.:
           return XYZ
       return XYZ / den
   def spec_to_rgb(self, spec, out_fmt=None):
       """Convert a spectrum to an rgb value."""
       xyz = self.spec_to_xyz(spec)
       return self.xyz_to_rgb(xyz, out_fmt)

illuminant_D65 = xyz_from_xy(0.3127, 0.3291) cs_hdtv = ColourSystem(red=xyz_from_xy(0.67, 0.33),

                      green=xyz_from_xy(0.21, 0.71),
                      blue=xyz_from_xy(0.15, 0.06),
                      white=illuminant_D65)

cs_smpte = ColourSystem(red=xyz_from_xy(0.63, 0.34),

                       green=xyz_from_xy(0.31, 0.595),
                       blue=xyz_from_xy(0.155, 0.070),
                       white=illuminant_D65)

cs_srgb = ColourSystem(red=xyz_from_xy(0.64, 0.33),

                      green=xyz_from_xy(0.30, 0.60),
                      blue=xyz_from_xy(0.15, 0.06),
                      white=illuminant_D65)

Stellar data

spectral,radius, mass, luminosity,teff "O2",12,100,800000,50000 "O6",9.8,35,180000,38000 "B0",7.4,18,20000,30000 "B5",3.8,6.5,800,16400 "A0",2.5,3.2,80,10800 "A5",1.7,2.1,20,8620 "F0",1.3,1.7,6,7240 "F5",1.2,1.3,2.5,6540 "G0",1.05,1.10,1.26,5920 "G5",0.93,0.93,0.79,5610 "K0",0.85,0.78,0.40,5240 "K5",0.74,0.69,0.16,4410 "M0",0.51,0.60,0.072,3800 "M5",0.18,0.15,0.0027,3120 "M8",0.11,0.08,0.0004,2650 "L1",0.09,0.07,0.00017,2200

Cie colour system file

380 0.0014 0.0000 0.0065 385 0.0022 0.0001 0.0105 390 0.0042 0.0001 0.0201 395 0.0076 0.0002 0.0362 400 0.0143 0.0004 0.0679 405 0.0232 0.0006 0.1102 410 0.0435 0.0012 0.2074 415 0.0776 0.0022 0.3713 420 0.1344 0.0040 0.6456 425 0.2148 0.0073 1.0391 430 0.2839 0.0116 1.3856 435 0.3285 0.0168 1.6230 440 0.3483 0.0230 1.7471 445 0.3481 0.0298 1.7826 450 0.3362 0.0380 1.7721 455 0.3187 0.0480 1.7441 460 0.2908 0.0600 1.6692 465 0.2511 0.0739 1.5281 470 0.1954 0.0910 1.2876 475 0.1421 0.1126 1.0419 480 0.0956 0.1390 0.8130 485 0.0580 0.1693 0.6162 490 0.0320 0.2080 0.4652 495 0.0147 0.2586 0.3533 500 0.0049 0.3230 0.2720 505 0.0024 0.4073 0.2123 510 0.0093 0.5030 0.1582 515 0.0291 0.6082 0.1117 520 0.0633 0.7100 0.0782 525 0.1096 0.7932 0.0573 530 0.1655 0.8620 0.0422 535 0.2257 0.9149 0.0298 540 0.2904 0.9540 0.0203 545 0.3597 0.9803 0.0134 550 0.4334 0.9950 0.0087 555 0.5121 1.0000 0.0057 560 0.5945 0.9950 0.0039 565 0.6784 0.9786 0.0027 570 0.7621 0.9520 0.0021 575 0.8425 0.9154 0.0018 580 0.9163 0.8700 0.0017 585 0.9786 0.8163 0.0014 590 1.0263 0.7570 0.0011 595 1.0567 0.6949 0.0010 600 1.0622 0.6310 0.0008 605 1.0456 0.5668 0.0006 610 1.0026 0.5030 0.0003 615 0.9384 0.4412 0.0002 620 0.8544 0.3810 0.0002 625 0.7514 0.3210 0.0001 630 0.6424 0.2650 0.0000 635 0.5419 0.2170 0.0000 640 0.4479 0.1750 0.0000 645 0.3608 0.1382 0.0000 650 0.2835 0.1070 0.0000 655 0.2187 0.0816 0.0000 660 0.1649 0.0610 0.0000 665 0.1212 0.0446 0.0000 670 0.0874 0.0320 0.0000 675 0.0636 0.0232 0.0000 680 0.0468 0.0170 0.0000 685 0.0329 0.0119 0.0000 690 0.0227 0.0082 0.0000 695 0.0158 0.0057 0.0000 700 0.0114 0.0041 0.0000 705 0.0081 0.0029 0.0000 710 0.0058 0.0021 0.0000 715 0.0041 0.0015 0.0000 720 0.0029 0.0010 0.0000 725 0.0020 0.0007 0.0000 730 0.0014 0.0005 0.0000 735 0.0010 0.0004 0.0000 740 0.0007 0.0002 0.0000 745 0.0005 0.0002 0.0000 750 0.0003 0.0001 0.0000 755 0.0002 0.0001 0.0000 760 0.0002 0.0001 0.0000 765 0.0001 0.0000 0.0000 770 0.0001 0.0000 0.0000 775 0.0001 0.0000 0.0000 780 0.0000 0.0000 0.0000

Licensing

[edit]
I, the copyright holder of this work, hereby publish it under the following license:
w:en:Creative Commons
attribution share alike
This file is licensed under the Creative Commons Attribution-Share Alike 4.0 International license.
You are free:
  • to share – to copy, distribute and transmit the work
  • to remix – to adapt the work
Under the following conditions:
  • attribution – You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use.
  • share alike – If you remix, transform, or build upon the material, you must distribute your contributions under the same or compatible license as the original.

File history

Click on a date/time to view the file as it appeared at that time.

Date/TimeThumbnailDimensionsUserComment
current10:47, 13 February 2023Thumbnail for version as of 10:47, 13 February 20231,333 × 819 (44 KB)Merikanto (talk | contribs)Update
10:22, 13 February 2023Thumbnail for version as of 10:22, 13 February 20231,138 × 791 (44 KB)Merikanto (talk | contribs)Uploaded own work with UploadWizard

There are no pages that use this file.

Metadata