blender-atom-render
Skill0 starsChanged 6 months agoMITView on GitHub
Render individual atom spheres from structure files using Blender and create per-system legends. Triggers - /blender-atom-render, "atom render", "원자 렌더링", "atom legend", "레전드 만들어", "blender로 렌더", "구 렌더링
1 other project uses a version of this, 1 of them edited.
Adopted by
Most recently taken up by
- s-choung/Research-Skillsedited, first seen May 16, 2026
Other versions1 project uses a version of this.
Word for word · 0
None found.
Edited · 1
- s-choung/Research-Skills★ 3631% same
Wrote their own version · 0
None found.
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository15 other files it gives its agents.
- analysis-protocolSkill
- corpus-phrase-checkSkill
- docx-scientific-formattingSkill
- html-minimalSkill
- layout-guardSkill
- matplotlib-scientificSkill
- paper-sectionsSkill
- paper-sentence-loopSkill
- paper-styleSkill
- reference-crosscheckSkill
- slide-auditSkill
- smart-compactSkill
- transcript2htmlSkill
- youtube2mp4Skill
- youtubeSkill
The file
We split this skill into the rules it gives an agent
3 rules. About 0 are common, 1 is distinctive, and 2 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
2
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 20
Use ASE to read all structure files and extract unique chemical symbols.
- Very specific: line 161
Use Pillow to compose horizontal legends with rendered 3D sphere PNGs as icons: [rendered sphere] Name [rendered sphere] Name ...
- Very specific: line 224
Use bpy.data.objects.remove(obj, do_unlink=True) for reliable deletion
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Blender Atom Render
Render individual atom spheres from atomic structure files (traj, xyz, etc.) using Blender's io_mesh_atomic addon, then compose per-system legend images.
Prerequisites
- Blender installed at
/Applications/Blender.app/Contents/MacOS/Blender(or find viawhich blender) - Python with ASE (
ase) and Pillow (PIL) in base conda - A Blender
.blendfile with camera and lighting setup
Workflow
Step 1: Extract unique atoms from structure files
Use ASE to read all structure files and extract unique chemical symbols. Create single-atom XYZ files at (0,0,0).
from ase.io import read
from ase import Atoms
from ase.io import write
import glob, os
traj_files = glob.glob('**/*.traj', recursive=True)
all_symbols = set()
for f in traj_files:
atoms = read(f, index=-1)
all_symbols.update(atoms.get_chemical_symbols())
for symbol in sorted(all_symbols):
atom = Atoms(symbol, positions=[(0, 0, 0)])
write(f'{symbol}.xyz', atom)Step 2: Create a clean blend file (camera + lights only)
Copy the original blend file, removing all mesh objects while preserving camera and lighting. Add a close-up orthographic camera for single-atom rendering.
Key: use bpy.data.objects.remove() instead of select_set() + delete — some objects may not be in the active ViewLayer and will fail with select-based deletion.
# make_clean_blend.py — run with: blender original.blend --background --python make_clean_blend.py
import bpy, mathutils
OUTPUT_BLEND = "camera_light_clean.blend"
# Delete all non-camera/light objects via data API (bypasses ViewLayer issues)
keep_types = {'CAMERA', 'LIGHT', 'EMPTY'}
to_delete = [obj for obj in bpy.data.objects if obj.type not in keep_types]
for obj in to_delete:
bpy.data.objects.remove(obj, do_unlink=True)
bpy.ops.outliner.orphans_purge(do_recursive=True)
# Add close-up orthographic camera for single atom
cam_data = bpy.data.cameras.new("AtomCam")
cam_data.type = 'ORTHO'
cam_data.ortho_scale = 4.0 # adjust to frame atom nicely
cam_obj = bpy.data.objects.new("AtomCam", cam_data)
bpy.context.collection.objects.link(cam_obj)
cam_obj.location = (5.0, -5.0, 3.5)
direction = mathutils.Vector((0, 0, 0)) - cam_obj.location
cam_obj.rotation_euler = direction.to_track_quat('-Z', 'Y').to_euler()
bpy.context.scene.camera = cam_obj
bpy.ops.wm.save_as_mainfile(filepath=OUTPUT_BLEND)Step 3: Render each atom INDEPENDENTLY
Critical lesson learned: Rendering in a loop within a single Blender session causes material contamination — _ball objects persist across iterations despite deletion attempts. Always launch a separate Blender process per atom.
Default CPK colors
# render_single.py — run with: blender clean.blend --background --python render_single.py -- input.xyz output.png
import bpy, sys
argv = sys.argv[sys.argv.index("--") + 1:]
xyz_path, output_path = argv[0], argv[1]
bpy.ops.preferences.addon_enable(module="io_mesh_atomic")
bpy.ops.import_mesh.xyz(
filepath=xyz_path,
ball="1", # '0'=NURBS, '1'=MESH, '2'=META
mesh_azimuth=128, # high = smoother sphere
mesh_zenith=128,
scale_ballradius=1.0,
scale_distances=1.0,
)
bpy.context.scene.render.filepath = output_path
bpy.ops.render.render(write_still=True)Custom RGB colors
# render_single_color.py — run with: blender clean.blend --background --python render_single_color.py -- input.xyz output.png R G B
import bpy, sys
argv = sys.argv[sys.argv.index("--") + 1:]
xyz_path, output_path = argv[0], argv[1]
r, g, b = float(argv[2]), float(argv[3]), float(argv[4])
bpy.ops.preferences.addon_enable(module="io_mesh_atomic")
bpy.ops.import_mesh.xyz(
filepath=xyz_path,
ball="1",
mesh_azimuth=128,
mesh_zenith=128,
scale_ballradius=1.0,
scale_distances=1.0,
)
# Override material color on the ball object
for obj in bpy.context.scene.objects:
if "_ball" in obj.name:
if obj.data.materials:
mat = obj.data.materials[0]
mat.diffuse_color = (r, g, b, 1.0)
if mat.use_nodes:
for node in mat.node_tree.nodes:
if node.type == 'BSDF_PRINCIPLED':
node.inputs['Base Color'].default_value = (r, g, b, 1.0)
break
bpy.context.scene.render.filepath = output_path
bpy.ops.render.render(write_still=True)Shell loop (custom colors via function):
BLENDER=/Applications/Blender.app/Contents/MacOS/Blender
render_atom() {
local elem=$1 r=$2 g=$3 b=$4
"$BLENDER" "$CLEAN_BLEND" --background --python render_single_color.py -- \
"${elem}.xyz" "renders/${elem}.png" "$r" "$g" "$b"
}
render_atom Ba 0 0.78 0
render_atom La 0.502 0.922 0.973
# ... etc. RGB values are floats 0.0-1.0Shell loop (default CPK colors):
for xyz in input_dir/*.xyz; do
elem=$(basename "$xyz" .xyz)
"$BLENDER" "$CLEAN_BLEND" --background --python render_single.py -- "$xyz" "renders/${elem}.png"
doneStep 4: Create per-system legend images
Use Pillow to compose horizontal legends with rendered 3D sphere PNGs as icons: [rendered sphere] Name [rendered sphere] Name ...
from PIL import Image, ImageDraw, ImageFont
FONT_PATH = '/System/Library/Fonts/Supplemental/Arial.ttf'
ICON_SIZE = 60 # rendered sphere resized to this
FONT_SIZE = 48
SPACING = 10 # gap between icon and text
ITEM_GAP = 40 # gap between pairs
PADDING_X = 30
systems = {
'BCZYYb-GCCCO': ['Ba', 'Ca', 'Ce', 'Co', 'Cu', 'Gd', 'O', 'Y', 'Yb', 'Zr'],
'GDC-GCCCO': ['Ca', 'Ce', 'Co', 'Cu', 'Gd', 'O'],
'GDC-LSCF': ['Ce', 'Co', 'Fe', 'Gd', 'La', 'O', 'Sr'],
}
font = ImageFont.truetype(FONT_PATH, FONT_SIZE)
for sys_name, elements in systems.items():
items_widths = []
for elem in elements:
bbox = font.getbbox(elem)
items_widths.append(ICON_SIZE + SPACING + bbox[2] - bbox[0])
total_w = PADDING_X * 2 + sum(items_widths) + ITEM_GAP * (len(elements) - 1)
total_h = max(ICON_SIZE + 20, 100)
img = Image.new('RGBA', (total_w, total_h), (255, 255, 255, 0))
draw = ImageDraw.Draw(img)
x = PADDING_X
cy = total_h // 2
for elem in elements:
# Use rendered 3D sphere as icon
sphere = Image.open(f'renders/{elem}.png').convert('RGBA')
sphere = sphere.resize((ICON_SIZE, ICON_SIZE), Image.LANCZOS)
img.paste(sphere, (x, cy - ICON_SIZE // 2), sphere)
bbox = font.getbbox(elem)
th = bbox[3] - bbox[1]
ty = cy - th // 2 - bbox[1]
draw.text((x + ICON_SIZE + SPACING, ty), elem, fill=(0, 0, 0, 255), font=font)
tw = bbox[2] - bbox[0]
x += ICON_SIZE + SPACING + tw + ITEM_GAP
img.save(f'renders/legend_{sys_name}_v2_WJ.png', 'PNG')For a merged legend with all atoms: collect sorted(set(...)) of all atoms across systems and generate one combined image (legend_v2_WJ.png).
Important Notes
io_mesh_atomic API quirks
ballparameter uses string enums:'0'=NURBS,'1'=MESH,'2'=META (NOT'MESH'etc.)use_camera,use_lightparameters may not exist in some Blender versions — omit them- Each element gets its own Principled BSDF material with CPK-style colors automatically
Object cleanup pitfalls
bpy.ops.object.select_set()fails for objects not in the active ViewLayer- Use
bpy.data.objects.remove(obj, do_unlink=True)for reliable deletion _ballobjects fromio_mesh_atomictend to persist — separate processes are the safest solution
Camera for single atoms
- Original blend cameras are typically set for large structures (ortho_scale 14-300)
- Single atoms need ortho_scale ~3-5 depending on element radius
- Ortho cameras: distance doesn't matter, only
ortho_scalecontrols framing
Mesh smoothness
mesh_azimuthandmesh_zenithcontrol sphere polygon count- 32x32 = visibly faceted, 64x64 = acceptable, 128x128 = smooth sphere
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

