File size: 3,933 Bytes
dfc428f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
import streamlit as st
import plotly.graph_objects as go
import numpy as np

# Dictionary of elements (atomic number: (name, symbol))
elements = {
    1: ("Hydrogen", "H"),
    2: ("Helium", "He"),
    3: ("Lithium", "Li"),
    4: ("Beryllium", "Be"),
    5: ("Boron", "B"),
    6: ("Carbon", "C"),
    7: ("Nitrogen", "N"),
    8: ("Oxygen", "O"),
    9: ("Fluorine", "F"),
    10: ("Neon", "Ne"),
    # Add more elements as needed
}

# Function to calculate electron shells
def get_electron_shells(electrons):
    shells = []
    n = 1
    while electrons > 0:
        max_electrons = 2 * n**2
        if electrons >= max_electrons:
            shells.append(max_electrons)
            electrons -= max_electrons
        else:
            shells.append(electrons)
            electrons = 0
        n += 1
    return shells

# Streamlit app
st.title("Atomic Structure Visualizer")

# User inputs
col1, col2, col3 = st.columns(3)
with col1:
    Z = st.number_input("Number of protons (Z)", min_value=1, max_value=118, value=6)
with col2:
    N = st.number_input("Number of neutrons (N)", min_value=0, value=6)
with col3:
    E = st.number_input("Number of electrons (E)", min_value=0, value=Z)

# Calculate atomic properties
A = Z + N  # Mass number
charge = Z - E  # Charge of the ion
name, symbol = elements.get(Z, ("Unknown", "?"))

# Display atomic information
st.subheader("Atomic Information")
st.write(f"**Element**: {name} ({symbol})")
st.write(f"**Atomic Number**: {Z}")
st.write(f"**Mass Number**: {A}")
st.write(f"**Number of Electrons**: {E}")
st.write(f"**Charge**: {'+' if charge > 0 else ''}{charge}" if charge != 0 else "Neutral atom")

# Calculate electron shells
shells = get_electron_shells(E)

# Nucleus parameters
nucleus_radius = 0.1

# Generate proton positions
proton_theta = np.random.uniform(0, 2 * np.pi, Z)
proton_r = np.random.uniform(0, nucleus_radius, Z)
proton_x = proton_r * np.cos(proton_theta)
proton_y = proton_r * np.sin(proton_theta)

# Generate neutron positions
neutron_theta = np.random.uniform(0, 2 * np.pi, N)
neutron_r = np.random.uniform(0, nucleus_radius, N)
neutron_x = neutron_r * np.cos(neutron_theta)
neutron_y = neutron_r * np.sin(neutron_theta)

# Generate electron positions
electron_x = []
electron_y = []
r_shell = 1.0  # Radius increment per shell
for n, k in enumerate(shells, start=1):
    r = n * r_shell
    angles = np.linspace(0, 2 * np.pi, k, endpoint=False)
    for angle in angles:
        electron_x.append(r * np.cos(angle))
        electron_y.append(r * np.sin(angle))

# Create Plotly figure
fig = go.Figure()

# Add protons
fig.add_trace(go.Scatter(
    x=proton_x, y=proton_y,
    mode='markers',
    name='Protons',
    marker=dict(color='red', size=8)
))

# Add neutrons
fig.add_trace(go.Scatter(
    x=neutron_x, y=neutron_y,
    mode='markers',
    name='Neutrons',
    marker=dict(color='blue', size=8)
))

# Add electrons
fig.add_trace(go.Scatter(
    x=electron_x, y=electron_y,
    mode='markers',
    name='Electrons',
    marker=dict(color='green', size=10)
))

# Add shell circles
for n in range(1, len(shells) + 1):
    fig.add_shape(
        type="circle",
        x0=-n * r_shell, y0=-n * r_shell,
        x1=n * r_shell, y1=n * r_shell,
        line=dict(color="gray", width=1, dash="dash")
    )

# Set plot limits and aspect ratio
max_r = max(0.5, len(shells) * r_shell)
fig.update_xaxes(range=[-max_r, max_r])
fig.update_yaxes(range=[-max_r, max_r], scaleanchor="x", scaleratio=1)

# Update layout
fig.update_layout(
    title="Atomic Structure",
    width=600,
    height=600,
    showlegend=True
)

# Display plot in Streamlit
st.plotly_chart(fig)

# Instructions
st.markdown("""
### How to Use
- **Protons (Z)**: Defines the element (e.g., Z=6 for Carbon).
- **Neutrons (N)**: Affects the mass number (A = Z + N).
- **Electrons (E)**: Determines if it's an ion (Charge = Z - E).
- Adjust the inputs to visualize different atoms or ions!
""")