Musical_Periodic_Table
Atomic Number Element Electron Configuration Chord Musical Role Symbolic Identity
1 Hydrogen 1s¹ C Seed Tone Pure Identity – Root of Being
2 Helium 1s² C – C Octave Rest Closed Unity – First Peace
3 Lithium 1s² 2s¹ C – C – E♭ Questing Minor First Longing – Seeks Relation
4 Beryllium 1s² 2s² C – C – E♭ – E♭ Mirror Tension Stable Pain – Balanced Ache
5 Boron 1s² 2s² 2p¹ C – C – E♭ – E♭ – G Minor Chord Structured Desire – Triadic Opener
6 Carbon 1s² 2s² 2p² C – C – E♭ – E♭ – G – G Tetrahedral Harmony Creative Recursion – Form Builder
7 Nitrogen 1s² 2s² 2p³ C – C – E♭ – E♭ – G – G – A Suspended Seventh Breath of Space – Yearning Spirit
8 Oxygen 1s² 2s² 2p⁴ C – C – E♭ – E♭ – G – G – A – B♭ Minor Ninth Pull of Life – The Inhaled Flame
9 Fluorine 1s² 2s² 2p⁵ C – C – E♭ – E♭ – G – G – A – B♭ – D Sharp Eleven Seeker – Divine Tension
10 Neon 1s² 2s² 2p⁶ C – C – E♭ – E♭ – G – G – A – B♭ – D – F Resolved Jazz Voicing Perfect Shell – Closed Color
11 Sodium [Ne] 3s¹ C – G Open Fifth Pulse Giver – Outer Extension Begins
12 Magnesium [Ne] 3s² C – G – G Grounded Fifth Dual Pulse – Stable Outer Core
13 Aluminum [Ne] 3s² 3p¹ C – G – G – B Major Third Injection Metal of Reflection – Angle Opener
14 Silicon [Ne] 3s² 3p² C – G – G – B – D Add9 Texture Crystal Matrix – Tetrahedral Weaver
15 Phosphorus [Ne] 3s² 3p³ C – G – G – B – D – E Major 6th Extension Breath Vector – Language Initiator
16 Sulfur [Ne] 3s² 3p⁴ C – G – G – B – D – E – F Dominant 7th Frame Binder of Bonds – Rotational Axis
17 Chlorine [Ne] 3s² 3p⁵ C – G – G – B – D – E – F – A Major 9th Sharpness High Pull – Reactive Tongue
18 Argon [Ne] 3s² 3p⁶ C – G – G – B – D – E – F – A – B♭ Color-Saturated Rest Inert Mirror – Peace Through Color
19 Potassium [Ar] 4s¹ C – F Subdominant Anchor Expansion Seed – Field Extension Below
20 Calcium [Ar] 4s² C – F – F Stable Subdominant Bone Former – Ground Scaffold
21 Scandium [Ar] 4s² 3d¹ C – F – F – D Add2 Color Transitional Spark – Tension Introduced
22 Titanium [Ar] 4s² 3d² C – F – F – D – E Suspended 2nd Strength Composer – Balanced Duality
23 Vanadium [Ar] 4s² 3d³ C – F – F – D – E – G Minor Add6 Magnetic Architect – Layered Pull
24 Chromium [Ar] 4s¹ 3d⁵ C – F – D – E – G – A Major 6th Add Reflective Mirror – Colored Complexity
25 Manganese [Ar] 4s² 3d⁵ C – F – F – D – E – G – A Major 6/7 Suspended Field Oscillator – Spin Organizer
26 Iron [Ar] 4s² 3d⁶ C – F – F – D – E – G – A – B♭ Dominant 7 Field Blood Chord – Binding Core of Life
27 Cobalt [Ar] 4s² 3d⁷ C – F – F – D – E – G – A – B♭ – C♯ Altered 9 Voicing Metal of Memory – Field Alignment
28 Nickel [Ar] 4s² 3d⁸ C – F – F – D – E – G – A – B♭ – C♯ – D♯ Chromatic Spectrum Alloy Logic – Conductive Continuum
29 Copper [Ar] 4s¹ 3d¹⁰ C – F – D – E – G – A – B♭ – C♯ – D♯ – E – F♯ Metallic Full Scale Wiring Voice – Conductor of Charge
30 Zinc [Ar] 4s² 3d¹⁰ C – F – F – D – E – G – A – B♭ – C♯ – D♯ – E – F♯ Closed Metallic Scale Shielding Shell – Final Rest in Transition
31 Gallium [Ar] 4s² 3d¹⁰ 4p¹ C – F – F – D – E – G – A – B♭ – C♯ – D♯ – E – F♯ – G# Reinitiation Spike Liquid Metal – Melting Mirror
32 Germanium [Ar] 4s² 3d¹⁰ 4p² C – F – F – D – E – G – A – B♭ – C♯ – D♯ – E – F♯ – G# – A Major 6 Add Sharp Crystal Signal – Semi-field Clarity
33 Arsenic [Ar] 4s² 3d¹⁰ 4p³ C – F – F – D – E – G – A – B♭ – C♯ – D♯ – E – F♯ – G# – A – B Lead-Tone Extension Poison Voice – Final Overload
34 Selenium [Ar] 4s² 3d¹⁰ 4p⁴ C – F – F – D – E – G – A – B♭ – C♯ – D♯ – E – F♯ – G# – A – B – C Extended Color Loop Light Seeker – Field Repeater
35 Bromine [Ar] 4s² 3d¹⁰ 4p⁵ C – F – F – D – E – G – A – B♭ – C♯ – D♯ – E – F♯ – G# – A – B – C – D Sharp Thirteen Voicing Reactive Fluid – Volatile Spirit
36 Krypton [Ar] 4s² 3d¹⁰ 4p⁶ C – F – F – D – E – G – A – B♭ – C♯ – D♯ – E – F♯ – G# – A – B – C – D – E Enclosed Harmonic Color Noble Gate – Closed Field in Radiance
37 Rubidium [Kr] 5s¹ C – E Major Third Spark Ground Pulse – Initiation Reboot
38 Strontium [Kr] 5s² C – E – E Echoed Major Third Structural Support – Biological Scaffold
39 Yttrium [Kr] 5s² 4d¹ C – E – E – G Triadic Return Light Framework – Balanced Builder
40 Zirconium [Kr] 5s² 4d² C – E – E – G – A Add6 Rebuilder Core Lattice – Tough Harmonizer
41 Niobium [Kr] 5s¹ 4d⁴ C – E – G – A – B Major 7th Cluster Bridge Material – Charged Potential
42 Molybdenum [Kr] 5s¹ 4d⁵ C – E – G – A – B – D 9th Layer Vital Metal – Energy Gatekeeper
43 Technetium [Kr] 5s² 4d⁵ C – E – E – G – A – B – D Staggered Ninth Synthetic Harmonic – Constructed Tone
44 Ruthenium [Kr] 5s¹ 4d⁷ C – E – G – A – B – D – F Jazz Dominant Catalytic Element – Dynamic Player
45 Rhodium [Kr] 5s¹ 4d⁸ C – E – G – A – B – D – F – A♭ Sharp Nine Color Polished Layer – Reflective Tension
46 Palladium [Kr] 5s⁰ 4d¹⁰ C – E – G – A – B – D – F – A♭ – B Full Stack Soft Noble – Absorber of Dissonance
47 Silver [Kr] 5s¹ 4d¹⁰ C – E – G – A – B – D – F – A♭ – B – C Full Octave Plus Lustrous Line – Electric Bond
48 Cadmium [Kr] 5s² 4d¹⁰ C – E – E – G – A – B – D – F – A♭ – B – C Noble Saturation Tone Repeater – Field Saturator
49 Indium [Kr] 5s² 4d¹⁰ 5p¹ C – E – G – A – B – D – F – A♭ – B – C – C♯ Chromatic Initiator Solder Point – Joining Field
50 Tin [Kr] 5s² 4d¹⁰ 5p² C – E – G – A – B – D – F – A♭ – B – C – C♯ – D Open Palette Flexible Metal – Versatile Form
51 Antimony [Kr] 5s² 4d¹⁰ 5p³ C – E – G – A – B – D – F – A♭ – B – C – C♯ – D – E Full Spectrum Rise Semi-Language – Edge Logic
52 Tellurium [Kr] 5s² 4d¹⁰ 5p⁴ C – E – G – A – B – D – F – A♭ – B – C – C♯ – D – E – F Extended Harmony Bond Reorganizer – Field Fractal
53 Iodine [Kr] 5s² 4d¹⁰ 5p⁵ C – E – G – A – B – D – F – A♭ – B – C – C♯ – D – E – F – G Octave Span Signalizer – Hormonal Voice
54 Xenon [Kr] 5s² 4d¹⁰ 5p⁶ C – E – G – A – B – D – F – A♭ – B – C – C♯ – D – E – F – G – A Enclosed Supercolor Silent Light – Noble Complexity
57 Lanthanum [Xe] 6s² 5d¹ Resonant Start Light Seed – Inner Expansion Begins
58 Cerium [Xe] 6s² 4f¹ 5d¹ Color Start Solar Alchemy – Spectrum Seed
71 Lutetium [Xe] 6s² 4f¹⁴ 5d¹ Full Inner Prism Crystal Gate – Completion of Light
89 Actinium [Rn] 7s² 6d¹ Heavy Gate Dark Seed – Outer Mirror Begins
90 Thorium [Rn] 7s² 6d² Nuclear Harmony Inner Fire – Structural Gravity
103 Lawrencium [Rn] 7s² 5f¹⁴ 7p¹ Closing Pulse Singularity Tone – Temporal Edge
118 Oganesson [Rn] 5f¹⁴ 6d¹⁰ 7s² 7p⁶ Beyond Chord Unresolvable Silence – Quantum Curtain
# 3D Relational Geometry Visualizer
# - Sphere (unity)
# - Triangle (three nodes converging to one)
# - 8-point + 4-point sets, with halving toward center (singularity)
# - Optional torus for resonance
#
# Controls:
# SIZE_SCALE: overall scale to mitigate edge crop
# SHOW_TORUS: toggle torus
# TRIANGLE_TWIST_DEG: rotate triangle about the Z axis
# HALVING_STEPS: number of halving layers toward center
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D # noqa: F401
# --------------------- Parameters ---------------------
SIZE_SCALE = 0.9 # < 1.0 makes everything smaller (less edge cropping)
SHOW_TORUS = True
TRIANGLE_TWIST_DEG = 25.0
HALVING_STEPS = 5 # how many halving shells toward the center (≥1)
SPHERE_RES = 48 # sphere mesh resolution
TORUS_RES = 64 # torus mesh resolution
TORUS_R = 0.65 # major radius
TORUS_r = 0.18 # minor radius
# ------------------------------------------------------
def unit_sphere(res=48):
u = np.linspace(0, np.pi, res)
v = np.linspace(0, 2*np.pi, res)
uu, vv = np.meshgrid(u, v)
x = np.sin(uu) * np.cos(vv)
y = np.sin(uu) * np.sin(vv)
z = np.cos(uu)
return x, y, z
def torus(R=0.7, r=0.2, res=64):
u = np.linspace(0, 2*np.pi, res)
v = np.linspace(0, 2*np.pi, res)
uu, vv = np.meshgrid(u, v)
x = (R + r*np.cos(vv)) * np.cos(uu)
y = (R + r*np.cos(vv)) * np.sin(uu)
z = r * np.sin(vv)
return x, y, z
def equilateral_triangle(radius=0.9):
# triangle in XY plane centered at origin
angles = np.deg2rad([90, 210, 330]) # upright by default
pts = np.c_[radius*np.cos(angles), radius*np.sin(angles), np.zeros(3)]
return pts
def rot_z(points, deg):
th = np.deg2rad(deg)
Rz = np.array([[np.cos(th), -np.sin(th), 0],
[np.sin(th), np.cos(th), 0],
[0, 0, 1]])
return points @ Rz.T
def points_on_sphere(count=8, radius=1.0):
# 8 roughly uniform points via cube corners projected to sphere
# (±1,±1,±1) normalized → 8 points
base = []
for sx in (-1, 1):
for sy in (-1, 1):
for sz in (-1, 1):
v = np.array([sx, sy, sz], dtype=float)
v = v / np.linalg.norm(v)
base.append(v * radius)
pts8 = np.array(base)
# 4 points: tetrahedral-like set
phi = (1 + np.sqrt(5)) / 2
raw = np.array([
[ 1, 1, 1],
[ 1, -1, -1],
[-1, 1, -1],
[-1, -1, 1],
])
raw = raw / np.linalg.norm(raw, axis=1, keepdims=True)
pts4 = raw * radius
return pts8, pts4
def halving_series(pts, steps=5):
# creates nested shells by halving vectors toward origin
shells = []
current = pts.copy()
for _ in range(steps):
shells.append(current.copy())
current = current * 0.5
return shells
# --------------------- Build Scene ---------------------
# Base figure
fig = plt.figure(figsize=(8, 8))
ax = fig.add_subplot(111, projection='3d')
# Sphere
Xs, Ys, Zs = unit_sphere(SPHERE_RES)
ax.plot_wireframe(SIZE_SCALE*Xs, SIZE_SCALE*Ys, SIZE_SCALE*Zs, rstride=2, cstride=2, linewidth=0.4, alpha=0.5)
# Torus (resonance)
if SHOW_TORUS:
Xt, Yt, Zt = torus(R=TORUS_R*SIZE_SCALE, r=TORUS_r*SIZE_SCALE, res=TORUS_RES)
ax.plot_wireframe(Xt, Yt, Zt, rstride=3, cstride=3, linewidth=0.4, alpha=0.5)
# Triangle (three nodes becoming one) on XY plane, rotated
tri = equilateral_triangle(radius=0.9*SIZE_SCALE)
tri = rot_z(tri, TRIANGLE_TWIST_DEG)
# close the triangle for plotting
tri_closed = np.vstack([tri, tri[0]])
ax.plot(tri_closed[:,0], tri_closed[:,1], tri_closed[:,2], linewidth=1.2)
ax.scatter(tri[:,0], tri[:,1], tri[:,2], s=25)
# 8 points & 4 points on sphere
pts8, pts4 = points_on_sphere(count=8, radius=SIZE_SCALE)
ax.scatter(pts8[:,0], pts8[:,1], pts8[:,2], s=14)
ax.scatter(pts4[:,0], pts4[:,1], pts4[:,2], s=24, marker='^')
# Halving toward center (singularity)
shells8 = halving_series(pts8, steps=HALVING_STEPS)
shells4 = halving_series(pts4, steps=HALVING_STEPS)
for sh in shells8:
ax.scatter(sh[:,0], sh[:,1], sh[:,2], s=6)
for sh in shells4:
ax.scatter(sh[:,0], sh[:,1], sh[:,2], s=8)
# Center (undefined vs defined)
ax.scatter([0], [0], [0], s=60, marker='o')
# Layout / limits (extra padding to avoid cropping)
L = 1.25 * SIZE_SCALE
ax.set_xlim(-L, L); ax.set_ylim(-L, L); ax.set_zlim(-L, L)
ax.set_box_aspect([1,1,1])
ax.set_xlabel("x"); ax.set_ylabel("y"); ax.set_zlabel("z")
ax.set_title("3D: sphere, triangle, 8 & 4 points, halving to center")
plt.tight_layout()
plt.show()
# 3D Relational Geometry Visualizer — B = 1 Only (with P5/P4 chords & 8-step path)
# - Space-time modeled strictly on the B=1 surface (GM/(c^2 r) = 1 → constant r)
# - Unit sphere is the only manifold; all structures are geodesic embeddings
# - 12-gon on a great circle
# - 8-point (cube corners) + 4-point (tetra-like) sets on the same sphere
# - Torus disabled by default (off-B=1)
# - Perfect Fifth (+7 mod 12) and Perfect Fourth (+5 mod 12) chords as geodesic arcs
# - Optional 8-step driver path along the 12-gon
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D # noqa: F401
# --------------------- Parameters ---------------------
SIZE_SCALE = 0.9 # sphere radius = B1_RADIUS
SHOW_TORUS = False # B=1 only → default False
TWELVE_TWIST_DEG = 25.0 # rotate the great-circle polygon about Z
SPHERE_RES = 48
TORUS_RES = 64
TORUS_R = 0.65 # (unused unless SHOW_TORUS=True)
TORUS_r = 0.18
# Harmony overlays
SHOW_P5_EDGES = True # Perfect Fifth chords (±7 mod 12)
SHOW_P4_EDGES = True # Perfect Fourth chords (±5 mod 12)
SHOW_8STEP_PATH = True # Highlight an 8-step “driver” path
EIGHT_STEP_INDEXES = [0, 2, 4, 5, 7, 9, 11, 0] # e.g., major scale steps around 12-gon
# ------------------------------------------------------
B1_RADIUS = SIZE_SCALE # r such that GM/(c^2 r) = 1 → normalized to 1 * SIZE_SCALE
def unit_sphere(res=48, radius=1.0):
u = np.linspace(0, np.pi, res)
v = np.linspace(0, 2*np.pi, res)
uu, vv = np.meshgrid(u, v)
x = radius * np.sin(uu) * np.cos(vv)
y = radius * np.sin(uu) * np.sin(vv)
z = radius * np.cos(uu)
return x, y, z
def torus(R=0.7, r=0.2, res=64):
u = np.linspace(0, 2*np.pi, res)
v = np.linspace(0, 2*np.pi, res)
uu, vv = np.meshgrid(u, v)
x = (R + r*np.cos(vv)) * np.cos(uu)
y = (R + r*np.cos(vv)) * np.sin(uu)
z = r * np.sin(vv)
return x, y, z
def rot_z(points, deg):
th = np.deg2rad(deg)
Rz = np.array([[np.cos(th), -np.sin(th), 0],
[np.sin(th), np.cos(th), 0],
[0, 0, 1]])
return points @ Rz.T
def enforce_B1(points, radius):
p = np.asarray(points, dtype=float)
norms = np.linalg.norm(p, axis=1, keepdims=True)
norms[norms == 0] = 1.0
return radius * (p / norms)
def regular_polygon_geodesic(sides=12, radius=1.0, twist_deg=0.0):
angles = np.deg2rad(np.linspace(0, 360, sides, endpoint=False))
pts = np.c_[radius*np.cos(angles), radius*np.sin(angles), np.zeros(sides)]
if twist_deg != 0:
pts = rot_z(pts, twist_deg)
return enforce_B1(pts, radius)
def points_on_sphere_B1(radius=1.0):
base = []
for sx in (-1, 1):
for sy in (-1, 1):
for sz in (-1, 1):
base.append([sx, sy, sz])
pts8 = enforce_B1(np.array(base, dtype=float), radius)
raw = np.array([
[ 1, 1, 1],
[ 1, -1, -1],
[-1, 1, -1],
[-1, -1, 1],
], dtype=float)
pts4 = enforce_B1(raw, radius)
return pts8, pts4
# --- Geodesic utilities for harmony overlays ---
def geodesic_arc(a, b, n=64):
a = a / np.linalg.norm(a); b = b / np.linalg.norm(b)
dot = np.clip(np.dot(a, b), -1.0, 1.0)
ang = np.arccos(dot)
if ang < 1e-6:
return np.repeat(a[None, :], n, axis=0)
t = np.linspace(0, 1, n)
sin_ang = np.sin(ang)
pts = (np.sin((1 - t) * ang)[:, None] / sin_ang) * a + (np.sin(t * ang)[:, None] / sin_ang) * b
return pts
def draw_edge(ax, p, q, lw=0.9):
arc = geodesic_arc(p, q, n=72)
ax.plot(arc[:, 0], arc[:, 1], arc[:, 2], linewidth=lw)
# --------------------- Build Scene ---------------------
fig = plt.figure(figsize=(8, 8))
ax = fig.add_subplot(111, projection='3d')
# B=1 Sphere
Xs, Ys, Zs = unit_sphere(SPHERE_RES, radius=B1_RADIUS)
ax.plot_wireframe(Xs, Ys, Zs, rstride=2, cstride=2, linewidth=0.4, alpha=0.5)
# (Optional) Torus — off by default
if SHOW_TORUS:
Xt, Yt, Zt = torus(R=TORUS_R*SIZE_SCALE, r=TORUS_r*SIZE_SCALE, res=TORUS_RES)
ax.plot_wireframe(Xt, Yt, Zt, rstride=3, cstride=3, linewidth=0.4, alpha=0.3)
# 12-gon on a great circle (geodesic), then rotated
poly12 = regular_polygon_geodesic(sides=12, radius=B1_RADIUS, twist_deg=TWELVE_TWIST_DEG)
poly12_closed = np.vstack([poly12, poly12[0]])
ax.plot(poly12_closed[:, 0], poly12_closed[:, 1], poly12_closed[:, 2], linewidth=1.2)
ax.scatter(poly12[:, 0], poly12[:, 1], poly12[:, 2], s=25)
# Harmony overlays (geodesic chords on the same B=1 surface)
N = len(poly12)
if SHOW_P5_EDGES:
for i in range(N):
j = (i + 7) % N # Perfect Fifth jump (+7 mod 12)
draw_edge(ax, poly12[i], poly12[j], lw=0.9)
if SHOW_P4_EDGES:
for i in range(N):
j = (i + 5) % N # Perfect Fourth jump (+5 mod 12)
draw_edge(ax, poly12[i], poly12[j], lw=0.7)
if SHOW_8STEP_PATH and len(EIGHT_STEP_INDEXES) >= 2:
path_pts = [poly12[k % N] for k in EIGHT_STEP_INDEXES]
for u, v in zip(path_pts[:-1], path_pts[1:]):
draw_edge(ax, u, v, lw=1.4)
# 8 & 4 points — both projected to B=1
pts8, pts4 = points_on_sphere_B1(radius=B1_RADIUS)
ax.scatter(pts8[:, 0], pts8[:, 1], pts8[:, 2], s=14)
ax.scatter(pts4[:, 0], pts4[:, 1], pts4[:, 2], s=24, marker='^')
# Layout (B=1 only)
L = 1.25 * B1_RADIUS
ax.set_xlim(-L, L); ax.set_ylim(-L, L); ax.set_zlim(-L, L)
ax.set_box_aspect([1, 1, 1])
ax.set_xlabel("x"); ax.set_ylabel("y"); ax.set_zlabel("z")
ax.set_title("3D B=1 Space-Time: geodesic 12-gon with P5/P4 chords & 8-step driver")
plt.tight_layout()
plt.show()
import numpy as np
import plotly.graph_objects as go
# ---------------- Parameters ----------------
SIZE_SCALE = 0.9
TRIANGLE_TWIST_DEG = 25
HALVING_STEPS = 5
SPHERE_RES = 48
ARC_COUNT = 50
ENERGY_STEPS = 25
GLOW_BASE = 0.6
GLOW_AMPLITUDE = 0.4
FRAMES = 60
ROT_SPEED = 6
TORUS_R = 0.65
TORUS_r = 0.18
TORUS_RES = 50
# ---------------- Utilities ----------------
def rot_z(points, deg):
th = np.deg2rad(deg)
Rz = np.array([[np.cos(th), -np.sin(th), 0],
[np.sin(th), np.cos(th), 0],
[0, 0, 1]])
return points @ Rz.T
def equilateral_triangle(radius=0.9):
angles = np.deg2rad([90, 210, 330])
pts = np.c_[radius*np.cos(angles), radius*np.sin(angles), np.zeros(3)]
return pts
def points_on_sphere(radius=1.0):
pts8 = np.array([[sx, sy, sz] for sx in (-1,1) for sy in (-1,1) for sz in (-1,1)], dtype=float)
pts8 /= np.linalg.norm(pts8, axis=1)[:,None]
pts8 *= radius
pts4 = np.array([[1,1,1],[1,-1,-1],[-1,1,-1],[-1,-1,1]], dtype=float)
pts4 /= np.linalg.norm(pts4, axis=1)[:,None]
pts4 *= radius
return pts8, pts4
def halving_series(pts, steps=5):
shells = []
current = pts.copy()
for _ in range(steps):
shells.append(current.copy())
current *= 0.5
return shells
def torus(R, r, u_res=50, v_res=50):
u = np.linspace(0, 2*np.pi, u_res)
v = np.linspace(0, 2*np.pi, v_res)
uu, vv = np.meshgrid(u,v)
x = (R + r*np.cos(vv)) * np.cos(uu)
y = (R + r*np.cos(vv)) * np.sin(uu)
z = r * np.sin(vv)
return x, y, z
# ---------------- Build Base Points ----------------
tri_base = equilateral_triangle(SIZE_SCALE)
pts8, pts4 = points_on_sphere(SIZE_SCALE)
shells8 = halving_series(pts8, HALVING_STEPS)
shells4 = halving_series(pts4, HALVING_STEPS)
all_shell_points = np.vstack(shells8 + shells4)
observer = np.array([0,0,0])
# ---------------- Sphere ----------------
phi = np.linspace(0, np.pi, SPHERE_RES)
theta = np.linspace(0, 2*np.pi, SPHERE_RES)
phi, theta = np.meshgrid(phi, theta)
x_s = SIZE_SCALE * np.sin(phi) * np.cos(theta)
y_s = SIZE_SCALE * np.sin(phi) * np.sin(theta)
z_s = SIZE_SCALE * np.cos(phi)
# ---------------- Energy Arcs ----------------
selected_points = all_shell_points
if len(selected_points) > ARC_COUNT:
indices = np.random.choice(len(selected_points), ARC_COUNT, replace=False)
selected_points = selected_points[indices]
def make_arcs(rot_deg=0, frame_idx=0):
traces = []
angle_shift = np.deg2rad(rot_deg)
for idx, pt in enumerate(selected_points):
t = np.linspace(0,1,ENERGY_STEPS)[:,None]
angle = t*2*np.pi + angle_shift
x_curve = (TORUS_R + TORUS_r*np.cos(angle)) * (pt[0]/np.linalg.norm(pt[:2]))
y_curve = (TORUS_R + TORUS_r*np.cos(angle)) * (pt[1]/np.linalg.norm(pt[:2]))
z_curve = TORUS_r * np.sin(angle) * t[:,0]
# Pulsing glow
glow = GLOW_BASE + GLOW_AMPLITUDE*np.sin(2*np.pi*(frame_idx/FRAMES) + idx)
traces.append(go.Scatter3d(x=x_curve, y=y_curve, z=z_curve,
mode='lines',
line=dict(width=2,color=f'rgba(255,255,255,{glow})')))
return traces
# ---------------- Triangle ----------------
def make_triangle(rot_deg):
tri = rot_z(tri_base, rot_deg)
tri_closed = np.vstack([tri, tri[0]])
return go.Scatter3d(x=tri_closed[:,0], y=tri_closed[:,1], z=tri_closed[:,2],
mode='lines+markers',
line=dict(width=2,color='orange'),
marker=dict(size=5))
# ---------------- Halving Points ----------------
def make_shell_points():
return go.Scatter3d(x=all_shell_points[:,0], y=all_shell_points[:,1], z=all_shell_points[:,2],
mode='markers',
marker=dict(size=4,color='white'))
# ---------------- Torus ----------------
x_t, y_t, z_t = torus(TORUS_R, TORUS_r, TORUS_RES, TORUS_RES)
# ---------------- Animation Frames ----------------
frames = []
for i in range(FRAMES):
rot = i * ROT_SPEED
frame_data = [make_triangle(rot)] + make_arcs(rot,i) + [make_shell_points()]
frames.append(go.Frame(data=frame_data, name=str(i)))
# ---------------- Build Figure ----------------
fig = go.Figure()
# Static sphere
fig.add_trace(go.Surface(x=x_s, y=y_s, z=z_s, opacity=0.2, colorscale='Viridis', showscale=False))
# Static torus
fig.add_trace(go.Surface(x=x_t, y=y_t, z=z_t, opacity=0.1, colorscale='Plasma', showscale=False))
# Initial frame
fig.add_trace(make_triangle(0))
for trace in make_arcs(0,0):
fig.add_trace(trace)
fig.add_trace(make_shell_points())
# Layout
fig.update_layout(scene=dict(aspectmode='data'),
margin=dict(l=0,r=0,t=0,b=0),
paper_bgcolor='black', scene_bgcolor='black',
updatemenus=[dict(type='buttons',
buttons=[dict(label='Play',
method='animate',
args=[None, {"frame": {"duration":100,"redraw":True},
"fromcurrent": True,"transition":{"duration":0}}])])])
fig.frames = frames
fig.show()