Create an app showing 3D data visualizations. Generate mock 3D data: - Spiral helix with noise (100 points) - Surface plot (z = sin(x)*cos(y)) - 3D clusters (3 clusters, 50 points each) Features: - Viz selector dropdown - Interactive 3D plots with rotate/zoom - Controls for: * Point styling (size, color, opacity) * Axis settings * Animation speed Surface plot options: - Function parameter sliders - Color scheme toggle - Contour lines All plots should be fully interactive.
Drop files here
or click to upload
import streamlit as st
import numpy as np
import plotly.graph_objects as go
import plotly.express as px
from sklearn.datasets import make_blobs
# Set page config
st.set_page_config(
page_title="3D Data Visualizations",
layout="wide",
initial_sidebar_state="expanded"
)
# Page title
st.title("3D Data Visualizations")
st.write("Explore different 3D data visualizations with interactive controls")
# Sidebar for visualization selection and controls
st.sidebar.header("Visualization Controls")
# Visualization selector
viz_type = st.sidebar.selectbox(
"Select Visualization",
["3D Spiral Helix", "3D Surface Plot", "3D Clusters"]
)
# Common styling controls
st.sidebar.subheader("Common Style Controls")
point_size = st.sidebar.slider("Point Size", 2, 10, 5)
opacity = st.sidebar.slider("Opacity", 0.1, 1.0, 0.8)
color_scale = st.sidebar.selectbox(
"Color Scale",
['Viridis', 'Plasma', 'Inferno', 'Magma', 'Cividis', 'Rainbow']
)
# Generate spiral helix data
def generate_helix(n_points=100, noise=0.5):
t = np.linspace(0, 10 * np.pi, n_points)
x = np.cos(t)
y = np.sin(t)
z = t / 3
# Add some noise
x += np.random.normal(0, noise, n_points) * 0.1
y += np.random.normal(0, noise, n_points) * 0.1
z += np.random.normal(0, noise, n_points) * 0.1
return x, y, z, t
# Generate surface data
def generate_surface(n_points=50, a=1, b=1):
x = np.linspace(-5, 5, n_points)
y = np.linspace(-5, 5, n_points)
x_grid, y_grid = np.meshgrid(x, y)
z_grid = np.sin(a * x_grid) * np.cos(b * y_grid)
return x_grid, y_grid, z_grid
# Generate cluster data
def generate_clusters(n_clusters=3, n_points=50, random_state=42):
centers = [[-2, -2, -2], [0, 0, 0], [2, 2, 2]]
X, y = make_blobs(
n_samples=n_points * n_clusters,
centers=centers,
n_features=3,
random_state=random_state
)
return X, y
# Plot the selected visualization
if viz_type == "3D Spiral Helix":
st.header("3D Spiral Helix with Noise")
st.sidebar.subheader("Helix Controls")
n_points = st.sidebar.slider("Number of Points", 50, 500, 100)
noise_level = st.sidebar.slider("Noise Level", 0.0, 2.0, 0.5)
animation_speed = st.sidebar.slider("Animation Speed", 0, 100, 50)
rotate = st.sidebar.checkbox("Auto-rotate", True)
x, y, z, t = generate_helix(n_points, noise_level)
# Create the 3D scatter plot
fig = go.Figure(data=[go.Scatter3d(
x=x, y=y, z=z,
mode='markers',
marker=dict(
size=point_size,
color=t,
colorscale=color_scale.lower(),
opacity=opacity
)
)])
# Set the layout
fig.update_layout(
width=800,
height=700,
scene=dict(
xaxis_title='X',
yaxis_title='Y',
zaxis_title='Z',
aspectmode='cube'
),
scene_camera=dict(
eye=dict(x=1.5, y=1.5, z=1.5)
)
)
# Set animation parameters if auto-rotate is enabled
if rotate:
fig.update_layout(
updatemenus=[dict(
type='buttons',
showactive=False,
buttons=[dict(
label='Play',
method='animate',
args=[None, dict(
frame=dict(duration=500/animation_speed, redraw=True),
fromcurrent=True,
mode='immediate'
)]
)]
)]
)
st.plotly_chart(fig, use_container_width=True)
st.write("A 3D spiral helix with random noise. You can adjust the number of points, noise level, and animation speed.")
elif viz_type == "3D Surface Plot":
st.header("3D Surface Plot")
st.sidebar.subheader("Surface Controls")
resolution = st.sidebar.slider("Resolution", 20, 100, 50)
a_param = st.sidebar.slider("Parameter A", 0.1, 3.0, 1.0, 0.1)
b_param = st.sidebar.slider("Parameter B", 0.1, 3.0, 1.0, 0.1)
show_contours = st.sidebar.checkbox("Show Contours", True)
contour_width = st.sidebar.slider("Contour Width", 1, 10, 2) if show_contours else 0
x_grid, y_grid, z_grid = generate_surface(resolution, a_param, b_param)
# Create the 3D surface plot
fig = go.Figure()
# Add surface
fig.add_trace(go.Surface(
z=z_grid,
x=x_grid,
y=y_grid,
colorscale=color_scale.lower(),
opacity=opacity,
contours={
"z": {"show": show_contours, "width": contour_width}
}
))
# Set the layout
fig.update_layout(
width=800,
height=700,
title=f"z = sin({a_param}x) * cos({b_param}y)",
scene=dict(
xaxis_title='X',
yaxis_title='Y',
zaxis_title='Z',
aspectmode='cube'
),
scene_camera=dict(
eye=dict(x=1.5, y=1.5, z=1.5)
)
)
st.plotly_chart(fig, use_container_width=True)
# Explanation of the plot
st.write(f"""
This surface plot shows the function z = sin({a_param}x) * cos({b_param}y).
You can adjust:
- Parameters A and B to change the frequency of the sine and cosine functions
- Resolution to make the surface smoother or more detailed
- Contour lines to better visualize the surface topology
""")
# Display the equation
st.latex(f"z = \\sin({a_param}x) \\cdot \\cos({b_param}y)")
elif viz_type == "3D Clusters":
st.header("3D Clusters")
st.sidebar.subheader("Cluster Controls")
n_clusters = st.sidebar.slider("Number of Clusters", 2, 5, 3)
points_per_cluster = st.sidebar.slider("Points per Cluster", 20, 200, 50)
random_seed = st.sidebar.slider("Random Seed", 0, 100, 42)
show_centroids = st.sidebar.checkbox("Show Centroids", True)
X, y = generate_clusters(n_clusters, points_per_cluster, random_seed)
# Create a 3D scatter plot for clusters
fig = px.scatter_3d(
x=X[:, 0], y=X[:, 1], z=X[:, 2],
color=y,
color_continuous_scale=color_scale.lower(),
opacity=opacity,
size=[point_size] * len(X),
size_max=point_size,
)
# Add centroids if requested
if show_centroids:
# Calculate centroids
centroids = []
for i in range(n_clusters):
mask = (y == i)
centroids.append([
np.mean(X[mask, 0]),
np.mean(X[mask, 1]),
np.mean(X[mask, 2])
])
centroids = np.array(centroids)
# Add centroids to the plot
fig.add_trace(go.Scatter3d(
x=centroids[:, 0],
y=centroids[:, 1],
z=centroids[:, 2],
mode='markers',
marker=dict(
color='black',
size=point_size * 2,
symbol='diamond'
),
name='Centroids'
))
# Set the layout
fig.update_layout(
width=800,
height=700,
scene=dict(
xaxis_title='X',
yaxis_title='Y',
zaxis_title='Z',
aspectmode='cube'
),
scene_camera=dict(
eye=dict(x=1.5, y=1.5, z=1.5)
)
)
st.plotly_chart(fig, use_container_width=True)
# Explanation of the plot
st.write(f"""
This 3D cluster visualization shows {n_clusters} clusters with {points_per_cluster} points each.
The clusters are generated using scikit-learn's make_blobs function.
You can adjust:
- Number of clusters
- Points per cluster
- Random seed to create different cluster arrangements
- Show/hide centroids of each cluster
""")
# Add instructions at the bottom
st.sidebar.markdown("---")
st.sidebar.subheader("Navigation Tips")
st.sidebar.markdown("""
- **Rotate**: Click and drag
- **Zoom**: Scroll or pinch
- **Pan**: Right-click and drag
- **Reset View**: Double-click
""")
# Footer
st.markdown("---")
st.markdown("Built with Streamlit and Plotly | Created for 3D data exploration")
Hi! I can help you with any questions about Streamlit and Python. What would you like to know?