Update app.py
Browse files
app.py
CHANGED
|
@@ -135,76 +135,85 @@ def draw_mri(mri_result):
|
|
| 135 |
ax.axis('off')
|
| 136 |
return get_image_from_plot(fig)
|
| 137 |
|
| 138 |
-
# --- ฟังก์ชันวาดกราฟ Pulse Sequence
|
| 139 |
def draw_pulse_sequence(current_step, total_steps):
|
| 140 |
-
fig, axes = plt.subplots(4, 1, figsize=(5, 6), gridspec_kw={'height_ratios': [1, 1, 1
|
| 141 |
-
t = np.linspace(0, 10,
|
| 142 |
|
| 143 |
-
# 1. RF
|
| 144 |
ax = axes[0]
|
| 145 |
-
|
| 146 |
-
|
|
|
|
|
|
|
|
|
|
| 147 |
ax.text(0, 0.5, 'RF', fontsize=14, fontweight='bold', va='center', ha='right', transform=ax.get_yaxis_transform())
|
| 148 |
ax.axis('off')
|
| 149 |
|
| 150 |
-
# 2.
|
| 151 |
ax = axes[1]
|
| 152 |
-
gx = np.zeros_like(t)
|
| 153 |
-
gx[(t > 4.5) & (t < 5.5)] = -1 # Dephase
|
| 154 |
-
gx[(t > 6) & (t < 9)] = 1 # Readout
|
| 155 |
-
ax.plot(t, gx, color='black', lw=2)
|
| 156 |
-
ax.fill_between(t, gx, 0, alpha=0.3, color='gray')
|
| 157 |
-
ax.text(0, 0, 'Gx', fontsize=14, fontweight='bold', va='center', ha='right', transform=ax.get_yaxis_transform())
|
| 158 |
-
ax.axis('off')
|
| 159 |
-
|
| 160 |
-
# 3. Gy (Phase Encoding)
|
| 161 |
-
ax = axes[2]
|
| 162 |
gy_vals = np.linspace(1, -1, total_steps)
|
| 163 |
for i, gy_amp in enumerate(gy_vals):
|
| 164 |
gy = np.zeros_like(t)
|
| 165 |
-
gy[(t >
|
| 166 |
if i == current_step:
|
| 167 |
-
ax.plot(t, gy, color='red', lw=3, zorder=10) # ไฮไลต์เส้น
|
| 168 |
-
elif i < current_step:
|
| 169 |
-
ax.plot(t, gy, color='gray', lw=1, alpha=0.5)
|
| 170 |
else:
|
| 171 |
-
ax.plot(t, gy, color='
|
| 172 |
ax.text(0, 0, 'Gy', fontsize=14, fontweight='bold', va='center', ha='right', transform=ax.get_yaxis_transform())
|
| 173 |
ax.axis('off')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 174 |
|
| 175 |
-
# 4. Echo
|
| 176 |
ax = axes[3]
|
| 177 |
-
|
| 178 |
-
ax.plot(t,
|
| 179 |
-
ax.
|
|
|
|
| 180 |
ax.axis('off')
|
| 181 |
|
| 182 |
plt.tight_layout()
|
| 183 |
return get_image_from_plot(fig)
|
| 184 |
|
|
|
|
| 185 |
def draw_kspace_filling(current_step, total_steps, mode_type, real_bg):
|
| 186 |
fig, ax = plt.subplots(figsize=(5, 6))
|
| 187 |
-
|
|
|
|
| 188 |
lines_per_step = 224 // total_steps
|
| 189 |
current_line_idx = current_step * lines_per_step
|
| 190 |
|
| 191 |
if mode_type == "ข้อมูลจำลอง (Simulated)":
|
| 192 |
-
|
| 193 |
-
|
| 194 |
-
|
| 195 |
-
|
| 196 |
-
|
|
|
|
| 197 |
else:
|
|
|
|
|
|
|
| 198 |
if current_step >= total_steps - 1:
|
| 199 |
display_img = real_bg
|
| 200 |
else:
|
| 201 |
display_img[:current_line_idx + lines_per_step, :] = real_bg[:current_line_idx + lines_per_step, :]
|
|
|
|
| 202 |
ax.imshow(display_img, cmap='gray', extent=[-112, 112, -112, 112], vmin=0, vmax=1)
|
| 203 |
|
| 204 |
ax.set_xlim(-112, 112)
|
| 205 |
-
ax.set_ylim(112,
|
| 206 |
|
| 207 |
-
# วาดลูกศรชี้
|
|
|
|
| 208 |
y_pos = 112 - (current_line_idx + lines_per_step//2)
|
| 209 |
ax.annotate('', xy=(0, y_pos), xytext=(-100, y_pos), arrowprops=dict(arrowstyle='->', color='red', lw=3))
|
| 210 |
|
|
@@ -274,7 +283,6 @@ with col_main:
|
|
| 274 |
def reset_anim():
|
| 275 |
st.session_state.fill_step = 0
|
| 276 |
|
| 277 |
-
# แถบควบคุมบน
|
| 278 |
_, col_ctrl1, col_ctrl2, _ = st.columns([0.5, 2.5, 2.5, 0.5])
|
| 279 |
with col_ctrl1:
|
| 280 |
data_mode = st.radio("เลือกรูปแบบ K-Space:", ["ข้อมูลจำลอง (Simulated)", "ข้อมูลจริง (kspace.mat)"])
|
|
@@ -288,7 +296,6 @@ with col_main:
|
|
| 288 |
|
| 289 |
st.progress((st.session_state.fill_step + 1) / total_anim_steps)
|
| 290 |
|
| 291 |
-
# ใช้ Placeholder เพื่อลดการสั่นกระตุกตอนวาดรูปใหม่
|
| 292 |
anim_placeholder = st.empty()
|
| 293 |
with anim_placeholder.container():
|
| 294 |
col_anim1, col_anim2 = st.columns([1, 1])
|
|
|
|
| 135 |
ax.axis('off')
|
| 136 |
return get_image_from_plot(fig)
|
| 137 |
|
| 138 |
+
# --- ฟังก์ชันวาดกราฟ Pulse Sequence รูปแบบใหม่ (เหมือนภาพอ้างอิง) ---
|
| 139 |
def draw_pulse_sequence(current_step, total_steps):
|
| 140 |
+
fig, axes = plt.subplots(4, 1, figsize=(5, 6), sharex=True, gridspec_kw={'height_ratios': [1, 1.5, 1, 1]})
|
| 141 |
+
t = np.linspace(0, 10, 1000)
|
| 142 |
|
| 143 |
+
# 1. RF Pulse (90° และ 180°)
|
| 144 |
ax = axes[0]
|
| 145 |
+
rf90 = np.sinc(t - 1.5) * (t > 0.5) * (t < 2.5)
|
| 146 |
+
rf180 = np.sinc((t - 4.5)*2) * (t > 3.5) * (t < 5.5) * 1.5
|
| 147 |
+
ax.plot(t, rf90 + rf180, color='black', lw=2)
|
| 148 |
+
ax.text(1.5, 1.2, '90°', ha='center', fontsize=12, fontweight='bold')
|
| 149 |
+
ax.text(4.5, 1.7, '180°', ha='center', fontsize=12, fontweight='bold')
|
| 150 |
ax.text(0, 0.5, 'RF', fontsize=14, fontweight='bold', va='center', ha='right', transform=ax.get_yaxis_transform())
|
| 151 |
ax.axis('off')
|
| 152 |
|
| 153 |
+
# 2. Gy (Phase Encoding) เรียงเส้นจากบวกไปลบ
|
| 154 |
ax = axes[1]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 155 |
gy_vals = np.linspace(1, -1, total_steps)
|
| 156 |
for i, gy_amp in enumerate(gy_vals):
|
| 157 |
gy = np.zeros_like(t)
|
| 158 |
+
gy[(t > 2.5) & (t < 3.5)] = gy_amp
|
| 159 |
if i == current_step:
|
| 160 |
+
ax.plot(t, gy, color='red', lw=3, zorder=10) # ไฮไลต์เส้นทำงาน
|
|
|
|
|
|
|
| 161 |
else:
|
| 162 |
+
ax.plot(t, gy, color='black', lw=1, alpha=0.3)
|
| 163 |
ax.text(0, 0, 'Gy', fontsize=14, fontweight='bold', va='center', ha='right', transform=ax.get_yaxis_transform())
|
| 164 |
ax.axis('off')
|
| 165 |
+
|
| 166 |
+
# 3. Gx (Frequency Encoding) มีลบ (Dephasing) แล้วบวก (Readout)
|
| 167 |
+
ax = axes[2]
|
| 168 |
+
gx = np.zeros_like(t)
|
| 169 |
+
gx[(t > 2.5) & (t < 3.5)] = -0.5
|
| 170 |
+
gx[(t > 6) & (t < 9)] = 0.5
|
| 171 |
+
ax.plot(t, gx, color='black', lw=2)
|
| 172 |
+
ax.fill_between(t, gx, 0, alpha=0.3, color='gray')
|
| 173 |
+
ax.text(0, 0, 'Gx', fontsize=14, fontweight='bold', va='center', ha='right', transform=ax.get_yaxis_transform())
|
| 174 |
+
ax.axis('off')
|
| 175 |
|
| 176 |
+
# 4. Signal (Echo)
|
| 177 |
ax = axes[3]
|
| 178 |
+
echo_env = np.exp(-((t - 7.5)**2) / 0.5) * (t > 6) * (t < 9)
|
| 179 |
+
ax.plot(t, echo_env, color='black', lw=2)
|
| 180 |
+
ax.fill_between(t, echo_env, 0, alpha=0.3, color='gray')
|
| 181 |
+
ax.text(0, 0.5, 'Signal\n(Echo)', fontsize=14, fontweight='bold', va='center', ha='right', transform=ax.get_yaxis_transform())
|
| 182 |
ax.axis('off')
|
| 183 |
|
| 184 |
plt.tight_layout()
|
| 185 |
return get_image_from_plot(fig)
|
| 186 |
|
| 187 |
+
# --- ฟังก์ชันการเติม K-Space จากซ้ายบนลงมา (เส้นทึบขาว) ---
|
| 188 |
def draw_kspace_filling(current_step, total_steps, mode_type, real_bg):
|
| 189 |
fig, ax = plt.subplots(figsize=(5, 6))
|
| 190 |
+
|
| 191 |
+
# พิกัด K-space ภาพขนาด 224x224
|
| 192 |
lines_per_step = 224 // total_steps
|
| 193 |
current_line_idx = current_step * lines_per_step
|
| 194 |
|
| 195 |
if mode_type == "ข้อมูลจำลอง (Simulated)":
|
| 196 |
+
# พื้นหลังดำล้วน
|
| 197 |
+
display_img = np.zeros((224, 224))
|
| 198 |
+
# ขีดเส้นสีขาวเป็นแถบๆ จากบนลงล่าง ตามภาพร่างจำลอง
|
| 199 |
+
display_img[:current_line_idx + lines_per_step, :] = 1.0
|
| 200 |
+
|
| 201 |
+
ax.imshow(display_img, cmap='gray', extent=[-112, 112, -112, 112], vmin=0, vmax=1)
|
| 202 |
else:
|
| 203 |
+
# ใช้ข้อมู�� kspace.mat จริง
|
| 204 |
+
display_img = np.zeros((224, 224))
|
| 205 |
if current_step >= total_steps - 1:
|
| 206 |
display_img = real_bg
|
| 207 |
else:
|
| 208 |
display_img[:current_line_idx + lines_per_step, :] = real_bg[:current_line_idx + lines_per_step, :]
|
| 209 |
+
|
| 210 |
ax.imshow(display_img, cmap='gray', extent=[-112, 112, -112, 112], vmin=0, vmax=1)
|
| 211 |
|
| 212 |
ax.set_xlim(-112, 112)
|
| 213 |
+
ax.set_ylim(-112, 112)
|
| 214 |
|
| 215 |
+
# วาดลูกศรชี้ (เริ่มจากมุมซ้ายบนลงล่าง)
|
| 216 |
+
# y = 112 คือบนสุด, y = -112 คือล่างสุด
|
| 217 |
y_pos = 112 - (current_line_idx + lines_per_step//2)
|
| 218 |
ax.annotate('', xy=(0, y_pos), xytext=(-100, y_pos), arrowprops=dict(arrowstyle='->', color='red', lw=3))
|
| 219 |
|
|
|
|
| 283 |
def reset_anim():
|
| 284 |
st.session_state.fill_step = 0
|
| 285 |
|
|
|
|
| 286 |
_, col_ctrl1, col_ctrl2, _ = st.columns([0.5, 2.5, 2.5, 0.5])
|
| 287 |
with col_ctrl1:
|
| 288 |
data_mode = st.radio("เลือกรูปแบบ K-Space:", ["ข้อมูลจำลอง (Simulated)", "ข้อมูลจริง (kspace.mat)"])
|
|
|
|
| 296 |
|
| 297 |
st.progress((st.session_state.fill_step + 1) / total_anim_steps)
|
| 298 |
|
|
|
|
| 299 |
anim_placeholder = st.empty()
|
| 300 |
with anim_placeholder.container():
|
| 301 |
col_anim1, col_anim2 = st.columns([1, 1])
|