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()