blochsimulator 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. blochsimulator-1.0.0/MANIFEST.in +6 -0
  2. blochsimulator-1.0.0/PKG-INFO +344 -0
  3. blochsimulator-1.0.0/README.md +318 -0
  4. blochsimulator-1.0.0/pyproject.toml +36 -0
  5. blochsimulator-1.0.0/requirements.txt +25 -0
  6. blochsimulator-1.0.0/rfpulses/.DS_Store +0 -0
  7. blochsimulator-1.0.0/rfpulses/AHP_5ms_Hsn.dat +1024 -0
  8. blochsimulator-1.0.0/rfpulses/SLR_sharpness_5.txt +1 -0
  9. blochsimulator-1.0.0/rfpulses/bruker/13C_Ultimate_SPSP_Pulse_QuEMRT.exc +2502 -0
  10. blochsimulator-1.0.0/setup.cfg +4 -0
  11. blochsimulator-1.0.0/setup.py +81 -0
  12. blochsimulator-1.0.0/src/bloch_simulator/__init__.py +11 -0
  13. blochsimulator-1.0.0/src/bloch_simulator/bloch_core.h +98 -0
  14. blochsimulator-1.0.0/src/bloch_simulator/bloch_core_modified.c +794 -0
  15. blochsimulator-1.0.0/src/bloch_simulator/bloch_wrapper.c +24462 -0
  16. blochsimulator-1.0.0/src/bloch_simulator/bloch_wrapper.pyx +708 -0
  17. blochsimulator-1.0.0/src/bloch_simulator/gui.py +8549 -0
  18. blochsimulator-1.0.0/src/bloch_simulator/gui_phantom_integration.py +116 -0
  19. blochsimulator-1.0.0/src/bloch_simulator/kspace.py +1173 -0
  20. blochsimulator-1.0.0/src/bloch_simulator/kspace_widget.py +1309 -0
  21. blochsimulator-1.0.0/src/bloch_simulator/notebook_exporter.py +677 -0
  22. blochsimulator-1.0.0/src/bloch_simulator/phantom.py +1036 -0
  23. blochsimulator-1.0.0/src/bloch_simulator/phantom_widget.py +980 -0
  24. blochsimulator-1.0.0/src/bloch_simulator/pulse_loader.py +578 -0
  25. blochsimulator-1.0.0/src/bloch_simulator/simulator.py +1531 -0
  26. blochsimulator-1.0.0/src/bloch_simulator/spectral_phantom.py +932 -0
  27. blochsimulator-1.0.0/src/bloch_simulator/visualization.py +862 -0
  28. blochsimulator-1.0.0/src/blochsimulator.egg-info/PKG-INFO +344 -0
  29. blochsimulator-1.0.0/src/blochsimulator.egg-info/SOURCES.txt +37 -0
  30. blochsimulator-1.0.0/src/blochsimulator.egg-info/dependency_links.txt +1 -0
  31. blochsimulator-1.0.0/src/blochsimulator.egg-info/entry_points.txt +2 -0
  32. blochsimulator-1.0.0/src/blochsimulator.egg-info/not-zip-safe +1 -0
  33. blochsimulator-1.0.0/src/blochsimulator.egg-info/requires.txt +18 -0
  34. blochsimulator-1.0.0/src/blochsimulator.egg-info/top_level.txt +1 -0
  35. blochsimulator-1.0.0/tests/test_export.py +131 -0
  36. blochsimulator-1.0.0/tests/test_export_simple.py +57 -0
  37. blochsimulator-1.0.0/tests/test_input_shapes.py +53 -0
  38. blochsimulator-1.0.0/tests/test_notebook_export.py +290 -0
  39. blochsimulator-1.0.0/tests/test_visualization_export.py +309 -0
