MRArbGrad 3.1.0__tar.gz → 4.1.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 (42) hide show
  1. {mrarbgrad-3.1.0 → mrarbgrad-4.1.0/MRArbGrad.egg-info}/PKG-INFO +2 -2
  2. {mrarbgrad-3.1.0/MRArbGrad.egg-info → mrarbgrad-4.1.0}/PKG-INFO +2 -2
  3. {mrarbgrad-3.1.0 → mrarbgrad-4.1.0}/README.md +1 -1
  4. {mrarbgrad-3.1.0 → mrarbgrad-4.1.0}/mrarbgrad_src/Function.py +29 -8
  5. {mrarbgrad-3.1.0 → mrarbgrad-4.1.0}/mrarbgrad_src/__init__.py +1 -1
  6. {mrarbgrad-3.1.0 → mrarbgrad-4.1.0}/mrarbgrad_src/ext/main.cpp +47 -13
  7. {mrarbgrad-3.1.0 → mrarbgrad-4.1.0}/mrarbgrad_src/ext/traj/MrTraj.h +1 -1
  8. {mrarbgrad-3.1.0 → mrarbgrad-4.1.0}/mrarbgrad_src/ext/traj/Shell3d.h +6 -6
  9. {mrarbgrad-3.1.0 → mrarbgrad-4.1.0}/mrarbgrad_src/ext/traj/VDSpiral.h +13 -11
  10. {mrarbgrad-3.1.0 → mrarbgrad-4.1.0}/mrarbgrad_src/ext/traj/Yarnball.h +25 -19
  11. {mrarbgrad-3.1.0 → mrarbgrad-4.1.0}/mrarbgrad_src/ext/utility/global.h +5 -2
  12. {mrarbgrad-3.1.0 → mrarbgrad-4.1.0}/mrarbgrad_src/ext/utility/v3.cpp +78 -1
  13. mrarbgrad-4.1.0/mrarbgrad_src/ext/utility/v3.h +72 -0
  14. {mrarbgrad-3.1.0 → mrarbgrad-4.1.0}/pyproject.toml +1 -1
  15. mrarbgrad-3.1.0/mrarbgrad_src/ext/utility/v3.h +0 -156
  16. {mrarbgrad-3.1.0 → mrarbgrad-4.1.0}/LICENSE +0 -0
  17. {mrarbgrad-3.1.0 → mrarbgrad-4.1.0}/MANIFEST.in +0 -0
  18. {mrarbgrad-3.1.0 → mrarbgrad-4.1.0}/MRArbGrad.egg-info/SOURCES.txt +0 -0
  19. {mrarbgrad-3.1.0 → mrarbgrad-4.1.0}/MRArbGrad.egg-info/dependency_links.txt +0 -0
  20. {mrarbgrad-3.1.0 → mrarbgrad-4.1.0}/MRArbGrad.egg-info/requires.txt +0 -0
  21. {mrarbgrad-3.1.0 → mrarbgrad-4.1.0}/MRArbGrad.egg-info/top_level.txt +0 -0
  22. {mrarbgrad-3.1.0 → mrarbgrad-4.1.0}/example/example_BuiltInTraj.py +0 -0
  23. {mrarbgrad-3.1.0 → mrarbgrad-4.1.0}/example/example_ExternalFunction2D.py +0 -0
  24. {mrarbgrad-3.1.0 → mrarbgrad-4.1.0}/example/example_ExternalSamples2D.py +0 -0
  25. {mrarbgrad-3.1.0 → mrarbgrad-4.1.0}/example/example_ExternalSamples3D.py +0 -0
  26. {mrarbgrad-3.1.0 → mrarbgrad-4.1.0}/mrarbgrad_src/Utility.py +0 -0
  27. {mrarbgrad-3.1.0 → mrarbgrad-4.1.0}/mrarbgrad_src/ext/mag/Mag.cpp +0 -0
  28. {mrarbgrad-3.1.0 → mrarbgrad-4.1.0}/mrarbgrad_src/ext/mag/Mag.h +0 -0
  29. {mrarbgrad-3.1.0 → mrarbgrad-4.1.0}/mrarbgrad_src/ext/traj/Cones.h +0 -0
  30. {mrarbgrad-3.1.0 → mrarbgrad-4.1.0}/mrarbgrad_src/ext/traj/MrTraj_2D.h +0 -0
  31. {mrarbgrad-3.1.0 → mrarbgrad-4.1.0}/mrarbgrad_src/ext/traj/Rosette.h +0 -0
  32. {mrarbgrad-3.1.0 → mrarbgrad-4.1.0}/mrarbgrad_src/ext/traj/Seiffert.h +0 -0
  33. {mrarbgrad-3.1.0 → mrarbgrad-4.1.0}/mrarbgrad_src/ext/traj/Spiral.h +0 -0
  34. {mrarbgrad-3.1.0 → mrarbgrad-4.1.0}/mrarbgrad_src/ext/traj/TrajFunc.h +0 -0
  35. {mrarbgrad-3.1.0 → mrarbgrad-4.1.0}/mrarbgrad_src/ext/utility/Intp.h +0 -0
  36. {mrarbgrad-3.1.0 → mrarbgrad-4.1.0}/mrarbgrad_src/ext/utility/LinIntp.h +0 -0
  37. {mrarbgrad-3.1.0 → mrarbgrad-4.1.0}/mrarbgrad_src/ext/utility/SplineIntp.h +0 -0
  38. {mrarbgrad-3.1.0 → mrarbgrad-4.1.0}/mrarbgrad_src/ext/utility/global.cpp +0 -0
  39. {mrarbgrad-3.1.0 → mrarbgrad-4.1.0}/mrarbgrad_src/trajfunc/__init__.py +0 -0
  40. {mrarbgrad-3.1.0 → mrarbgrad-4.1.0}/mrarbgrad_src/trajfunc/main.py +0 -0
  41. {mrarbgrad-3.1.0 → mrarbgrad-4.1.0}/setup.cfg +0 -0
  42. {mrarbgrad-3.1.0 → mrarbgrad-4.1.0}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: MRArbGrad
