Update app.py
Browse files
app.py
CHANGED
|
@@ -218,8 +218,8 @@ def draw_mri(mri_result):
|
|
| 218 |
|
| 219 |
@st.cache_data
|
| 220 |
def draw_pulse_sequence(current_step, total_steps):
|
| 221 |
-
# ปรับเ
|
| 222 |
-
fig, axes = plt.subplots(
|
| 223 |
t = np.linspace(0, 11, 1000)
|
| 224 |
|
| 225 |
t_90 = 1.5
|
|
@@ -233,7 +233,7 @@ def draw_pulse_sequence(current_step, total_steps):
|
|
| 233 |
ax.plot(t, rf90 + rf180, color='black', lw=2)
|
| 234 |
ax.text(t_90, 1.2, '90°', ha='right', fontsize=12, fontweight='bold')
|
| 235 |
ax.text(t_180, 1.7, '180°', ha='left', fontsize=12, fontweight='bold')
|
| 236 |
-
ax.text(-0.05, 0.2, '
|
| 237 |
ax.axis('off')
|
| 238 |
|
| 239 |
# เพิ่มเส้นประบอกเวลา (Dashed Lines)
|
|
@@ -248,64 +248,53 @@ def draw_pulse_sequence(current_step, total_steps):
|
|
| 248 |
ax.annotate('', xy=(t_90, 2.8), xytext=(t_echo, 2.8), arrowprops=dict(arrowstyle='<->', color='black'))
|
| 249 |
ax.text((t_90+t_echo)/2, 2.9, 'TE', ha='center', va='bottom', fontsize=12, fontweight='bold')
|
| 250 |
ax.set_ylim(-0.5, 3.5)
|
| 251 |
-
|
| 252 |
-
# 2. G_SS (Slice Selection - สีเขียวแบบในรูป)
|
| 253 |
-
ax = axes[1]
|
| 254 |
-
gss = np.zeros_like(t)
|
| 255 |
-
gss[(t > t_90 - 0.5) & (t < t_90 + 0.5)] = 0.8
|
| 256 |
-
gss[(t > t_90 + 0.5) & (t < t_90 + 1.0)] = -0.4
|
| 257 |
-
gss[(t > t_180 - 0.5) & (t < t_180 + 0.5)] = 0.8
|
| 258 |
-
ax.plot(t, gss, color='#7cb342', lw=2)
|
| 259 |
-
ax.fill_between(t, gss, 0, alpha=0.2, color='#7cb342')
|
| 260 |
-
ax.text(-0.05, 0, '$G_{SS}$', fontsize=14, fontweight='bold', va='center', ha='right', transform=ax.transAxes)
|
| 261 |
-
ax.set_ylim(-1.2, 1.2)
|
| 262 |
-
ax.axis('off')
|
| 263 |
|
| 264 |
-
#
|
| 265 |
-
ax = axes[
|
| 266 |
gy_vals = np.linspace(0.8, -0.8, total_steps)
|
| 267 |
t_pe_start, t_pe_end = 2.8, 3.8
|
| 268 |
for i, gy_amp in enumerate(gy_vals):
|
| 269 |
gy = np.zeros_like(t)
|
| 270 |
gy[(t > t_pe_start) & (t < t_pe_end)] = gy_amp
|
| 271 |
if i == current_step:
|
| 272 |
-
ax.plot(t, gy, color='
|
| 273 |
else:
|
| 274 |
-
ax.plot(t, gy, color='
|
| 275 |
-
|
| 276 |
-
ax.
|
|
|
|
| 277 |
ax.set_ylim(-1.2, 1.2)
|
| 278 |
ax.axis('off')
|
| 279 |
|
| 280 |
-
#
|
| 281 |
-
ax = axes[
|
| 282 |
gx = np.zeros_like(t)
|
| 283 |
-
#
|
| 284 |
gx[(t > 2.8) & (t < 3.8)] = -0.6
|
| 285 |
gx[(t > t_echo - 1.0) & (t < t_echo + 1.0)] = 0.6
|
| 286 |
ax.plot(t, gx, color='#d32f2f', lw=2)
|
| 287 |
ax.fill_between(t, gx, 0, alpha=0.2, color='#d32f2f')
|
| 288 |
ax.text(3.3, -0.4, '-', color='#d32f2f', fontsize=16, fontweight='bold', ha='center', va='center')
|
| 289 |
ax.text(t_echo, 0.4, '+', color='#d32f2f', fontsize=16, fontweight='bold', ha='center', va='center')
|
| 290 |
-
ax.text(-0.05, 0, '
|
| 291 |
ax.set_ylim(-1.2, 1.2)
|
| 292 |
ax.axis('off')
|
| 293 |
|
| 294 |
-
#
|
| 295 |
-
ax = axes[
|
| 296 |
echo_env = np.exp(-((t - t_echo)**2) / 0.15) * (t > t_echo - 1.0) * (t < t_echo + 1.0)
|
| 297 |
ax.plot(t, echo_env, color='black', lw=2)
|
| 298 |
ax.fill_between(t, echo_env, 0, alpha=0.3, color='gray')
|
| 299 |
-
ax.text(-0.05, 0.5, 'Echo
|
| 300 |
ax.axis('off')
|
| 301 |
|
| 302 |
-
# ถ่างระยะขอบซ้ายให้กว้างพอเพื่อไม่ให้ตัวหนังสือตกจอ
|
| 303 |
-
fig.subplots_adjust(left=0.
|
| 304 |
return get_image_from_plot(fig)
|
| 305 |
|
| 306 |
@st.cache_data
|
| 307 |
def draw_kspace_filling(current_step, total_steps):
|
| 308 |
-
fig, ax = plt.subplots(figsize=(5, 6
|
| 309 |
|
| 310 |
ax.set_facecolor('black')
|
| 311 |
ax.axhline(0, color='gray', lw=1, ls='--')
|
|
@@ -502,4 +491,6 @@ with col_main:
|
|
| 502 |
with col_fimg2:
|
| 503 |
st_image(draw_mri(mri_result), caption="ภาพ MRI ผลลัพธ์")
|
| 504 |
|
|
|
|
|
|
|
| 505 |
st.markdown('<div style="height: 300px;"></div>', unsafe_allow_html=True)
|
|
|
|
| 218 |
|
| 219 |
@st.cache_data
|
| 220 |
def draw_pulse_sequence(current_step, total_steps):
|
| 221 |
+
# ปรับให้เหลือ 4 กราฟ (RF, Gy, Gx, Signal) ตามที่ขอ
|
| 222 |
+
fig, axes = plt.subplots(4, 1, figsize=(6, 6), sharex=True, gridspec_kw={'height_ratios': [1.5, 1.2, 1.2, 1.2]})
|
| 223 |
t = np.linspace(0, 11, 1000)
|
| 224 |
|
| 225 |
t_90 = 1.5
|
|
|
|
| 233 |
ax.plot(t, rf90 + rf180, color='black', lw=2)
|
| 234 |
ax.text(t_90, 1.2, '90°', ha='right', fontsize=12, fontweight='bold')
|
| 235 |
ax.text(t_180, 1.7, '180°', ha='left', fontsize=12, fontweight='bold')
|
| 236 |
+
ax.text(-0.05, 0.2, 'RF', fontsize=16, fontweight='bold', va='center', ha='right', transform=ax.transAxes)
|
| 237 |
ax.axis('off')
|
| 238 |
|
| 239 |
# เพิ่มเส้นประบอกเวลา (Dashed Lines)
|
|
|
|
| 248 |
ax.annotate('', xy=(t_90, 2.8), xytext=(t_echo, 2.8), arrowprops=dict(arrowstyle='<->', color='black'))
|
| 249 |
ax.text((t_90+t_echo)/2, 2.9, 'TE', ha='center', va='bottom', fontsize=12, fontweight='bold')
|
| 250 |
ax.set_ylim(-0.5, 3.5)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 251 |
|
| 252 |
+
# 2. Gy (Phase Encoding - เส้นแอคทีฟสีเขียว เส้นอื่นและกรอบสีดำ)
|
| 253 |
+
ax = axes[1]
|
| 254 |
gy_vals = np.linspace(0.8, -0.8, total_steps)
|
| 255 |
t_pe_start, t_pe_end = 2.8, 3.8
|
| 256 |
for i, gy_amp in enumerate(gy_vals):
|
| 257 |
gy = np.zeros_like(t)
|
| 258 |
gy[(t > t_pe_start) & (t < t_pe_end)] = gy_amp
|
| 259 |
if i == current_step:
|
| 260 |
+
ax.plot(t, gy, color='green', lw=3, zorder=10) # สีเขียวเส้นที่กำลังทำงาน
|
| 261 |
else:
|
| 262 |
+
ax.plot(t, gy, color='black', lw=1, alpha=0.3) # เส้นอื่นสีดำจางๆ
|
| 263 |
+
# ตีกรอบสีดำทับ
|
| 264 |
+
ax.plot([t_pe_start, t_pe_end, t_pe_end, t_pe_start, t_pe_start], [0.8, 0.8, -0.8, -0.8, 0.8], color='black', lw=1.5)
|
| 265 |
+
ax.text(-0.05, 0, 'Gy', fontsize=16, fontweight='bold', va='center', ha='right', transform=ax.transAxes)
|
| 266 |
ax.set_ylim(-1.2, 1.2)
|
| 267 |
ax.axis('off')
|
| 268 |
|
| 269 |
+
# 3. Gx (Frequency Encoding - สีแดง)
|
| 270 |
+
ax = axes[2]
|
| 271 |
gx = np.zeros_like(t)
|
| 272 |
+
# อันแรกติดลบเพื่อกวาดไปด้านซ้าย
|
| 273 |
gx[(t > 2.8) & (t < 3.8)] = -0.6
|
| 274 |
gx[(t > t_echo - 1.0) & (t < t_echo + 1.0)] = 0.6
|
| 275 |
ax.plot(t, gx, color='#d32f2f', lw=2)
|
| 276 |
ax.fill_between(t, gx, 0, alpha=0.2, color='#d32f2f')
|
| 277 |
ax.text(3.3, -0.4, '-', color='#d32f2f', fontsize=16, fontweight='bold', ha='center', va='center')
|
| 278 |
ax.text(t_echo, 0.4, '+', color='#d32f2f', fontsize=16, fontweight='bold', ha='center', va='center')
|
| 279 |
+
ax.text(-0.05, 0, 'Gx', fontsize=16, fontweight='bold', va='center', ha='right', transform=ax.transAxes)
|
| 280 |
ax.set_ylim(-1.2, 1.2)
|
| 281 |
ax.axis('off')
|
| 282 |
|
| 283 |
+
# 4. Echo Signal
|
| 284 |
+
ax = axes[3]
|
| 285 |
echo_env = np.exp(-((t - t_echo)**2) / 0.15) * (t > t_echo - 1.0) * (t < t_echo + 1.0)
|
| 286 |
ax.plot(t, echo_env, color='black', lw=2)
|
| 287 |
ax.fill_between(t, echo_env, 0, alpha=0.3, color='gray')
|
| 288 |
+
ax.text(-0.05, 0.5, 'Signal\n(Echo)', fontsize=16, fontweight='bold', va='center', ha='right', transform=ax.transAxes)
|
| 289 |
ax.axis('off')
|
| 290 |
|
| 291 |
+
# ถ่างระยะขอบซ้าย (left=0.25) ให้กว้างพอเพื่อไม่ให้ตัวหนังสือตกจอ
|
| 292 |
+
fig.subplots_adjust(left=0.25, right=0.95, top=0.95, bottom=0.05, hspace=0.1)
|
| 293 |
return get_image_from_plot(fig)
|
| 294 |
|
| 295 |
@st.cache_data
|
| 296 |
def draw_kspace_filling(current_step, total_steps):
|
| 297 |
+
fig, ax = plt.subplots(figsize=(5, 6)) # ปรับความสูงให้สัมพันธ์กัน
|
| 298 |
|
| 299 |
ax.set_facecolor('black')
|
| 300 |
ax.axhline(0, color='gray', lw=1, ls='--')
|
|
|
|
| 491 |
with col_fimg2:
|
| 492 |
st_image(draw_mri(mri_result), caption="ภาพ MRI ผลลัพธ์")
|
| 493 |
|
| 494 |
+
# Spacer: keeps page taller than viewport at all zoom levels so the
|
| 495 |
+
# scrollbar never disappears and never causes a layout-shift jiggle.
|
| 496 |
st.markdown('<div style="height: 300px;"></div>', unsafe_allow_html=True)
|