|
import marimo |
|
|
|
__generated_with = "0.9.20" |
|
app = marimo.App() |
|
|
|
|
|
@app.cell |
|
def __(mo): |
|
mo.md("""# Marimo + Blender""") |
|
return |
|
|
|
|
|
@app.cell |
|
def __(): |
|
|
|
|
|
|
|
import marimo as mo |
|
import numpy as np |
|
import polars as pl |
|
import quak |
|
import bpy |
|
|
|
blend_file_path = "housing_data_igor.blend" |
|
bpy.ops.wm.open_mainfile(filepath=blend_file_path) |
|
|
|
bpy.context.scene.render.engine = "BLENDER_EEVEE_NEXT" |
|
bpy.context.scene.render.resolution_x = 800 |
|
bpy.context.scene.render.resolution_y = 500 |
|
|
|
df = pl.read_csv("a_df.csv") |
|
reference_frame = pl.read_csv("b_reference_frame.csv") |
|
|
|
vertices = [(row["longitude_normalized"], row["latitude_normalized"], 0) for row in reference_frame.iter_rows(named=True)] |
|
|
|
mesh = bpy.data.meshes.new("NormalizedMesh") |
|
obj = bpy.data.objects.new("CaliforninaNormalizedObject", mesh) |
|
bpy.context.collection.objects.link(obj) |
|
|
|
mesh.from_pydata(vertices, [], []) |
|
mesh.update() |
|
obj.modifiers.new(name="GeometryNodes", type='NODES').node_group = bpy.data.node_groups["geo_house"] |
|
bpy.context.view_layer.objects.active = obj |
|
obj.select_set(True) |
|
reference_frame.head() |
|
|
|
def render_result(): |
|
|
|
bpy.ops.render.render() |
|
bpy.data.images['Render Result'].save_render(filepath="img.png") |
|
return mo.image(src="img.png") |
|
return ( |
|
blend_file_path, |
|
bpy, |
|
df, |
|
mesh, |
|
mo, |
|
np, |
|
obj, |
|
pl, |
|
quak, |
|
reference_frame, |
|
render_result, |
|
vertices, |
|
) |
|
|
|
|
|
@app.cell |
|
def __(df, mo, quak): |
|
widget = mo.ui.anywidget(quak.Widget(df)) |
|
widget |
|
return (widget,) |
|
|
|
|
|
@app.cell |
|
def __(np, obj, pl, reference_frame, render_result, widget): |
|
widget_df = widget.data().pl() |
|
|
|
plotting_frame = reference_frame.with_columns( |
|
pl.lit(0).alias("custom_plotting") |
|
).join( |
|
widget_df.select(["short_id", "median_house_value"]), |
|
on="short_id", |
|
how="left" |
|
).with_columns( |
|
pl.when(pl.col("median_house_value").is_not_null()) |
|
.then(pl.col("median_house_value")) |
|
.otherwise(pl.col("custom_plotting")) |
|
.alias("custom_plotting") |
|
).select(["short_id", "custom_plotting"]) |
|
|
|
custom_plotting_list = plotting_frame["custom_plotting"].to_list() |
|
normalized_values = list(np.interp(custom_plotting_list, |
|
(min(custom_plotting_list), max(custom_plotting_list)), |
|
(0.1, 3))) |
|
|
|
attr_name = 'median_house_value' |
|
attr = obj.data.attributes.get(attr_name) or obj.data.attributes.new( |
|
name=attr_name, |
|
type='FLOAT', |
|
domain='POINT' |
|
) |
|
attr.data.foreach_set('value', normalized_values) |
|
obj.data.update() |
|
|
|
render_result() |
|
return ( |
|
attr, |
|
attr_name, |
|
custom_plotting_list, |
|
normalized_values, |
|
plotting_frame, |
|
widget_df, |
|
) |
|
|
|
|
|
@app.cell |
|
def __(): |
|
return |
|
|
|
|
|
if __name__ == "__main__": |
|
app.run() |
|
|