Update app.py
Browse files
app.py
CHANGED
|
@@ -45,6 +45,13 @@ st.markdown("""
|
|
| 45 |
background-color: #1E88E5;
|
| 46 |
color: white;
|
| 47 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 48 |
</style>
|
| 49 |
""", unsafe_allow_html=True)
|
| 50 |
|
|
@@ -149,7 +156,7 @@ def draw_pulse_sequence(current_step, total_steps):
|
|
| 149 |
ax.text(0, 0.5, 'RF', fontsize=14, fontweight='bold', va='center', ha='right', transform=ax.get_yaxis_transform())
|
| 150 |
ax.axis('off')
|
| 151 |
|
| 152 |
-
# 2. Gy
|
| 153 |
ax = axes[1]
|
| 154 |
gy_vals = np.linspace(1, -1, total_steps)
|
| 155 |
for i, gy_amp in enumerate(gy_vals):
|
|
@@ -162,7 +169,7 @@ def draw_pulse_sequence(current_step, total_steps):
|
|
| 162 |
ax.text(0, 0, 'Gy', fontsize=14, fontweight='bold', va='center', ha='right', transform=ax.get_yaxis_transform())
|
| 163 |
ax.axis('off')
|
| 164 |
|
| 165 |
-
# 3. Gx
|
| 166 |
ax = axes[2]
|
| 167 |
gx = np.zeros_like(t)
|
| 168 |
gx[(t > 2.5) & (t < 3.5)] = -0.5
|
|
@@ -183,30 +190,24 @@ def draw_pulse_sequence(current_step, total_steps):
|
|
| 183 |
plt.tight_layout()
|
| 184 |
return get_image_from_plot(fig)
|
| 185 |
|
| 186 |
-
# --- ฟังก์ชันวาด Trajectory (เริ่มซ้ายบน วิ่งไปขวา) ---
|
| 187 |
def draw_kspace_filling(current_step, total_steps, mode_type, real_bg):
|
| 188 |
fig, ax = plt.subplots(figsize=(5, 6))
|
| 189 |
|
| 190 |
if mode_type == "ข้อมูลจำลอง (Simulated)":
|
| 191 |
-
# สร้างกราฟดำ
|
| 192 |
ax.set_facecolor('black')
|
| 193 |
|
| 194 |
-
# แกน kx, ky
|
| 195 |
ax.axhline(0, color='gray', lw=1, ls='--')
|
| 196 |
ax.axvline(0, color='gray', lw=1, ls='--')
|
| 197 |
|
| 198 |
-
# คำนวณพิกัด Y จากบนลงล่าง (+ky ไป -ky)
|
| 199 |
y_vals = np.linspace(90, -90, total_steps)
|
| 200 |
|
| 201 |
for i in range(current_step + 1):
|
| 202 |
y = y_vals[i]
|
| 203 |
-
# วาดเส้นลูกศรวิ่งจาก ซ้าย (-kx) ไป ขวา (+kx)
|
| 204 |
if i == current_step:
|
| 205 |
ax.annotate('', xy=(100, y), xytext=(-100, y), arrowprops=dict(arrowstyle='->', color='red', lw=3))
|
| 206 |
else:
|
| 207 |
ax.annotate('', xy=(100, y), xytext=(-100, y), arrowprops=dict(arrowstyle='->', color='white', lw=1.5))
|
| 208 |
|
| 209 |
-
# วาดเส้นประเฉียงๆ โยงจากจุดจบขวา ไปเริ่มซ้ายในบรรทัดถัดไป
|
| 210 |
for i in range(current_step):
|
| 211 |
ax.plot([100, -100], [y_vals[i], y_vals[i+1]], color='gray', ls=':', lw=1)
|
| 212 |
|
|
@@ -214,7 +215,6 @@ def draw_kspace_filling(current_step, total_steps, mode_type, real_bg):
|
|
| 214 |
ax.set_ylim(-112, 112)
|
| 215 |
|
| 216 |
else:
|
| 217 |
-
# โหมดข้อมูลจริง (kspace.mat) เติมจากบนลงล่าง
|
| 218 |
display_img = np.zeros((224, 224))
|
| 219 |
step_size = 224 / total_steps
|
| 220 |
|
|
@@ -222,13 +222,10 @@ def draw_kspace_filling(current_step, total_steps, mode_type, real_bg):
|
|
| 222 |
display_img = real_bg
|
| 223 |
else:
|
| 224 |
current_line_idx = int(current_step * step_size)
|
| 225 |
-
# เติมข้อมูลจากแถวบน (index 0) ลงมา
|
| 226 |
display_img[:current_line_idx + int(step_size), :] = real_bg[:current_line_idx + int(step_size), :]
|
| 227 |
|
| 228 |
-
# origin='upper' ควบคุมให้ index 0 อยู่ด้านบนสุด (y=112)
|
| 229 |
ax.imshow(display_img, cmap='gray', extent=[-112, 112, -112, 112], origin='upper', vmin=0, vmax=1)
|
| 230 |
|
| 231 |
-
# ลูกศรชี้พิกัดที่กำลังทำงาน
|
| 232 |
current_y_center = 112 - int(current_step * step_size + step_size / 2)
|
| 233 |
ax.annotate('', xy=(112, current_y_center), xytext=(-112, current_y_center), arrowprops=dict(arrowstyle='->', color='red', lw=2))
|
| 234 |
|
|
@@ -265,10 +262,17 @@ with col_main:
|
|
| 265 |
|
| 266 |
_, col_img_center, _ = st.columns([1.5, 3, 1.5])
|
| 267 |
with col_img_center:
|
| 268 |
-
|
| 269 |
-
|
| 270 |
-
|
| 271 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 272 |
|
| 273 |
# ---------------------------------------------------------
|
| 274 |
# NEW: K-Space Trajectories
|
|
@@ -323,7 +327,6 @@ with col_main:
|
|
| 323 |
with col_anim2:
|
| 324 |
st.image(draw_kspace_filling(st.session_state.fill_step, total_anim_steps, data_mode, kspace_bg_image), use_container_width=True)
|
| 325 |
|
| 326 |
-
|
| 327 |
st.markdown("---")
|
| 328 |
st.markdown("## 📍 1 จุดบน k-space")
|
| 329 |
|
|
|
|
| 45 |
background-color: #1E88E5;
|
| 46 |
color: white;
|
| 47 |
}
|
| 48 |
+
/* ปรับแต่งส่วนอ้างอิง */
|
| 49 |
+
.reference-text {
|
| 50 |
+
font-size: 14px;
|
| 51 |
+
color: #666;
|
| 52 |
+
text-align: center;
|
| 53 |
+
margin-top: 5px;
|
| 54 |
+
}
|
| 55 |
</style>
|
| 56 |
""", unsafe_allow_html=True)
|
| 57 |
|
|
|
|
| 156 |
ax.text(0, 0.5, 'RF', fontsize=14, fontweight='bold', va='center', ha='right', transform=ax.get_yaxis_transform())
|
| 157 |
ax.axis('off')
|
| 158 |
|
| 159 |
+
# 2. Gy
|
| 160 |
ax = axes[1]
|
| 161 |
gy_vals = np.linspace(1, -1, total_steps)
|
| 162 |
for i, gy_amp in enumerate(gy_vals):
|
|
|
|
| 169 |
ax.text(0, 0, 'Gy', fontsize=14, fontweight='bold', va='center', ha='right', transform=ax.get_yaxis_transform())
|
| 170 |
ax.axis('off')
|
| 171 |
|
| 172 |
+
# 3. Gx
|
| 173 |
ax = axes[2]
|
| 174 |
gx = np.zeros_like(t)
|
| 175 |
gx[(t > 2.5) & (t < 3.5)] = -0.5
|
|
|
|
| 190 |
plt.tight_layout()
|
| 191 |
return get_image_from_plot(fig)
|
| 192 |
|
|
|
|
| 193 |
def draw_kspace_filling(current_step, total_steps, mode_type, real_bg):
|
| 194 |
fig, ax = plt.subplots(figsize=(5, 6))
|
| 195 |
|
| 196 |
if mode_type == "ข้อมูลจำลอง (Simulated)":
|
|
|
|
| 197 |
ax.set_facecolor('black')
|
| 198 |
|
|
|
|
| 199 |
ax.axhline(0, color='gray', lw=1, ls='--')
|
| 200 |
ax.axvline(0, color='gray', lw=1, ls='--')
|
| 201 |
|
|
|
|
| 202 |
y_vals = np.linspace(90, -90, total_steps)
|
| 203 |
|
| 204 |
for i in range(current_step + 1):
|
| 205 |
y = y_vals[i]
|
|
|
|
| 206 |
if i == current_step:
|
| 207 |
ax.annotate('', xy=(100, y), xytext=(-100, y), arrowprops=dict(arrowstyle='->', color='red', lw=3))
|
| 208 |
else:
|
| 209 |
ax.annotate('', xy=(100, y), xytext=(-100, y), arrowprops=dict(arrowstyle='->', color='white', lw=1.5))
|
| 210 |
|
|
|
|
| 211 |
for i in range(current_step):
|
| 212 |
ax.plot([100, -100], [y_vals[i], y_vals[i+1]], color='gray', ls=':', lw=1)
|
| 213 |
|
|
|
|
| 215 |
ax.set_ylim(-112, 112)
|
| 216 |
|
| 217 |
else:
|
|
|
|
| 218 |
display_img = np.zeros((224, 224))
|
| 219 |
step_size = 224 / total_steps
|
| 220 |
|
|
|
|
| 222 |
display_img = real_bg
|
| 223 |
else:
|
| 224 |
current_line_idx = int(current_step * step_size)
|
|
|
|
| 225 |
display_img[:current_line_idx + int(step_size), :] = real_bg[:current_line_idx + int(step_size), :]
|
| 226 |
|
|
|
|
| 227 |
ax.imshow(display_img, cmap='gray', extent=[-112, 112, -112, 112], origin='upper', vmin=0, vmax=1)
|
| 228 |
|
|
|
|
| 229 |
current_y_center = 112 - int(current_step * step_size + step_size / 2)
|
| 230 |
ax.annotate('', xy=(112, current_y_center), xytext=(-112, current_y_center), arrowprops=dict(arrowstyle='->', color='red', lw=2))
|
| 231 |
|
|
|
|
| 262 |
|
| 263 |
_, col_img_center, _ = st.columns([1.5, 3, 1.5])
|
| 264 |
with col_img_center:
|
| 265 |
+
# เช็คไฟล์รูปภาพใหม่
|
| 266 |
+
if os.path.exists("kspaceaxis.png"):
|
| 267 |
+
st.image("kspaceaxis.png", use_container_width=True)
|
| 268 |
+
# เพิ่มคำอธิบายอ้างอิงด้านล่างภาพ
|
| 269 |
+
st.markdown(
|
| 270 |
+
"""<p class="reference-text">ภาพดัดแปลงจาก: Clover Learning. (2024). <i>MRI k-space made easy - MRI physics explained</i> [Video]. YouTube.
|
| 271 |
+
<a href="https://youtu.be/cfE6SL2Xj6o?t=68" target="_blank">https://youtu.be/cfE6SL2Xj6o?t=68</a></p>""",
|
| 272 |
+
unsafe_allow_html=True
|
| 273 |
+
)
|
| 274 |
+
else:
|
| 275 |
+
st.info("กรุณาอัปโหลดรูปภาพ kspaceaxis.png เข้าระบบ")
|
| 276 |
|
| 277 |
# ---------------------------------------------------------
|
| 278 |
# NEW: K-Space Trajectories
|
|
|
|
| 327 |
with col_anim2:
|
| 328 |
st.image(draw_kspace_filling(st.session_state.fill_step, total_anim_steps, data_mode, kspace_bg_image), use_container_width=True)
|
| 329 |
|
|
|
|
| 330 |
st.markdown("---")
|
| 331 |
st.markdown("## 📍 1 จุดบน k-space")
|
| 332 |
|