Nicha1234 commited on
Commit
08ab726
·
verified ·
1 Parent(s): 5e6471a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +51 -54
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 (Phase Encoding)
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 (Frequency Encoding)
166
  ax = axes[2]
167
  gx = np.zeros_like(t)
168
  gx[(t > 2.5) & (t < 3.5)] = -0.5
@@ -183,62 +190,46 @@ 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
 
213
- ax.set_xlim(-112, 112)
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
-
221
  if current_step >= total_steps - 1:
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
-
235
- ax.set_xlim(-112, 112)
236
- ax.set_ylim(-112, 112)
237
-
238
- ax.set_title("K-Space Trajectory", fontweight='bold', color='white' if mode_type=="ข้อมูลจำลอง (Simulated)" else 'black')
239
- if mode_type == "ข้อมูลจำลอง (Simulated)":
240
- fig.patch.set_facecolor('black')
241
 
 
 
 
 
 
 
 
 
 
242
  ax.axis('off')
243
  return get_image_from_plot(fig)
244
 
@@ -265,10 +256,17 @@ with col_main:
265
 
266
  _, col_img_center, _ = st.columns([1.5, 3, 1.5])
267
  with col_img_center:
268
- if os.path.exists("Screenshot 2026-05-07 205051.png"):
269
- st.image("Screenshot 2026-05-07 205051.png", use_container_width=True)
270
- elif os.path.exists("Screenshot 2026-05-07 205051.jpg"):
271
- st.image("Screenshot 2026-05-07 205051.jpg", use_container_width=True)
 
 
 
 
 
 
 
272
 
273
  # ---------------------------------------------------------
274
  # NEW: K-Space Trajectories
@@ -278,10 +276,10 @@ with col_main:
278
  **การบันทึกข้อมูลลงใน K-space สามารถทำได้หลายรูปแบบ** โดยจะยกตัวอย่างให้การเก็บข้อมูลจะดำเนินไปทีละบรรทัด โดยสัญญาณจะเกิดขึ้นหลังจากกระตุ้นด้วย RF Pulse โดยมีลำดับดังนี้
279
 
280
  1. กระบวนการเริ่มต้นขึ้นเมื่อสนามแม่เหล็กเกรเดียนท์ **Gx** และ **Gy** เริ่มทำงานพร้อมกันเพื่อสร้างพิกัดอ้างอิง
281
- 2. ระบบจะเริ่มบันทึกข้อมูลจุดแรกของเฟสในแถวที่ 1 โดยจะเริ่มต้นที่ค่าแอมปลิจูดของ **Gy ทางฝั่งบวกก่อน (พิกัดด้านบนของ K-Space)**
282
- 3. สัญญาณจะถูกบันทึกไล่ไปตามแกน **Gx (ากซ้าย -kx ไป ขวา +kx)** จนได้ข้อมูลครบถ้วนเต็ม 1 แถว
283
  4. เมื่อจบแถวแรก ระบบจะเริ่มกระบวนการใหม่เพื่อบันทึกข้อมูลในเฟสแถวที่ 2, 3, 4 ต่อไปเรื่อยๆ