@@ -0,0 +1,6 @@
1
+ include src/bloch_simulator/bloch_core_modified.c
2
+ include src/bloch_simulator/bloch_core.h
3
+ include src/bloch_simulator/bloch_wrapper.pyx
4
+ include requirements.txt
5
+ include README.md
6
+ recursive-include rfpulses *
@@ -0,0 +1,344 @@
1
+ Metadata-Version: 2.4
2
+ Name: blochsimulator
3
+ Version: 1.0.0
4
+ Summary: High-performance Bloch equation simulator for MRI
5
+ Author: Luca Nagel
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/yourusername/bloch_simulator
8
+ Requires-Python: >=3.8
9
+ Description-Content-Type: text/markdown
10
+ Requires-Dist: numpy>=1.20.0
11
+ Requires-Dist: scipy>=1.7.0
12
+ Requires-Dist: matplotlib>=3.3.0
13
+ Requires-Dist: cython>=0.29.0
14
+ Requires-Dist: PyQt5>=5.15.0
15
+ Requires-Dist: pyqtgraph>=0.12.0
16
+ Requires-Dist: PyOpenGL>=3.1.0
17
+ Requires-Dist: imageio>=2.34.0
18
+ Requires-Dist: imageio-ffmpeg>=0.4.9
19
+ Requires-Dist: h5py>=3.0.0
20
+ Provides-Extra: dev
21
+ Requires-Dist: pytest; extra == "dev"
22
+ Requires-Dist: black; extra == "dev"
23
+ Requires-Dist: flake8; extra == "dev"
24
+ Provides-Extra: notebook
25
+ Requires-Dist: jupyterlab; extra == "notebook"
26
+
27
+ # Bloch Equation Simulator for Python
28
+
29
+ A high-performance Python implementation of the Bloch equation solver originally developed by Brian Hargreaves at Stanford University. This package provides a fast C-based core with Python bindings, parallel processing support, and an interactive GUI for MRI pulse sequence simulation.
30
+
31
+ ## Features
32
+
33
+ - **High Performance**: C implementation with Cython bindings maintains original speed
34
+ - **Parallel Processing**: OpenMP support for multi-core acceleration
35
+ - **Interactive GUI**: Real-time visualization and parameter adjustment
36
+ - **Flexible API**: Easy-to-use Python interface for scripting
37
+ - **Comprehensive**: Supports arbitrary RF pulses, gradient waveforms, and tissue parameters
38
+ - **Visualization**: 3D magnetization vectors, time evolution plots, frequency spectra, and **animation export**
39
+
40
+ ## Installation
41
+
42
+ ### Prerequisites
43
+
44
+ 1. **Python 3.7+**
45
+ 2. **C Compiler**:
46
+ - Linux: `gcc` (usually pre-installed)
47
+ - macOS: Xcode Command Line Tools (`xcode-select --install`)
48
+ - Windows: Visual Studio Build Tools
49
+ 3. **OpenMP** (optional but recommended):
50
+ - Linux: Included with gcc
51
+ - macOS: `brew install libomp`
52
+ - Windows: Included with Visual Studio
53
+
54
+ ### Quick Setup
55
+
56
+ ```bash
57
+ # Clone or download the repository
58
+ cd bloch_simulator
59
+
60
+ # Install dependencies
61
+ pip install -r requirements.txt
62
+
63
+ # Build the extension
64
+ python build.py
65
+
66
+ # Or manually:
67
+ python setup.py build_ext --inplace
68
+ ```
69
+
70
+ ### Verification
71
+
72
+ Test the installation:
73
+
74
+ ```python
75
+ from bloch_simulator import BlochSimulator, TissueParameters
76
+
77
+ sim = BlochSimulator()
78
+ tissue = TissueParameters.gray_matter(3.0)
79
+ print(f"T1: {tissue.t1:.3f}s, T2: {tissue.t2:.3f}s")
80
+ ```
81
+
82
+ ## Usage
83
+
84
+ ### 1. GUI Application
85
+
86
+ Launch the interactive GUI:
87
+
88
+ ```bash
89
+ python bloch_gui.py
90
+ ```
91
+
92
+ Features:
93
+ - Design RF pulses (rectangular, sinc, Gaussian)
94
+ - Configure tissue parameters (T1, T2, proton density)
95
+ - Select pulse sequences (spin echo, gradient echo, etc.)
96
+ - Real-time 3D magnetization visualization
97
+ - Signal analysis and frequency spectra
98
+
99
+ ### 2. Python API
100
+
101
+ #### Basic Simulation
102
+
103
+ ```python
104
+ import numpy as np
105
+ from bloch_simulator import BlochSimulator, TissueParameters
106
+
107
+ # Create simulator
108
+ sim = BlochSimulator(use_parallel=True, num_threads=4)
109
+
110
+ # Define tissue parameters
111
+ tissue = TissueParameters(
112
+ name="Gray Matter",
113
+ t1=1.33, # seconds
114
+ t2=0.083 # seconds
115
+ )
116
+
117
+ # Create a simple 90-degree pulse
118
+ ntime = 100
119
+ dt = 1e-5 # 10 microseconds
120
+ time = np.arange(ntime) * dt
121
+
122
+ b1 = np.zeros(ntime, dtype=complex)
123
+ b1[0] = 0.0235 # 90-degree hard pulse
124
+
125
+ gradients = np.zeros((ntime, 3)) # No gradients
126
+
127
+ # Run simulation
128
+ result = sim.simulate(
129
+ sequence=(b1, gradients, time),
130
+ tissue=tissue,
131
+ mode=2 # Time-resolved output
132
+ )
133
+
134
+ # Plot results
135
+ sim.plot_magnetization()
136
+ ```
137
+
138
+ #### Spin Echo Sequence
139
+
140
+ ```python
141
+ from bloch_simulator import BlochSimulator, SpinEcho, TissueParameters
142
+
143
+ sim = BlochSimulator()
144
+
145
+ # Create spin echo sequence
146
+ sequence = SpinEcho(te=20e-3, tr=500e-3) # 20ms TE, 500ms TR
147
+
148
+ # Simulate white matter
149
+ tissue = TissueParameters.white_matter(3.0)
150
+
151
+ # Run simulation with multiple frequencies (T2* effects)
152
+ frequencies = np.linspace(-50, 50, 11) # Hz
153
+ result = sim.simulate(sequence, tissue, frequencies=frequencies)
154
+
155
+ # Access magnetization components
156
+ mx, my, mz = result['mx'], result['my'], result['mz']
157
+ signal = result['signal']
158
+ ```
159
+
160
+ #### Custom Pulse Design
161
+
162
+ ```python
163
+ from bloch_simulator import design_rf_pulse
164
+
165
+ # Design a sinc pulse
166
+ b1, time = design_rf_pulse(
167
+ pulse_type='sinc',
168
+ duration=2e-3, # 2 ms
169
+ flip_angle=180, # degrees
170
+ time_bw_product=4, # Time-bandwidth product
171
+ npoints=200
172
+ )
173
+
174
+ # Apply phase
175
+ phase = np.pi/4 # 45 degrees
176
+ b1_phased = b1 * np.exp(1j * phase)
177
+ ```
178
+
179
+ #### Parallel Simulation
180
+
181
+ ```python
182
+ # Simulate multiple positions and frequencies in parallel
183
+ positions = np.random.randn(100, 3) * 0.01 # Random positions in 1cm cube
184
+ frequencies = np.linspace(-200, 200, 41) # 41 frequencies
185
+
186
+ result = sim.simulate(
187
+ sequence=sequence,
188
+ tissue=tissue,
189
+ positions=positions,
190
+ frequencies=frequencies,
191
+ mode=0 # Endpoint only (faster)
192
+ )
193
+
194
+ # Result shape: (100 positions, 41 frequencies)
195
+ print(f"Signal shape: {result['signal'].shape}")
196
+ ```
197
+
198
+ ### 3. Sequence Library
199
+
200
+ Pre-defined sequences are available:
201
+
202
+ ```python
203
+ from bloch_simulator import SpinEcho, GradientEcho
204
+
205
+ # Spin Echo
206
+ se = SpinEcho(te=30e-3, tr=1.0)
207
+
208
+ # Gradient Echo
209
+ gre = GradientEcho(te=5e-3, tr=10e-3, flip_angle=30)
210
+
211
+ # Compile to waveforms
212
+ b1, gradients, time = se.compile(dt=1e-6)
213
+ ```
214
+
215
+ ### 4. Tissue Parameter Library
216
+
217
+ Common tissues at different field strengths:
218
+
219
+ ```python
220
+ from bloch_simulator import TissueParameters
221
+
222
+ # 3T parameters
223
+ gm = TissueParameters.gray_matter(3.0)
224
+ wm = TissueParameters.white_matter(3.0)
225
+ csf = TissueParameters.csf(3.0)
226
+
227
+ # 7T parameters
228
+ gm_7t = TissueParameters.gray_matter(7.0)
229
+
230
+ # Custom tissue
231
+ liver = TissueParameters(
232
+ name="Liver",
233
+ t1=0.812,
234
+ t2=0.042,
235
+ t2_star=0.028,
236
+ density=0.9
237
+ )
238
+ ```
239
+
240
+ ## Desktop app build (PyInstaller)
241
+
242
+ One build per OS is required (macOS build won’t run on Windows/Linux).
243
+
244
+ ### Prereqs
245
+ - macOS: Xcode CLT; `brew install libomp`.
246
+ - Windows: Python 3.8+ and MSVC Build Tools (for C extension).
247
+ - Linux: gcc/g++; ensure `libgomp` available.
248
+
249
+ ### Quick build (any OS)
250
+ ```bash
251
+ python -m pip install -r requirements.txt
252
+ python -m pip install pyinstaller
253
+ python setup.py build_ext --inplace
254
+ PYINSTALLER_CONFIG_DIR=.pyinstaller pyinstaller bloch_gui.spec --noconfirm
255
+ ```
256
+ Artifact: `dist/BlochSimulator` (single binary; `.exe` on Windows).
257
+
258
+ ### One-liner helper
259
+ ```bash
260
+ ./scripts/build_pyinstaller.sh # creates a venv, installs deps, builds, packages
261
+ ```
262
+
263
+ ### Run the packaged app
264
+ - macOS/Linux: `./dist/BlochSimulator`
265
+ - Windows: `dist\\BlochSimulator.exe`
266
+
267
+ ### Runtime data/exports
268
+ - `rfpulses/` is bundled automatically.
269
+ - Exports default to per-user data dirs:
270
+ - macOS: `~/Library/Application Support/BlochSimulator/exports`
271
+ - Windows: `%APPDATA%\\BlochSimulator\\exports`
272
+ - Linux: `~/.local/share/BlochSimulator/exports`
273
+ - Override with `BLOCH_APP_DIR` or `BLOCH_EXPORT_DIR` if you need a custom location.
274
+
275
+ ## Theory
276
+
277
+ The simulator solves the Bloch equations:
278
+
279
+ ```
280
+ dM/dt = γ(M × B) - [Mx/T2, My/T2, (Mz-M0)/T1]
281
+ ```
282
+
283
+ Using:
284
+ - Rotation matrices for RF and gradient effects
285
+ - Exponential decay for relaxation
286
+ - Cayley-Klein parameters for efficient rotation calculation
287
+
288
+ ## Troubleshooting
289
+
290
+ ### Build Issues
291
+
292
+ 1. **Missing compiler**: Install gcc (Linux), Xcode (macOS), or Visual Studio (Windows)
293
+ 2. **OpenMP not found**: The code will still work but without parallelization
294
+ 3. **Import error**: Ensure the .so/.pyd file is in the same directory
295
+
296
+ ## Contributing
297
+
298
+ Contributions are welcome! Please:
299
+ 1. Fork the repository
300
+ 2. Create a feature branch
301
+ 3. Add tests for new features
302
+ 4. Submit a pull request
303
+
304
+ ## Citation
305
+
306
+ If you use this simulator in your research, please cite:
307
+
308
+ ```bibtex
309
+ @software{bloch_simulator_python,
310
+ title={Python Bloch Equation Simulator GUI and API},
311
+ author={Luca Nagel},
312
+ year={2025},
313
+ url={https://github.com/LucaNagel/bloch_sim_gui}
314
+ }
315
+ ```
316
+
317
+ ## Acknowledgments
318
+
319
+ This project is based on [code](http://mrsrl.stanford.edu/~brian/blochsim/) originally developed by Brian Hargreaves at Stanford University. Currently (11/2025) it is unfortunately not available. A python adaption of this code can be found [here](https://github.com/ZhengguoTan/BlochSim).
320
+
321
+ - Original Bloch simulator by Brian Hargreaves, Stanford University
322
+ - NumPy and SciPy communities
323
+ - PyQt/PySide developers
324
+ - OpenMP project
325
+ - Built partially with [codex](https://openai.com/codex/), [claude code](https://claude.ai/) and [gemini cli](https://github.com/google-gemini/gemini-cli)
326
+
327
+ ## Contact
328
+
329
+ Luca Nagel
330
+
331
+ ## Appendix: File Structure
332
+
333
+ ```
334
+ bloch_simulator/
335
+ ├── bloch_core_modified.c # C implementation (from original)
336
+ ├── bloch_core.h # C header file
337
+ ├── bloch_wrapper.pyx # Cython wrapper
338
+ ├── setup.py # Build configuration
339
+ ├── build.py # Build script
340
+ ├── bloch_simulator.py # Python API
341
+ ├── bloch_gui.py # GUI application
342
+ ├── requirements.txt # Dependencies
343
+ └── README.md # This file
344
+ ```
@@ -0,0 +1,318 @@
1
+ # Bloch Equation Simulator for Python
2
+
3
+ A high-performance Python implementation of the Bloch equation solver originally developed by Brian Hargreaves at Stanford University. This package provides a fast C-based core with Python bindings, parallel processing support, and an interactive GUI for MRI pulse sequence simulation.
4
+
5
+ ## Features
6
+
7
+ - **High Performance**: C implementation with Cython bindings maintains original speed
8
+ - **Parallel Processing**: OpenMP support for multi-core acceleration
9
+ - **Interactive GUI**: Real-time visualization and parameter adjustment
10
+ - **Flexible API**: Easy-to-use Python interface for scripting
11
+ - **Comprehensive**: Supports arbitrary RF pulses, gradient waveforms, and tissue parameters
12
+ - **Visualization**: 3D magnetization vectors, time evolution plots, frequency spectra, and **animation export**
13
+
14
+ ## Installation
15
+
16
+ ### Prerequisites
17
+
18
+ 1. **Python 3.7+**
19
+ 2. **C Compiler**:
20
+ - Linux: `gcc` (usually pre-installed)
21
+ - macOS: Xcode Command Line Tools (`xcode-select --install`)
22
+ - Windows: Visual Studio Build Tools
23
+ 3. **OpenMP** (optional but recommended):
24
+ - Linux: Included with gcc
25
+ - macOS: `brew install libomp`
26
+ - Windows: Included with Visual Studio
27
+
28
+ ### Quick Setup
29
+
30
+ ```bash
31
+ # Clone or download the repository
32
+ cd bloch_simulator
33
+
34
+ # Install dependencies
35
+ pip install -r requirements.txt
36
+
37
+ # Build the extension
38
+ python build.py
39
+
40
+ # Or manually:
41
+ python setup.py build_ext --inplace
42
+ ```
43
+
44
+ ### Verification
45
+
46
+ Test the installation:
47
+
48
+ ```python
49
+ from bloch_simulator import BlochSimulator, TissueParameters
50
+
51
+ sim = BlochSimulator()
52
+ tissue = TissueParameters.gray_matter(3.0)
53
+ print(f"T1: {tissue.t1:.3f}s, T2: {tissue.t2:.3f}s")
54
+ ```
55
+
56
+ ## Usage
57
+
58
+ ### 1. GUI Application
59
+
60
+ Launch the interactive GUI:
61
+
62
+ ```bash
63
+ python bloch_gui.py
64
+ ```
65
+
66
+ Features:
67
+ - Design RF pulses (rectangular, sinc, Gaussian)
68
+ - Configure tissue parameters (T1, T2, proton density)
69
+ - Select pulse sequences (spin echo, gradient echo, etc.)
70
+ - Real-time 3D magnetization visualization
71
+ - Signal analysis and frequency spectra
72
+
73
+ ### 2. Python API
74
+
75
+ #### Basic Simulation
76
+
77
+ ```python
78
+ import numpy as np
79
+ from bloch_simulator import BlochSimulator, TissueParameters
80
+
81
+ # Create simulator
82
+ sim = BlochSimulator(use_parallel=True, num_threads=4)
83
+
84
+ # Define tissue parameters
85
+ tissue = TissueParameters(
86
+ name="Gray Matter",
87
+ t1=1.33, # seconds
88
+ t2=0.083 # seconds
89
+ )
90
+
91
+ # Create a simple 90-degree pulse
92
+ ntime = 100
93
+ dt = 1e-5 # 10 microseconds
94
+ time = np.arange(ntime) * dt
95
+
96
+ b1 = np.zeros(ntime, dtype=complex)
97
+ b1[0] = 0.0235 # 90-degree hard pulse
98
+
99
+ gradients = np.zeros((ntime, 3)) # No gradients
100
+
101
+ # Run simulation
102
+ result = sim.simulate(
103
+ sequence=(b1, gradients, time),
104
+ tissue=tissue,
105
+ mode=2 # Time-resolved output
106
+ )
107
+
108
+ # Plot results
109
+ sim.plot_magnetization()
110
+ ```
111
+
112
+ #### Spin Echo Sequence
113
+
114
+ ```python
115
+ from bloch_simulator import BlochSimulator, SpinEcho, TissueParameters
116
+
117
+ sim = BlochSimulator()
118
+
119
+ # Create spin echo sequence
120
+ sequence = SpinEcho(te=20e-3, tr=500e-3) # 20ms TE, 500ms TR
121
+
122
+ # Simulate white matter
123
+ tissue = TissueParameters.white_matter(3.0)
124
+
125
+ # Run simulation with multiple frequencies (T2* effects)
126
+ frequencies = np.linspace(-50, 50, 11) # Hz
127
+ result = sim.simulate(sequence, tissue, frequencies=frequencies)
128
+
129
+ # Access magnetization components
130
+ mx, my, mz = result['mx'], result['my'], result['mz']
131
+ signal = result['signal']
132
+ ```
133
+
134
+ #### Custom Pulse Design
135
+
136
+ ```python
137
+ from bloch_simulator import design_rf_pulse
138
+
139
+ # Design a sinc pulse
140
+ b1, time = design_rf_pulse(
141
+ pulse_type='sinc',
142
+ duration=2e-3, # 2 ms
143
+ flip_angle=180, # degrees
144
+ time_bw_product=4, # Time-bandwidth product
145
+ npoints=200
146
+ )
147
+
148
+ # Apply phase
149
+ phase = np.pi/4 # 45 degrees
150
+ b1_phased = b1 * np.exp(1j * phase)
151
+ ```
152
+
153
+ #### Parallel Simulation
154
+
155
+ ```python
156
+ # Simulate multiple positions and frequencies in parallel
157
+ positions = np.random.randn(100, 3) * 0.01 # Random positions in 1cm cube
158
+ frequencies = np.linspace(-200, 200, 41) # 41 frequencies
159
+
160
+ result = sim.simulate(
161
+ sequence=sequence,
162
+ tissue=tissue,
163
+ positions=positions,
164
+ frequencies=frequencies,
165
+ mode=0 # Endpoint only (faster)
166
+ )
167
+
168
+ # Result shape: (100 positions, 41 frequencies)
169
+ print(f"Signal shape: {result['signal'].shape}")
170
+ ```
171
+
172
+ ### 3. Sequence Library
173
+
174
+ Pre-defined sequences are available:
175
+
176
+ ```python
177
+ from bloch_simulator import SpinEcho, GradientEcho
178
+
179
+ # Spin Echo
180
+ se = SpinEcho(te=30e-3, tr=1.0)
181
+
182
+ # Gradient Echo
183
+ gre = GradientEcho(te=5e-3, tr=10e-3, flip_angle=30)
184
+
185
+ # Compile to waveforms
186
+ b1, gradients, time = se.compile(dt=1e-6)
187
+ ```
188
+
189
+ ### 4. Tissue Parameter Library
190
+
191
+ Common tissues at different field strengths:
192
+
193
+ ```python
194
+ from bloch_simulator import TissueParameters
195
+
196
+ # 3T parameters
197
+ gm = TissueParameters.gray_matter(3.0)
198
+ wm = TissueParameters.white_matter(3.0)
199
+ csf = TissueParameters.csf(3.0)
200
+
201
+ # 7T parameters
202
+ gm_7t = TissueParameters.gray_matter(7.0)
203
+
204
+ # Custom tissue
205
+ liver = TissueParameters(
206
+ name="Liver",
207
+ t1=0.812,
208
+ t2=0.042,
209
+ t2_star=0.028,
210
+ density=0.9
211
+ )
212
+ ```
213
+
214
+ ## Desktop app build (PyInstaller)
215
+
216
+ One build per OS is required (macOS build won’t run on Windows/Linux).
217
+
218
+ ### Prereqs
219
+ - macOS: Xcode CLT; `brew install libomp`.
220
+ - Windows: Python 3.8+ and MSVC Build Tools (for C extension).
221
+ - Linux: gcc/g++; ensure `libgomp` available.
222
+
223
+ ### Quick build (any OS)
224
+ ```bash
225
+ python -m pip install -r requirements.txt
226
+ python -m pip install pyinstaller
227
+ python setup.py build_ext --inplace
228
+ PYINSTALLER_CONFIG_DIR=.pyinstaller pyinstaller bloch_gui.spec --noconfirm
229
+ ```
230
+ Artifact: `dist/BlochSimulator` (single binary; `.exe` on Windows).
231
+
232
+ ### One-liner helper
233
+ ```bash
234
+ ./scripts/build_pyinstaller.sh # creates a venv, installs deps, builds, packages
235
+ ```
236
+
237
+ ### Run the packaged app
238
+ - macOS/Linux: `./dist/BlochSimulator`
239
+ - Windows: `dist\\BlochSimulator.exe`
240
+
241
+ ### Runtime data/exports
242
+ - `rfpulses/` is bundled automatically.
243
+ - Exports default to per-user data dirs:
244
+ - macOS: `~/Library/Application Support/BlochSimulator/exports`
245
+ - Windows: `%APPDATA%\\BlochSimulator\\exports`
246
+ - Linux: `~/.local/share/BlochSimulator/exports`
247
+ - Override with `BLOCH_APP_DIR` or `BLOCH_EXPORT_DIR` if you need a custom location.
248
+
249
+ ## Theory
250
+
251
+ The simulator solves the Bloch equations:
252
+
253
+ ```
254
+ dM/dt = γ(M × B) - [Mx/T2, My/T2, (Mz-M0)/T1]
255
+ ```
256
+
257
+ Using:
258
+ - Rotation matrices for RF and gradient effects
259
+ - Exponential decay for relaxation
260
+ - Cayley-Klein parameters for efficient rotation calculation
261
+
262
+ ## Troubleshooting
263
+
264
+ ### Build Issues
265
+
266
+ 1. **Missing compiler**: Install gcc (Linux), Xcode (macOS), or Visual Studio (Windows)
267
+ 2. **OpenMP not found**: The code will still work but without parallelization
268
+ 3. **Import error**: Ensure the .so/.pyd file is in the same directory
269
+
270
+ ## Contributing
271
+
272
+ Contributions are welcome! Please:
273
+ 1. Fork the repository
274
+ 2. Create a feature branch
275
+ 3. Add tests for new features
276
+ 4. Submit a pull request
277
+
278
+ ## Citation
279
+
280
+ If you use this simulator in your research, please cite:
281
+
282
+ ```bibtex
283
+ @software{bloch_simulator_python,
284
+ title={Python Bloch Equation Simulator GUI and API},
285
+ author={Luca Nagel},
286
+ year={2025},
287
+ url={https://github.com/LucaNagel/bloch_sim_gui}
288
+ }
289
+ ```
290
+
291
+ ## Acknowledgments
292
+
293
+ This project is based on [code](http://mrsrl.stanford.edu/~brian/blochsim/) originally developed by Brian Hargreaves at Stanford University. Currently (11/2025) it is unfortunately not available. A python adaption of this code can be found [here](https://github.com/ZhengguoTan/BlochSim).
294
+
295
+ - Original Bloch simulator by Brian Hargreaves, Stanford University
296
+ - NumPy and SciPy communities
297
+ - PyQt/PySide developers
298
+ - OpenMP project
299
+ - Built partially with [codex](https://openai.com/codex/), [claude code](https://claude.ai/) and [gemini cli](https://github.com/google-gemini/gemini-cli)
300
+
301
+ ## Contact
302
+
303
+ Luca Nagel
304
+
305
+ ## Appendix: File Structure
306
+
307
+ ```
308
+ bloch_simulator/
309
+ ├── bloch_core_modified.c # C implementation (from original)
310
+ ├── bloch_core.h # C header file
311
+ ├── bloch_wrapper.pyx # Cython wrapper
312
+ ├── setup.py # Build configuration
313
+ ├── build.py # Build script
314
+ ├── bloch_simulator.py # Python API
315
+ ├── bloch_gui.py # GUI application
316
+ ├── requirements.txt # Dependencies
317
+ └── README.md # This file
318
+ ```
@@ -0,0 +1,36 @@
1
+ [build-system]
2
+ requires = ["setuptools>=42", "wheel", "Cython>=0.29", "numpy>=1.20"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "blochsimulator"
7
+ version = "1.0.0"
8
+ description = "High-performance Bloch equation simulator for MRI"
9
+ readme = "README.md"
10
+ requires-python = ">=3.8"
11
+ license = {text = "MIT"}
12
+ authors = [
13
+ {name = "Luca Nagel"}
14
+ ]
15
+ dependencies = [
16
+ "numpy>=1.20.0",
17
+ "scipy>=1.7.0",
18
+ "matplotlib>=3.3.0",
19
+ "cython>=0.29.0",
20
+ "PyQt5>=5.15.0",
21
+ "pyqtgraph>=0.12.0",
22
+ "PyOpenGL>=3.1.0",
23
+ "imageio>=2.34.0",
24
+ "imageio-ffmpeg>=0.4.9",
25
+ "h5py>=3.0.0",
26
+ ]
27
+
28
+ [project.optional-dependencies]
29
+ dev = ["pytest", "black", "flake8"]
30
+ notebook = ["jupyterlab"]
31
+
32
+ [project.scripts]
33
+ bloch-gui = "bloch_simulator.gui:main"
34
+
35
+ [project.urls]
36
+ Homepage = "https://github.com/yourusername/bloch_simulator"