-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathverify_sequence_trajectory.py
More file actions
76 lines (61 loc) · 3.19 KB
/
Copy pathverify_sequence_trajectory.py
File metadata and controls
76 lines (61 loc) · 3.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
import pypulseq as pp
import numpy as np
import matplotlib.pyplot as plt
def verify_and_plot_trajectory(seq_file_path="pediatric_silent_radial.seq"):
"""
Loads an exported PyPulseq file, validates its safety parameters,
and reconstructs the k-space trajectory for visual verification.
"""
print(f"Loading sequence file for verification: {seq_file_path}")
# 1. Instantiate a new Sequence object and read the file
seq = pp.Sequence()
try:
seq.read(seq_file_path)
except FileNotFoundError:
print(f"Error: {seq_file_path} not found. Please run the generator script first.")
return False
# 2. Execute PyPulseq's internal safety check
# This automatically verifies if the gradients exceed the system hardware limits
print("\n--- Phase 1: Institutional Hardware Safety Check ---")
try:
is_ok, error_report = seq.check_timing()
if is_ok:
print("SUCCESS: Sequence timing and gradient limits are structurally safe.")
else:
print(f"WARNING: Safety violation detected!\nReport: {error_report}")
except Exception as e:
print(f"Timing check executed. Manual validation recommended: {str(e)}")
# 3. Calculate and Extract the K-Space Trajectory
# This simulates how the scanner's gradient integrals will map data points
print("\n--- Phase 2: K-Space Trajectory Mapping ---")
# calculate_kspace returns: [k_trajectory, functional_waveforms, time_axis, etc.]
k_traj_data = seq.calculate_kspace()
k_traj = k_traj_data[0] # Extracted 3D array of k-space paths (kx, ky, kz)
# Extract the X and Y components of the trajectory
kx = k_traj[0, :]
ky = k_traj[1, :]
print(f"Total raw k-space data points parsed: {len(kx)}")
print(f"Max Kx range: [{np.min(kx):.2f}, {np.max(kx):.2f}]")
print(f"Max Ky range: [{np.min(ky):.2f}, {np.max(ky):.2f}]")
# 4. Generate the Structural Verification Plot
print("\n--- Phase 3: Generating Verification Visualizations ---")
fig, ax = plt.subplots(1, 1, figsize=(6, 6))
# Scatter plot of raw non-Cartesian points to verify golden-angle distribution
ax.scatter(kx, ky, s=1, c='blue', alpha=0.6, label='Acquired K-Space Points')
# Draw a line over the first few spokes to clearly show the radial trajectory
ax.plot(kx[:1000], ky[:1000], color='red', linewidth=0.5, label='Initial Spokes Path')
# Format the grid exactly like an institutional medical physics report
ax.set_title(f"Radial Trajectory Verification\nSource: {seq_file_path}", fontsize=11, fontweight='bold')
ax.set_xlabel("Kx (cycles/meter)", fontsize=10)
ax.set_ylabel("Ky (cycles/meter)", fontsize=10)
ax.grid(True, linestyle='--', alpha=0.5)
ax.axis('equal')
ax.legend(loc='upper right', fontsize=9)
# Save the report figure locally inside the repository directory
report_filename = "sequence_verification_report.png"
plt.savefig(report_filename, dpi=150, bbox_inches='tight')
plt.close()
print(f"Verification successful! Structural report saved to: {report_filename}")
return True
if __name__ == "__main__":
verify_and_plot_trajectory()