Python script - lookup table

Hi

I was thinking of writing a script to look up values from a table e.g.

http://www.uni.edu/morgans/astro/course/Notes/section2/spectraltemps.html

Can anyone suggest good tutorials to get me started?

Thanks

what do you want to lookup, which column is the key?

Or do you mean a conversion table? Convert any type to another?

from collections import namedtuple

spectral_props = namedtuple("SpectralProps", "temparature magnitude lumiosity")

spectral_types = {
    'main_seq_stars': {
        'O5': spectral_props(54000, -4.5, 200000),
        'O6': spectral_props(45000, -4.0, 140000),
    },
    'giants': {
        # ...
    }
}

print(spectral_types['main_seq_stars']['O6'].lumiosity)

I want to lookup the spectral type and output either the colour temperature (to plug into the black body node in cycles) - or an RGB colour value based off the conversion table below - and plug this into the colour slot of a cycles shader node.

http://www.vendian.org/mncharity/dir3/blackbody/UnstableURLs/bbr_color.html

I want to create a custom node in cycles that has the spectral type as selectable from a list - and it spits out the desired property (temperature or RGB value).

Cheers

You can’t create actual nodes with python, I don’t think you can feed any existing node input with a custom node output. Python gives access to the node interface API, but functional nodes are still C-written.

You could add a panel to the node editor sidebar however, with a list and an operator to assign to an Input > Value node (or create a new one).

Sorry - have I misunderstood how the “script” node in cycles works.

I though it allowed you to execute a script and output the result of that script. To be useable - I would have thought it would allow you to define inputs and outputs to the node.

Is this not how it works?

It does, but it uses OSL not python.

Ah - ok, my misunderstanding then

This adds a panel to the node editor T-shelf with spectral types, and lets you assign the properties to an Input > Value node:

import bpy
from bpy.props import PointerProperty, EnumProperty, FloatProperty, IntProperty

spectral_types = {
    'main_sequence_stars': {
        'O5': (54000, -4.5, 200000),
        'O6': (45000, -4.0, 140000),
        'O7': (43300, -3.9, 120000),
        'O8': (40600, -3.8, 80000),
        'O9': (37800, -3.6, 55000),
        'B0': (29200, -3.3, 24000),
        'B1': (23000, -2.3, 5550),
        'B2': (21000, -1.9, 3190),
        'B3': (17600, -1.1, 1060),
        'B5': (15200, -0.4, 380),
        'B6': (14300, 0, 240),
        'B7': (13500, 0.3, 140),
        'B8': (12300, 0.7, 73),
        'B9': (11400, 1.1, 42),
        'A0': (9600, 1.5, 24),
        'A1': (9330, 1.7, 20),
        'A2': (9040, 1.8, 17),
        'A3': (8750, 2.0, 14),
        'A4': (8480, 2.1, 12),
        'A5': (8310, 2.2, 11),
        'A7': (7920, 2.4, 8.8),
        'F0': (7350, 3.0, 5.1),
        'F2': (7050, 3.3, 3.8),
        'F3': (6850, 3.5, 3.2),
        'F5': (6700, 3.7, 2.7),
        'F6': (6550, 4.0, 2.0),
        'F7': (6400, 4.3, 1.5),
        'F8': (6300, 4.4, 1.4),
        'G0': (6050, 4.7, 1.2),
        'G1': (5930, 4.9, 1.1),
        'G2': (5800, 5.0, 1),
        'G5': (5660, 5.2, 0.73),
        'G8': (5440, 2.6, 0.51),
        'K0': (5240, 6.0, 0.38),
        'K1': (5110, 6.2, 0.32),
        'K2': (4960, 6.4, 0.29),
        'K3': (4800, 6.7, 0.24),
        'K4': (4600, 7.1, 0.18),
        'K5': (4400, 7.4, 0.15),
        'K7': (4000, 8.1, 0.11),
        'M0': (3750, 8.7, 0.080),
        'M1': (3700, 9.4, 0.055),
        'M2': (3600, 10.1, 0.035),
        'M3': (3500, 10.7, 0.027),
        'M4': (3400, 11.2, 0.022),
        'M5': (3200, 12.3, 0.011),
        'M6': (3100, 13.4, 0.0051),
        'M7': (2900, 13.9, 0.0032),
        'M8': (2700, 14.4, 0.0020),
        'L0': (2600, float("nan"), 0.00029),
        'L3': (2200, float("nan"), 0.00013),
        'L8': (1500, float("nan"), 0.000032),
        'T2': (1400, float("nan"), 0.000025),
        'T6': (1000, float("nan"), 0.0000056),
        'T8': (800, float("nan"), 0.0000036),
    },
    'giants': {
        'G5': (5010, 0.7, 127),
        'G8': (4870, 0.6, 113),
        'K0': (4720, 0.5, 96),
        'K1': (4580, 0.4, 82),
        'K2': (4460, 0.2, 70),
        'K3': (4210, 0.1, 58),
        'K4': (4010, 0.0, 45),
        'K5': (3780, -0.2, 32),
        'M0': (3660, -0.4, 15),
        'M1': (3600, -0.5, 13),
        'M2': (3500, -0.6, 11),
        'M3': (3300, -0.7, 9.5),
        'M4': (3100, -0.75, 7.4),
        'M5': (2950, -0.8, 5.1),
        'M6': (2800, -0.9, 3.3),
    },
    'supergiants': {
        'B0': (21000, -6.4, 320000),
        'B1': (16000, -6.4, 280000),
        'B2': (14000, -6.4, 220000),
        'B3': (12800, -6.3, 180000),
        'B5': (11500, -6.3, 140000),
        'B6': (11000, -6.3, 98000),
        'B7': (10500, -6.3, 82000),
        'B8': (10000, -6.2, 73000),
        'B9': (9700, -6.2, 61000),
        'A0': (9400, -6.2, 50600),
        'A1': (9100, -6.2, 44000),
        'A2': (8900, -6.2, 40000),
        'A5': (8300, -6.1, 36000),
        'F0': (7500, -6, 20000),
        'F2': (7200, -6, 18000),
        'F5': (6800, -5.9, 16000),
        'F8': (6150, -5.9, 12000),
        'G0': (5800, -5.9, 9600),
        'G2': (5500, -5.8, 9500),
        'G5': (5100, -5.8, 9800),
        'G8': (5050, -5.7, 11000),
        'K0': (4900, -5.7, 12000),
        'K1': (4700, -5.6, 13500),
        'K2': (4500, -5.6, 15200),
        'K3': (4300, -5.6, 17000),
        'K4': (4100, -5.5, 18300),
        'K5': (3750, -5.5, 20000),
        'M0': (3660, -5.3, 50600),
        'M1': (3600, -5.3, 52000),
        'M2': (3500, -5.3, 53000),
        'M3': (3300, -5.3, 54000),
        'M4': (3100, -5.2, 56000),
        'M5': (2950, -5.2, 58000),
    },
}

