3D Isosurface Sphere of 24,000 Stars Using Python and Claude.ai
by matt392 in Circuits > Computers
1 Views, 0 Favorites, 0 Comments
3D Isosurface Sphere of 24,000 Stars Using Python and Claude.ai
3D data visualization of 24,000 stars using an isosurface sphere. Utilized Python and Claude.ai for code.
import pandas as pd
import numpy as np
from scipy.ndimage import gaussian_filter
import pyvista as pv
# Load data
df = pd.read_csv('24000stars.csv')
# Convert parallax to distance (light years)
df['distance_ly'] = 3262 / df['parallax']
# Remove rows with NaN values
df = df.dropna(subset=['ra', 'dec', 'distance_ly', 'parallax'])
df = df[np.isfinite(df['distance_ly'])]
df = df.reset_index(drop=True)
# Convert RA/Dec to Cartesian coordinates
ra_rad = np.radians(df['ra'])
dec_rad = np.radians(df['dec'])
x = df['distance_ly'] * np.cos(dec_rad) * np.cos(ra_rad)
y = df['distance_ly'] * np.cos(dec_rad) * np.sin(ra_rad)
z = df['distance_ly'] * np.sin(dec_rad)
# Create 3D grid for density calculation
grid_size = 60 # REDUCED from 80 for faster rendering
x_range = np.linspace(-130, 130, grid_size)
y_range = np.linspace(-130, 130, grid_size)
z_range = np.linspace(-130, 130, grid_size)
X, Y, Z = np.meshgrid(x_range, y_range, z_range, indexing='ij')
# Calculate density using histogram in 3D
H, edges = np.histogramdd(
np.column_stack([x, y, z]),
bins=(x_range, y_range, z_range)
)
# Smooth the density field
H_smooth = gaussian_filter(H, sigma=2) # REDUCED sigma from 3
# Print diagnostics
print(f"Density stats: min={H_smooth.min():.4f}, max={H_smooth.max():.4f}, mean={H_smooth.mean():.4f}")
print(f"Non-zero cells: {np.sum(H_smooth > 0)}/{H_smooth.size}")
# Create PyVista uniform grid
grid = pv.ImageData()
grid.dimensions = H_smooth.shape
grid.spacing = (
(x_range.max() - x_range.min()) / (grid_size - 1),
(y_range.max() - y_range.min()) / (grid_size - 1),
(z_range.max() - z_range.min()) / (grid_size - 1)
)
grid.origin = (x_range.min(), y_range.min(), z_range.min())
# Add density as POINT data for contouring
grid.point_data['density'] = H_smooth.flatten(order='F')
# ===== BUILD SCENE FUNCTION =====
def build_scene(plotter):
"""Add all meshes and settings to plotter"""
plotter.set_background('black')
# Define density thresholds - REDUCED to 3 surfaces for speed
thresholds = [
(0.05, 'cyan', 0.4, 'Sparse'),
(0.15, 'yellow', 0.6, 'Medium'),
(0.30, 'red', 0.8, 'Dense')
]
print(f"Thresholds: {[t[0] for t in thresholds]}")
# Add isosurfaces for each density level
surfaces_added = 0
for threshold, color, opacity, label in thresholds:
try:
contour = grid.contour([threshold], scalars='density')
if contour.n_points > 0:
plotter.add_mesh(
contour,
color=color,
opacity=opacity,
show_edges=False,
smooth_shading=True,
label=label
)
surfaces_added += 1
print(f"Added surface at threshold {threshold:.3f}: {contour.n_points} points")
else:
print(f"No surface at threshold {threshold:.3f}")
except Exception as e:
print(f"Failed at threshold {threshold:.3f}: {e}")
continue
print(f"Total surfaces added: {surfaces_added}")
# Add title
plotter.add_text(
'3D Stellar Density Isosurfaces\n24,071 Stars within 131 Light Years',
position='upper_edge',
font_size=12,
color='white'
)
plotter.add_text(
'Thin shells near Earth = Stellar Desert\nThick shells at distance = Dense regions',
position='lower_left',
font_size=9,
color='white'
)
# Add axes
plotter.show_axes()
# Add Earth marker
origin_sphere = pv.Sphere(radius=5, center=(0, 0, 0))
plotter.add_mesh(origin_sphere, color='white', opacity=0.8, label='Earth')
# Set camera
plotter.camera_position = 'iso'
plotter.camera.zoom(1.2)
# ===== LIVE INTERACTIVE WINDOW =====
print("Opening live interactive window...")
print("Close the window when ready.")
plotter_live = pv.Plotter()
build_scene(plotter_live)
plotter_live.show()
print("Live window closed.")
# Set camera
plotter.camera_position = 'iso'
plotter.camera.zoom(1.2)
"""
print("Generating video...")
plotter_video = pv.Plotter(off_screen=True, window_size=[1920, 1080])
build_scene(plotter_video)
plotter_video.open_movie('isosurface_rotation.mp4', framerate=30)
plotter_video.render()
n_frames = 360
path = plotter_video.generate_orbital_path(n_points=n_frames, shift=0, viewup=[0, 0, 1], factor=2.5)
for i in range(n_frames):
plotter_video.camera.position = path.points[i]
plotter_video.write_frame()
plotter_video.close()
print("Video saved as isosurface_rotation.mp4")
"""
print(f"\nTotal stars: {len(df)}")
print(f"Grid resolution: {grid_size}³ = {grid_size**3} cells")
print(f"Density range: {H_smooth.min():.2f} to {H_smooth.max():.2f}")
Supplies
Python libraries:
- Pandas
- Numpy
- Scipy
- Pyvista
3D Isosurface Sphere of 24,000 Stars Using Python and Claude.ai
import pandas as pd
import numpy as np
from scipy.ndimage import gaussian_filter
import pyvista as pv
# Load data
df = pd.read_csv('24000stars.csv')
# Convert parallax to distance (light years)
df['distance_ly'] = 3262 / df['parallax']
# Remove rows with NaN values
df = df.dropna(subset=['ra', 'dec', 'distance_ly', 'parallax'])
df = df[np.isfinite(df['distance_ly'])]
df = df.reset_index(drop=True)
# Convert RA/Dec to Cartesian coordinates
ra_rad = np.radians(df['ra'])
dec_rad = np.radians(df['dec'])
x = df['distance_ly'] * np.cos(dec_rad) * np.cos(ra_rad)
y = df['distance_ly'] * np.cos(dec_rad) * np.sin(ra_rad)
z = df['distance_ly'] * np.sin(dec_rad)
# Create 3D grid for density calculation
grid_size = 60 # REDUCED from 80 for faster rendering
x_range = np.linspace(-130, 130, grid_size)
y_range = np.linspace(-130, 130, grid_size)
z_range = np.linspace(-130, 130, grid_size)
X, Y, Z = np.meshgrid(x_range, y_range, z_range, indexing='ij')
# Calculate density using histogram in 3D
H, edges = np.histogramdd(
np.column_stack([x, y, z]),
bins=(x_range, y_range, z_range)
)
# Smooth the density field
H_smooth = gaussian_filter(H, sigma=2) # REDUCED sigma from 3
# Print diagnostics
print(f"Density stats: min={H_smooth.min():.4f}, max={H_smooth.max():.4f}, mean={H_smooth.mean():.4f}")
print(f"Non-zero cells: {np.sum(H_smooth > 0)}/{H_smooth.size}")
# Create PyVista uniform grid
grid = pv.ImageData()
grid.dimensions = H_smooth.shape
grid.spacing = (
(x_range.max() - x_range.min()) / (grid_size - 1),
(y_range.max() - y_range.min()) / (grid_size - 1),
(z_range.max() - z_range.min()) / (grid_size - 1)
)
grid.origin = (x_range.min(), y_range.min(), z_range.min())
# Add density as POINT data for contouring
grid.point_data['density'] = H_smooth.flatten(order='F')
# ===== BUILD SCENE FUNCTION =====
def build_scene(plotter):
"""Add all meshes and settings to plotter"""
plotter.set_background('black')
# Define density thresholds - REDUCED to 3 surfaces for speed
thresholds = [
(0.05, 'cyan', 0.4, 'Sparse'),
(0.15, 'yellow', 0.6, 'Medium'),
(0.30, 'red', 0.8, 'Dense')
]
print(f"Thresholds: {[t[0] for t in thresholds]}")
# Add isosurfaces for each density level
surfaces_added = 0
for threshold, color, opacity, label in thresholds:
try:
contour = grid.contour([threshold], scalars='density')
if contour.n_points > 0:
plotter.add_mesh(
contour,
color=color,
opacity=opacity,
show_edges=False,
smooth_shading=True,
label=label
)
surfaces_added += 1
print(f"Added surface at threshold {threshold:.3f}: {contour.n_points} points")
else:
print(f"No surface at threshold {threshold:.3f}")
except Exception as e:
print(f"Failed at threshold {threshold:.3f}: {e}")
continue
print(f"Total surfaces added: {surfaces_added}")
# Add title
plotter.add_text(
'3D Stellar Density Isosurfaces\n24,071 Stars within 131 Light Years',
position='upper_edge',
font_size=12,
color='white'
)
plotter.add_text(
'Thin shells near Earth = Stellar Desert\nThick shells at distance = Dense regions',
position='lower_left',
font_size=9,
color='white'
)
# Add axes
plotter.show_axes()
# Add Earth marker
origin_sphere = pv.Sphere(radius=5, center=(0, 0, 0))
plotter.add_mesh(origin_sphere, color='white', opacity=0.8, label='Earth')
# Set camera
plotter.camera_position = 'iso'
plotter.camera.zoom(1.2)
# ===== LIVE INTERACTIVE WINDOW =====
print("Opening live interactive window...")
print("Close the window when ready.")
plotter_live = pv.Plotter()
build_scene(plotter_live)
plotter_live.show()
print("Live window closed.")
# Set camera
plotter.camera_position = 'iso'
plotter.camera.zoom(1.2)
"""
print("Generating video...")
plotter_video = pv.Plotter(off_screen=True, window_size=[1920, 1080])
build_scene(plotter_video)
plotter_video.open_movie('isosurface_rotation.mp4', framerate=30)
plotter_video.render()
n_frames = 360
path = plotter_video.generate_orbital_path(n_points=n_frames, shift=0, viewup=[0, 0, 1], factor=2.5)
for i in range(n_frames):
plotter_video.camera.position = path.points[i]
plotter_video.write_frame()
plotter_video.close()
print("Video saved as isosurface_rotation.mp4")
"""
print(f"\nTotal stars: {len(df)}")
print(f"Grid resolution: {grid_size}³ = {grid_size**3} cells")
print(f"Density range: {H_smooth.min():.2f} to {H_smooth.max():.2f}")