284
- 5. การวนรอบนี้จะดำเนินต่อไปพร้อมกับการเปลี่ยนค่า **Gy ให้ลดลงจนไปถึงค่าทางฝั่งลบ (พิกัดด้านล่าง)** เมื่อบันทึกครบทุกแถวตามจำนวนความละเอียดที่ตั้งไว้ จะถือว่าสิ้นสุดกระบวนการเก็บข้อมูล MRI แบบสองมิติลงบน K-space
285
  """)
286
 
287
  total_anim_steps = 15
@@ -323,7 +321,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
+ display_img = np.zeros((224, 224))
196
+
197
+ step_size = 224 / total_steps
198
 
199
  if mode_type == "ข้อมูลจำลอง (Simulated)":
200
+ x_array = np.linspace(-10, 10, 224)
201
+ for step in range(current_step + 1):
202
+ y_center = int(step * step_size + step_size / 2)
203
+ y_start = max(0, y_center - 1)
204
+ y_end = min(224, y_center + 1)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
205
 
206
+ signal = np.abs(np.sinc(x_array))
207
+ noise = np.random.uniform(0.1, 0.4, 224)
208
+ line_detail = signal + noise
209
+
210
+ ky_dist = abs(step - (total_steps - 1)/2) / ((total_steps - 1)/2)
211
+ line_detail = line_detail * (1.0 - 0.7 * ky_dist)
212
+
213
+ display_img[y_start:y_end, :] = np.clip(line_detail, 0, 1)
214
+
215
+ ax.imshow(display_img, cmap='gray', extent=[-112, 112, -112, 112], vmin=0, vmax=1)
216
  else:
 
 
 
 
217
  if current_step >= total_steps - 1:
218
  display_img = real_bg
219
  else:
220
  current_line_idx = int(current_step * step_size)
 
221
  display_img[:current_line_idx + int(step_size), :] = real_bg[:current_line_idx + int(step_size), :]
222
+ ax.imshow(display_img, cmap='gray', extent=[-112, 112, -112, 112], vmin=0, vmax=1)
 
 
 
 
 
 
 
 
 
 
 
 
 
223
 
224
+ ax.set_xlim(-112, 112)
225
+ ax.set_ylim(112, -112)
226
+
227
+ current_y_center = 112 - int(current_step * step_size + step_size / 2)
228
+ ax.annotate('', xy=(-70, current_y_center), xytext=(-110, current_y_center), arrowprops=dict(arrowstyle='->', color='red', lw=2))
229
+
230
+ ax.axhline(0, color='white', linewidth=0.5, linestyle='--')
231
+ ax.axvline(0, color='white', linewidth=0.5, linestyle='--')
232
+ ax.set_title("K-Space Filling", fontweight='bold')
233
  ax.axis('off')
234
  return get_image_from_plot(fig)
235
 
 
256
 
257
  _, col_img_center, _ = st.columns([1.5, 3, 1.5])
258
  with col_img_center:
259
+ # เช็คไฟล์รูปภาพใหม่
260
+ if os.path.exists("image_729a00.jpg"):
261
+ st.image("image_729a00.jpg", use_container_width=True)
262
+ # เพิ่มคำอธิบายอ้างอิงด้านล่างภาพ
263
+ st.markdown(
264
+ """<p class="reference-text">ภาพดัดแปลงจาก: Clover Learning. (2024). <i>MRI k-space made easy - MRI physics explained</i> [Video]. YouTube.
265
+ <a href="https://youtu.be/cfE6SL2Xj6o?t=68" target="_blank">https://youtu.be/cfE6SL2Xj6o?t=68</a></p>""",
266
+ unsafe_allow_html=True
267
+ )
268
+ else:
269
+ st.info("กรุณาอัปโหลดรูปภาพ image_729a00.jpg เข้าระบบ")
270
 
271
  # ---------------------------------------------------------
272
  # NEW: K-Space Trajectories
 
276
  **การบันทึกข้อมูลลงใน K-space สามารถทำได้หลายรูปแบบ** โดยจะยกตัวอย่างให้การเก็บข้อมูลจะดำเนินไปทีละบรรทัด โดยสัญญาณจะเกิดขึ้นหลังจากกระตุ้นด้วย RF Pulse โดยมีลำดับดังนี้
277
 
278
  1. กระบวนการเริ่มต้นขึ้นเมื่อสนามแม่เหล็กเกรเดียนท์ **Gx** และ **Gy** เริ่มทำงานพร้อมกันเพื่อสร้างพิกัดอ้างอิง
279
+ 2. ระบบจะเริ่มบันทึกข้อมูลจุดแรกของเฟสในแถวที่ 1 โดยจะเริ่มต้นที่ค่าแอมปลิจูดของ **Gy ทางฝั่งบวกก่อน**
280
+ 3. สัญญาณจะถูกบันทึกไล่ไปตามแกน Gx จนได้ข้อมูลครบถ้วนเต็ม 1 แถว
281
  4. เมื่อจบแถวแรก ระบบจะเริ่มกระบวนการใหม่เพื่อบันทึกข้อมูลในเฟสแถวที่ 2, 3, 4 ต่อไปเรื่อยๆ
282
+ 5. การวนรอบนี้จะดำเนินต่อไปพร้อมกับการเปลี่ยนค่า **Gy ให้ลดลงจนไปถึงค่าทางฝั่งลบ** เมื่อบันทึกครบทุกแถวตามจำนวนความละเอียดที่ตั้งไว้ จะถือว่าสิ้นสุดกระบวนการเก็บข้อมูล MRI แบบสองมิติลงบน K-space
283
  """)
284
 
285
  total_anim_steps = 15
 
321
  with col_anim2:
322
  st.image(draw_kspace_filling(st.session_state.fill_step, total_anim_steps, data_mode, kspace_bg_image), use_container_width=True)
323
 
 
324
  st.markdown("---")
325
  st.markdown("## 📍 1 จุดบน k-space")
326