Nicha1234 commited on
Commit
c3d5dfd
·
verified ·
1 Parent(s): 65e869d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +50 -42
app.py CHANGED
@@ -135,7 +135,6 @@ 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), sharex=True, gridspec_kw={'height_ratios': [1, 1.5, 1, 1]})
141
  t = np.linspace(0, 10, 1000)
@@ -150,7 +149,7 @@ def draw_pulse_sequence(current_step, total_steps):
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
154
  ax = axes[1]
155
  gy_vals = np.linspace(1, -1, total_steps)
156
  for i, gy_amp in enumerate(gy_vals):
@@ -163,7 +162,7 @@ def draw_pulse_sequence(current_step, total_steps):
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
167
  ax = axes[2]
168
  gx = np.zeros_like(t)
169
  gx[(t > 2.5) & (t < 3.5)] = -0.5
@@ -184,54 +183,62 @@ def draw_pulse_sequence(current_step, total_steps):
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
- display_img = np.zeros((224, 224))
191
-
192
- step_size = 224 / total_steps
193
 
194
  if mode_type == "ข้อมูลจำลอง (Simulated)":
195
- # สร้างเส้นละเอียดแยเป็นบรทัสุดขอบ (Edge-to-Edge)
196
- x_array = np.linspace(-10, 10, 224)
197
- for step in range(current_step + 1):
198
- # คำนวณพิัด Y ของแต่ละเส้น
199
- y_center = int(step * step_size + step_size / 2)
200
- y_start = max(0, y_center - 1)
201
- y_end = min(224, y_center + 1) # ความหนาเส้น 2 พิกเซล
202
-
203
- # จำลองลวดลายของเส้น (Signal + Noise ละเอียดๆ)
204
- signal = np.abs(np.sinc(x_array)) # คลื่นตรงกลางสว่าง
205
- noise = np.random.uniform(0.1, 0.4, 224) # ลายเส้นขรุขระให้ดูสมจริง
206
- line_detail = signal + noise
207
-
208
- # ให้เส้นตรงกลางสว่างสุด แล้วค่อยๆ มืดลงเมื่อไปที่ขอบบน/ล่างของ K-space
209
- ky_dist = abs(step - (total_steps - 1)/2) / ((total_steps - 1)/2)
210
- line_detail = line_detail * (1.0 - 0.7 * ky_dist)
211
-
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
- # โหมดข้อมูลจริง
 
 
 
218
  if current_step >= total_steps - 1:
219
  display_img = real_bg
220
  else:
221
  current_line_idx = int(current_step * step_size)
 
222
  display_img[:current_line_idx + int(step_size), :] = real_bg[:current_line_idx + int(step_size), :]
223
- ax.imshow(display_img, cmap='gray', extent=[-112, 112, -112, 112], vmin=0, vmax=1)
 
 
 
 
 
 
 
 
 
 
 
 
 
224
 
225
- ax.set_xlim(-112, 112)
226
- ax.set_ylim(112, -112) # วาดจากบนลงล่าง (+ky -> -ky)
227
-
228
- # วาดลูกศรชี้พิกัดที่กำลังวาด (ชี้เฉพาะบรรทัดนั้นๆ)
229
- current_y_center = 112 - int(current_step * step_size + step_size / 2)
230
- ax.annotate('', xy=(-70, current_y_center), xytext=(-110, current_y_center), arrowprops=dict(arrowstyle='->', color='red', lw=2))
231
-
232
- ax.axhline(0, color='white', linewidth=0.5, linestyle='--')
233
- ax.axvline(0, color='white', linewidth=0.5, linestyle='--')
234
- ax.set_title("K-Space Filling", fontweight='bold')
235
  ax.axis('off')
236
  return get_image_from_plot(fig)
237
 
@@ -271,10 +278,10 @@ with col_main:
271
  **การบันทึกข้อมูลลงใน K-space สามารถทำได้หลายรูปแบบ** โดยจะยกตัวอย่างให้การเก็บข้อมูลจะดำเนินไปทีละบรรทัด โดยสัญญาณจะเกิดขึ้นหลังจากกระตุ้นด้วย RF Pulse โดยมีลำดับดังนี้
272
 
273
  1. กระบวนการเริ่มต้นขึ้นเมื่อสนามแม่เหล็กเกรเดียนท์ **Gx** และ **Gy** เริ่มทำงานพร้อมกันเพื่อสร้างพิกัดอ้างอิง
274
- 2. ระบบจะเริ่มบันทึกข้อมูลจุดแรกของเฟสในแถวที่ 1 โดยจะเริ่มต้นที่ค่าแอมปลิจูดของ **Gy ทางฝั่งบวกก่อน**
275
- 3. สัญญาณจะถูกบันทึกไล่ไปตามแกน Gx จนได้ข้อมูลครบถ้วนเต็ม 1 แถว
276
  4. เมื่อจบแถวแรก ระบบจะเริ่มกระบวนการใหม่เพื่อบันทึกข้อมูลในเฟสแถวที่ 2, 3, 4 ต่อไปเรื่อยๆ
277
- 5. การวนรอบนี้จะดำเนินต่อไปพร้อมกับการเปลี่ยนค่า **Gy ให้ลดลงจนไปถึงค่าทางฝั่งลบ** เมื่อบันทึกครบทุกแถวตามจำนวนความละเอียดที่ตั้งไว้ จะถือว่าสิ้นสุดกระบวนการเก็บข้อมูล MRI แบบสองมิติลงบน K-space
278
  """)
279
 
280
  total_anim_steps = 15
@@ -316,6 +323,7 @@ with col_main:
316
  with col_anim2:
317
  st.image(draw_kspace_filling(st.session_state.fill_step, total_anim_steps, data_mode, kspace_bg_image), use_container_width=True)
318
 
 
319
  st.markdown("---")
320
  st.markdown("## 📍 1 จุดบน k-space")
321
 
 
135
  ax.axis('off')
136
  return get_image_from_plot(fig)
137
 
 
138
  def draw_pulse_sequence(current_step, total_steps):
139
  fig, axes = plt.subplots(4, 1, figsize=(5, 6), sharex=True, gridspec_kw={'height_ratios': [1, 1.5, 1, 1]})
140
  t = np.linspace(0, 10, 1000)
 
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
  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
  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
 
 
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
  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