3
- Version: 3.1.0
3
+ Version: 4.1.0
4
4
  Summary: Gradient waveform design tool for arbitrary k-space trajectories.
5
5
  Author-email: Ryan <ryan_shanghaitech@proton.me>
6
6
  License-Expression: MIT
@@ -41,7 +41,7 @@ You can also install via `pip install .` but remember to delete `*.egg-info` or
41
41
  ## Examples & Usages
42
42
  Examples for generating gradient waveforms for either built-in trajectory (trajectory library) or external trajectory (expressed by trajectory function or trajectory samples) can be found in the `example` folder.
43
43
 
44
- ## Citation
44
+ ## Reference
45
45
  If this project helps you, please cite [our paper](https://ieeexplore.ieee.org/document/11352950):
46
46
 
47
47
  [1] Luo R, Huang H, Miao Q, Xu J, Hu P, Qi H. Real-Time Gradient Waveform Design for Arbitrary k-Space Trajectories. IEEE Transactions on Biomedical Engineering. 2026;1–12.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: MRArbGrad
3
- Version: 3.1.0
3
+ Version: 4.1.0
4
4
  Summary: Gradient waveform design tool for arbitrary k-space trajectories.
5
5
  Author-email: Ryan <ryan_shanghaitech@proton.me>
6
6
  License-Expression: MIT
@@ -41,7 +41,7 @@ You can also install via `pip install .` but remember to delete `*.egg-info` or
41
41
  ## Examples & Usages
42
42
  Examples for generating gradient waveforms for either built-in trajectory (trajectory library) or external trajectory (expressed by trajectory function or trajectory samples) can be found in the `example` folder.
43
43
 
44
- ## Citation
44
+ ## Reference
45
45
  If this project helps you, please cite [our paper](https://ieeexplore.ieee.org/document/11352950):
46
46
 
47
47
  [1] Luo R, Huang H, Miao Q, Xu J, Hu P, Qi H. Real-Time Gradient Waveform Design for Arbitrary k-Space Trajectories. IEEE Transactions on Biomedical Engineering. 2026;1–12.
@@ -27,7 +27,7 @@ You can also install via `pip install .` but remember to delete `*.egg-info` or
27
27
  ## Examples & Usages
28
28
  Examples for generating gradient waveforms for either built-in trajectory (trajectory library) or external trajectory (expressed by trajectory function or trajectory samples) can be found in the `example` folder.
29
29
 
30
- ## Citation
30
+ ## Reference
31
31
  If this project helps you, please cite [our paper](https://ieeexplore.ieee.org/document/11352950):
32
32
 
33
33
  [1] Luo R, Huang H, Miao Q, Xu J, Hu P, Qi H. Real-Time Gradient Waveform Design for Arbitrary k-Space Trajectories. IEEE Transactions on Biomedical Engineering. 2026;1–12.
@@ -142,7 +142,6 @@ def getG_VDSpiral_RT\
142
142
 
143
143
  kRhoPhi0: float64 = 0.5 / (8 * pi),
144
144
  kRhoPhi1: float64 = 0.5 / (2 * pi),
145
- nAcq: int64 = 128,
146
145
  ) -> tuple[list[NDArray], list[NDArray]]:
147
146
  '''
148
147
  :return: list of trajectory start, list of gradient waveforms
@@ -158,9 +157,7 @@ def getG_VDSpiral_RT\
158
157
  float64(dt),
159
158
 
160
159
  float64(kRhoPhi0),
161
- float64(kRhoPhi1),
162
-
163
- int64(nAcq)
160
+ float64(kRhoPhi1)
164
161
  )
165
162
 
166
163
  def getG_Rosette\
@@ -294,8 +291,7 @@ def getG_Yarnball_RT\
294
291
  gLim: float64 = 50e-3 * 42.5756e6 * 0.256 / 256,
295
292
  dt: float64 = 10e-6,
296
293
 
297
- kRhoPhi: float64 = 0.5 / (2 * pi),
298
- nAcq: int64 = 16384,
294
+ kRhoPhi: float64 = 0.5 / (2 * pi)
299
295
  ) -> tuple[list[NDArray], list[NDArray]]:
300
296
  '''
301
297
  :return: list of trajectory start, list of gradient waveforms
@@ -310,8 +306,7 @@ def getG_Yarnball_RT\
310
306
  float64(gLim),
311
307
  float64(dt),
312
308
 
313
- float64(kRhoPhi),
314
- int64(nAcq),
309
+ float64(kRhoPhi)
315
310
  )
316
311
 
317
312
  def getG_Seiffert\
@@ -381,3 +376,29 @@ def setMagSFS(x): ext.setMagSFS(x)
381
376
  def setMagGradRep(x): ext.setMagGradRep(x)
382
377
  def setMagTrajRep(x): ext.setMagTrajRep(x)
383
378
  def setDbgPrint(x): ext.setDbgPrint(x)
379
+
380
+ def loadF64(hdr:str, bin:str) -> list[NDArray]:
381
+ """
382
+ load saved vector file (float64)
383
+
384
+ Args:
385
+ hdr (str): header (hdr) file path
386
+ bin (str): bin file path
387
+
388
+ Returns:
389
+ list[NDArray]: list of loaded array
390
+ """
391
+ return ext.loadF64(str(hdr), str(bin))
392
+
393
+ def loadF32(hdr:str, bin:str) -> list[NDArray]:
394
+ """
395
+ load saved vector file (float32)
396
+
397
+ Args:
398
+ hdr (str): header (hdr) file path
399
+ bin (str): bin file path
400
+
401
+ Returns:
402
+ list[NDArray]: list of loaded array
403
+ """
404
+ return ext.loadF32(str(hdr), str(bin))
@@ -1,6 +1,6 @@
1
1
  from .Function import calGrad4ExFunc, calGrad4ExSamp
2
2
  from .Function import getG_Cones, getG_Rosette, getG_Rosette_Trad, getG_Seiffert, getG_Shell3d, getG_Spiral, getG_VDSpiral, getG_VDSpiral_RT, getG_Yarnball, getG_Yarnball_RT
3
- from .Function import setSolverMtg, setTrajRev, setGoldAng, setShuf, setMaxG0, setMaxG1, setMagOverSamp, setMagSFS, setMagGradRep, setMagTrajRep, setDbgPrint
3
+ from .Function import setSolverMtg, setTrajRev, setGoldAng, setShuf, setMaxG0, setMaxG1, setMagOverSamp, setMagSFS, setMagGradRep, setMagTrajRep, setDbgPrint, loadF64, loadF32
4
4
  from .Utility import _calDiaphony, rotate, _calJacElip, _calCompElipInt, _calSphFibPt, cvtGrad2Traj, getGoldang, getGoldrat, rand3d, gradClip
5
5
 
6
6
  from . import trajfunc
@@ -137,7 +137,7 @@ bool inline checkNarg(i64 nArg, i64 nArgExp)
137
137
  {
138
138
  if (nArg != nArgExp)
139
139
  {
140
- printf("wrong num. of arg, narg=%ld, %ld expected\n", nArg, nArgExp);
140
+ printf("wrong num. of arg, narg=%ld, %ld expected\n", (long)nArg, (long)nArgExp);
141
141
  abort();
142
142
  return false;
143
143
  }
@@ -389,7 +389,7 @@ bool getG(MrTraj* pmt, vv3* pvv3M0PE, vvv3* pvvv3GRO)
389
389
  pvvv3GRO->resize(nAcq);
390
390
 
391
391
  bool& enShuf = gMain_enShuffle;
392
- vi64 vi64ShufSeq; MrTraj::genRandIdx(&vi64ShufSeq, nAcq);
392
+ vi64 vi64ShufSeq; MrTraj::genPermTab(&vi64ShufSeq, nAcq);
393
393
  for (i64 i = 0; i < nAcq; ++i)
394
394
  {
395
395
  i64 _i = enShuf?vi64ShufSeq[i]:i;
@@ -451,7 +451,7 @@ PyObject* getG_VDSpiral(PyObject* self, PyObject* const* args, Py_ssize_t narg)
451
451
 
452
452
  PyObject* getG_VDSpiral_RT(PyObject* self, PyObject* const* args, Py_ssize_t narg)
453
453
  {
454
- checkNarg(narg, 8);
454
+ checkNarg(narg, 7);
455
455
 
456
456
  MrTraj::GeoPara objGeoPara;
457
457
  MrTraj::GradPara objGradPara;
@@ -459,8 +459,7 @@ PyObject* getG_VDSpiral_RT(PyObject* self, PyObject* const* args, Py_ssize_t nar
459
459
 
460
460
  f64 kRhoPhi0 = (f64)PyFloat_AsDouble(args[5]);
461
461
  f64 kRhoPhi1 = (f64)PyFloat_AsDouble(args[6]);
462
- i64 nAcq = (i64)PyLong_AsLong(args[7]);
463
- VDSpiral_RT traj(objGeoPara, objGradPara, kRhoPhi0, kRhoPhi1, nAcq);
462
+ VDSpiral_RT traj(objGeoPara, objGradPara, kRhoPhi0, kRhoPhi1);
464
463
 
465
464
  vv3 vv3K0;
466
465
  vvv3 vvv3G;
@@ -555,15 +554,14 @@ PyObject* getG_Yarnball(PyObject* self, PyObject* const* args, Py_ssize_t narg)
555
554
 
556
555
  PyObject* getG_Yarnball_RT(PyObject* self, PyObject* const* args, Py_ssize_t narg)
557
556
  {
558
- checkNarg(narg, 7);
557
+ checkNarg(narg, 6);
559
558
 
560
559
  MrTraj::GeoPara objGeoPara;
561
560
  MrTraj::GradPara objGradPara;
562
561
  getGeoGradPara(args, &objGeoPara, &objGradPara);
563
562
 
564
563
  f64 kRhoPhi = (f64)PyFloat_AsDouble(args[5]);
565
- i64 nAcq = (i64)PyLong_AsLong(args[6]);
566
- Yarnball_RT traj(objGeoPara, objGradPara, kRhoPhi, nAcq);
564
+ Yarnball_RT traj(objGeoPara, objGradPara, kRhoPhi);
567
565
 
568
566
  vv3 vv3K0;
569
567
  vvv3 vvv3G;
@@ -709,11 +707,46 @@ PyObject* setDbgPrint(PyObject* self, PyObject* const* args, Py_ssize_t narg)
709
707
  return Py_None;
710
708
  }
711
709
 
712
- vv3 vv3Test;
713
- PyObject* getTestVal(PyObject* self, PyObject* const* args, Py_ssize_t narg)
710
+ PyObject* loadF64(PyObject* self, PyObject* const* args, Py_ssize_t narg)
714
711
  {
715
- checkNarg(narg, 0);
716
- return Py_BuildValue("O", cvtVv3toNpa(vv3Test));
712
+ checkNarg(narg, 2);
713
+ const char* strHdr = PyUnicode_AsUTF8(args[0]);
714
+ const char* strBin = PyUnicode_AsUTF8(args[1]);
715
+ typedef std::list<vv3> lvv3;
716
+ FILE* fHdr = fopen(strHdr, "r");
717
+ FILE* fBin = fopen(strHdr, "rb");
718
+
719
+ lvv3 lvv3Data;
720
+ bool ret; vv3 vv3Data;
721
+ while (1)
722
+ {
723
+ ret = v3::loadF64(fHdr, fBin, &vv3Data);
724
+ if (vv3Data.empty() || !ret) break;
725
+ lvv3Data.push_back(vv3Data);
726
+ }
727
+ vvv3 vvv3Data(lvv3Data.begin(), lvv3Data.end());
728
+ Py_BuildValue("%O", cvtVvv3toList(vvv3Data));
729
+ }
730
+
731
+ PyObject* loadF32(PyObject* self, PyObject* const* args, Py_ssize_t narg)
732
+ {
733
+ checkNarg(narg, 2);
734
+ const char* strHdr = PyUnicode_AsUTF8(args[0]);
735
+ const char* strBin = PyUnicode_AsUTF8(args[1]);
736
+ typedef std::list<vv3> lvv3;
737
+ FILE* fHdr = fopen(strHdr, "r");
738
+ FILE* fBin = fopen(strHdr, "rb");
739
+
740
+ lvv3 lvv3Data;
741
+ bool ret; vv3 vv3Data;
742
+ while (1)
743
+ {
744
+ ret = v3::loadF32(fHdr, fBin, &vv3Data);
745
+ if (vv3Data.empty() || !ret) break;
746
+ lvv3Data.push_back(vv3Data);
747
+ }
748
+ vvv3 vvv3Data(lvv3Data.begin(), lvv3Data.end());
749
+ Py_BuildValue("%O", cvtVvv3toList(vvv3Data));
717
750
  }
718
751
 
719
752
  static PyMethodDef aMeth[] =
@@ -736,12 +769,13 @@ static PyMethodDef aMeth[] =
736
769
  {"setShuf", (PyCFunction)setShuf, METH_FASTCALL, ""},
737
770
  {"setMaxG0", (PyCFunction)setMaxG0, METH_FASTCALL, ""},
738
771
  {"setMaxG1", (PyCFunction)setMaxG1, METH_FASTCALL, ""},
739
- {"getTestVal", (PyCFunction)getTestVal, METH_FASTCALL, ""},
740
772
  {"setMagOverSamp", (PyCFunction)setMagOverSamp, METH_FASTCALL, ""},
741
773
  {"setMagSFS", (PyCFunction)setMagSFS, METH_FASTCALL, ""},
742
774
  {"setMagGradRep", (PyCFunction)setMagGradRep, METH_FASTCALL, ""},
743
775
  {"setMagTrajRep", (PyCFunction)setMagTrajRep, METH_FASTCALL, ""},
744
776
  {"setDbgPrint", (PyCFunction)setDbgPrint, METH_FASTCALL, ""},
777
+ {"loadF64", (PyCFunction)loadF64, METH_FASTCALL, ""},
778
+ {"loadF32", (PyCFunction)loadF32, METH_FASTCALL, ""},
745
779
  {NULL, NULL, 0, NULL} /* Sentinel */
746
780
  };
747
781
 
@@ -95,7 +95,7 @@ public:
95
95
  }
96
96
 
97
97
  // a deterministic shuffle sequence generator
98
- static bool genRandIdx(vi64* pvi64Idx, i64 len)
98
+ static bool genPermTab(vi64* pvi64Idx, i64 len)
99
99
  {
100
100
  // resize target container rationally
101
101
  pvi64Idx->clear();
@@ -80,18 +80,18 @@ public:
80
80
  {
81
81
  bool ret = true;
82
82
  const f64& rotang = m_rotang;
83
- i64 iSet = iAcq%m_nRot;
84
- i64 iRot = iAcq/m_nRot;
83
+ i64 iPhi = iAcq%m_nRot;
84
+ i64 iTht = iAcq/m_nRot%m_nRot;
85
85
 
86
86
  if (pv3M0PE)
87
87
  {
88
- *pv3M0PE = m_vv3BaseM0PE[iSet];
89
- ret &= v3::rotate(pv3M0PE, 2, rotang * iRot, *pv3M0PE);
88
+ *pv3M0PE = m_vv3BaseM0PE[iTht];
89
+ ret &= v3::rotate(pv3M0PE, 2, rotang*iPhi, *pv3M0PE);
90
90
  }
91
91
  if (pvv3GRO)
92
92
  {
93
- *pvv3GRO = m_vvv3BaseGRO[iSet];
94
- ret &= v3::rotate(pvv3GRO, 2, rotang * iRot, *pvv3GRO);
93
+ *pvv3GRO = m_vvv3BaseGRO[iTht];
94
+ ret &= v3::rotate(pvv3GRO, 2, rotang*iPhi, *pvv3GRO);
95
95
  }
96
96
 
97
97
  return ret;
@@ -70,21 +70,21 @@ class VDSpiral_RT: public MrTraj
70
70
  {
71
71
  // TODO: Goldang sampling is incomplete, shuffled sampling is incomplete.
72
72
  public:
73
- VDSpiral_RT(const GeoPara& objGeoPara, const GradPara& objGradPara, f64 kRhoPhi0, f64 kRhoPhi1, i64 nAcq):
73
+ VDSpiral_RT(const GeoPara& objGeoPara, const GradPara& objGradPara, f64 kRhoPhi0, f64 kRhoPhi1):
74
74
  /*
75
75
  * nAcq: Num of Acq, used to preallocate an array to store PE M0
76
76
  */
77
- MrTraj(objGeoPara,objGradPara,nAcq,0)
77
+ MrTraj(objGeoPara,objGradPara,0,0)
78
78
  {
79
79
  m_kRhoPhi0 = kRhoPhi0;
80
80
  m_kRhoPhi1 = kRhoPhi1;
81
- m_nRot = calNRot(kRhoPhi1, objGeoPara.nPix);
82
- m_dRotAng = 2e0*M_PI/m_nRot;
83
- genRandIdx(&m_vi64Idx, m_nRot);
81
+ m_nAcq = calNRot(kRhoPhi1, objGeoPara.nPix);
82
+ m_dRotAng = 2e0*M_PI/m_nAcq;
83
+ genPermTab(&m_vi64PermTab, m_nAcq);
84
84
 
85
85
  VDSpiral_TrajFunc tf(m_kRhoPhi0, m_kRhoPhi1, 0);
86
86
  vv3 vv3GRO; calGrad(NULL, &vv3GRO, NULL, tf, m_objGradPara, 4);
87
- m_nSampMax = vv3GRO.size();
87
+ m_nSampMax = vv3GRO.size() + 0;
88
88
  }
89
89
 
90
90
  virtual ~VDSpiral_RT()
@@ -93,15 +93,17 @@ public:
93
93
  virtual bool getGrad(v3* pv3M0PE, vv3* pvv3GRO, i64 iAcq)
94
94
  {
95
95
  bool ret = true;
96
- VDSpiral_TrajFunc tf(m_kRhoPhi0, m_kRhoPhi1, m_vi64Idx[iAcq]*m_dRotAng);
97
- ASSERT(iAcq < m_nAcq);
98
- ret &= calGrad(pv3M0PE, pvv3GRO, NULL, tf, m_objGradPara, 4);
96
+ ASSERT(iAcq >= 0);
97
+ i64 iPhi = m_vi64PermTab[iAcq%m_nAcq];
98
+ f64 phi = iPhi*m_dRotAng;
99
+ VDSpiral_TrajFunc tf(m_kRhoPhi0, m_kRhoPhi1, phi);
100
+ ret &= calGrad(pv3M0PE, pvv3GRO, NULL, tf, m_objGradPara, 2);
99
101
  return ret;
100
102
  }
101
103
 
102
104
  protected:
103
105
  f64 m_kRhoPhi0;
104
106
  f64 m_kRhoPhi1;
105
- i64 m_nRot; f64 m_dRotAng;
106
- vi64 m_vi64Idx;
107
+ f64 m_dRotAng;
108
+ vi64 m_vi64PermTab;
107
109
  };
@@ -80,14 +80,20 @@ public:
80
80
  {
81
81
  bool ret = true;
82
82
  const f64& rotang = m_rotang;
83
- i64 iSet = iAcq%m_nRot;
84
- i64 iRot = iAcq/m_nRot;
83
+ i64 iPhi = iAcq%m_nRot;
84
+ i64 iTht = iAcq/m_nRot%m_nRot;
85
+
86
+ if (pv3M0PE)
87
+ {
88
+ *pv3M0PE = m_vv3BaseM0PE[iTht];
89
+ ret &= v3::rotate(pv3M0PE, 2, rotang*iPhi, *pv3M0PE);
90
+ }
91
+ if (pvv3GRO)
92
+ {
93
+ *pvv3GRO = m_vvv3BaseGRO[iTht];
94
+ ret &= v3::rotate(pvv3GRO, 2, rotang*iPhi, *pvv3GRO);
95
+ }
85
96
 
86
- *pv3M0PE = m_vv3BaseM0PE[iSet];
87
- *pvv3GRO = m_vvv3BaseGRO[iSet];
88
- ret &= v3::rotate(pv3M0PE, 2, rotang*iRot, *pv3M0PE);
89
- ret &= v3::rotate(pvv3GRO, 2, rotang*iRot, *pvv3GRO);
90
-
91
97
  return ret;
92
98
  }
93
99
 
@@ -100,21 +106,21 @@ protected:
100
106
  vvv3 m_vvv3BaseGRO;
101
107
  };
102
108
 
103
- /* incomplete - we plan to test 2D real-time first before 3D */
104
109
  class Yarnball_RT: public MrTraj
105
110
  {
106
111
  public:
107
- Yarnball_RT(const GeoPara& objGeoPara, const GradPara& objGradPara, f64 kRhoPhi, i64 nAcq):
108
- MrTraj(objGeoPara, objGradPara, nAcq, 0)
112
+ Yarnball_RT(const GeoPara& objGeoPara, const GradPara& objGradPara, f64 kRhoPhi):
113
+ MrTraj(objGeoPara,objGradPara,0,0)
109
114
  {
110
115
  m_kRhoPhi = kRhoPhi;
111
116
  m_nRot = calNRot(kRhoPhi, objGeoPara.nPix);
112
117
  m_dRotAng = 2e0*M_PI/m_nRot;
113
- genRandIdx(&m_vi64Idx, m_nRot);
118
+ m_nAcq = m_nRot*m_nRot;
119
+ genPermTab(&m_vi64PermTab, m_nAcq);
114
120
 
115
121
  Yarnball_TrajFunc tf(m_kRhoPhi, M_PI/2e0, 0);
116
122
  vv3 vv3GRO; calGrad(NULL, &vv3GRO, NULL, tf, m_objGradPara, 4);
117
- m_nSampMax = vv3GRO.size();
123
+ m_nSampMax = vv3GRO.size() + 1; // 1 for redundance
118
124
  }
119
125
 
120
126
  virtual ~Yarnball_RT()
@@ -123,18 +129,18 @@ public:
123
129
  virtual bool getGrad(v3* pv3M0PE, vv3* pvv3GRO, i64 iAcq)
124
130
  {
125
131
  bool ret = true;
126
- i64 iTht = iAcq%m_nRot;
127
- i64 iPhi = iAcq/m_nRot;
128
- f64 tht = m_dRotAng*m_vi64Idx[iTht];
129
- f64 phi = m_dRotAng*m_vi64Idx[iPhi];
132
+ ASSERT(iAcq >= 0);
133
+ i64 iPhi = m_vi64PermTab[iAcq%m_nAcq]%m_nRot;
134
+ i64 iTht = m_vi64PermTab[iAcq%m_nAcq]/m_nRot;
135
+ f64 phi = m_dRotAng*iPhi;
136
+ f64 tht = m_dRotAng*iTht;
130
137
  Yarnball_TrajFunc tf(m_kRhoPhi, tht, phi);
131
- ASSERT(iAcq<m_nAcq);
132
- ret &= calGrad(pv3M0PE, pvv3GRO, NULL, tf, m_objGradPara, 4);
138
+ ret &= calGrad(pv3M0PE, pvv3GRO, NULL, tf, m_objGradPara, 2);
133
139
  return ret;
134
140
  }
135
141
 
136
142
  protected:
137
143
  f64 m_kRhoPhi;
138
144
  i64 m_nRot; f64 m_dRotAng;
139
- vi64 m_vi64Idx;
145
+ vi64 m_vi64PermTab;
140
146
  };
@@ -24,6 +24,10 @@ typedef std::vector<i64> vi64;
24
24
  typedef std::vector<f64> vf64;
25
25
  typedef std::list<i64> li64;
26
26
  typedef std::list<f64> lf64;
27
+ typedef std::vector<i32> vi32;
28
+ typedef std::vector<f32> vf32;
29
+ typedef std::list<i32> li32;
30
+ typedef std::list<f32> lf32;
27
31
 
28
32
  typedef std::string str;
29
33
 
@@ -49,7 +53,7 @@ inline T gcd(T x, T y)
49
53
  #define GOLDRAT (1.6180339887498949e0) // ((1e0+std::sqrt(5e0))/2e0)
50
54
  #define GOLDANG (2.3999632297286531e0) // ((3e0-std::sqrt(5e0))*M_PI)
51
55
 
52
- #define PRINT(X) {printf("%s: %ld\n", #X, (i64)(X));}
56
+ #define PRINT(X) {printf("%s: %ld\n", #X, (long)(X));}
53
57
  #define PRINT_F(X) {printf("%s: %.3lf\n", #X, (f64)(X));}
54
58
  #define PRINT_E(X) {printf("%s: %.3e\n", #X, (f64)(X));}
55
59
  #define ASSERT(X) {if(!(X)) throw std::runtime_error(#X);}
@@ -62,4 +66,3 @@ inline T gcd(T x, T y)
62
66
  if (glob_enDbgPrint) printf("Elapsed time: %.3lf ms\n", 1e3*cTick/CLOCKS_PER_SEC);
63
67
 
64
68
  extern bool glob_enDbgPrint;
65
-
@@ -1,5 +1,6 @@
1
1
  #include "v3.h"
2
2
  #include <array>
3
+ #include <cinttypes>
3
4
 
4
5
  v3::v3() :x(0e0), y(0e0), z(0e0) {}
5
6
  v3::v3(f64 _) :x(_), y(_), z(_) {}
@@ -362,4 +363,80 @@ v3 v3::axisroll(const v3& v3In, i64 nShift)
362
363
  break;
363
364
  }
364
365
  return v3Ot;
365
- }
366
+ }
367
+
368
+ bool v3::saveF64(FILE* pfHdr, FILE* pfBin, const vv3& vv3Data)
369
+ {
370
+ bool ret = true;
371
+ i64 lenData = vv3Data.size();
372
+ fprintf(pfHdr, "float64[%ld][3];\n", (long)lenData);
373
+
374
+ f64* bufFile = new f64[lenData*3];
375
+ for(i64 i=0; i<(i64)lenData; ++i)
376
+ {
377
+ for(i64 j=0; j<3; ++j)
378
+ { bufFile[3*i+j] = (f64)vv3Data[i][j]; }
379
+ }
380
+ ret &= (i64)fwrite(bufFile, sizeof(f64), lenData*3, pfBin)==lenData*3;
381
+ delete[] bufFile;
382
+ return ret;
383
+ }
384
+
385
+ bool v3::loadF64(FILE* pfHdr, FILE* pfBin, vv3* pvv3Data)
386
+ {
387
+ bool ret = true;
388
+ i64 lenData = 0;
389
+ pvv3Data->clear();
390
+ int nRead = fscanf(pfHdr, "float64[%" SCNi64 "][3];\n", &lenData);
391
+ if (nRead==EOF) return true; // EOF
392
+ else if (nRead!=1) return false;
393
+ pvv3Data->resize(lenData);
394
+
395
+ f64* bufFile = new f64[lenData*3];
396
+ ret &= (i64)fread(bufFile, sizeof(f64), lenData*3, pfBin)==lenData*3;
397
+ for(i64 i=0; i<(i64)pvv3Data->size(); ++i)
398
+ {
399
+ for(i64 j=0; j<3; ++j)
400
+ { (*pvv3Data)[i][j] = (f64)bufFile[3*i+j]; }
401
+ }
402
+ delete[] bufFile;
403
+ return ret;
404
+ }
405
+
406
+ bool v3::saveF32(FILE* pfHdr, FILE* pfBin, const vv3& vv3Data)
407
+ {
408
+ bool ret = true;
409
+ i64 lenData = vv3Data.size();
410
+ fprintf(pfHdr, "float32[%ld][3];\n", (long)lenData);
411
+
412
+ f32* bufFile = new f32[lenData*3];
413
+ for(i64 i=0; i<(i64)lenData; ++i)
414
+ {
415
+ for(i64 j=0; j<3; ++j)
416
+ { bufFile[3*i+j] = (f32)vv3Data[i][j]; }
417
+ }
418
+ ret &= (i64)fwrite(bufFile, sizeof(f32), lenData*3, pfBin)==lenData*3;
419
+ delete[] bufFile;
420
+ return ret;
421
+ }
422
+
423
+ bool v3::loadF32(FILE* pfHdr, FILE* pfBin, vv3* pvv3Data)
424
+ {
425
+ bool ret = true;
426
+ i64 lenData = 0;
427
+ pvv3Data->clear();
428
+ int nRead = fscanf(pfHdr, "float32[%" SCNi64 "][3];\n", &lenData);
429
+ if (nRead==EOF) return true; // EOF
430
+ else if (nRead!=1) return false;
431
+ pvv3Data->resize(lenData);
432
+
433
+ f32* bufFile = new f32[lenData*3];
434
+ ret &= (i64)fread(bufFile, sizeof(f32), lenData*3, pfBin)==lenData*3;
435
+ for(i64 i=0; i<(i64)pvv3Data->size(); ++i)
436
+ {
437
+ for(i64 j=0; j<3; ++j)
438
+ { (*pvv3Data)[i][j] = (f64)bufFile[3*i+j]; }
439
+ }
440
+ delete[] bufFile;
441
+ return ret;
442
+ }
@@ -0,0 +1,72 @@
1
+ #pragma once
2
+
3
+ #include <cmath>
4
+ #include <list>
5
+ #include <array>
6
+ #include "global.h"
7
+
8
+ class v3;
9
+
10
+ typedef std::vector<v3> vv3;
11
+ typedef std::vector<vv3> vvv3;
12
+ typedef std::list<v3> lv3;
13
+
14
+ class v3
15
+ {
16
+ public:
17
+ f64 x, y, z;
18
+
19
+ v3();
20
+ v3(f64 _);
21
+ v3(f64 x, f64 y, f64 z);
22
+ ~v3();
23
+ v3 operator+(const v3 &rhs) const;
24
+ v3& operator+=(const v3 &rhs);
25
+ v3 operator+(const f64 &rhs) const;
26
+ v3& operator+=(const f64 &rhs);
27
+ v3 operator-(const v3 &rhs) const;
28
+ v3& operator-=(const v3 &rhs);
29
+ v3 operator-(const f64 &rhs) const;
30
+ v3& operator-=(const f64 &rhs);
31
+ v3 operator*(const v3 &rhs) const;
32
+ v3& operator*=(const v3 &rhs);
33
+ v3 operator*(const f64 &rhs) const;
34
+ v3& operator*=(const f64 &rhs);
35
+ v3 operator/(const v3 &rhs) const;
36
+ v3& operator/=(const v3 &rhs);
37
+ v3 operator/(const f64 &rhs) const;
38
+ v3& operator/=(const f64 &rhs);
39
+ bool operator==(const v3 &rhs) const;
40
+ bool operator!=(const v3 &rhs) const;
41
+ f64& operator[](i64 idx);
42
+ f64 operator[](i64 idx) const;
43
+ static f64 norm(const v3& v3In);
44
+ static v3 cross(const v3& v3In0, const v3& v3In1);
45
+ static f64 inner(const v3& v3In0, const v3& v3In1);
46
+ static v3 pow(const v3& v3In, f64 exp);
47
+ static bool rotate
48
+ (
49
+ v3* pv3Dst,
50
+ int iAx, f64 ang,
51
+ const v3& v3Src
52
+ );
53
+ static bool rotate
54
+ (
55
+ vv3* pvv3Dst,
56
+ int iAx, f64 ang,
57
+ const vv3& vv3Src
58
+ );
59
+ static bool rotate
60
+ (
61
+ lv3* plv3Dst,
62
+ int iAx, f64 ang,
63
+ const lv3& lv3Src
64
+ );
65
+ static v3 axisroll(const v3& v3In, i64 lShift);
66
+ static bool saveF64(FILE* pfHdr, FILE* pfBin, const vv3& vv3Data);
67
+ static bool loadF64(FILE* pfHdr, FILE* pfBin, vv3* pvv3Data);
68
+ static bool saveF32(FILE* pfHdr, FILE* pfBin, const vv3& vv3Data);
69
+ static bool loadF32(FILE* pfHdr, FILE* pfBin, vv3* pvv3Data);
70
+ private:
71
+ static bool genRotMat(std::array<v3,3>* pav3RotMat, int iAx, f64 ang);
72
+ };
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "MRArbGrad"
7
- version = "3.1.0"
7
+ version = "4.1.0"
8
8
  dependencies = ["numpy"]
9
9
 
10
10
  description = "Gradient waveform design tool for arbitrary k-space trajectories."
@@ -1,156 +0,0 @@
1
- #pragma once
2
-
3
- #include <cmath>
4
- #include <list>
5
- #include <array>
6
- #include "global.h"
7
-
8
- class v3;
9
-
10
- typedef std::vector<v3> vv3;
11
- typedef std::vector<vv3> vvv3;
12
- typedef std::list<v3> lv3;
13
-
14
- class v3
15
- {
16
- public:
17
- f64 x, y, z;
18
-
19
- v3();
20
- v3(f64 _);
21
- v3(f64 x, f64 y, f64 z);
22
- ~v3();
23
- v3 operator+(const v3 &rhs) const;
24
- v3& operator+=(const v3 &rhs);
25
- v3 operator+(const f64 &rhs) const;
26
- v3& operator+=(const f64 &rhs);
27
- v3 operator-(const v3 &rhs) const;
28
- v3& operator-=(const v3 &rhs);
29
- v3 operator-(const f64 &rhs) const;
30
- v3& operator-=(const f64 &rhs);
31
- v3 operator*(const v3 &rhs) const;
32
- v3& operator*=(const v3 &rhs);
33
- v3 operator*(const f64 &rhs) const;
34
- v3& operator*=(const f64 &rhs);
35
- v3 operator/(const v3 &rhs) const;
36
- v3& operator/=(const v3 &rhs);
37
- v3 operator/(const f64 &rhs) const;
38
- v3& operator/=(const f64 &rhs);
39
- bool operator==(const v3 &rhs) const;
40
- bool operator!=(const v3 &rhs) const;
41
- f64& operator[](i64 idx);
42
- f64 operator[](i64 idx) const;
43
- static f64 norm(const v3& v3In);
44
- static v3 cross(const v3& v3In0, const v3& v3In1);
45
- static f64 inner(const v3& v3In0, const v3& v3In1);
46
- static v3 pow(const v3& v3In, f64 exp);
47
- static bool rotate
48
- (
49
- v3* pv3Dst,
50
- int iAx, f64 ang,
51
- const v3& v3Src
52
- );
53
- static bool rotate
54
- (
55
- vv3* pvv3Dst,
56
- int iAx, f64 ang,
57
- const vv3& vv3Src
58
- );
59
- static bool rotate
60
- (
61
- lv3* plv3Dst,
62
- int iAx, f64 ang,
63
- const lv3& lv3Src
64
- );
65
- static v3 axisroll(const v3& v3In, i64 lShift);
66
- template<typename cv3>
67
- static bool saveF64(FILE* pfBHdr, FILE* pfBin, const cv3& cv3Data);
68
- template<typename cv3>
69
- static bool loadF64(FILE* pfBHdr, FILE* pfBin, cv3* pcv3Data);
70
- template<typename cv3>
71
- static bool saveF32(FILE* pfBHdr, FILE* pfBin, const cv3& cv3Data);
72
- template<typename cv3>
73
- static bool loadF32(FILE* pfBHdr, FILE* pfBin, cv3* pcv3Data);
74
- private:
75
- static bool genRotMat(std::array<v3,3>* pav3RotMat, int iAx, f64 ang);
76
- };
77
-
78
- template<typename cv3>
79
- bool v3::saveF64(FILE* pfBHdr, FILE* pfBin, const cv3& cv3Data)
80
- {
81
- bool ret = true;
82
- fprintf(pfBHdr, "float64[%ld][3];\n", (i64)cv3Data.size());
83
- typename cv3::const_iterator icv3Data = cv3Data.begin();
84
- while (icv3Data!=cv3Data.end())
85
- {
86
- ret &= (fwrite(&icv3Data->x, sizeof(f64), 1, pfBin) == 1);
87
- ret &= (fwrite(&icv3Data->y, sizeof(f64), 1, pfBin) == 1);
88
- ret &= (fwrite(&icv3Data->z, sizeof(f64), 1, pfBin) == 1);
89
- ++icv3Data;
90
- }
91
- return ret;
92
- }
93
-
94
- template<typename cv3>
95
- bool v3::loadF64(FILE* pfBHdr, FILE* pfBin, cv3* pcv3Data)
96
- {
97
- bool ret = true;
98
- i64 lenData = 0;
99
- int nByte = fscanf(pfBHdr, "float64[%ld][3];\n", &lenData);
100
- if (nByte!=1) ret = false;
101
- pcv3Data->resize(lenData);
102
- typename cv3::iterator icv3Data = pcv3Data->begin();
103
- while (icv3Data!=pcv3Data->end())
104
- {
105
- ret &= (fread(&icv3Data->x, sizeof(f64), 1, pfBin) == 1);
106
- ret &= (fread(&icv3Data->y, sizeof(f64), 1, pfBin) == 1);
107
- ret &= (fread(&icv3Data->z, sizeof(f64), 1, pfBin) == 1);
108
- ++icv3Data;
109
- }
110
- return ret;
111
- }
112
-
113
- template<typename cv3>
114
- bool v3::saveF32(FILE* pfBHdr, FILE* pfBin, const cv3& cv3Data)
115
- {
116
- bool ret = true;
117
- fprintf(pfBHdr, "float32[%ld][3];\n", (i64)cv3Data.size());
118
- typename cv3::const_iterator icv3Data = cv3Data.begin();
119
- float f32X, f32Y, f32Z;
120
- while (icv3Data!=cv3Data.end())
121
- {
122
- f32X = (float)icv3Data->x;
123
- f32Y = (float)icv3Data->y;
124
- f32Z = (float)icv3Data->z;
125
- ret &= (fwrite(&f32X, sizeof(float), 1, pfBin) == 1);
126
- ret &= (fwrite(&f32Y, sizeof(float), 1, pfBin) == 1);
127
- ret &= (fwrite(&f32Z, sizeof(float), 1, pfBin) == 1);
128
- ++icv3Data;
129
- }
130
- return ret;
131
- }
132
-
133
- template<typename cv3>
134
- bool v3::loadF32(FILE* pfBHdr, FILE* pfBin, cv3* pcv3Data)
135
- {
136
- bool ret = true;
137
- i64 lenData = 0;
138
- int nByte = fscanf(pfBHdr, "float32[%ld][3];\n", &lenData);
139
- if (nByte!=1) ret = false;
140
- pcv3Data->resize(lenData);
141
- typename cv3::iterator icv3Data = pcv3Data->begin();
142
- float f32X, f32Y, f32Z;
143
- while (icv3Data!=pcv3Data->end())
144
- {
145
- ret &= (fread(&f32X, sizeof(float), 1, pfBin) == 1);
146
- ret &= (fread(&f32Y, sizeof(float), 1, pfBin) == 1);
147
- ret &= (fread(&f32Z, sizeof(float), 1, pfBin) == 1);
148
-
149
- icv3Data->x = (f64)f32X;
150
- icv3Data->y = (f64)f32Y;
151
- icv3Data->z = (f64)f32Z;
152
-
153
- ++icv3Data;
154
- }
155
- return ret;
156
- }
File without changes
File without changes
File without changes
File without changes