spectral_categories = [(cat, cat.replace("_", " ").title(), "") for cat in spectral_types.keys()]


def spectral_types_category(self, context):
    cat = context.window_manager.spectral_types.category
    spec_types = spectral_types[cat]
    return [(k, k, "") for k in sorted(spec_types, key=spec_types.get, reverse=True)]


def spectral_type_update(self, context):
    spec = context.window_manager.spectral_types
    cat = spec.category
    temp, mag, lumi = spectral_types[cat][self.types]
    
    spec.temparature = temp
    spec.magnitude = mag
    spec.luminosity = lumi


class HelloWorldPanel(bpy.types.Panel):
    """Creates a Panel in the Object properties window"""
    bl_label = "Spectral Types"
    bl_idname = "OBJECT_PT_hello"
    bl_space_type = 'NODE_EDITOR'
    bl_region_type = 'TOOLS'

    def draw(self, context):
        layout = self.layout
        spec = context.window_manager.spectral_types
        
        col = layout.column()
        col.prop(spec, "category", text="")
        
        row = col.row()
        row.label(icon="BLANK1")
        sub = row.column()
        sub.prop(spec, "types", text="")
        
        box = sub.box()
        box.enabled = context.space_data.node_tree.nodes.active.bl_idname.endswith("NodeValue")
        
        data_path = "space_data.node_tree.nodes.active.outputs[0].default_value"
        
        subsub = box.row()
        subsub.label("Temparature:")
        subsub.label("%i" % spec.temparature)
        props = subsub.operator("wm.context_set_float", icon="FORWARD", text="")
        props.data_path = data_path
        props.value = spec.temparature
        
        subsub = box.row()
        subsub.label("Magnitude:")
        subsub.label("%s" % round(spec.magnitude, 6))
        props = subsub.operator("wm.context_set_float", icon="FORWARD", text="")
        props.data_path = data_path
        props.value = spec.magnitude
        
        subsub = box.row()
        subsub.label("Luminosity:")
        subsub.label("%s" % round(spec.luminosity, 6))
        props = subsub.operator("wm.context_set_float", icon="FORWARD", text="")
        props.data_path = data_path
        props.value = spec.luminosity

class SpectralTypes(bpy.types.PropertyGroup):
    category = EnumProperty(items=spectral_categories)
    types = EnumProperty(items=spectral_types_category, update=spectral_type_update)
    temparature = IntProperty()
    magnitude = FloatProperty()
    luminosity = FloatProperty()

def register():
    bpy.utils.register_module(__name__)    
    bpy.types.WindowManager.spectral_types = PointerProperty(type=SpectralTypes)


def unregister():
    bpy.utils.unregister_module(__name__)
    del bpy.types.WindowManager.spectral_types


if __name__ == "__main__":
    register()