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.
To upload files, please first save the app
import streamlit as st
import numpy as np
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import plotly.express as px
st.set_page_config(layout="wide")
st.title("3D Data Visualizations")
# Data generation functions
def generate_helix(n_points=100, noise=0.1):
t = np.linspace(0, 10, n_points)
x = np.cos(t)
y = np.sin(t)
z = t/3
# Add noise
x += np.random.normal(0, noise, n_points)
y += np.random.normal(0, noise, n_points)
z += np.random.normal(0, noise, n_points)
return x, y, z
def generate_surface(resolution=50):
x = np.linspace(-5, 5, resolution)
y = np.linspace(-5, 5, resolution)
X, Y = np.meshgrid(x, y)
Z = np.sin(X) * np.cos(Y)
return X, Y, Z
def generate_clusters(n_clusters=3, points_per_cluster=50):
clusters = []
centers = np.random.uniform(-5, 5, (n_clusters, 3))
for center in centers:
cluster = np.random.normal(center, 1, (points_per_cluster, 3))
clusters.append(cluster)
return np.vstack(clusters)
# Sidebar controls
st.sidebar.header("Visualization Controls")
viz_type = st.sidebar.selectbox(
"Select Visualization",
["Spiral Helix", "Surface Plot", "3D Clusters"]
)
# Common plot settings
point_size = st.sidebar.slider("Point Size", 1, 20, 5)
opacity = st.sidebar.slider("Opacity", 0.0, 1.0, 0.7)
colorscale = st.sidebar.selectbox(
"Color Scheme",
["Viridis", "Plasma", "Inferno", "Magma", "Cividis"]
)
# Create figure with common settings
fig = go.Figure()
fig.update_layout(
scene=dict(
xaxis_title="X",
yaxis_title="Y",
zaxis_title="Z"
),
width=800,
height=800
)
if viz_type == "Spiral Helix":
noise = st.sidebar.slider("Noise Level", 0.0, 0.5, 0.1)
animation_speed = st.sidebar.slider("Animation Speed", 0, 100, 50)
x, y, z = generate_helix(noise=noise)
fig.add_trace(go.Scatter3d(
x=x, y=y, z=z,
mode='markers',
marker=dict(
size=point_size,
opacity=opacity,
color=z,
colorscale=colorscale
)
))
elif viz_type == "Surface Plot":
resolution = st.sidebar.slider("Resolution", 20, 100, 50)
show_contours = st.sidebar.checkbox("Show Contours", True)
X, Y, Z = generate_surface(resolution)
fig.add_trace(go.Surface(
x=X, y=Y, z=Z,
opacity=opacity,
colorscale=colorscale,
contours=dict(
z=dict(
show=show_contours,
usecolormap=True,
project_z=True
)
)
))
else: # 3D Clusters
n_clusters = st.sidebar.slider("Number of Clusters", 2, 5, 3)
points_per_cluster = st.sidebar.slider("Points per Cluster", 20, 100, 50)
clusters = generate_clusters(n_clusters, points_per_cluster)
fig.add_trace(go.Scatter3d(
x=clusters[:, 0],
y=clusters[:, 1],
z=clusters[:, 2],
mode='markers',
marker=dict(
size=point_size,
opacity=opacity,
color=np.repeat(range(n_clusters), points_per_cluster),
colorscale=colorscale
)
))
# Common layout settings
fig.update_layout(
title=viz_type,
scene=dict(
camera=dict(
up=dict(x=0, y=0, z=1),
center=dict(x=0, y=0, z=0),
eye=dict(x=1.5, y=1.5, z=1.5)
)
)
)
# Display the plot
st.plotly_chart(fig, use_container_width=True)
# Additional information
st.sidebar.markdown("---")
st.sidebar.markdown("""
### Instructions
- Use mouse to rotate the plot
- Scroll to zoom
- Double click to reset view
""")
# Description of the visualization
if viz_type == "Spiral Helix":
st.markdown("""
### Spiral Helix
A 3D helix with added random noise. The color represents the z-coordinate.
Adjust the noise level to see how it affects the spiral structure.
""")
elif viz_type == "Surface Plot":
st.markdown("""
### Surface Plot
A 3D surface plot showing z = sin(x)*cos(y).
Toggle contour lines and adjust resolution to explore the surface structure.
""")
else:
st.markdown("""
### 3D Clusters
Random clusters in 3D space. Each cluster follows a normal distribution around its center.
Adjust the number of clusters and points per cluster to explore different patterns.
""")
Hi! I can help you with any questions about Streamlit and Python. What would you like to know?