From a67cf777de8198d1af5ed58f1395352e651f5ba0 Mon Sep 17 00:00:00 2001 From: alineyyy Date: Thu, 30 Jan 2025 14:00:30 +0100 Subject: [PATCH 01/15] FIX:add config in MRD-header --- src/cli-conf/scenario2-2d.yaml | 93 ++++++++++++++ src/cli-conf/scenario2.yaml | 11 +- .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 177 bytes src/snake/__pycache__/_meta.cpython-310.pyc | Bin 0 -> 5884 bytes .../__pycache__/_version.cpython-310.pyc | Bin 0 -> 489 bytes .../core/__pycache__/__init__.cpython-310.pyc | Bin 0 -> 770 bytes .../core/__pycache__/parallel.cpython-310.pyc | Bin 0 -> 3753 bytes .../__pycache__/simulation.cpython-310.pyc | Bin 0 -> 4943 bytes .../core/__pycache__/smaps.cpython-310.pyc | Bin 0 -> 2489 bytes .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 396 bytes .../engine/__pycache__/base.cpython-310.pyc | Bin 0 -> 9031 bytes .../__pycache__/cartesian.cpython-310.pyc | Bin 0 -> 8845 bytes .../engine/__pycache__/nufft.cpython-310.pyc | Bin 0 -> 4706 bytes .../engine/__pycache__/utils.cpython-310.pyc | Bin 0 -> 2808 bytes src/snake/core/engine/base.py | 2 +- .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 508 bytes .../handlers/__pycache__/base.cpython-310.pyc | Bin 0 -> 3986 bytes .../__pycache__/noise.cpython-310.pyc | Bin 0 -> 2075 bytes .../__pycache__/utils.cpython-310.pyc | Bin 0 -> 712 bytes .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 445 bytes .../__pycache__/activations.cpython-310.pyc | Bin 0 -> 5550 bytes .../__pycache__/bold.cpython-310.pyc | Bin 0 -> 3954 bytes .../__pycache__/roi.cpython-310.pyc | Bin 0 -> 1098 bytes .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 287 bytes .../motion/__pycache__/image.cpython-310.pyc | Bin 0 -> 3220 bytes .../motion/__pycache__/utils.cpython-310.pyc | Bin 0 -> 5191 bytes .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 371 bytes .../__pycache__/dynamic.cpython-310.pyc | Bin 0 -> 1953 bytes .../__pycache__/static.cpython-310.pyc | Bin 0 -> 9118 bytes .../phantom/__pycache__/utils.cpython-310.pyc | Bin 0 -> 595 bytes .../data/__pycache__/__init__.cpython-310.pyc | Bin 0 -> 225 bytes .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 491 bytes .../sampling/__pycache__/base.cpython-310.pyc | Bin 0 -> 2146 bytes .../__pycache__/factories.cpython-310.pyc | Bin 0 -> 12568 bytes .../__pycache__/samplers.cpython-310.pyc | Bin 0 -> 13833 bytes .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 605 bytes .../__pycache__/loader.cpython-310.pyc | Bin 0 -> 13905 bytes .../__pycache__/utils.cpython-310.pyc | Bin 0 -> 3658 bytes .../__pycache__/writer.cpython-310.pyc | Bin 0 -> 7521 bytes src/snake/mrd_utils/writer.py | 13 +- .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 189 bytes .../__pycache__/stats.cpython-310.pyc | Bin 0 -> 3743 bytes .../cli/__pycache__/__init__.cpython-310.pyc | Bin 0 -> 209 bytes .../__pycache__/acquisition.cpython-310.pyc | Bin 0 -> 2533 bytes .../cli/__pycache__/config.cpython-310.pyc | Bin 0 -> 4340 bytes .../reconstruction.cpython-310.pyc | Bin 0 -> 3223 bytes src/snake/toolkit/cli/acquisition.py | 41 +++++-- src/snake/toolkit/cli/config.py | 2 +- src/snake/toolkit/cli/reconstruction.py | 2 +- .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 420 bytes .../__pycache__/base.cpython-310.pyc | Bin 0 -> 2400 bytes .../__pycache__/fourier.cpython-310.pyc | Bin 0 -> 1196 bytes .../__pycache__/pysap.cpython-310.pyc | Bin 0 -> 9806 bytes src/snake_fmri.egg-info/PKG-INFO | 113 ++++++++++++++++++ src/snake_fmri.egg-info/SOURCES.txt | 100 ++++++++++++++++ src/snake_fmri.egg-info/dependency_links.txt | 1 + src/snake_fmri.egg-info/entry_points.txt | 4 + src/snake_fmri.egg-info/requires.txt | 35 ++++++ src/snake_fmri.egg-info/top_level.txt | 2 + 59 files changed, 391 insertions(+), 28 deletions(-) create mode 100644 src/cli-conf/scenario2-2d.yaml create mode 100644 src/snake/__pycache__/__init__.cpython-310.pyc create mode 100644 src/snake/__pycache__/_meta.cpython-310.pyc create mode 100644 src/snake/__pycache__/_version.cpython-310.pyc create mode 100644 src/snake/core/__pycache__/__init__.cpython-310.pyc create mode 100644 src/snake/core/__pycache__/parallel.cpython-310.pyc create mode 100644 src/snake/core/__pycache__/simulation.cpython-310.pyc create mode 100644 src/snake/core/__pycache__/smaps.cpython-310.pyc create mode 100644 src/snake/core/engine/__pycache__/__init__.cpython-310.pyc create mode 100644 src/snake/core/engine/__pycache__/base.cpython-310.pyc create mode 100644 src/snake/core/engine/__pycache__/cartesian.cpython-310.pyc create mode 100644 src/snake/core/engine/__pycache__/nufft.cpython-310.pyc create mode 100644 src/snake/core/engine/__pycache__/utils.cpython-310.pyc create mode 100644 src/snake/core/handlers/__pycache__/__init__.cpython-310.pyc create mode 100644 src/snake/core/handlers/__pycache__/base.cpython-310.pyc create mode 100644 src/snake/core/handlers/__pycache__/noise.cpython-310.pyc create mode 100644 src/snake/core/handlers/__pycache__/utils.cpython-310.pyc create mode 100644 src/snake/core/handlers/activations/__pycache__/__init__.cpython-310.pyc create mode 100644 src/snake/core/handlers/activations/__pycache__/activations.cpython-310.pyc create mode 100644 src/snake/core/handlers/activations/__pycache__/bold.cpython-310.pyc create mode 100644 src/snake/core/handlers/activations/__pycache__/roi.cpython-310.pyc create mode 100644 src/snake/core/handlers/motion/__pycache__/__init__.cpython-310.pyc create mode 100644 src/snake/core/handlers/motion/__pycache__/image.cpython-310.pyc create mode 100644 src/snake/core/handlers/motion/__pycache__/utils.cpython-310.pyc create mode 100644 src/snake/core/phantom/__pycache__/__init__.cpython-310.pyc create mode 100644 src/snake/core/phantom/__pycache__/dynamic.cpython-310.pyc create mode 100644 src/snake/core/phantom/__pycache__/static.cpython-310.pyc create mode 100644 src/snake/core/phantom/__pycache__/utils.cpython-310.pyc create mode 100644 src/snake/core/phantom/data/__pycache__/__init__.cpython-310.pyc create mode 100644 src/snake/core/sampling/__pycache__/__init__.cpython-310.pyc create mode 100644 src/snake/core/sampling/__pycache__/base.cpython-310.pyc create mode 100644 src/snake/core/sampling/__pycache__/factories.cpython-310.pyc create mode 100644 src/snake/core/sampling/__pycache__/samplers.cpython-310.pyc create mode 100644 src/snake/mrd_utils/__pycache__/__init__.cpython-310.pyc create mode 100644 src/snake/mrd_utils/__pycache__/loader.cpython-310.pyc create mode 100644 src/snake/mrd_utils/__pycache__/utils.cpython-310.pyc create mode 100644 src/snake/mrd_utils/__pycache__/writer.cpython-310.pyc create mode 100644 src/snake/toolkit/__pycache__/__init__.cpython-310.pyc create mode 100644 src/snake/toolkit/analysis/__pycache__/stats.cpython-310.pyc create mode 100644 src/snake/toolkit/cli/__pycache__/__init__.cpython-310.pyc create mode 100644 src/snake/toolkit/cli/__pycache__/acquisition.cpython-310.pyc create mode 100644 src/snake/toolkit/cli/__pycache__/config.cpython-310.pyc create mode 100644 src/snake/toolkit/cli/__pycache__/reconstruction.cpython-310.pyc create mode 100644 src/snake/toolkit/reconstructors/__pycache__/__init__.cpython-310.pyc create mode 100644 src/snake/toolkit/reconstructors/__pycache__/base.cpython-310.pyc create mode 100644 src/snake/toolkit/reconstructors/__pycache__/fourier.cpython-310.pyc create mode 100644 src/snake/toolkit/reconstructors/__pycache__/pysap.cpython-310.pyc create mode 100644 src/snake_fmri.egg-info/PKG-INFO create mode 100644 src/snake_fmri.egg-info/SOURCES.txt create mode 100644 src/snake_fmri.egg-info/dependency_links.txt create mode 100644 src/snake_fmri.egg-info/entry_points.txt create mode 100644 src/snake_fmri.egg-info/requires.txt create mode 100644 src/snake_fmri.egg-info/top_level.txt diff --git a/src/cli-conf/scenario2-2d.yaml b/src/cli-conf/scenario2-2d.yaml new file mode 100644 index 00000000..23f721db --- /dev/null +++ b/src/cli-conf/scenario2-2d.yaml @@ -0,0 +1,93 @@ +# This files contains the configuration to reproduce the scenario 1 of the Snkf paper. + +defaults: + - base_config + - handlers: + - activation-block + - sampler: + - stack-of-spiral + - reconstructors: + - adjoint + #- sequential + - _self_ + +cache_dir: ${oc.env:PWD}/cache +result_dir: results/scenario2 +filename: ${cache_dir}/scenario2_2d_${engine.model}_${engine.snr}_${sampler.stack-of-spiral.constant}_${sampler.stack-of-spiral.accelz}.mrd + +sim_conf: + max_sim_time: 360 + seq: {TR: 50, TE: 25, FA: 12} + hardware: + n_coils: 1 + dwell_time_ms: 0.001 + shape: [60, 72, 60] + fov_mm: [181.0, 217.0, 181.0] + +phantom: + name: brainweb + sub_id: 4 + tissue_file: "tissue_7T" + +handlers: + activation-block: + event_name: block_on + block_on: 20 # seconds + block_off: 20 #seconds + duration: 360 # seconds + #delta_r2s: 1000 # millisecond^-1 + +sampler: + stack-of-spiral: + acsz: 1 + accelz: 1 + nb_revolutions: 10 + constant: true + spiral_name: "galilean" + +engine: + n_jobs: 1 + chunk_size: 10 + model: "simple" + snr: 10000 + nufft_backend: "gpuNUFFT" + slice_2d: true + +reconstructors: + adjoint: + nufft_backend: "gpuNUFFT" + density_compensation: "pipe" + # sequential: + # nufft_backend: "gpuNUFFT" + # density_compensation: false + # restart_strategy: WARM + # max_iter_per_frame: 50 + # wavelet: "sym4" + + + + + +hydra: + job: + chdir: true + + run: + dir: ${result_dir}/outputs/${hydra.job.name}/${now:%Y-%m-%d_%H-%M-%S} + sweep: + dir: ${result_dir}/multirun/${hydra.job.name}/${now:%Y-%m-%d_%H-%M-%S} + subdir: ${hydra.job.num} + + callbacks: + # gather_files: + # _target_: hydra_callbacks.MultiRunGatherer + # aggregator: + # _partial_: true + # _target_: snkf.cli.utils.aggregate_results + + log_job: + _target_: hydra.experimental.callbacks.LogJobReturnCallback + latest_run: + _target_: hydra_callbacks.LatestRunLink + run_base_dir: ${result_dir}/outputs + multirun_base_dir: ${result_dir}/multirun diff --git a/src/cli-conf/scenario2.yaml b/src/cli-conf/scenario2.yaml index aff266d7..59386cf8 100644 --- a/src/cli-conf/scenario2.yaml +++ b/src/cli-conf/scenario2.yaml @@ -52,16 +52,7 @@ engine: nufft_backend: "stacked-gpunufft" reconstructors: # adjoint: - # nufft_backend: "stacked-gpunufft" - # density_compensation: "pipe" - sequential: - nufft_backend: "stacked-gpunufft" - density_compensation: false - restart_strategy: WARM - max_iter_per_frame: 50 - wavelet: "sym4" - - + # nufft_backend: "stacked-gpunufft"/snake-fmri diff --git a/src/snake/__pycache__/__init__.cpython-310.pyc b/src/snake/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..148adfaaec6cfdf9aa5e564b39880d465fa17b1c GIT binary patch literal 177 zcmd1j<>g`kf_}f*>7qdTF^Gc<7=auIATH(r5-AK(3@MDk44O<;e8GN>-mVG(iOJcC z>8W~tnvA#D2iJ5ts`o$%gxurmnRQ=+- t#OzevwA><~U{NxJs~;Z^R8$fluUAlci^C>2KczG$)ehu{Vvv~}3;?-oE8hSB literal 0 HcmV?d00001 diff --git a/src/snake/__pycache__/_meta.cpython-310.pyc b/src/snake/__pycache__/_meta.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b96441792f3a67bce7cc0b85f35bb7730b876203 GIT binary patch literal 5884 zcma)ATXWmS6~+SKRTM?bk}UZa#7>;hvFYhGO`@c7WyNt4Gp?;TEj%s;=B{K)AfPTl zIpWYWY2}&tp-!Iqlx8NL=}Uf0{{UY5vCZ9YeD~2KB8^SQ8;Tlp%GY}oqH3f~Wz;Z2q+pf*;oSWl!-p%v7 z;1=+-uXFh8MYR85|IV!N+^c1oTG?KFPjsKVB( z@|A6&zm*r{>+&49oe3?K+dAW(!Iy8yH}U10#LYd6d0n2z{Jc7gy)5@N_1eDSzAmj> zM*U)M@w!TUXEpHS*ts1=GK!pzzu9gzo{<&mBAxQXFiQNS9ffg|=2C6=-5`Ir}maNO+URqe++flcDjfKLF zuamYPV0cveiQgijyhQt9ybI z{lG)Nz$4-d=#}9LV1fBL^o!^>l`XAhL(Z^)r)Bj~#m#*U>$`bqyp~qU^RBGkRGaM> zKHB^EvO|>2>3u0-R7dk7{1<-iz}=jO@0V}%zbY?%q4}sE%UOl zZ^=T}(C6Dm-}Z_`?dOPU8xOJC75W`e?5$!yzl<-S%VO`rC}2iPxZpf!C-=#r$3a9Y z^Se;hK(BklrM8M2<+3w)nvoMKC0XGsqYWLYS`kA@WAr6^7kNry;3=u;d1+w~7iq=w zhMYXFSudrGoD*eXi{8RP zS7{7nsFyRYXK6oX&5p+W&k>D;&~H*l;H2y5An6ibY1#8Sk?aNvM}c1c+VumLlhozO zs0H$j=S{#mbVq`w(*wk5sUQH2Vms^JrV+)neia?XY+OWFHf*zKE|^R`G-6jMVhI<9 z5liukXe~%v<{rT_k*g_2i)r!GX!Cme%XZj1i|C{Q1sa0W8A2t`9gdhrc4$JNmtYtn zVyqHdQW(MT5P%teMXvxxgzuVwNFS$ed{90k$-9Ea&{(s2m7!=E5SnA=^*n1_|BiNf zhq`yEYfv{v!xy%HAFI?@g+;>_rdbo3D2J*LbP*X@Tyv!&rrJJ8ADKWVm*sI*jNo$^yfO#-v5G%y6GUoq==j6AzSka>$QB@DkadPi102xO^V(3ZJB>!;g0p^Ce+((II)_rt0U^n| zMs+Vm(qrSX*rFzuAmB3QTM%X2(hHAqnk^IcusCMCZJ35(d*_j+VB}2I4vTJX;wm>rXozOc9=Y$8(x0zaAki7w7Yi?gbImEp#rzX zpBWhZ4c;lmwxLUjA z&nQpz7DA`fjT1^Ze&Phm$2bZVCF$FK&{b<%lCfp%3Vj4+4kH$z!zAb+df&k9hu=%11Yv3NWv*`6sSvVU)r_#^#nOg6 z?_0D%X|o8|@6C=*gG`b6JQRNjU<@kzi7J7)vtP4IFOx81zaCdOr2T)4*cuh8aENxO zRaQtJ=dn7h6SCVi{#Ub5r`v8GbwWj!WSJ}XqMU-$O{b-`=Izzbnjc=f+B?1$?zVLl zc2t-+t5LYo-t1;q>PFALlyr9504gIO{nKOP8nvzV#<}I^YtdB_jY?`%qQ;ik1(4Fa zk2J&i4s^~=(3n~*v|B7gXs&fP52}O|?YwT_O3oSE^RVLHSj}A3ia8kL( zJB+chj33rZhoMk9eXDu-lQnPs`VH^OwVUaDHvQ z{b%YJTV0Im=lC{5*U618{$s;+Qd64Mo77#R?l06Wpu>N0d$4@+;gxH_KMBJS(cFYNfeSHD9h*%zUY4&6dhD{{ut(9*6({ literal 0 HcmV?d00001 diff --git a/src/snake/__pycache__/_version.cpython-310.pyc b/src/snake/__pycache__/_version.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b73ceb1d5c197c1bc5ec0e2be9811ec9671ae7be GIT binary patch literal 489 zcmYjN-A=+V6mGk%jGslhA^HehxS?0Z5Mx46i3W*)iMwf#7MyM!=>`eDicetliF)f5 zui%xZ{6yRI`_A{BbJCuso>xM!KD+PJFO1N)5&xGB;sQ?g3@}6-g-9TEz%eH=PDn@+ zE3_~YL|DQW&V(EyZW#=zB%%;f;Ru)8O|)hQn1ZHTE;JE$Z4?&65-$Rm!wN6;QN4V* zg6mM7XlF2=#X>tn8Ku(Kg@sTVM7qq_He^g!|3q%e!SZ(5weePI_znNq=VEbk+Nj$K zMn!8_nMl)3qFeX0H+bx|S?jvpy6JSUG|iW@NKO?o4VJ03BAII|%a!&X+V}m=U6&1p zz1y~?>C=lC=X#H^k(6mZ%Hg3IW6CkT<|7p~PyqNqs%l~bKWD)rjiEXgL2DGrD9G|C znS&#OOpac~(Iin|s_{k!yUG38QoGG0n%?03|lw$2Dvdm$-PnNd^A`-wAw; literal 0 HcmV?d00001 diff --git a/src/snake/core/__pycache__/__init__.cpython-310.pyc b/src/snake/core/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..47426a68be93645ddc262946c9294410309b7d54 GIT binary patch literal 770 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 literal 0 HcmV?d00001 diff --git a/src/snake/core/__pycache__/simulation.cpython-310.pyc b/src/snake/core/__pycache__/simulation.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7359ab529b2cfcf79627b1eb9c467540e0bf3326 GIT binary patch literal 4943 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 literal 0 HcmV?d00001 diff --git a/src/snake/core/engine/__pycache__/__init__.cpython-310.pyc b/src/snake/core/engine/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..645e0a59dd45231547c57cbea0e870acd43ead4b GIT binary patch literal 396 zcmZuty-oxn5C-<|G-nEB?Lfx#{o+X(Erdg(sle2>9zBM_Xx_J;rh)kt7LH10`FaP$+M^l6<= zeyX!RuXBt#B(hgr7b3q#W%0DXHk~qZ*;=>c&Hbpn8k9AD^?{*jiNo$0_ww{7v(ZCh zXMJ_~AHP?PZ9DwUBrd+!B@t49s+@&_F<~3VLV5$YOoFi0a5qS=xS6yeGqK-P67^hb z#@>*NUo*ki1%0rZ4@ygV&XrNr52_!5k<=T0D-YV<0qL4eNE_=UmDAXiF(?=qTirc| W*->xBsO52-+{gYYnv*$(MZN*qtZYyK literal 0 HcmV?d00001 diff --git a/src/snake/core/engine/__pycache__/base.cpython-310.pyc b/src/snake/core/engine/__pycache__/base.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..274d74f8f32d91f1e3ba91e03f3b21a5870d5a26 GIT binary patch literal 9031 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 Z$YT(LBL1m{a$`ybK-a6S$Q5-W{eO@LmWcoW literal 0 HcmV?d00001 diff --git a/src/snake/core/engine/__pycache__/cartesian.cpython-310.pyc b/src/snake/core/engine/__pycache__/cartesian.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..052f4e1f2493f2e65036cb97b5d3fca9cdc000d3 GIT binary patch literal 8845 zcmb7KOOqSdb?!GBK;tnpm?s~CB-#!VX(-FG6)TKFNz^m)L=h?3L9DbpfPj1 zhty0p;v}SECys2Z%CYmPBtuta!OA9^EK=Fz2V{{&vgs_n3Ad?ARZL4{zV9|>1_KWD zz*HaHXZP)U&-u>z4rW*?6*PQ)u=dyMKl!qz{fw2#kA=#4T+u&52(76JT^N0RU^ES# zWwUP%tfr;PR^J{tO-GgOey-`F-|pv|1$;aG;=pTqsxQ|s4a&{(pwg_Uy4$Y~W|}jq zobS&L=9+UT7eujN8_YN7RoUw=3>KS;4y{H%WhGE?g*L$H~?+#`Cg|>|SsMikbv1|u^Cmzb4AFbZT zTWSqGHJ=N2@a10gx3>MTT&5~b6*+n_;S46?D`ZLQ~*AhkH-LRUosC|^q5sNd`OttUlV6wrlMU!8aANI%|| zVaJ#_Dq0omFYvS;gGls13v{6`Yk@H`5+g7JE74ju+MPrT>=kWf#<|42u3yw{8EaB0 zk()XjK6NT}p`%053)j=~e(CkzpchB!!j)*VjaBV8Lv{Sk))&*O{AO}7?R?LG7fds*9aZ)$t_ zxDXU?>U&;XO04U8;v_lY+_Xk+;^H)OyHCIDhrYyK)#DAK(>9<;)`y#H15{n!srO=* zalUE;Q_((!|Y7x+Gn)B`NQ(XH-pWc`K=k0^Vc>-$hY;&k#AvF5j-2 zRI;{YM%8Db^~G&X{veqhkA<)3;tfZ$;T-!ob3Ar#dQ37`!?<_`?Iph7s1`mvzTdx~ zb^IjUL)}r7$73q@_a#;hJ|^prXR|#}@B8Fvo_oXnsA&iLv4AlZoEO%qM$L^DlZB*~ zEGF}Ot9UM{2DR(7>teFFtktxqwb8=X&ys~bST1%JCy{vAJ&Zo5ZTCjwYQMpuoO#QX=UF~zXv{-(Gn<5s%BRqoI&HZ==!Ni80DQB3 zIg(%DoFe;Xm8}tUvBZ{IV(MX$F!x)7D7ANeIgI4foR|v%t-XGf z<~u_=!*{>(RGRn0?SX_WwiaJNz@irZ%eyOn}pJD5-Q7C{o$I`D;%v1a-g@THF z*oxY`btGR!BfMN^W7z76chh`)u-1IH7q#k7)sJS|%v7na?*Ep%4 zHmZgNKj_?>HP7fvguLADqYs9>gLNH&v01DyhfBfO8&Ihjp+{_t;e&yP8Q99L@f!vK zDA58(m@rW%3qk-T-vgB7Ms5rU0+i$wl;klk4=4k;VQfBe_X@%hxtj)HtC$poMT65d zfJ}gz3z%SQUgQBX_#T5yA;~92^mzb-Jiz6x#1pC>mf6B_Nm0R1DeFl}01^)X=m}3f zxg0Kz=Uzi=p0fclTvItL?6)Y;7`MVPtB^~AeAn z6BH^63cjvo`1ChG>=9B8}Y17G^e5RsVIQ<@`MBECiK%0Pz-?xc;85ZPab^(iE zPXTt}q182J^_oFTDbs5Beb@L1cJVQxz~n>If(i{)46xR*@bvu;T|Wax6IaxQh_yZa zJ6acEx-f3Q315IV-(;X@?itX06J--)P#31KZki(#VWQ12FoEVHh&16qR6WSSg`ji} zws1HG#7l$rIBOl^{Qietf#y1gE25uR*AnfWxsgt@P4w@AF(CQ`*IU%GGM6Is_stKC zErV=9sgLBoHmn1Gz`#C3SzCp2w~W+SeFB00#xTC6XMx-qOpz)eE1Y92PMm-CpScV& zO-C~v>ldy%6ze1B-tIHU1JN~!=(TmY$*boGzWwM~6!veLE%7-%?^hriZnn-MVt3%Q zAL5ckl{bO*z$K7FM8B4;UoM#aD7Oa!4S^c-*=T;dRHC=Yg%EhW>&m~+P= z=kz-N34IYmKFciVc-1@BJ+El#4luiH*7RBZK^iuFqlW%c<6#8TEu;zjRx2&ET2R34 zKFeOKwYA;uk9%^hmKb)>Txo%@F;}rar-(V5oQ6q~ngCxOOO9)Y;SkvX__7FH%H5m2 zuq$gEWUK8`el@i&4~Ko3M{~vmUSsL=>Q)0OQuEyiZnGB+Bxq?W=+6YR!JP2?nqaa8BQP=_%p-YH z78Q(J@E4K5S`st4}<{zX2NAJozccGQq;Jr_}TJpSi@liDe{9 zR>TQB^|V+9?wm}^FTOpQEZKb)^}6z8M-phO^^4HtdONDa;vcJD-i{S5RVG$P)L8Ei zi7uzcDV0L0y`Pano~PGBPVq3$V0 za^y^o(EtB|i$0+L@a$vypCtlFfRP9YjMyAU)kq$ZIwp44Mmy*~Vo?{dw5?J{P+d^_ zJYrCd1V7gIT#UkLAd+AbshCC4h?P+jF46^vmJdpZquDl27r00lIHE947a%RL$Jo{i z${@3Ol`c3;2mJUj9f0Ro5~c_WAoanfnU8#x5T0?E=Ql;!Ln#6BK{$fa0G_YQZT* z@x2L(|DT}vDp`PYLNtf;%09{e*R5|cSqJ5Rmb#(X_IZ?Ue@GsGfo+W0CL(tg%+QSG z^AM|RS=fF$i_Yn$kB!|gvg0+1-=t7s``1`f0S*bfT%&k{;u3`gky_pDu%kjJN#BLw zz~4%Zm!3^O2%y;Fzy{#s{>qt!&Aw{%vyoWdtllL6M_z` z)!jM+uFVvo7tr!OSUzP1)>^=GtH2JVw}lOhHQ+X9CM?zsW|2q(V~151VYfEywguZS zlB*+$gJ#JApI&MvJdo})K2d-a=i4w>ojM;P<$+9vKv658cg`^ZLDmG1&sU5?n zfrv?2vFUBFY5s`k$#v|XJWrtvkLCu0QU*ukk{cASP&`IKl7uwV1C2~+tFp8M3z9$L zL~;*hK=RL7`Z2{%DE@*%8RK8F^j8!fg)+-JOK(xU4bhmH@FdEo9k`RsVh$Pf-*C>~ zQv4l-BGj~mj8!Wm2w1&BF=YgOw4KKmL_`ZKKTVj&YHc2>wdJfpk)haz^O0+lG*h+j zqs_sxQJnXisbhP@Fm|z?Ezdl z_c2_VX-37BmydE~uw?TnW6oN*s6*Z?LribjnHCLE&H|DTSlXo6qKGNf$tYynMs=Hq zQbi#n$Yr1l_zem2Q`3ks%@jWcHC7rv=Ew3XpH2`|EtQ(@uuUycEmf_O zq-%?-TtMNF-C9LtP{3_h$ZhXagXy(49+D&8`}ZlnP4Nd5e@O916mt~UDQ-|aMe!a* zjpC0f@)Rb8a(RrS<##FmgyK&rT#D~ee3jzQCUY+|9(LJ zzS_Rr$+qK3bY-4BH)iB&U%)@M2b();FH=vISI0NwCZx0Kx7JnuxVk!ax!D$R$I|(U zUL@T3>nxs{k^D;52kPJ2#;>@MIvS)5@H=DnGl88oE6`(zk);*M(LqNZK)P!~`DxnCLdOZ`Ypre*vNkcmMzZ literal 0 HcmV?d00001 diff --git a/src/snake/core/engine/__pycache__/nufft.cpython-310.pyc b/src/snake/core/engine/__pycache__/nufft.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c2d65a8a0158c27e8d8ade162ae5ec6bace79652 GIT binary patch literal 4706 zcmbtYTaO$^74CcY%=FC8&R%@U#S@#5Oo(TL6CfZfB=N=}fR+fyfQE#ocdEwQvway? z_r%^+k3iUwKqBx1;9)KCl1KhdJt6UcEb#+~12NyJo*8c(M}X+noUZGs>Qmo$&Z*6s z&ANu?_d9>MHaV$jf2GRt$3o>*{PNonOdDuSXGW|i#=y|2Y{urmQg3_U;BCcj;tjl{ zHmIq7JFX{fyAPtjfxE&Uubl=_! z(;`bSq;@4rE@kN`x^`Eumf0Xx$F}r_+7X7XlJ-e8Gsugu;6vKk@u!2ztN7(-p^R$- z9VRxe!mtCA88EClu$eV*xXV3eU(|SQTpu*JkD7B)WA32ITPS-d*Z9h~&FYY=;|^=^ zH5hH3Z=BLtlW&gdti@JtTZ0q)WX)w~S(|UFF{^lYxXV1=!nji-pRKX=+x9JeaC$y+ zgFnVL`Q!WvXdDRx@TJM%xzdyGA<=5^;^@Wg!APhyQGJ2UcF zmpz4@KgG`A@XyK39XjLBnOo3dNPFk%<;(9#JD-F%Qt9MTGKsmglZ^3Lnt3WNOD~V3 zArCGv=`tK`&I@VoF@g3d35GaWl=iYBh}cc(2wqG@I<%pC@ib7N`X&7GUqTdGX%+e{ zBlk+{nm)5ieQYot)-v!jPiZr|#2Mo4;BDjW7UtM0?9#fWmrm)9Ow=9bd}z$P!ll-2 z?Y*^kjahA0U+609(B+=ejy#%i$0)tBc2T?jT4tj-4+eSyX^!k0vJbd=i zsPBJHk#rYkw(}&M(U)7&vb_v*C#Eh9sK%IdA;-w0*%>4lHM@yymCA_@~`lSijYa<;H zwo8}Q@K^sMH2q2coj$9TH2}JC_~ctDyn7f&hd>(8rYzT8IO_h6pbx;O7W8fG@R=)B zp{wZMWf?G^W<@ujP9~Wsx)-*)iuKY8r$r{+!yrl-zj^mQo}STHc)i@S;Wr2{(oNwA zqBs{9)GCY+S{z6}M>OGwoIsoREb%4kt^X*Dr~C~eG9g|@gCO6~tBbEvS>cS7h!;t$ zk@zNrboOtA;#v+5MQ0S?O$!IoRv)U6R*5Ydy^8HdMWDP`phkQR&G`!u>orUF2`+}G zTZRL;v=n$8!_bZU21)g2-7{S0W2^SXKzeuy>CPjUtg(Z%VxIU4ZKtWW5G-)zqHXce z7gAl}>Seg((j05=nlpFi&1wZOQo5xvhWjf$xIKMrGaYWPUN~d7M8G=*ER_~;;V|<< zd)B}Ruh5S$^Qd0+-vI{KG)P-HOuuLx`ATE6^nobtjx}o*tx_AW0A-D!U91w`;83r^ zp|)l#MW@tCy=(#H)~sDR;upnQxk9d$c_*;?SR)s`uHDjSt7r#0KQJJz4~!A*t`V%4 z7OR0N1>W^?b>6yBwwGh6mE3(h^^doXC=|5I6{Vwbv{|;!9+ow9kyEbC

~-I{kaq=-!<%qKlmd-LaP@uh1T3$x{E_hh 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 literal 0 HcmV?d00001 diff --git a/src/snake/core/handlers/__pycache__/base.cpython-310.pyc b/src/snake/core/handlers/__pycache__/base.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..06877d2f8a81d257e5d6b158093009adacec1549 GIT binary patch literal 3986 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 E1v?THbpQYW literal 0 HcmV?d00001 diff --git a/src/snake/core/handlers/__pycache__/utils.cpython-310.pyc b/src/snake/core/handlers/__pycache__/utils.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..da2ef5892f3bde3871f8f8c33ca13ba545c8f98a GIT binary patch literal 712 zcmY*Xy>1jS5VpPEpZkjtq#zQ4ZLi?=1x_eYprJS+A)0Ge%i4Em;`Od*S|1AKRtLXK6(sl-h*Lii5O-? z;)*N@Ml4`d1{GaW*kcyTu!@!u>?2ND%wv{t!UjBHLrzyiHe%zibU9#?k7#;u_3D!q zQrIqCwW_qDRwiB5I^7hCNv_T84ho_vcJboviPlATNA~ywq}aNGP{KHG%DU-X-0Ylg zWQ8#;&s9-z7hiC(-dN)jD=MA~cIhI`ZL3vD{q1{+U=2V|LCqYDMLoL4TiTNwe2cck zk{*2tuJH}+@h#qlfWkgJLOtn&BXo#*>hT;_V1}<=oHUK>(tYvN)~Vg_bl2Ey8tD*9 zxKJ18TskU+u`ZIuXD*Ekg<|~Dg;inB3}pJwbnH#y&A=ZVDSnYZ&>imS0<|AVKZW@3 zciDL@3z#j>P79$#W`KMP9-bLhoblJIN`q6EJD8QV=Gnv4vlb4T8BBCicoO-ZgfDOW zUr1x}viDcq mcm2pb^V!L~s#z=f8~BsRyaYqhn2hlllYn6I_dg{EfBpgCp}e{P literal 0 HcmV?d00001 diff --git a/src/snake/core/handlers/activations/__pycache__/__init__.cpython-310.pyc b/src/snake/core/handlers/activations/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..08d84a9002752e82fe631a847eb5398e40931e66 GIT binary patch literal 445 zcmYjOJxc>I7*29&@3bvAIfz5o8*ISILBzHQ9!M*-AlwqpORS;Er6kuv{S*EGH#h%M zRww_0lSwPKFXYMl@w|CIqC1^K;N@-fK0Aj1dPE&48QfkA=-zqHGt4^rzU(}TL7HgMWZntz5 QmSn?UVbDfxcm&(%7s%Xs=Kufz literal 0 HcmV?d00001 diff --git a/src/snake/core/handlers/activations/__pycache__/activations.cpython-310.pyc b/src/snake/core/handlers/activations/__pycache__/activations.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e5a0e67ed66e1955e85dd04343ad7cbcff2c6aff GIT binary patch literal 5550 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 XJz*{OZ!hS4%--^7@6zzt+SC66`6Dq@ literal 0 HcmV?d00001 diff --git a/src/snake/core/handlers/activations/__pycache__/roi.cpython-310.pyc b/src/snake/core/handlers/activations/__pycache__/roi.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..182f3f8e4689c8ff3868f03c65337cc8edaa08b3 GIT binary patch literal 1098 zcmZuwJ8x4l6!!If<~D5#s(2R2fDjo-B!rkML>nO#3ALzHLdtSw#ZKb%zGOR96WwgA z6=H^=8Clu*D_)uM7iggzCoO8F+VW?g&-U^0ckFC=IYdxCZ-4D=xCs3+#^tgE#%pL& z08rFM)S@`H+8BB}wiBoAScp2zWuB>B`!1sH70bI~`B$uf;ep=`X^DoPoOVE$Xqhh4 z6GQ6PoM;D0FNUXlflBMer04?1@u2z&eFBweFyatK5M{?ZT!Gb&u?cS9r&M z;ZCiIU-$*Sk0yaagJ4i90_su!2v16|8y6+;3ge^ho`DL0uE;*`Dn_G=LjrM;i^_a-Y3inN zMq)m`#FZ$QillJW??|kJ$KN}RgDi$@#;nmKJmn3kcrpZrHDpTm*|TmUfE1mD+2~|~ zHToo_kXG3s9mNmkZ$UOh#_Rb=ulJa`2oHMmj-vmM$cH24D!^K>f>&{91%PEcu*5?k zYxZmait---;?aWm3Ek|4fiDY!n(>-}=W{}s9L!;M0y(NV*Qp1&@uP@lohZ_7I!yAB zSb=T&w(RhHRF^s2fy8wsNGiJ^+ago08s;(6Hhd24r*x4+6R5tmwY%Bc{`h7q+G#dh z?^}DD?;`j(b4f431G6^RNHPk);FSqfJ^^r0fXf!Pp`Dd6{#&;3pR$8b9XC9|_poJZ Gc=``qe>GVE literal 0 HcmV?d00001 diff --git a/src/snake/core/handlers/motion/__pycache__/__init__.cpython-310.pyc b/src/snake/core/handlers/motion/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e34937358f09117b95bc83936d0f6e5490ffe5eb GIT binary patch literal 287 zcmYk0F>V4e5JhdXBnUx^qExh7fG>a$QkqZz66v-XS!=Uc*lT1jk-{Z704Lx|+fwBU zR2lD5WF*h%KmXBuHyri})@6MyJkEO*|BInm;0y2AB*}=Rk{N1Q#wd}Uf@U3=e37(! z9<5xZT{->~r8LTqS5BUcn*LH;OlkeLMeb~CT3S)4r_sj~>olof0i??T>aLF84UbS5 z18^h$1$|9>Z1}e`qS8k351~uVL#6EriQ=IY2Q}GQkI?6>T@7r8~+a@Omz|9I^ Vdi<$-Guxz{$FLzDO2~lq*&puYPF?^2 literal 0 HcmV?d00001 diff --git a/src/snake/core/handlers/motion/__pycache__/image.cpython-310.pyc b/src/snake/core/handlers/motion/__pycache__/image.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d1a3e431a68510f75e1cb7fabbc59aa2b2be51f3 GIT binary patch literal 3220 zcmaJ@TaO#J6`q?$quZ`_qae07Ee2>BRIM!mH4wCc5oBuzNq}@4*lr$#1Ou)}X=gJR zg{0Qrh4!WE0!4wM&qZJ2zV$EhwJ-HwXpyAf;f%C$(qx384msrEIp_Nh56fP!?cn+A z(ckBzp5y$BI@?c#&bxTkpV4q<;&7LHnVWkP&n4N<{7HcSAZz5|B*a*Qhgma^CQ;s+ zv~0hbwe!xT13BWYtef{HJ;-g|$#(MH$!^}C^j+tDhj)4JnZtXccjZs^_>O4tT@muW z*ynqqHH-K@f8|*)d4>CroZ;Z&;J2kt%OXyTSf7YE&DmVUyv$izj9$Q4XXu)U3$d7% zi}NFNnnw=~rDW$XeER5_&V%!U<>~YR)66tKK4FC}bIfZ!O7r_=F-zw!yh_dP;jz+^ zP4x$?;F*vw+)6{6ah~MX4AZavles8_WV)17%z5bv(R&xK`V$)AOk9N1`#pj<@wtZ} z`jdtTMU#Fr|E9zJ-#8-T!97Tm*8lm^uwUAuQ_l=-zbl$`zllBq{>+*5cw6l7j@ad0 z(VvC9$9E9OJsZefbK@brD)TCwA5s`=H`(71sYA}=YC?P+a64<%ZpU~&W|HMX3#n}P z&gQXQtrDdXq}=vs{$t4sl`)H*(%70w9&>S)+M(NoXP%GM$S#oIS^lupKe$#ho?-)1 zU^UdR%+gG}9RtOU9Uso(g)GlfF8FQBplW7JGvidnS;_DzhJmpZisg$8Jzd5*)6)~X zpjhU|;#y%ji)R!HwWg#>^JV4eD1Hoz)*C=K2wTJ;Po8~E#Ho3Fhp;x z{+&$cX~DAi@xvG!($X!vZS<6wmIYt?e^hF*g^X47vN1JdVaxG(%q4r07ISz~<}r(l zQs&rIhr4Ht8Cwisph zwmP6!lB+2lX6uJ!Iv(%iRiB_)Ij1=GmyT*f!ilwX^o)&P^{#7Nyb& z6zL@SB{op|Xa?@U^*qlFz6t%dyYB^GU%dH!hwV*z$~$!~eIVj;cj?NXTBNL`{VxN&jg=3qywh;tP)`$jK$h@3^#;TT z_ql%=6hDC!SsfohYE=?e5KmgqT`PH~o#*a>bJ@_{mA@iZM5LK}2V_U@s&N_U9gOa- zg44c6J^Blk_Tb{i`$EUOs?NwLWB?9b)cVm;`fqqQ^i6=uElglx3}(w>I@|}(+0&#* z)Jdt89Kct(N6o8fOqdp^Pzw{{I4b7Cv?ywp{>INlQPGEpWEza_2oy|(swKNL=F4I( z8zl9Uqy{-53zEdRkIidrvB=KX)Y4^AV>1lpYgi-?sCk{1M@3SV2oqKm*<|e^eQJqU zH8*K;XD)P7N8ud|sGp+=y@3~aJ0MQrhF=XDH(byD0yn})@Lw-Ni;?iFi#NWPN?VE% zw&4^x*Cvy_Glf zZaP;U%~|0p_C;$&6!k7%KP1f8RSwqzDmyjqqoZLU>FQ`&0(S(u4kAuDQ=co@!7zAX zDe)`F^4B!4Q-~*P))+T69i1w*6bY^Qc3gge1rxlAuI5p&@BSEoOBx*xpYLu`Md5eO+TLLMAw7O2`%|ZJ-)umHjp;Z2XOnys~?5 qS!uzv436$qbb5!%ih2W0;B>vn>jK5Di`MP?-bWztH=Ebn`TBo}>xY*B literal 0 HcmV?d00001 diff --git a/src/snake/core/handlers/motion/__pycache__/utils.cpython-310.pyc b/src/snake/core/handlers/motion/__pycache__/utils.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b39a4bdc709946cc3b258d7e14b5eb8f2501d856 GIT binary patch literal 5191 zcmcgwTW=gm74ELS%uL%(oQZRBlFinJy?CVq+(5N$2Gj8v6 z_fXxFc&xDmN}}DDh#$a9vJwx=BhQF`frRRn2b33(ka%EoS-w-*>nSOrW z`kp1eF&>MzA)SKjs(44di!YoI?8jE)?AF3h@~9W(L*5xA?L118jCWGSf!yY=@UI}3nh(Gd1&YZPf8TqEK=Jo~~RYuh=6OM52v+Wun&ZtI)g;_8PAQCV9 z3$v{67mQ0Djzs}(He@?b)vy@^9M6wJ;w6_VGt+aE$4tkpnhBw=4C0$o@wCGW88pp` zk;4RMl_b_P^5$6{CL&aV3wbLtphX@fJdT%&?-|iecHT(ymu^#`h(LQOD?eKbe6oKP z01geLy#Z<4d@7UeG!f+vC}x6u11C#ko)jFFHj=7RE;o$!_6Wu7O!`e?2$nM;bafC9 zh}~O~UoQ;qIVrECx!gs|Y+YTKW35El*hZz`H-}uP@OG4RA!8gc~Rrgxr%NY z*7)rxU!O?V(3?oun0^lGACBq6s!Jtb&S*ml$ErW!PRX3}un$X?aRTf+D=|rcsn6#`?XmEn}JF zhH9ulHBSxJ%`hXKcBGO?TNa8}h_TiqhZ-8eaoun;${Mcr3t4HF^z{@J-wtz`;MG1@ zz#$t`s)8M=N==O#3hRm-Q&(ZeeJMqzt1!!Ql(!0Y2v&|NMW5*aG)v$YmO23%Uw*uF zDE3zOX1u%SpO@FDdM^;1@tjmP7)F6*)p)QyC}MwCO@*4cg3dH&jS;`qWgTtgOy zU(X0sJM9#?FN+e$VF70`IO<&*k#Fqcb0VAb*REs5ShVZSvAWHkG1q_WR@6Db_t-1B zD7o%c+VDp-U$+V_IG+Q8AWCH!!l((FdLOm#O1}Jm5h-^UVLR#n6~Qrn zt>E~gqf&fSl$cCvMqr@4ysI%w#spYl0;Kr;;$r;ucrmr>lb>Q^R!8I314i2PZT5uu z{=eOtBF$)5gn6ia6D+em(UOurMN5jB+2?3->r<;^^mrF#wQ%m(*Q`7C9ebN01v25z zTWCGg`tw%qY`CIw-`#e`t8j9&ZhBx$?clh%^S~>E5=wYO%QLh*v6~i(deE&rsE+)H z_AG+VEK2>n_8G#*9g54%?}zc)0gZk!%CYAZ^8Z4^vJHE!xDs!E$}lKl9gTtVC} z zm0dBsc8RKz&Az()dm>J`k^SnFwe@~T$8C*|+6wblam?nWUW#m<2eM8&V3x+}{AGgW=H+f#k_tC1C0Y z^s!1JQM_h3m85Yhq@F2DIOBszkCE7HlSal59e0w!Kfol1hH|7ciYWKkJlP{N7Uvi! z^fZAMF~tc<VUW#*eZmlF8&!c&E0BDbB9M`tt%*QNYm;&X!KNJF6NH`L^Ipo= zCQW^~C2r5UR{q71Dwuw8FE*DE%`y&o3u%j$Wxt} zyva?`6bV`*k-aBPDe^m17cWPvN7nY%oGh#uw48k>u&2hM{L{nX%GvH-c|XYOb}-P| zpKn@b6rZ!6h2vY_F)nwcI&<++E{l*yNCB306-r8l<&=iP_pDcZoQvI1igD+^D^4@5 zDg8h$e!&)gZpgFM;MI~`G1V&Kdu0YtB=IeKlBW;Gf#~>13Aav?Zj4AM1xHWmtlNa@ T+-w71#Js)&$j}r|@j?0vI1gcx literal 0 HcmV?d00001 diff --git a/src/snake/core/phantom/__pycache__/dynamic.cpython-310.pyc b/src/snake/core/phantom/__pycache__/dynamic.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1ef44a1a469a6c89b7f7277e843463d91ae2f9d5 GIT binary patch literal 1953 zcmbVN&2QsG6!(lB+ew_H>BrJ`cagORL`s_okT{?f+N#xZ07Xa(Lh@>5Ii5-Cc5H{S z(~>H;_KLW0#`EYyKU#t~9x4U~m(V=TzR zI3)}77TZNGKRKLE#oRAXxX)G_SLWKc%%I<+vI7UmHi(|3tb&WNTu09aicJuI8FCx8 z``3f>TtJHj9~?zVmJABWbOs(iD6;5`ABt6GGaJ%b|) zB*7ZJ?5<$n*HPtOMCW{*%kob>PNFGSZVa8zxF}RNo24Tz!+abT zQ92d8=$XolMIoQ!NzYLr?3LI7O|`?Z%+v4z86SMQ`;^+GO*-W7Bh2bx= zNGu~x7_vMDcP9*2rbHM@L{9F4P)$7^QeK|qOn!>)|4P>y)~_K(Ru))5!?37JT`1cl z4N9#wqT?}y-do6tS9njp0_A^9jV5rxQ{C_M&0WFu^7EzPA0NUzEKj1+zet4eN8CpW zC!E1J(0A?ZK)>9V9;8sw2U)7wvN}&5$H=4d{yfoq`%&VB*VqlALp?P1P<)1BAH@L* z4ep0f96%HwD=-^CkyI!Gei-R}q|d;9j%P4Da@JwT<4ts{{Khe#DuNj_rb!w<>a`c{3}()eACut(t|m(a!kUT2_uV+d1E^*%G$edB0FANI27;@Qbyg zgtP5Qzf>zpIM<%?%eAtE?e?@kQ=5^n-riT6mEYK3o5MTbp7#&b4xq2VCfW!6L$yQx zL$!ze!?nZyk=hYCr`UG@Yh5=qaXO zQ7XrJk6#X1x9vG`=rp+J#-7tzaf3MYoo2|LsO5LtZrlok>PLk0iYoGM5QMR8ixyDN zUGf5tyK%^=!ra(xwB0B|CG&a^zZ!IXfM&DR_NZ<8%8JW9cG>eoe&@0qxXT{RD~vbO z)T?(o-rFv9Wfop}nREBfM;d+K5Vown$-_=0iZ1okn>_UE(TXn$X*~|p8t(@6j?3M4 z+iPPbdm+5wM&4jcxhpOILKrk#%MCi&_z!%Pa@4~BJf)_Bt2Cy9i!^YM4(>6)Ic6=x ztXh_3fXA#T(vGgSqNpoB&^tn(kvNQ3fL+<)bTG!_am$OUoIdgq6+BOnPKAMDp^_8X zdOdJ`uU;2+z3xi_0WQ?*H@a?n(37dxS=d0ccJ&mV(?Y*`Iubfx35DKRY28=&5n7yz ztyfRp42g_w@8kuy6|_!9aY|V4WE8mXcuzHbjz-={t0x;F_f8J@0An$;QSIE}Wvq1w zPgF#aRSeb8@Zc}2%Dx8>Nr!rgMDu9?jQ`z>9l{u z&>`a9f;J-_^uUAX6lUOU;tk}n%%GkF;TMGgdaJUB}x< z)Ma&3ZEBlp-x`cJ6MZyRkFCV$JciMk#7wM2Uo(JDqj&aY#(=c}wxH2T^$exJxggbh zgaLtfYlQD`Y1M1Q)rz)|swC)1!@b>#pwhIUBl4g}16Cox!ym`?c?E?qrK06eP{Sis z5MNg^!ic5tKyTqZlO2l8+F=}y0!Qp_` zasUm|Ai@oQr1;1Yk%UZOj9}Kaw&H_CzShscZ0m3(bl>R1l}JoJn;3jHHW|e2T{X!h zDzjMTJ#E8^A&?+!F3xP^mKB!$F-T2tqOIDS>Wngg^PB2HrEjBFNOG$aG-Fxm=X=lh zN^vpKF?{$q8%d9-=FMH%E@#xlk7`on^u1gnEVs888?;aFM!!U18m+@0UOcZCnlc! z#-U`6_LEEkvXcE94{a**3bow$;WeDkPz+^FSCt@pN{RmY7TW3W8+hcICX-3v1nw0p zuPaIZ71*SE%7=zrF_%nYPdU)Q?$0Olw8Leh*I`Mg`Qb@6)x@5`7eU`6o9d6%Ur_o7 za8@UwGRvkR;s@iSNjAwP2bmflOKe!bnfFZW`5;z@%a%xvV6!`WNcn>8A8%oE?~$<2 z_vSBou@vwxbC~p7-qKK{2Xd^5DcN()TS_G$di%7mrPUbok~gB7z7#+bWNT+#n66`g;1 zkwaz_S@cYjL#J1ASm;F#97)H6vWcq;z4BWTRPa!FkpQ3FQk^aJM6Y~BimS&4ozYpR zr=4&bOQ1qz1aL39b6HP~!*m z(K*rzjnMC$zm0W1rj=)uUS+6>q_ep+zD_<3$w0?842A_)7%aZ@X={!<>g) zSYQd@grB00%)l1&FUTp;irazpY=$@MzAvWShA+zq>tv@=4zD(n{61FmS$@TAKm z%$u~h(85R<9XDPPmgJ;JOc9GMgz?3&8!-9t)FaT_;j%DVK{FHv-0(o;U=Ufm6?icB zQK#LCh3>l@?6iYkhLhmUg~@3h{+!%t&*NdlCnX$rJ8iFW2;Mf%OQwrIPsJCh_!1Q_ zP%*+xijqPqLs6Yv3H~NVh*1-9kkGx`4WTxLnQqKVO_eaHDh!-C5?Tz0KZe5}pN{xL z^pV3vRYQ1(F>ZbYTLG^ zeX4C2Omg^bxcs(e+%2jFwX7Dlvv;*^?e2_GmOb!n@ji?(B~{b3?X0R{ep(V_>t$8D ztNquZPmIYq)!5GJmRhB;qd!Zver9Aa7cFJ{S^wMH_n87HY#b_VgXzLx%a$a$4!>Zr zK|DMB5lqU0O!vp6C1T}WwW9V84OQrs6|d8I>Wy$2DsA`~i19SI=ye}d_PrqXQeL{R z@itcAzet4?$dOcv(jXAUVs$W^8xR_$0x|U7+;HK&gFbhwypQSQ+q~5E;HEzHRgdp% zlYfgga+iwF+|9C_Q-23@en^AfMX_fuV?(5V6d8(`A}`*W_c^P+l2+g%g;DiQNZK2% zcRXRXd<3`+9m@@WyIkEBw8l!J#_FoJrbQF{Av8O# zgA+J|<5Vw#rlmB?QExTtf#)%giA*PrLQ(;eD(+QmKGk!^nByv)S?TEJ`E`tdy5N{T zzz=bv%jzv3DGfvlUhE3J6LzG+lX{MOG-s+CM4+PECbOGrH-q+9$)tR>PM`iRjRb}% zJ0it;qWB zDM)~%Zuor4#-J<$6NIQ6Cf=anJ$ST$vha6|AHi$f$iYuUh_hic6I_vBEy$8M1Yspc zmflw+JOz)q{66gX>NKqIIDjug^1FjIa<%(yXTFLh&Tkl|(93o5!WR=_9x*YF8Z+B>8&D>;ix+fKGu z7?;6Ga+AVX4O>APe@*V;A<3*FH)=&DOd7G29r+JvCG&O3ntAzp4SRrb({D#i6nBnE zX*WbKEgFz{NPfQ8|-dEm+=|Kph4nq(IhD8u^Xgmm^wu;t!;Zp0S=eUiA7e$g|Q#8xG z2eC5}AEN}K(+V6|cjQtXUnWzlNXGIBY^P$SnnWs&pQ3>idin35Kxof-w3is=fkmRl z>gi&Cg~2is*X|bW8THt9@4yhv4-OU?KTYIvvH)An)C#91IRAw6GG%Gsq=d@n!HXxH zbo_W8_=NNMwZ+{QK8FvJ!jcMV0RSjMc@`A`rrw8}6=q6L{1wCIDD3|g|N z8=$0_WSR!(X(ibvvM!*FnkpC<>8TFlBg95ymgWIUKp2YHLuxvt)sXs|2vW(Va`O9t zN7)LQR#NNIPwRTpHLOR_F$2#~vS=hG2VNZU0ClIDAeSbr(6E=RrB*;fyhGG~!Z#zz z;g(JEsS0}PUumBhpY9liy_2>kM^4oVr&_Hp?us@@QR;Xk-b(<0LExRtJVhG7oZdS+ z^s=y-P8wJOc}s9G9Au@tzE@2H5yTfVNkrZ&A~mT_cDpqEH_`R)cw|IU(#O(6BaQXI z_Q?5@+p__rY_Ue-ruGgDHwH&$$>TdAZ-jIh|1AtpH}uB@?b*ps(DomAr;?)(C~(91W5nTlu;U-pL+(g;2>pKc3p`LN=Iy}`<3Su z*{{<(md15WMS{iorbZl2>m^X(>?Tq&>1s?*SG@6v zG@G`5nf=sHor%PQ!6uPEqGM5l?Au^~#T>SWO~6_!_Y6{h zH<0Qi1t+vKbY&#NF<|(0OhD`gcHV*H8+oz1=%L#B{yR zy$-L}$71l|tX;S#2B1wM*4(|xU&bcqabvh=lj@l?CLZok?SLDl6puW8{-;>)Q#=t7 zR=azEt1hbNai`-E$3?ikv1Awe~#!>v$y;{QY~qL^~!s8 zn4acnA0tTaTS78hTcx&>R6K&BQb^-lih*n!BRr~ zqgI*VfT>!i*6&d9T`J@!MuTwsBKu|JBE1Uv;XNa%7srzLm&f`ktwcsYwR{pH^Ov^C z)qj`f7@X9wv|8!L{(xGw6#kt;Kyl3kBVB~cu}L!XhINDv2ZGyxQX~<&cL^IA1Pjjv5;kHgrf$HS-+-Fi&^IYRYHT7q4P|Am zrAjQbrY<8YApOv*UKxf)(!k2_NZ#_bGA%BRgY51&Fq1EeP5t1}vkwJO( zjL0oLd&UbIA@f8g4wvr4@KP=2QG?VwGC9J@MSvpu8@$Gl=TP-S6v*Z)5wVS-m5>1e z&OR}=Wsg7-oz6J?k^Gx@ z0!Mp4HIq-jwG$ZrzfRBp7N6snQ2+-XUc&I8OwtUSO>Wv!x7qYK|2yga!dzbUX$p{GxIZWDI zjw+cJoGx&tjMjvS9pH}q6!jD&TpbLilS6g~|A>$(p$W95PU0l>=F@9y*aZZ8C2FyE z{`Dfg+R80^F)~!h2&8(*r4`7&q-=eZphu`6IhDLB$umaAk!}##bLl@7oF`U}NU_4W kjuZrC4R-!01z1q$5R$?CY9+mFYZ?6W%P(cG*?KYmf4f#9YybcN literal 0 HcmV?d00001 diff --git a/src/snake/core/phantom/__pycache__/utils.cpython-310.pyc b/src/snake/core/phantom/__pycache__/utils.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3461e798b0d093934373e66a63fc78cf28f10ce2 GIT binary patch literal 595 zcmYjPv5wR*5VajU*}Y4af&$&qtmsm(`GFGx-BlD@K(|d4#oj%OIF7~+(ncw15g))8 z+%LJMx?i9G#>;|kr1xg#$+F+rwncG4FurZSA6`;Ie#GW!6xh5)xc5ks?1-e2b=0sO zqp?o9#PA)bWXa`93dLlK$dr%^m8$HD$R*Yn@^YWcTozx%ZXqu}lJeQ~V)VMxUMsiW zTUZbGP4BI7n@2o|lr&`9yLSN1@qq?DS!*5>)PvCdF#3?%(Z@`6pi>YQq=Jxw@+0)y zR>UpN5$lLsgu6!aWF|AaB6BixNxvpDo!JeM3{54|^AF1DNv-`oLOVAqw<#&aJK91t zPzp#fK^AEdX&EUlcp#8t`gvD6<;#B1_WOXfVTh}4)M>8BZ{y6CV0C8<7T&q#) zr8dn$0gqaudmn@!hfW2t?`-2w8=kyBq4@A&abv6;JM{*?263;DILTSg80WtkW&e@> ItJ&(;AJu%5ZvX%Q literal 0 HcmV?d00001 diff --git a/src/snake/core/phantom/data/__pycache__/__init__.cpython-310.pyc b/src/snake/core/phantom/data/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4263b21f6cdd6d2463479696f7ba17407e1f8e9f GIT binary patch literal 225 zcmYjLK?=e!5KMcq2>u~gLCwLdh|sGP!JC&5nr$sMSxL5ne!>U%0>9+dUwCqBFAnT1 zGq5v@lgU^x?!}{C@_zT?9|?;MPt2ICI0&2U#WcOma`a>x4?$KKBppFoLq-zH8rU@i za(6VI(8WbDO^yudi(7&~`1X`=?{yl8G-dPCl~$ literal 0 HcmV?d00001 diff --git a/src/snake/core/sampling/__pycache__/__init__.cpython-310.pyc b/src/snake/core/sampling/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..141cadf619319ad683b2248f8f5e497ab5b642f7 GIT binary patch literal 491 zcmZvYy-ve05XbE_UzBzOl>s5v3~dG$284jB5(rd~f*8D5CUz@RI}Ub=R9=DyU}J+v z%F4tmFkzDxG4v$=Io=4Ak&ICc!4y#c4WbPiWFQHjcP{%`NpiMth%5y!ru$OSxnP4Y`zlCa zy?I6q%UqJ_B&d6%n~MW_nm^9D;T2cKGF5M770GAUldR;Lh*flNtcoGg6*HU^YgE0_ z-THRhSBlVEO&(ZYDZN+?5Nh{v9XYfdLI>X=uox%pI>MN$9OK%*x0Ceb1 zeIs|>oQw#8@jK8R*UsVlJbhAvR9vuhNO-|hQ*k-B5tf>Q%vgUSwGHaLanoFBn^|r$ c#n?(Jj0feSj*ptX9=o-g*un=LZx?prAIuAhbN~PV literal 0 HcmV?d00001 diff --git a/src/snake/core/sampling/__pycache__/base.cpython-310.pyc b/src/snake/core/sampling/__pycache__/base.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fa4fdd5361a3709f71c47e58e372fff640773bd8 GIT binary patch literal 2146 zcmZt{%Wf1$a9+DJJNvK+7H^VKLJ~HD@hvCEg4h;9N_>bz4uh=Lu-&^1na5Jyi|~q5 z%r(k25{d*ze@p(LuQ_q%#wk@jGkAIQYHO;htE%hST@8n!h3l{V7qfpmmh~SIs|$J7 zEz7dy6GXU`Sls4LZWm7C*o3>eo4EM(aRZ2h^%|t06 zRasTa_%%5^wsk)(%SzSEeWZh(JeBgd6cG3KcW(ovM~IGo7AoD{`9;h!iMC!lwRZ0y zD|V`Kn$0F;Z*|#7+@d6GAR?^9#zZ*W#=xD#GcJ0%Pgaea0+#2AFsDb;3ZjNBW9>@{ zM8N*IqXWjuv=EHxkg=lTi=6NQV~-bU-t72{@oIwXK3|kvfYCUyU=1BH;O*|_lPbrU zbFsOTW@WZ1RaPvJBQ|B3{w{7#3qU4JYI1W@0q!*E+#wIjr=qz0(IAWd@`Si3&VIA4p zMb&GFNC&}&yIfldHpV?2;F%1An}UxLKweKswq1l%I26ho+Evyc_SjxtxKm#SrpB0t zTtrjA$%;>GeRjW6cWLAbfgQv504g|f;0kKP=LFtOQtjlBNn?Q-3uBacL&ti~^5Uwy z?@4{+q>CCR-!~A!Oj~e9VaB!tI|euXr1aSt!JmSgI08jN}|=;47ryYXV;q_#mJW)`^jsTKgu7NUBoT3GIR1wL@olX*II<#kJ2< zh4ZK0_6y+gZcR)mz;+SdRt3I50xNQD@9De(6;TLgVpp$j9LgzPS208+?AEooj`$}F zvX*kr(mZGBrA$}@v4Z;BDjp_&U&M{t!SO-a5b>^lOdB{3LH1DruX&xs`ckZ#;C zumdcK;|%Q33%ya#$lx^f3Vcn>gpJp0C-A|TE^zemE&*y!xQIY^@e092164#1%0)3h ziW?RMto!Cch#8p!df0V%I^|~Ow4ccWFw5FSU|s;@#HS+A!B+ifZBzBl)96_PheE&~ L1`#;x?z!&&;z}EO literal 0 HcmV?d00001 diff --git a/src/snake/core/sampling/__pycache__/factories.cpython-310.pyc b/src/snake/core/sampling/__pycache__/factories.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e048696286eaf8de3efdc12928badc841cc77738 GIT binary patch literal 12568 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 C|Il9m literal 0 HcmV?d00001 diff --git a/src/snake/core/sampling/__pycache__/samplers.cpython-310.pyc b/src/snake/core/sampling/__pycache__/samplers.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a82e926e82bc45924fb29bd07d8538e283c002b6 GIT binary patch literal 13833 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 WQmKIUV(M^eU+Rr`Kc>By9QhyB;Hsbi literal 0 HcmV?d00001 diff --git a/src/snake/mrd_utils/__pycache__/__init__.cpython-310.pyc b/src/snake/mrd_utils/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4be9f46c3b9e2235f79af99c09b95faf2b163152 GIT binary patch literal 605 zcmZ{hy^ho{5XYVG{mPw?C=f^}B`LT_Cq#u1r(I}(6>yy!%Nsj~!5=3(dnb4a9)OOH zS8_|mD^M|$MJI%WrTpUgJ2U^x*wyud!1}WNdhsA7K*x-d(+oU~l8Oik;ATo6%wOX!g(&q-T-zW@5& zrWur$jk2Tk1Mg*M2Irge?b*xcCqEOgZOeFP&HX5Y;`W8-MsE1XUpX$Mk8>#SXM1n! z?0>&Iy5v4c7L;MVvqQXlh_CsT1Uti&#TOryv+>wVE|~Fxy@!qTZ5Fe$_1jqQ9zT+{ zcS4@J-G^8MPH&_(iM8P$CEIcEf#i1KXYltvL*N{Jjwlc%Vu`2_a|B+*wmps&W5V@} z#Zpf#9&)ED{}jO7SnNlo!@=sNPAspzf_Y9JSdnYZ*mvS@p%dcQrn_<)`qi>qb7fT* zMrHP($SzpuKF`5jf|aKeu}dv#)-X_Pw}Dxwvdx1y**nctMoV7 CP@_Zu literal 0 HcmV?d00001 diff --git a/src/snake/mrd_utils/__pycache__/loader.cpython-310.pyc b/src/snake/mrd_utils/__pycache__/loader.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d685f31b41b490ebdf625f860afd31f971f38fea GIT binary patch literal 13905 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 ZvRTb4e{D@`=gMDeC$f-2Q-}ZO{{dPL|7`#O literal 0 HcmV?d00001 diff --git a/src/snake/mrd_utils/writer.py b/src/snake/mrd_utils/writer.py index 3a62367a..7b04ab0b 100644 --- a/src/snake/mrd_utils/writer.py +++ b/src/snake/mrd_utils/writer.py @@ -22,7 +22,7 @@ log = logging.getLogger(__name__) -def get_mrd_header(sim_conf: SimConfig, engine: str) -> mrd.xsd.ismrmrdHeader: +def get_mrd_header(sim_conf: SimConfig, engine: str, model: str, slice_2d: bool) -> mrd.xsd.ismrmrdHeader: """Create a MRD Header for snake-fmri data.""" H = mrd.xsd.ismrmrdHeader() # Experimental conditions @@ -78,6 +78,13 @@ def get_mrd_header(sim_conf: SimConfig, engine: str) -> mrd.xsd.ismrmrdHeader: ("rng_seed", sim_conf.rng_seed), ("max_sim_time", sim_conf.max_sim_time), ] + ], + userParameterString=[ + mrd.xsd.userParameterStringType(name=name, value=value) + for name, value in [ + ("engine_model", model), + ("slice_2d", str(slice_2d)), + ] ] ) @@ -204,6 +211,8 @@ def make_base_mrd( handlers: list[AbstractHandler] | HandlerList | None = None, smaps: NDArray | None = None, coil_cov: NDArray | None = None, + model: str = "simple", + slice_2d: bool = False, ) -> mrd.Dataset: """ Create a base `.mrd` file from the simulation configurations. @@ -233,7 +242,7 @@ def make_base_mrd( pass dataset = mrd.Dataset(filename, "dataset", create_if_needed=True) dataset.write_xml_header( - mrd.xsd.ToXML(get_mrd_header(sim_conf, sampler.__engine__)) + mrd.xsd.ToXML(get_mrd_header(sim_conf, sampler.__engine__, model, slice_2d)) ) with PerfLogger(logger=log, name="acq"): sampler.add_all_acq_mrd(dataset, sim_conf) diff --git a/src/snake/toolkit/__pycache__/__init__.cpython-310.pyc b/src/snake/toolkit/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d922425b0f7681c83c171f97dc9a7cb77586d0f2 GIT binary patch literal 189 zcmd1j<>g`kf_}f*>5@SDF^Gc<7=auIATH(r5-AK(3@MDk44O<;LLvG2IoX*d3TgR8 z3c-Gk-mZFnnvA#D2iJ5ts`o$%gxurmn zRQ=+-#OzevwA><~U{NxJt6u^!T0cG>sJJ9PUaz3?7Kcr4eoARhsvXEd#UQge7yv<4 BFvS1> literal 0 HcmV?d00001 diff --git a/src/snake/toolkit/analysis/__pycache__/stats.cpython-310.pyc b/src/snake/toolkit/analysis/__pycache__/stats.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..459d21307cf15c1c03c16e628f7e6bf4ba1944c1 GIT binary patch literal 3743 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 literal 0 HcmV?d00001 diff --git a/src/snake/toolkit/cli/__pycache__/__init__.cpython-310.pyc b/src/snake/toolkit/cli/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d7b853c80902b243b963d36eb48db3d684d1e8bb GIT binary patch literal 209 zcmd1j<>g`kf_}f*>6$?LF^Gc<7=auIATH(r5-AK(3@MDk44O<;N=nZ8xw(mXDGENB zd8rDXc_pbuX^F|H3TgR83c-Gk-mZFnnvA#DTX}Lu}!J=dcSHC1bKPNl0L_awvQ$Ic)sG%f2 ZUaz3?7Kcr4eoARhsvXFY#US%J7yyjlH>3an literal 0 HcmV?d00001 diff --git a/src/snake/toolkit/cli/__pycache__/acquisition.cpython-310.pyc b/src/snake/toolkit/cli/__pycache__/acquisition.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..24ad1d0869a5f0f97c3575a103aa09afbe3d3a11 GIT binary patch literal 2533 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 literal 0 HcmV?d00001 diff --git a/src/snake/toolkit/cli/acquisition.py b/src/snake/toolkit/cli/acquisition.py index 6d902b19..dd49de11 100644 --- a/src/snake/toolkit/cli/acquisition.py +++ b/src/snake/toolkit/cli/acquisition.py @@ -8,6 +8,7 @@ from snake.core.phantom import Phantom from snake.core.smaps import get_smaps from snake.toolkit.cli.config import ConfigSNAKE, cleanup_cuda, make_hydra_cli +import os log = logging.getLogger(__name__) @@ -52,19 +53,33 @@ def acquisition(cfg: ConfigSNAKE) -> None: if engine_klass.__engine_name__ == "NUFFT": kwargs["nufft_backend"] = cfg.engine.nufft_backend engine = engine_klass(model=cfg.engine.model, snr=cfg.engine.snr, slice_2d=cfg.engine.slice_2d) # type: ignore - - engine( - cfg.filename, - sampler=sampler, - phantom=phantom, - sim_conf=sim_conf, - handlers=handlers, - smaps=smaps, - coil_cov=None, # FIXME: Add coil covariance in scenarios - worker_chunk_size=cfg.engine.chunk_size, - n_workers=cfg.engine.n_jobs, - **kwargs, - ) + if os.path.exists(cfg.filename): + log.warning(f"File '{cfg.filename}' already exists!") + while True: + choice = input("Overwrite? (y/n): ").strip().lower() + if choice == 'y': + log.info("User chose to overwrite.") + break + elif choice == 'n': + log.info("User chose to abort.") + log.info("Acquisition file not modified.") + overwrite = False + break + else: + log.warning("Invalid input, please enter 'y' or 'n'.") + if overwrite: + engine( + cfg.filename, + sampler=sampler, + phantom=phantom, + sim_conf=sim_conf, + handlers=handlers, + smaps=smaps, + coil_cov=None, # FIXME: Add coil covariance in scenarios + worker_chunk_size=cfg.engine.chunk_size, + n_workers=cfg.engine.n_jobs, + **kwargs, + ) log.info("Acquisition done") log.info("Output file is at %s", cfg.filename) diff --git a/src/snake/toolkit/cli/config.py b/src/snake/toolkit/cli/config.py index 7611cf82..39d2a4e2 100644 --- a/src/snake/toolkit/cli/config.py +++ b/src/snake/toolkit/cli/config.py @@ -125,5 +125,5 @@ def cleanup_cuda() -> None: def make_hydra_cli(fun: callable) -> callable: """Create a Hydra CLI for the function.""" return hydra.main( - version_base=None, config_path="../../../cli-conf", config_name="config" + version_base=None, config_path="../../../cli-conf", config_name="scenario2-2d" )(fun) diff --git a/src/snake/toolkit/cli/reconstruction.py b/src/snake/toolkit/cli/reconstruction.py index ab456d89..b6519af5 100644 --- a/src/snake/toolkit/cli/reconstruction.py +++ b/src/snake/toolkit/cli/reconstruction.py @@ -53,7 +53,7 @@ def reconstruction(cfg: DictConfig) -> None: # array = Reconstructor.reconstruct(dataloader, sim_conf) with DataLoader(cfg.filename) as data_loader: for name, rec in cfg.reconstructors.items(): - rec_str = str(rec) # FIXME Also use parameters of reconstructors + rec_str = str(rec) # FIXME Also use parameters of reconstructors maybe just name??? data_rec_file = Path(f"data_rec_{rec_str}.npy") log.info(f"Using {name} reconstructor") rec.setup(sim_conf) diff --git a/src/snake/toolkit/reconstructors/__pycache__/__init__.cpython-310.pyc b/src/snake/toolkit/reconstructors/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..201eb824a3b8fad46ca8996bcc7d8c1a122d5c1f GIT binary patch literal 420 zcmY*Vu};G<5VaGB7Su{GbK~{O0*SE_bjxCy*bP?gIM@!T`~)As#>OvsW#Si@ zIK$BPBtPA|dw2G;olZ{>#M|<{B^aTvMD`;Cas|hq0|-5_M literal 0 HcmV?d00001 diff --git a/src/snake/toolkit/reconstructors/__pycache__/base.cpython-310.pyc b/src/snake/toolkit/reconstructors/__pycache__/base.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6725b4c6adb67a49f6dc6fbf7edd763b31ad77d7 GIT binary patch literal 2400 zcmZuy&2JM&6rY)0+iQFMnUIha!nSJFx&>R6D)oX8G*qZ6@gWE*?PaxiX3fU?VP?lf zUO`n6uBcM42njBg`Y-LZC(ga~Q2O31X>GzJ^ZeeMH?!~KH*eBbt3hD=I({)ds1oug z3ag_6!gZM0??5TxId?g4)#0RV}ZY0aX(tGdu@{LiNwhx5zZ|)z8X_zS?VMG1k@aFB*=cRBb zjQ7(d2&WS~dv#C{uEWeWfe7MK$Rgtuvc_Cf`)d|GJblf{{5-142-X&cMN6(mGagh5 z%kvUH7M@o$JTFf9B0}EwyoU=vdbd*ZJf2QK-QPK`cQjC#5)2X&TK!HCl5g8{LQ059dpXxN2eC04rhqiYORX}Qr3a>t=t}QB} zCRzd0E48bHTfF{^xNY75U^Tf7P-^iu0H*|)){1^m0J8y3{i26(TB}0-?V*@U zk%>fQj(Q-RFacBq{zN!ZJY0lQa7U%ieF6W;d~{LVP#?LK^#F*l|n6KGM?bp z)1i+6LA$dH%wuvyUQtfrmmL`|$V>K`LQi1eq>=C35z1N2bzax9Gt4((30Bs$&Uj$T zZ8)?r!z4(Hy5~*s=0j?2&<>cyFG`H({fH|W9``Ykt z7@rR0*HW#>Q#zpeS1W+gq0F*5;seh?Y=p5t6^_;op&}dORQ(XoBM}3p1pi*jR1S>N z^-tgvAN0Sul8DdH=mL=Z;@KEh>;{`UEfVjhY$NF)!A4)0Je;Va<9U9PqzZZgbWOw` zw9dkepz{?qfZ{YvrbYEOFhWWUU+y45n8}Zj)RACTrG*4jD?df@U$ZGWM4j9Kf>Za$ z2J{J=*|baBbeCDIZ|<7f0vm1&9Z^@dFtMr0J=nE|di)T!9SyTw|B)X?c;y{m3V>)uhavG1D6AjFQWv;r-1DP_ zDESRc@OnGQ0KAuR2Nf&1)0ee374I2;35Gg}3=-I;43fy+GRFR~eqnFr*RVQ)xi+wP zI$4MVMHD?^uZ-8^gkrPE_ilqjD}k(l2wzdSbzi`?mAK5ASY|7Z>T>HMkHGL7nEINv znM8T8rICkSES@iiYB>j7m0%gba(Ux)y+x*BR#e~FXryVtRy+iStf75Jzf!|ka&G~z zSf;^OoGZ1HREi-qDSXcW)g?p`E2aCN;{hfdFLa{Hz|hGLMN?Q;%SZMa-uvu45R=$| RR>ZBX|GGxMy0yL4_!oOBSaARV literal 0 HcmV?d00001 diff --git a/src/snake/toolkit/reconstructors/__pycache__/fourier.cpython-310.pyc b/src/snake/toolkit/reconstructors/__pycache__/fourier.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ac734046efd7fb6a24eabf0869b0116445b70dd8 GIT binary patch literal 1196 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 +License: Copyright 2023 SNAKE-fMRI Contributors + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Project-URL: Homepage, https://github.com/paquiteau/simfmri +Project-URL: Bug Reports, https://github.com/paquiteau/simfmri/issues +Project-URL: Source, https://github.com/paquiteau/simfmri +Keywords: simulation,fMRI +Classifier: Development Status :: 3 - Alpha +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: MIT License +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 +Classifier: Programming Language :: Python :: 3.12 +Requires-Python: >=3.10 +Description-Content-Type: text/markdown +License-File: LICENSE.txt +Requires-Dist: numpy +Requires-Dist: scipy +Requires-Dist: nilearn +Requires-Dist: pandas +Requires-Dist: scikit-image +Requires-Dist: brainweb-dl +Requires-Dist: mri-nufft +Requires-Dist: ismrmrd +Requires-Dist: hydra-core +Requires-Dist: hydra-callbacks +Requires-Dist: hydra-colorlog +Provides-Extra: dev +Requires-Dist: black; extra == "dev" +Requires-Dist: ruff; extra == "dev" +Requires-Dist: isort; extra == "dev" +Provides-Extra: test +Requires-Dist: pytest; extra == "test" +Requires-Dist: pytest-cov; extra == "test" +Requires-Dist: pytest-sugar; extra == "test" +Requires-Dist: pytest-xdist; extra == "test" +Provides-Extra: doc +Requires-Dist: myst-parser; extra == "doc" +Requires-Dist: sphinx-copybutton; extra == "doc" +Requires-Dist: sphinx-gallery; extra == "doc" +Requires-Dist: sphinx-book-theme; extra == "doc" +Requires-Dist: matplotlib; extra == "doc" +Requires-Dist: pysap-fmri; extra == "doc" +Requires-Dist: ipywidgets; extra == "doc" +Provides-Extra: toolkit +Requires-Dist: matplotlib; extra == "toolkit" +Requires-Dist: pysap-fmri; extra == "toolkit" + +# SNAKE-fMRI: Simulator from neuro-activation to K-space Exploration + + + +

A Simulator from Neurovascular coupling to Acquisition of K-space data for Exploration of fMRI Technique

+ + +[![Test](https://github.com/paquiteau/snake-fmri/actions/workflows/test.yml/badge.svg)](https://github.com/paquiteau/snake-fmri/actions/workflows/test.yml) +[![deploy-docs](https://github.com/paquiteau/snake-fmri/actions/workflows/deploy-docs.yml/badge.svg)](https://paquiteau.github.io/snake-fmri) +[![HAL](https://img.shields.io/badge/preprint-04533862-purple?logo=HAL&logoColor=white)](https://hal.science/hal-04533862) + +[![python](https://img.shields.io/badge/python-3.10%2B-blue?logo=python&logoColor=blue)](https://pypi.org/project/snake-fmri) +![black](https://img.shields.io/badge/code--style-black-black) +![ruff](https://img.shields.io/badge/lint-ruff-purple?logo=stackblitz&logoColor=yellow) + + + +This package provides a simulation and reconstruction framework for fMRI data. It is designed to be used for benchmarking and testing of fMRI reconstruction methods. + + +## Installation +### Requirements +- A working Python 3.10 environment or higher +- Optional: a working CUDA environment for NUFFT accelerations. See [mri-nufft](https://github.com/mind-inria/mri-nufft) for details. SNAKE works best with a fast GPU NUFFT Backend such as [cufinufft](https://github.com/flatironinstitute/finufft) or [gpuNUFFT](https://github.com/chaithyagr/gpuNUFFT) + + +### from PyPA (soon) + +It is recommended to install the SNAKE toolkit on top of the core runtime (the toolkit contains reconstructors, statistical analysis tool and the CLI to run experiments). + +``` sh +pip install snake-fmri[toolkit] +``` + +Some Reconstructors requires extra dependencies such as [pysap-fmri](https://github.com/paquiteau/pysap-fmri) or [patch-denoising](https://github.com/paquiteau/patch-denoising) + + +### Development version + +``` sh +git clone git@github.com:paquiteau/snake-fmri +cd snake-fmri +pip install -e .[test,dev,doc,toolkit] +``` + + +## Getting Started + +Documentation is available at https://paquiteau.github.io/snake-fmri + +To get started, you can check the examples gallery: https://paquiteau/github.io/snake-fmri/examples diff --git a/src/snake_fmri.egg-info/SOURCES.txt b/src/snake_fmri.egg-info/SOURCES.txt new file mode 100644 index 00000000..8ee0d290 --- /dev/null +++ b/src/snake_fmri.egg-info/SOURCES.txt @@ -0,0 +1,100 @@ +.gitignore +LICENSE.txt +README.md +pyproject.toml +sparkling-3d.bin +.github/workflows/deploy-docs.yml +.github/workflows/tags-release.yaml +.github/workflows/test.yml +docs/api.rst +docs/conf.py +docs/extend-snake.md +docs/getting_started.md +docs/how-does-it-works.md +docs/index.md +docs/mrd-simulation.md +docs/_static/logos/snake-fmriV2-logo.png +docs/_static/logos/snake-fmriV2-logo_dark.png +docs/_templates/autosummary/base.rst +docs/_templates/autosummary/class.rst +docs/_templates/autosummary/function.rst +docs/_templates/autosummary/module.rst +docs/misc/contributors.md +docs/misc/development.md +docs/misc/license.md +examples/README.md +examples/conftest.py +examples/example_EPI_2D.py +examples/example_T2s_EPI.py +examples/example_anat_EPI.py +examples/example_generate_phantom.py +examples/example_gpu_anat_spirals.py +examples/example_gpu_anat_spirals_slice.py +src/cli-conf/__init__.py +src/cli-conf/config.yaml +src/cli-conf/scenario1-EVI.yaml +src/cli-conf/scenario1.yaml +src/cli-conf/scenario2-multi.yaml +src/cli-conf/scenario2-noise.yaml +src/cli-conf/scenario2.yaml +src/cli-conf/scenario3-tpz.yaml +src/cli-conf/scenario3.yaml +src/snake/__init__.py +src/snake/_meta.py +src/snake/_version.py +src/snake/core/__init__.py +src/snake/core/parallel.py +src/snake/core/simulation.py +src/snake/core/smaps.py +src/snake/core/engine/__init__.py +src/snake/core/engine/base.py +src/snake/core/engine/cartesian.py +src/snake/core/engine/nufft.py +src/snake/core/engine/utils.py +src/snake/core/handlers/__init__.py +src/snake/core/handlers/base.py +src/snake/core/handlers/noise.py +src/snake/core/handlers/utils.py +src/snake/core/handlers/activations/__init__.py +src/snake/core/handlers/activations/activations.py +src/snake/core/handlers/activations/bold.py +src/snake/core/handlers/activations/roi.py +src/snake/core/handlers/motion/__init__.py +src/snake/core/handlers/motion/image.py +src/snake/core/handlers/motion/utils.py +src/snake/core/phantom/__init__.py +src/snake/core/phantom/dynamic.py +src/snake/core/phantom/shepp_logan.py +src/snake/core/phantom/static.py +src/snake/core/phantom/utils.py +src/snake/core/phantom/data/__init__.py +src/snake/core/phantom/data/tissues_properties_1T5.csv +src/snake/core/phantom/data/tissues_properties_7T.csv +src/snake/core/sampling/__init__.py +src/snake/core/sampling/base.py +src/snake/core/sampling/factories.py +src/snake/core/sampling/samplers.py +src/snake/mrd_utils/__init__.py +src/snake/mrd_utils/loader.py +src/snake/mrd_utils/utils.py +src/snake/mrd_utils/writer.py +src/snake/toolkit/__init__.py +src/snake/toolkit/plotting.py +src/snake/toolkit/analysis/metrics.py +src/snake/toolkit/analysis/stats.py +src/snake/toolkit/cli/__init__.py +src/snake/toolkit/cli/acquisition.py +src/snake/toolkit/cli/config.py +src/snake/toolkit/cli/main.py +src/snake/toolkit/cli/reconstruction.py +src/snake/toolkit/reconstructors/__init__.py +src/snake/toolkit/reconstructors/base.py +src/snake/toolkit/reconstructors/fourier.py +src/snake/toolkit/reconstructors/pysap.py +src/snake_fmri.egg-info/PKG-INFO +src/snake_fmri.egg-info/SOURCES.txt +src/snake_fmri.egg-info/dependency_links.txt +src/snake_fmri.egg-info/entry_points.txt +src/snake_fmri.egg-info/requires.txt +src/snake_fmri.egg-info/top_level.txt +tests/test_snake.py \ No newline at end of file diff --git a/src/snake_fmri.egg-info/dependency_links.txt b/src/snake_fmri.egg-info/dependency_links.txt new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/src/snake_fmri.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/src/snake_fmri.egg-info/entry_points.txt b/src/snake_fmri.egg-info/entry_points.txt new file mode 100644 index 00000000..9edc5c07 --- /dev/null +++ b/src/snake_fmri.egg-info/entry_points.txt @@ -0,0 +1,4 @@ +[console_scripts] +snake-acq = snake.toolkit.cli.acquisition:acquisition_cli +snake-main = snake.toolkit.cli.main:main_cli +snake-rec = snake.toolkit.cli.reconstruction:reconstruction_cli diff --git a/src/snake_fmri.egg-info/requires.txt b/src/snake_fmri.egg-info/requires.txt new file mode 100644 index 00000000..53914332 --- /dev/null +++ b/src/snake_fmri.egg-info/requires.txt @@ -0,0 +1,35 @@ +numpy +scipy +nilearn +pandas +scikit-image +brainweb-dl +mri-nufft +ismrmrd +hydra-core +hydra-callbacks +hydra-colorlog + +[dev] +black +ruff +isort + +[doc] +myst-parser +sphinx-copybutton +sphinx-gallery +sphinx-book-theme +matplotlib +pysap-fmri +ipywidgets + +[test] +pytest +pytest-cov +pytest-sugar +pytest-xdist + +[toolkit] +matplotlib +pysap-fmri diff --git a/src/snake_fmri.egg-info/top_level.txt b/src/snake_fmri.egg-info/top_level.txt new file mode 100644 index 00000000..c8026f82 --- /dev/null +++ b/src/snake_fmri.egg-info/top_level.txt @@ -0,0 +1,2 @@ +cli-conf +snake From d6d98244e59e664a9f520cccf88a14e8ea6451a9 Mon Sep 17 00:00:00 2001 From: alineyyy Date: Thu, 30 Jan 2025 15:41:42 +0100 Subject: [PATCH 02/15] update --- src/cli-conf/scenario2-2d.yaml | 93 ---------------------------- src/snake/toolkit/cli/acquisition.py | 41 ++++-------- 2 files changed, 13 insertions(+), 121 deletions(-) delete mode 100644 src/cli-conf/scenario2-2d.yaml diff --git a/src/cli-conf/scenario2-2d.yaml b/src/cli-conf/scenario2-2d.yaml deleted file mode 100644 index 23f721db..00000000 --- a/src/cli-conf/scenario2-2d.yaml +++ /dev/null @@ -1,93 +0,0 @@ -# This files contains the configuration to reproduce the scenario 1 of the Snkf paper. - -defaults: - - base_config - - handlers: - - activation-block - - sampler: - - stack-of-spiral - - reconstructors: - - adjoint - #- sequential - - _self_ - -cache_dir: ${oc.env:PWD}/cache -result_dir: results/scenario2 -filename: ${cache_dir}/scenario2_2d_${engine.model}_${engine.snr}_${sampler.stack-of-spiral.constant}_${sampler.stack-of-spiral.accelz}.mrd - -sim_conf: - max_sim_time: 360 - seq: {TR: 50, TE: 25, FA: 12} - hardware: - n_coils: 1 - dwell_time_ms: 0.001 - shape: [60, 72, 60] - fov_mm: [181.0, 217.0, 181.0] - -phantom: - name: brainweb - sub_id: 4 - tissue_file: "tissue_7T" - -handlers: - activation-block: - event_name: block_on - block_on: 20 # seconds - block_off: 20 #seconds - duration: 360 # seconds - #delta_r2s: 1000 # millisecond^-1 - -sampler: - stack-of-spiral: - acsz: 1 - accelz: 1 - nb_revolutions: 10 - constant: true - spiral_name: "galilean" - -engine: - n_jobs: 1 - chunk_size: 10 - model: "simple" - snr: 10000 - nufft_backend: "gpuNUFFT" - slice_2d: true - -reconstructors: - adjoint: - nufft_backend: "gpuNUFFT" - density_compensation: "pipe" - # sequential: - # nufft_backend: "gpuNUFFT" - # density_compensation: false - # restart_strategy: WARM - # max_iter_per_frame: 50 - # wavelet: "sym4" - - - - - -hydra: - job: - chdir: true - - run: - dir: ${result_dir}/outputs/${hydra.job.name}/${now:%Y-%m-%d_%H-%M-%S} - sweep: - dir: ${result_dir}/multirun/${hydra.job.name}/${now:%Y-%m-%d_%H-%M-%S} - subdir: ${hydra.job.num} - - callbacks: - # gather_files: - # _target_: hydra_callbacks.MultiRunGatherer - # aggregator: - # _partial_: true - # _target_: snkf.cli.utils.aggregate_results - - log_job: - _target_: hydra.experimental.callbacks.LogJobReturnCallback - latest_run: - _target_: hydra_callbacks.LatestRunLink - run_base_dir: ${result_dir}/outputs - multirun_base_dir: ${result_dir}/multirun diff --git a/src/snake/toolkit/cli/acquisition.py b/src/snake/toolkit/cli/acquisition.py index dd49de11..6d902b19 100644 --- a/src/snake/toolkit/cli/acquisition.py +++ b/src/snake/toolkit/cli/acquisition.py @@ -8,7 +8,6 @@ from snake.core.phantom import Phantom from snake.core.smaps import get_smaps from snake.toolkit.cli.config import ConfigSNAKE, cleanup_cuda, make_hydra_cli -import os log = logging.getLogger(__name__) @@ -53,33 +52,19 @@ def acquisition(cfg: ConfigSNAKE) -> None: if engine_klass.__engine_name__ == "NUFFT": kwargs["nufft_backend"] = cfg.engine.nufft_backend engine = engine_klass(model=cfg.engine.model, snr=cfg.engine.snr, slice_2d=cfg.engine.slice_2d) # type: ignore - if os.path.exists(cfg.filename): - log.warning(f"File '{cfg.filename}' already exists!") - while True: - choice = input("Overwrite? (y/n): ").strip().lower() - if choice == 'y': - log.info("User chose to overwrite.") - break - elif choice == 'n': - log.info("User chose to abort.") - log.info("Acquisition file not modified.") - overwrite = False - break - else: - log.warning("Invalid input, please enter 'y' or 'n'.") - if overwrite: - engine( - cfg.filename, - sampler=sampler, - phantom=phantom, - sim_conf=sim_conf, - handlers=handlers, - smaps=smaps, - coil_cov=None, # FIXME: Add coil covariance in scenarios - worker_chunk_size=cfg.engine.chunk_size, - n_workers=cfg.engine.n_jobs, - **kwargs, - ) + + engine( + cfg.filename, + sampler=sampler, + phantom=phantom, + sim_conf=sim_conf, + handlers=handlers, + smaps=smaps, + coil_cov=None, # FIXME: Add coil covariance in scenarios + worker_chunk_size=cfg.engine.chunk_size, + n_workers=cfg.engine.n_jobs, + **kwargs, + ) log.info("Acquisition done") log.info("Output file is at %s", cfg.filename) From 0484517512cfdb21f21e4a74a488ac1aa647ad43 Mon Sep 17 00:00:00 2001 From: alineyyy Date: Thu, 30 Jan 2025 16:38:42 +0100 Subject: [PATCH 03/15] .gitignore --- .gitignore | 3 ++- .../__pycache__/pysap.cpython-310.pyc | Bin 9806 -> 9827 bytes 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 7a540e3f..e94a2bee 100644 --- a/.gitignore +++ b/.gitignore @@ -17,7 +17,8 @@ docs_build .mypy_cache/ .ipynb_checkpoints/ .ropeproject/ - +__pycache__/ +*.egg-info/ _version.py *.mrd diff --git a/src/snake/toolkit/reconstructors/__pycache__/pysap.cpython-310.pyc b/src/snake/toolkit/reconstructors/__pycache__/pysap.cpython-310.pyc index 95aaeb582de0f1f9fe99464d2f7d8f0593b26811..ff1078883b973b2f2add75393c00703d747c15e3 100644 GIT binary patch delta 1493 zcmZ9MZD?C%6vywAq_=r#n=~&=?3SiWTg-K(bu)WGHn-ZYQ>h(gqB6vAlY0{{YhHM6 z)}}LMxE5dN<~q+@2cjsVD88G43@m<7hTs(ZpdaoB5&R&6AGWU|;`4tx%~;_6a?bxe zFXuVux%Y?Z-==%2-Q9jg{EQ2)mEzgYdNkGV749MN*q3Nree!V73>bbhSo9hpqj$w~ zJY@8ky@t>1lB#NijfhagLXF&}Mva(IqekGEqHS^FR1L*jH&q`SalH1NRWNhAjDkmO z^4||OHl7fVJtxp)=kK9y-Z3rHRNnM7S<}^YzvX^HaVZA#C>~|m&6HzGy~A)Vvoma` zVviB`z8&`PgJLot0mguFx;Y%7-M*B+i-rF7s?onr4T@|Mt$E+q?!XL&>;@)UlijK- zeni+>)bWrPrXZ^T&cbmh zK1uiY-pBf=(%TBvA)Ex}fd$$b9$`!LbU4nITJzz(?(PQkmjyJ&4-jz7kBi@*u2TKmj;HwPZ$p2<95Sk<27s6sF^wvnr;}bJZH}6Tar+kI*m4 z9qc^$`*-wxg3+G>?*KCOXJF;&X#dvJvO-Dtv%mwugTS-EexRMnFx>Zmc3&;H?*lIZ z?*e53r$gslU)=2b3lIWU-Q>9<*UP5OuV7qBp+EW`4WMs)2{=RJsfhYG%w;;B+IFCw zy-Ylh2x`Ya0zL*RfDOn($rIGzUZGYhm*z0P5pdK-4jJ$)6bX5YrzkscBlI1_>%f=5 z24%PZx(^+jlARGn{X#g7r%<))n$PiytCFjTlW;llDq@|uI_Sc6nobX9P+7;1aVHjZ zUb6YaLeN~|J<)F^vLOV1mDbbS_x%X7-5}W&SZkT43{?zVlQVD7TW;{J(~dTcqi@t#awk;#{NrVEOd(V&06F;&sfw z?LCCs0MK8)2%G|B=JEoq!aWCk2*~>+JJf_Ld;T0Oc?IODUxC{L90EE8Xl5ulD!&o< vxO`qe delta 1410 zcmZ9MU2Gdg5XWzA$FZF_wv!k;NnIzgOLJ{Wp%lVH0;Ew*BT8r$5EKc8OYWScjX#*X z<^wDNF$L5wi%y}H;Gq?tf&fA%p-S`(RjsIm5O3TQ5__P+)N)zbbvGdsIC z`=7o0`QUd4J1Ws=M3cY9)I0OH?)|bu4@QF0eOM0r9FGT|9*VBb3Yfg*ltBZAUk7f_^dg#5VpB|D+X&11Y zN5XqV#624R#ozWABKHCN+#}JTFIAAX-tC1-v{*h~EIMRh@(?e_Mw8Ppbsz@x14X_b z8x#ir8apf|cr^ZZazDZlh4uj`o+en_nc`w%i@1a92{&#d=m5uoWiE8?>ZwWdLpf|H z9MS?J;0uV5pqhKCbHpE9LFO6vM)F6|)_{#t=@f6I9vAQOU#X#X33r_<*)3z6Csc=1w-EZ$2JjhB z0tirIs`FIfx_l!$6MP=#H+)xrpV-fn{lCY*Mc^jzHE@+D2Yz}0{VS+GNr}Ibju)7# z*p43dLh=U9l;r_PExdxc)+$w2(UY5O4CaQQs24%ru@!^nZ8{(Wx=+46#_9|dpsO-K zS9oJ^;EC^HZnjHxL&*pcypU;G)wxP_t*PoKNL~Q0W40BW8II+(E*Q4qI7BFimUtl7 zoxlBDm{AW?$~E=kBe{&Y#w)o}>4co0(zA5?JBVc~02)ZEz#5=xR9ECA+|$6PfVweC z^%vo)uD%RQHCdhSO+K6-Xnqj_m}voGz%_gkd{pO4`H4_nM)Ym8?EaP)BB>sIKaxfO KwQpUf&;A2c%26!< From 72d09bcb2537fe3bd7a36b0fe54d505349c94f6e Mon Sep 17 00:00:00 2001 From: alineyyy Date: Thu, 30 Jan 2025 16:44:22 +0100 Subject: [PATCH 04/15] apply new global .gitignore rules --- .../__pycache__/__init__.cpython-310.pyc | Bin 177 -> 0 bytes src/snake/__pycache__/_meta.cpython-310.pyc | Bin 5884 -> 0 bytes .../__pycache__/_version.cpython-310.pyc | Bin 489 -> 0 bytes .../core/__pycache__/__init__.cpython-310.pyc | Bin 770 -> 0 bytes .../core/__pycache__/parallel.cpython-310.pyc | Bin 3753 -> 0 bytes .../__pycache__/simulation.cpython-310.pyc | Bin 4943 -> 0 bytes .../core/__pycache__/smaps.cpython-310.pyc | Bin 2489 -> 0 bytes .../__pycache__/__init__.cpython-310.pyc | Bin 396 -> 0 bytes .../engine/__pycache__/base.cpython-310.pyc | Bin 9031 -> 0 bytes .../__pycache__/cartesian.cpython-310.pyc | Bin 8845 -> 0 bytes .../engine/__pycache__/nufft.cpython-310.pyc | Bin 4706 -> 0 bytes .../engine/__pycache__/utils.cpython-310.pyc | Bin 2808 -> 0 bytes .../__pycache__/__init__.cpython-310.pyc | Bin 508 -> 0 bytes .../handlers/__pycache__/base.cpython-310.pyc | Bin 3986 -> 0 bytes .../__pycache__/noise.cpython-310.pyc | Bin 2075 -> 0 bytes .../__pycache__/utils.cpython-310.pyc | Bin 712 -> 0 bytes .../__pycache__/__init__.cpython-310.pyc | Bin 445 -> 0 bytes .../__pycache__/activations.cpython-310.pyc | Bin 5550 -> 0 bytes .../__pycache__/bold.cpython-310.pyc | Bin 3954 -> 0 bytes .../__pycache__/roi.cpython-310.pyc | Bin 1098 -> 0 bytes .../__pycache__/__init__.cpython-310.pyc | Bin 287 -> 0 bytes .../motion/__pycache__/image.cpython-310.pyc | Bin 3220 -> 0 bytes .../motion/__pycache__/utils.cpython-310.pyc | Bin 5191 -> 0 bytes .../__pycache__/__init__.cpython-310.pyc | Bin 371 -> 0 bytes .../__pycache__/dynamic.cpython-310.pyc | Bin 1953 -> 0 bytes .../__pycache__/static.cpython-310.pyc | Bin 9118 -> 0 bytes .../phantom/__pycache__/utils.cpython-310.pyc | Bin 595 -> 0 bytes .../data/__pycache__/__init__.cpython-310.pyc | Bin 225 -> 0 bytes .../__pycache__/__init__.cpython-310.pyc | Bin 491 -> 0 bytes .../sampling/__pycache__/base.cpython-310.pyc | Bin 2146 -> 0 bytes .../__pycache__/factories.cpython-310.pyc | Bin 12568 -> 0 bytes .../__pycache__/samplers.cpython-310.pyc | Bin 13833 -> 0 bytes .../__pycache__/__init__.cpython-310.pyc | Bin 605 -> 0 bytes .../__pycache__/loader.cpython-310.pyc | Bin 13905 -> 0 bytes .../__pycache__/utils.cpython-310.pyc | Bin 3658 -> 0 bytes .../__pycache__/writer.cpython-310.pyc | Bin 7521 -> 0 bytes .../__pycache__/__init__.cpython-310.pyc | Bin 189 -> 0 bytes .../__pycache__/stats.cpython-310.pyc | Bin 3743 -> 0 bytes .../cli/__pycache__/__init__.cpython-310.pyc | Bin 209 -> 0 bytes .../__pycache__/acquisition.cpython-310.pyc | Bin 2533 -> 0 bytes .../cli/__pycache__/config.cpython-310.pyc | Bin 4340 -> 0 bytes .../reconstruction.cpython-310.pyc | Bin 3223 -> 0 bytes .../__pycache__/__init__.cpython-310.pyc | Bin 420 -> 0 bytes .../__pycache__/base.cpython-310.pyc | Bin 2400 -> 0 bytes .../__pycache__/fourier.cpython-310.pyc | Bin 1196 -> 0 bytes .../__pycache__/pysap.cpython-310.pyc | Bin 9827 -> 0 bytes src/snake_fmri.egg-info/PKG-INFO | 113 ------------------ src/snake_fmri.egg-info/SOURCES.txt | 100 ---------------- src/snake_fmri.egg-info/dependency_links.txt | 1 - src/snake_fmri.egg-info/entry_points.txt | 4 - src/snake_fmri.egg-info/requires.txt | 35 ------ src/snake_fmri.egg-info/top_level.txt | 2 - 52 files changed, 255 deletions(-) delete mode 100644 src/snake/__pycache__/__init__.cpython-310.pyc delete mode 100644 src/snake/__pycache__/_meta.cpython-310.pyc delete mode 100644 src/snake/__pycache__/_version.cpython-310.pyc delete mode 100644 src/snake/core/__pycache__/__init__.cpython-310.pyc delete mode 100644 src/snake/core/__pycache__/parallel.cpython-310.pyc delete mode 100644 src/snake/core/__pycache__/simulation.cpython-310.pyc delete mode 100644 src/snake/core/__pycache__/smaps.cpython-310.pyc delete mode 100644 src/snake/core/engine/__pycache__/__init__.cpython-310.pyc delete mode 100644 src/snake/core/engine/__pycache__/base.cpython-310.pyc delete mode 100644 src/snake/core/engine/__pycache__/cartesian.cpython-310.pyc delete mode 100644 src/snake/core/engine/__pycache__/nufft.cpython-310.pyc delete mode 100644 src/snake/core/engine/__pycache__/utils.cpython-310.pyc delete mode 100644 src/snake/core/handlers/__pycache__/__init__.cpython-310.pyc delete mode 100644 src/snake/core/handlers/__pycache__/base.cpython-310.pyc delete mode 100644 src/snake/core/handlers/__pycache__/noise.cpython-310.pyc delete mode 100644 src/snake/core/handlers/__pycache__/utils.cpython-310.pyc delete mode 100644 src/snake/core/handlers/activations/__pycache__/__init__.cpython-310.pyc delete mode 100644 src/snake/core/handlers/activations/__pycache__/activations.cpython-310.pyc delete mode 100644 src/snake/core/handlers/activations/__pycache__/bold.cpython-310.pyc delete mode 100644 src/snake/core/handlers/activations/__pycache__/roi.cpython-310.pyc delete mode 100644 src/snake/core/handlers/motion/__pycache__/__init__.cpython-310.pyc delete mode 100644 src/snake/core/handlers/motion/__pycache__/image.cpython-310.pyc delete mode 100644 src/snake/core/handlers/motion/__pycache__/utils.cpython-310.pyc delete mode 100644 src/snake/core/phantom/__pycache__/__init__.cpython-310.pyc delete mode 100644 src/snake/core/phantom/__pycache__/dynamic.cpython-310.pyc delete mode 100644 src/snake/core/phantom/__pycache__/static.cpython-310.pyc delete mode 100644 src/snake/core/phantom/__pycache__/utils.cpython-310.pyc delete mode 100644 src/snake/core/phantom/data/__pycache__/__init__.cpython-310.pyc delete mode 100644 src/snake/core/sampling/__pycache__/__init__.cpython-310.pyc delete mode 100644 src/snake/core/sampling/__pycache__/base.cpython-310.pyc delete mode 100644 src/snake/core/sampling/__pycache__/factories.cpython-310.pyc delete mode 100644 src/snake/core/sampling/__pycache__/samplers.cpython-310.pyc delete mode 100644 src/snake/mrd_utils/__pycache__/__init__.cpython-310.pyc delete mode 100644 src/snake/mrd_utils/__pycache__/loader.cpython-310.pyc delete mode 100644 src/snake/mrd_utils/__pycache__/utils.cpython-310.pyc delete mode 100644 src/snake/mrd_utils/__pycache__/writer.cpython-310.pyc delete mode 100644 src/snake/toolkit/__pycache__/__init__.cpython-310.pyc delete mode 100644 src/snake/toolkit/analysis/__pycache__/stats.cpython-310.pyc delete mode 100644 src/snake/toolkit/cli/__pycache__/__init__.cpython-310.pyc delete mode 100644 src/snake/toolkit/cli/__pycache__/acquisition.cpython-310.pyc delete mode 100644 src/snake/toolkit/cli/__pycache__/config.cpython-310.pyc delete mode 100644 src/snake/toolkit/cli/__pycache__/reconstruction.cpython-310.pyc delete mode 100644 src/snake/toolkit/reconstructors/__pycache__/__init__.cpython-310.pyc delete mode 100644 src/snake/toolkit/reconstructors/__pycache__/base.cpython-310.pyc delete mode 100644 src/snake/toolkit/reconstructors/__pycache__/fourier.cpython-310.pyc delete mode 100644 src/snake/toolkit/reconstructors/__pycache__/pysap.cpython-310.pyc delete mode 100644 src/snake_fmri.egg-info/PKG-INFO delete mode 100644 src/snake_fmri.egg-info/SOURCES.txt delete mode 100644 src/snake_fmri.egg-info/dependency_links.txt delete mode 100644 src/snake_fmri.egg-info/entry_points.txt delete mode 100644 src/snake_fmri.egg-info/requires.txt delete mode 100644 src/snake_fmri.egg-info/top_level.txt diff --git a/src/snake/__pycache__/__init__.cpython-310.pyc b/src/snake/__pycache__/__init__.cpython-310.pyc deleted file mode 100644 index 148adfaaec6cfdf9aa5e564b39880d465fa17b1c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 177 zcmd1j<>g`kf_}f*>7qdTF^Gc<7=auIATH(r5-AK(3@MDk44O<;e8GN>-mVG(iOJcC z>8W~tnvA#D2iJ5ts`o$%gxurmnRQ=+- t#OzevwA><~U{NxJs~;Z^R8$fluUAlci^C>2KczG$)ehu{Vvv~}3;?-oE8hSB diff --git a/src/snake/__pycache__/_meta.cpython-310.pyc b/src/snake/__pycache__/_meta.cpython-310.pyc deleted file mode 100644 index b96441792f3a67bce7cc0b85f35bb7730b876203..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5884 zcma)ATXWmS6~+SKRTM?bk}UZa#7>;hvFYhGO`@c7WyNt4Gp?;TEj%s;=B{K)AfPTl zIpWYWY2}&tp-!Iqlx8NL=}Uf0{{UY5vCZ9YeD~2KB8^SQ8;Tlp%GY}oqH3f~Wz;Z2q+pf*;oSWl!-p%v7 z;1=+-uXFh8MYR85|IV!N+^c1oTG?KFPjsKVB( z@|A6&zm*r{>+&49oe3?K+dAW(!Iy8yH}U10#LYd6d0n2z{Jc7gy)5@N_1eDSzAmj> zM*U)M@w!TUXEpHS*ts1=GK!pzzu9gzo{<&mBAxQXFiQNS9ffg|=2C6=-5`Ir}maNO+URqe++flcDjfKLF zuamYPV0cveiQgijyhQt9ybI z{lG)Nz$4-d=#}9LV1fBL^o!^>l`XAhL(Z^)r)Bj~#m#*U>$`bqyp~qU^RBGkRGaM> zKHB^EvO|>2>3u0-R7dk7{1<-iz}=jO@0V}%zbY?%q4}sE%UOl zZ^=T}(C6Dm-}Z_`?dOPU8xOJC75W`e?5$!yzl<-S%VO`rC}2iPxZpf!C-=#r$3a9Y z^Se;hK(BklrM8M2<+3w)nvoMKC0XGsqYWLYS`kA@WAr6^7kNry;3=u;d1+w~7iq=w zhMYXFSudrGoD*eXi{8RP zS7{7nsFyRYXK6oX&5p+W&k>D;&~H*l;H2y5An6ibY1#8Sk?aNvM}c1c+VumLlhozO zs0H$j=S{#mbVq`w(*wk5sUQH2Vms^JrV+)neia?XY+OWFHf*zKE|^R`G-6jMVhI<9 z5liukXe~%v<{rT_k*g_2i)r!GX!Cme%XZj1i|C{Q1sa0W8A2t`9gdhrc4$JNmtYtn zVyqHdQW(MT5P%teMXvxxgzuVwNFS$ed{90k$-9Ea&{(s2m7!=E5SnA=^*n1_|BiNf zhq`yEYfv{v!xy%HAFI?@g+;>_rdbo3D2J*LbP*X@Tyv!&rrJJ8ADKWVm*sI*jNo$^yfO#-v5G%y6GUoq==j6AzSka>$QB@DkadPi102xO^V(3ZJB>!;g0p^Ce+((II)_rt0U^n| zMs+Vm(qrSX*rFzuAmB3QTM%X2(hHAqnk^IcusCMCZJ35(d*_j+VB}2I4vTJX;wm>rXozOc9=Y$8(x0zaAki7w7Yi?gbImEp#rzX zpBWhZ4c;lmwxLUjA z&nQpz7DA`fjT1^Ze&Phm$2bZVCF$FK&{b<%lCfp%3Vj4+4kH$z!zAb+df&k9hu=%11Yv3NWv*`6sSvVU)r_#^#nOg6 z?_0D%X|o8|@6C=*gG`b6JQRNjU<@kzi7J7)vtP4IFOx81zaCdOr2T)4*cuh8aENxO zRaQtJ=dn7h6SCVi{#Ub5r`v8GbwWj!WSJ}XqMU-$O{b-`=Izzbnjc=f+B?1$?zVLl zc2t-+t5LYo-t1;q>PFALlyr9504gIO{nKOP8nvzV#<}I^YtdB_jY?`%qQ;ik1(4Fa zk2J&i4s^~=(3n~*v|B7gXs&fP52}O|?YwT_O3oSE^RVLHSj}A3ia8kL( zJB+chj33rZhoMk9eXDu-lQnPs`VH^OwVUaDHvQ z{b%YJTV0Im=lC{5*U618{$s;+Qd64Mo77#R?l06Wpu>N0d$4@+;gxH_KMBJS(cFYNfeSHD9h*%zUY4&6dhD{{ut(9*6({ diff --git a/src/snake/__pycache__/_version.cpython-310.pyc b/src/snake/__pycache__/_version.cpython-310.pyc deleted file mode 100644 index b73ceb1d5c197c1bc5ec0e2be9811ec9671ae7be..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 489 zcmYjN-A=+V6mGk%jGslhA^HehxS?0Z5Mx46i3W*)iMwf#7MyM!=>`eDicetliF)f5 zui%xZ{6yRI`_A{BbJCuso>xM!KD+PJFO1N)5&xGB;sQ?g3@}6-g-9TEz%eH=PDn@+ zE3_~YL|DQW&V(EyZW#=zB%%;f;Ru)8O|)hQn1ZHTE;JE$Z4?&65-$Rm!wN6;QN4V* zg6mM7XlF2=#X>tn8Ku(Kg@sTVM7qq_He^g!|3q%e!SZ(5weePI_znNq=VEbk+Nj$K zMn!8_nMl)3qFeX0H+bx|S?jvpy6JSUG|iW@NKO?o4VJ03BAII|%a!&X+V}m=U6&1p zz1y~?>C=lC=X#H^k(6mZ%Hg3IW6CkT<|7p~PyqNqs%l~bKWD)rjiEXgL2DGrD9G|C znS&#OOpac~(Iin|s_{k!yUG38QoGG0n%?03|lw$2Dvdm$-PnNd^A`-wAw; diff --git a/src/snake/core/__pycache__/__init__.cpython-310.pyc b/src/snake/core/__pycache__/__init__.cpython-310.pyc deleted file mode 100644 index 47426a68be93645ddc262946c9294410309b7d54..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 770 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 diff --git a/src/snake/core/__pycache__/simulation.cpython-310.pyc b/src/snake/core/__pycache__/simulation.cpython-310.pyc deleted file mode 100644 index 7359ab529b2cfcf79627b1eb9c467540e0bf3326..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4943 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 diff --git a/src/snake/core/engine/__pycache__/__init__.cpython-310.pyc b/src/snake/core/engine/__pycache__/__init__.cpython-310.pyc deleted file mode 100644 index 645e0a59dd45231547c57cbea0e870acd43ead4b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 396 zcmZuty-oxn5C-<|G-nEB?Lfx#{o+X(Erdg(sle2>9zBM_Xx_J;rh)kt7LH10`FaP$+M^l6<= zeyX!RuXBt#B(hgr7b3q#W%0DXHk~qZ*;=>c&Hbpn8k9AD^?{*jiNo$0_ww{7v(ZCh zXMJ_~AHP?PZ9DwUBrd+!B@t49s+@&_F<~3VLV5$YOoFi0a5qS=xS6yeGqK-P67^hb z#@>*NUo*ki1%0rZ4@ygV&XrNr52_!5k<=T0D-YV<0qL4eNE_=UmDAXiF(?=qTirc| W*->xBsO52-+{gYYnv*$(MZN*qtZYyK diff --git a/src/snake/core/engine/__pycache__/base.cpython-310.pyc b/src/snake/core/engine/__pycache__/base.cpython-310.pyc deleted file mode 100644 index 274d74f8f32d91f1e3ba91e03f3b21a5870d5a26..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9031 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 Z$YT(LBL1m{a$`ybK-a6S$Q5-W{eO@LmWcoW diff --git a/src/snake/core/engine/__pycache__/cartesian.cpython-310.pyc b/src/snake/core/engine/__pycache__/cartesian.cpython-310.pyc deleted file mode 100644 index 052f4e1f2493f2e65036cb97b5d3fca9cdc000d3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8845 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 diff --git a/src/snake/core/engine/__pycache__/nufft.cpython-310.pyc b/src/snake/core/engine/__pycache__/nufft.cpython-310.pyc deleted file mode 100644 index c2d65a8a0158c27e8d8ade162ae5ec6bace79652..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4706 zcmbtYTaO$^74CcY%=FC8&R%@U#S@#5Oo(TL6CfZfB=N=}fR+fyfQE#ocdEwQvway? z_r%^+k3iUwKqBx1;9)KCl1KhdJt6UcEb#+~12NyJo*8c(M}X+noUZGs>Qmo$&Z*6s z&ANu?_d9>MHaV$jf2GRt$3o>*{PNonOdDuSXGW|i#=y|2Y{urmQg3_U;BCcj;tjl{ zHmIq7JFX{fyAPtjfxE&Uubl=_! z(;`bSq;@4rE@kN`x^`Eumf0Xx$F}r_+7X7XlJ-e8Gsugu;6vKk@u!2ztN7(-p^R$- z9VRxe!mtCA88EClu$eV*xXV3eU(|SQTpu*JkD7B)WA32ITPS-d*Z9h~&FYY=;|^=^ zH5hH3Z=BLtlW&gdti@JtTZ0q)WX)w~S(|UFF{^lYxXV1=!nji-pRKX=+x9JeaC$y+ zgFnVL`Q!WvXdDRx@TJM%xzdyGA<=5^;^@Wg!APhyQGJ2UcF zmpz4@KgG`A@XyK39XjLBnOo3dNPFk%<;(9#JD-F%Qt9MTGKsmglZ^3Lnt3WNOD~V3 zArCGv=`tK`&I@VoF@g3d35GaWl=iYBh}cc(2wqG@I<%pC@ib7N`X&7GUqTdGX%+e{ zBlk+{nm)5ieQYot)-v!jPiZr|#2Mo4;BDjW7UtM0?9#fWmrm)9Ow=9bd}z$P!ll-2 z?Y*^kjahA0U+609(B+=ejy#%i$0)tBc2T?jT4tj-4+eSyX^!k0vJbd=i zsPBJHk#rYkw(}&M(U)7&vb_v*C#Eh9sK%IdA;-w0*%>4lHM@yymCA_@~`lSijYa<;H zwo8}Q@K^sMH2q2coj$9TH2}JC_~ctDyn7f&hd>(8rYzT8IO_h6pbx;O7W8fG@R=)B zp{wZMWf?G^W<@ujP9~Wsx)-*)iuKY8r$r{+!yrl-zj^mQo}STHc)i@S;Wr2{(oNwA zqBs{9)GCY+S{z6}M>OGwoIsoREb%4kt^X*Dr~C~eG9g|@gCO6~tBbEvS>cS7h!;t$ zk@zNrboOtA;#v+5MQ0S?O$!IoRv)U6R*5Ydy^8HdMWDP`phkQR&G`!u>orUF2`+}G zTZRL;v=n$8!_bZU21)g2-7{S0W2^SXKzeuy>CPjUtg(Z%VxIU4ZKtWW5G-)zqHXce z7gAl}>Seg((j05=nlpFi&1wZOQo5xvhWjf$xIKMrGaYWPUN~d7M8G=*ER_~;;V|<< zd)B}Ruh5S$^Qd0+-vI{KG)P-HOuuLx`ATE6^nobtjx}o*tx_AW0A-D!U91w`;83r^ zp|)l#MW@tCy=(#H)~sDR;upnQxk9d$c_*;?SR)s`uHDjSt7r#0KQJJz4~!A*t`V%4 z7OR0N1>W^?b>6yBwwGh6mE3(h^^doXC=|5I6{Vwbv{|;!9+ow9kyEbC

~-I{kaq=-!<%qKlmd-LaP@uh1T3$x{E_hh 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 diff --git a/src/snake/core/handlers/__pycache__/base.cpython-310.pyc b/src/snake/core/handlers/__pycache__/base.cpython-310.pyc deleted file mode 100644 index 06877d2f8a81d257e5d6b158093009adacec1549..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3986 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 E1v?THbpQYW diff --git a/src/snake/core/handlers/__pycache__/utils.cpython-310.pyc b/src/snake/core/handlers/__pycache__/utils.cpython-310.pyc deleted file mode 100644 index da2ef5892f3bde3871f8f8c33ca13ba545c8f98a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 712 zcmY*Xy>1jS5VpPEpZkjtq#zQ4ZLi?=1x_eYprJS+A)0Ge%i4Em;`Od*S|1AKRtLXK6(sl-h*Lii5O-? z;)*N@Ml4`d1{GaW*kcyTu!@!u>?2ND%wv{t!UjBHLrzyiHe%zibU9#?k7#;u_3D!q zQrIqCwW_qDRwiB5I^7hCNv_T84ho_vcJboviPlATNA~ywq}aNGP{KHG%DU-X-0Ylg zWQ8#;&s9-z7hiC(-dN)jD=MA~cIhI`ZL3vD{q1{+U=2V|LCqYDMLoL4TiTNwe2cck zk{*2tuJH}+@h#qlfWkgJLOtn&BXo#*>hT;_V1}<=oHUK>(tYvN)~Vg_bl2Ey8tD*9 zxKJ18TskU+u`ZIuXD*Ekg<|~Dg;inB3}pJwbnH#y&A=ZVDSnYZ&>imS0<|AVKZW@3 zciDL@3z#j>P79$#W`KMP9-bLhoblJIN`q6EJD8QV=Gnv4vlb4T8BBCicoO-ZgfDOW zUr1x}viDcq mcm2pb^V!L~s#z=f8~BsRyaYqhn2hlllYn6I_dg{EfBpgCp}e{P diff --git a/src/snake/core/handlers/activations/__pycache__/__init__.cpython-310.pyc b/src/snake/core/handlers/activations/__pycache__/__init__.cpython-310.pyc deleted file mode 100644 index 08d84a9002752e82fe631a847eb5398e40931e66..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 445 zcmYjOJxc>I7*29&@3bvAIfz5o8*ISILBzHQ9!M*-AlwqpORS;Er6kuv{S*EGH#h%M zRww_0lSwPKFXYMl@w|CIqC1^K;N@-fK0Aj1dPE&48QfkA=-zqHGt4^rzU(}TL7HgMWZntz5 QmSn?UVbDfxcm&(%7s%Xs=Kufz diff --git a/src/snake/core/handlers/activations/__pycache__/activations.cpython-310.pyc b/src/snake/core/handlers/activations/__pycache__/activations.cpython-310.pyc deleted file mode 100644 index e5a0e67ed66e1955e85dd04343ad7cbcff2c6aff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5550 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 XJz*{OZ!hS4%--^7@6zzt+SC66`6Dq@ diff --git a/src/snake/core/handlers/activations/__pycache__/roi.cpython-310.pyc b/src/snake/core/handlers/activations/__pycache__/roi.cpython-310.pyc deleted file mode 100644 index 182f3f8e4689c8ff3868f03c65337cc8edaa08b3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1098 zcmZuwJ8x4l6!!If<~D5#s(2R2fDjo-B!rkML>nO#3ALzHLdtSw#ZKb%zGOR96WwgA z6=H^=8Clu*D_)uM7iggzCoO8F+VW?g&-U^0ckFC=IYdxCZ-4D=xCs3+#^tgE#%pL& z08rFM)S@`H+8BB}wiBoAScp2zWuB>B`!1sH70bI~`B$uf;ep=`X^DoPoOVE$Xqhh4 z6GQ6PoM;D0FNUXlflBMer04?1@u2z&eFBweFyatK5M{?ZT!Gb&u?cS9r&M z;ZCiIU-$*Sk0yaagJ4i90_su!2v16|8y6+;3ge^ho`DL0uE;*`Dn_G=LjrM;i^_a-Y3inN zMq)m`#FZ$QillJW??|kJ$KN}RgDi$@#;nmKJmn3kcrpZrHDpTm*|TmUfE1mD+2~|~ zHToo_kXG3s9mNmkZ$UOh#_Rb=ulJa`2oHMmj-vmM$cH24D!^K>f>&{91%PEcu*5?k zYxZmait---;?aWm3Ek|4fiDY!n(>-}=W{}s9L!;M0y(NV*Qp1&@uP@lohZ_7I!yAB zSb=T&w(RhHRF^s2fy8wsNGiJ^+ago08s;(6Hhd24r*x4+6R5tmwY%Bc{`h7q+G#dh z?^}DD?;`j(b4f431G6^RNHPk);FSqfJ^^r0fXf!Pp`Dd6{#&;3pR$8b9XC9|_poJZ Gc=``qe>GVE diff --git a/src/snake/core/handlers/motion/__pycache__/__init__.cpython-310.pyc b/src/snake/core/handlers/motion/__pycache__/__init__.cpython-310.pyc deleted file mode 100644 index e34937358f09117b95bc83936d0f6e5490ffe5eb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 287 zcmYk0F>V4e5JhdXBnUx^qExh7fG>a$QkqZz66v-XS!=Uc*lT1jk-{Z704Lx|+fwBU zR2lD5WF*h%KmXBuHyri})@6MyJkEO*|BInm;0y2AB*}=Rk{N1Q#wd}Uf@U3=e37(! z9<5xZT{->~r8LTqS5BUcn*LH;OlkeLMeb~CT3S)4r_sj~>olof0i??T>aLF84UbS5 z18^h$1$|9>Z1}e`qS8k351~uVL#6EriQ=IY2Q}GQkI?6>T@7r8~+a@Omz|9I^ Vdi<$-Guxz{$FLzDO2~lq*&puYPF?^2 diff --git a/src/snake/core/handlers/motion/__pycache__/image.cpython-310.pyc b/src/snake/core/handlers/motion/__pycache__/image.cpython-310.pyc deleted file mode 100644 index d1a3e431a68510f75e1cb7fabbc59aa2b2be51f3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3220 zcmaJ@TaO#J6`q?$quZ`_qae07Ee2>BRIM!mH4wCc5oBuzNq}@4*lr$#1Ou)}X=gJR zg{0Qrh4!WE0!4wM&qZJ2zV$EhwJ-HwXpyAf;f%C$(qx384msrEIp_Nh56fP!?cn+A z(ckBzp5y$BI@?c#&bxTkpV4q<;&7LHnVWkP&n4N<{7HcSAZz5|B*a*Qhgma^CQ;s+ zv~0hbwe!xT13BWYtef{HJ;-g|$#(MH$!^}C^j+tDhj)4JnZtXccjZs^_>O4tT@muW z*ynqqHH-K@f8|*)d4>CroZ;Z&;J2kt%OXyTSf7YE&DmVUyv$izj9$Q4XXu)U3$d7% zi}NFNnnw=~rDW$XeER5_&V%!U<>~YR)66tKK4FC}bIfZ!O7r_=F-zw!yh_dP;jz+^ zP4x$?;F*vw+)6{6ah~MX4AZavles8_WV)17%z5bv(R&xK`V$)AOk9N1`#pj<@wtZ} z`jdtTMU#Fr|E9zJ-#8-T!97Tm*8lm^uwUAuQ_l=-zbl$`zllBq{>+*5cw6l7j@ad0 z(VvC9$9E9OJsZefbK@brD)TCwA5s`=H`(71sYA}=YC?P+a64<%ZpU~&W|HMX3#n}P z&gQXQtrDdXq}=vs{$t4sl`)H*(%70w9&>S)+M(NoXP%GM$S#oIS^lupKe$#ho?-)1 zU^UdR%+gG}9RtOU9Uso(g)GlfF8FQBplW7JGvidnS;_DzhJmpZisg$8Jzd5*)6)~X zpjhU|;#y%ji)R!HwWg#>^JV4eD1Hoz)*C=K2wTJ;Po8~E#Ho3Fhp;x z{+&$cX~DAi@xvG!($X!vZS<6wmIYt?e^hF*g^X47vN1JdVaxG(%q4r07ISz~<}r(l zQs&rIhr4Ht8Cwisph zwmP6!lB+2lX6uJ!Iv(%iRiB_)Ij1=GmyT*f!ilwX^o)&P^{#7Nyb& z6zL@SB{op|Xa?@U^*qlFz6t%dyYB^GU%dH!hwV*z$~$!~eIVj;cj?NXTBNL`{VxN&jg=3qywh;tP)`$jK$h@3^#;TT z_ql%=6hDC!SsfohYE=?e5KmgqT`PH~o#*a>bJ@_{mA@iZM5LK}2V_U@s&N_U9gOa- zg44c6J^Blk_Tb{i`$EUOs?NwLWB?9b)cVm;`fqqQ^i6=uElglx3}(w>I@|}(+0&#* z)Jdt89Kct(N6o8fOqdp^Pzw{{I4b7Cv?ywp{>INlQPGEpWEza_2oy|(swKNL=F4I( z8zl9Uqy{-53zEdRkIidrvB=KX)Y4^AV>1lpYgi-?sCk{1M@3SV2oqKm*<|e^eQJqU zH8*K;XD)P7N8ud|sGp+=y@3~aJ0MQrhF=XDH(byD0yn})@Lw-Ni;?iFi#NWPN?VE% zw&4^x*Cvy_Glf zZaP;U%~|0p_C;$&6!k7%KP1f8RSwqzDmyjqqoZLU>FQ`&0(S(u4kAuDQ=co@!7zAX zDe)`F^4B!4Q-~*P))+T69i1w*6bY^Qc3gge1rxlAuI5p&@BSEoOBx*xpYLu`Md5eO+TLLMAw7O2`%|ZJ-)umHjp;Z2XOnys~?5 qS!uzv436$qbb5!%ih2W0;B>vn>jK5Di`MP?-bWztH=Ebn`TBo}>xY*B diff --git a/src/snake/core/handlers/motion/__pycache__/utils.cpython-310.pyc b/src/snake/core/handlers/motion/__pycache__/utils.cpython-310.pyc deleted file mode 100644 index b39a4bdc709946cc3b258d7e14b5eb8f2501d856..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5191 zcmcgwTW=gm74ELS%uL%(oQZRBlFinJy?CVq+(5N$2Gj8v6 z_fXxFc&xDmN}}DDh#$a9vJwx=BhQF`frRRn2b33(ka%EoS-w-*>nSOrW z`kp1eF&>MzA)SKjs(44di!YoI?8jE)?AF3h@~9W(L*5xA?L118jCWGSf!yY=@UI}3nh(Gd1&YZPf8TqEK=Jo~~RYuh=6OM52v+Wun&ZtI)g;_8PAQCV9 z3$v{67mQ0Djzs}(He@?b)vy@^9M6wJ;w6_VGt+aE$4tkpnhBw=4C0$o@wCGW88pp` zk;4RMl_b_P^5$6{CL&aV3wbLtphX@fJdT%&?-|iecHT(ymu^#`h(LQOD?eKbe6oKP z01geLy#Z<4d@7UeG!f+vC}x6u11C#ko)jFFHj=7RE;o$!_6Wu7O!`e?2$nM;bafC9 zh}~O~UoQ;qIVrECx!gs|Y+YTKW35El*hZz`H-}uP@OG4RA!8gc~Rrgxr%NY z*7)rxU!O?V(3?oun0^lGACBq6s!Jtb&S*ml$ErW!PRX3}un$X?aRTf+D=|rcsn6#`?XmEn}JF zhH9ulHBSxJ%`hXKcBGO?TNa8}h_TiqhZ-8eaoun;${Mcr3t4HF^z{@J-wtz`;MG1@ zz#$t`s)8M=N==O#3hRm-Q&(ZeeJMqzt1!!Ql(!0Y2v&|NMW5*aG)v$YmO23%Uw*uF zDE3zOX1u%SpO@FDdM^;1@tjmP7)F6*)p)QyC}MwCO@*4cg3dH&jS;`qWgTtgOy zU(X0sJM9#?FN+e$VF70`IO<&*k#Fqcb0VAb*REs5ShVZSvAWHkG1q_WR@6Db_t-1B zD7o%c+VDp-U$+V_IG+Q8AWCH!!l((FdLOm#O1}Jm5h-^UVLR#n6~Qrn zt>E~gqf&fSl$cCvMqr@4ysI%w#spYl0;Kr;;$r;ucrmr>lb>Q^R!8I314i2PZT5uu z{=eOtBF$)5gn6ia6D+em(UOurMN5jB+2?3->r<;^^mrF#wQ%m(*Q`7C9ebN01v25z zTWCGg`tw%qY`CIw-`#e`t8j9&ZhBx$?clh%^S~>E5=wYO%QLh*v6~i(deE&rsE+)H z_AG+VEK2>n_8G#*9g54%?}zc)0gZk!%CYAZ^8Z4^vJHE!xDs!E$}lKl9gTtVC} z zm0dBsc8RKz&Az()dm>J`k^SnFwe@~T$8C*|+6wblam?nWUW#m<2eM8&V3x+}{AGgW=H+f#k_tC1C0Y z^s!1JQM_h3m85Yhq@F2DIOBszkCE7HlSal59e0w!Kfol1hH|7ciYWKkJlP{N7Uvi! z^fZAMF~tc<VUW#*eZmlF8&!c&E0BDbB9M`tt%*QNYm;&X!KNJF6NH`L^Ipo= zCQW^~C2r5UR{q71Dwuw8FE*DE%`y&o3u%j$Wxt} zyva?`6bV`*k-aBPDe^m17cWPvN7nY%oGh#uw48k>u&2hM{L{nX%GvH-c|XYOb}-P| zpKn@b6rZ!6h2vY_F)nwcI&<++E{l*yNCB306-r8l<&=iP_pDcZoQvI1igD+^D^4@5 zDg8h$e!&)gZpgFM;MI~`G1V&Kdu0YtB=IeKlBW;Gf#~>13Aav?Zj4AM1xHWmtlNa@ T+-w71#Js)&$j}r|@j?0vI1gcx diff --git a/src/snake/core/phantom/__pycache__/dynamic.cpython-310.pyc b/src/snake/core/phantom/__pycache__/dynamic.cpython-310.pyc deleted file mode 100644 index 1ef44a1a469a6c89b7f7277e843463d91ae2f9d5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1953 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 diff --git a/src/snake/core/phantom/__pycache__/utils.cpython-310.pyc b/src/snake/core/phantom/__pycache__/utils.cpython-310.pyc deleted file mode 100644 index 3461e798b0d093934373e66a63fc78cf28f10ce2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 595 zcmYjPv5wR*5VajU*}Y4af&$&qtmsm(`GFGx-BlD@K(|d4#oj%OIF7~+(ncw15g))8 z+%LJMx?i9G#>;|kr1xg#$+F+rwncG4FurZSA6`;Ie#GW!6xh5)xc5ks?1-e2b=0sO zqp?o9#PA)bWXa`93dLlK$dr%^m8$HD$R*Yn@^YWcTozx%ZXqu}lJeQ~V)VMxUMsiW zTUZbGP4BI7n@2o|lr&`9yLSN1@qq?DS!*5>)PvCdF#3?%(Z@`6pi>YQq=Jxw@+0)y zR>UpN5$lLsgu6!aWF|AaB6BixNxvpDo!JeM3{54|^AF1DNv-`oLOVAqw<#&aJK91t zPzp#fK^AEdX&EUlcp#8t`gvD6<;#B1_WOXfVTh}4)M>8BZ{y6CV0C8<7T&q#) zr8dn$0gqaudmn@!hfW2t?`-2w8=kyBq4@A&abv6;JM{*?263;DILTSg80WtkW&e@> ItJ&(;AJu%5ZvX%Q diff --git a/src/snake/core/phantom/data/__pycache__/__init__.cpython-310.pyc b/src/snake/core/phantom/data/__pycache__/__init__.cpython-310.pyc deleted file mode 100644 index 4263b21f6cdd6d2463479696f7ba17407e1f8e9f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 225 zcmYjLK?=e!5KMcq2>u~gLCwLdh|sGP!JC&5nr$sMSxL5ne!>U%0>9+dUwCqBFAnT1 zGq5v@lgU^x?!}{C@_zT?9|?;MPt2ICI0&2U#WcOma`a>x4?$KKBppFoLq-zH8rU@i za(6VI(8WbDO^yudi(7&~`1X`=?{yl8G-dPCl~$ diff --git a/src/snake/core/sampling/__pycache__/__init__.cpython-310.pyc b/src/snake/core/sampling/__pycache__/__init__.cpython-310.pyc deleted file mode 100644 index 141cadf619319ad683b2248f8f5e497ab5b642f7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 491 zcmZvYy-ve05XbE_UzBzOl>s5v3~dG$284jB5(rd~f*8D5CUz@RI}Ub=R9=DyU}J+v z%F4tmFkzDxG4v$=Io=4Ak&ICc!4y#c4WbPiWFQHjcP{%`NpiMth%5y!ru$OSxnP4Y`zlCa zy?I6q%UqJ_B&d6%n~MW_nm^9D;T2cKGF5M770GAUldR;Lh*flNtcoGg6*HU^YgE0_ z-THRhSBlVEO&(ZYDZN+?5Nh{v9XYfdLI>X=uox%pI>MN$9OK%*x0Ceb1 zeIs|>oQw#8@jK8R*UsVlJbhAvR9vuhNO-|hQ*k-B5tf>Q%vgUSwGHaLanoFBn^|r$ c#n?(Jj0feSj*ptX9=o-g*un=LZx?prAIuAhbN~PV diff --git a/src/snake/core/sampling/__pycache__/base.cpython-310.pyc b/src/snake/core/sampling/__pycache__/base.cpython-310.pyc deleted file mode 100644 index fa4fdd5361a3709f71c47e58e372fff640773bd8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2146 zcmZt{%Wf1$a9+DJJNvK+7H^VKLJ~HD@hvCEg4h;9N_>bz4uh=Lu-&^1na5Jyi|~q5 z%r(k25{d*ze@p(LuQ_q%#wk@jGkAIQYHO;htE%hST@8n!h3l{V7qfpmmh~SIs|$J7 zEz7dy6GXU`Sls4LZWm7C*o3>eo4EM(aRZ2h^%|t06 zRasTa_%%5^wsk)(%SzSEeWZh(JeBgd6cG3KcW(ovM~IGo7AoD{`9;h!iMC!lwRZ0y zD|V`Kn$0F;Z*|#7+@d6GAR?^9#zZ*W#=xD#GcJ0%Pgaea0+#2AFsDb;3ZjNBW9>@{ zM8N*IqXWjuv=EHxkg=lTi=6NQV~-bU-t72{@oIwXK3|kvfYCUyU=1BH;O*|_lPbrU zbFsOTW@WZ1RaPvJBQ|B3{w{7#3qU4JYI1W@0q!*E+#wIjr=qz0(IAWd@`Si3&VIA4p zMb&GFNC&}&yIfldHpV?2;F%1An}UxLKweKswq1l%I26ho+Evyc_SjxtxKm#SrpB0t zTtrjA$%;>GeRjW6cWLAbfgQv504g|f;0kKP=LFtOQtjlBNn?Q-3uBacL&ti~^5Uwy z?@4{+q>CCR-!~A!Oj~e9VaB!tI|euXr1aSt!JmSgI08jN}|=;47ryYXV;q_#mJW)`^jsTKgu7NUBoT3GIR1wL@olX*II<#kJ2< zh4ZK0_6y+gZcR)mz;+SdRt3I50xNQD@9De(6;TLgVpp$j9LgzPS208+?AEooj`$}F zvX*kr(mZGBrA$}@v4Z;BDjp_&U&M{t!SO-a5b>^lOdB{3LH1DruX&xs`ckZ#;C zumdcK;|%Q33%ya#$lx^f3Vcn>gpJp0C-A|TE^zemE&*y!xQIY^@e092164#1%0)3h ziW?RMto!Cch#8p!df0V%I^|~Ow4ccWFw5FSU|s;@#HS+A!B+ifZBzBl)96_PheE&~ L1`#;x?z!&&;z}EO diff --git a/src/snake/core/sampling/__pycache__/factories.cpython-310.pyc b/src/snake/core/sampling/__pycache__/factories.cpython-310.pyc deleted file mode 100644 index e048696286eaf8de3efdc12928badc841cc77738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12568 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 C|Il9m diff --git a/src/snake/core/sampling/__pycache__/samplers.cpython-310.pyc b/src/snake/core/sampling/__pycache__/samplers.cpython-310.pyc deleted file mode 100644 index a82e926e82bc45924fb29bd07d8538e283c002b6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13833 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 WQmKIUV(M^eU+Rr`Kc>By9QhyB;Hsbi diff --git a/src/snake/mrd_utils/__pycache__/__init__.cpython-310.pyc b/src/snake/mrd_utils/__pycache__/__init__.cpython-310.pyc deleted file mode 100644 index 4be9f46c3b9e2235f79af99c09b95faf2b163152..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 605 zcmZ{hy^ho{5XYVG{mPw?C=f^}B`LT_Cq#u1r(I}(6>yy!%Nsj~!5=3(dnb4a9)OOH zS8_|mD^M|$MJI%WrTpUgJ2U^x*wyud!1}WNdhsA7K*x-d(+oU~l8Oik;ATo6%wOX!g(&q-T-zW@5& zrWur$jk2Tk1Mg*M2Irge?b*xcCqEOgZOeFP&HX5Y;`W8-MsE1XUpX$Mk8>#SXM1n! z?0>&Iy5v4c7L;MVvqQXlh_CsT1Uti&#TOryv+>wVE|~Fxy@!qTZ5Fe$_1jqQ9zT+{ zcS4@J-G^8MPH&_(iM8P$CEIcEf#i1KXYltvL*N{Jjwlc%Vu`2_a|B+*wmps&W5V@} z#Zpf#9&)ED{}jO7SnNlo!@=sNPAspzf_Y9JSdnYZ*mvS@p%dcQrn_<)`qi>qb7fT* zMrHP($SzpuKF`5jf|aKeu}dv#)-X_Pw}Dxwvdx1y**nctMoV7 CP@_Zu diff --git a/src/snake/mrd_utils/__pycache__/loader.cpython-310.pyc b/src/snake/mrd_utils/__pycache__/loader.cpython-310.pyc deleted file mode 100644 index d685f31b41b490ebdf625f860afd31f971f38fea..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13905 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 ZvRTb4e{D@`=gMDeC$f-2Q-}ZO{{dPL|7`#O diff --git a/src/snake/toolkit/__pycache__/__init__.cpython-310.pyc b/src/snake/toolkit/__pycache__/__init__.cpython-310.pyc deleted file mode 100644 index d922425b0f7681c83c171f97dc9a7cb77586d0f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 189 zcmd1j<>g`kf_}f*>5@SDF^Gc<7=auIATH(r5-AK(3@MDk44O<;LLvG2IoX*d3TgR8 z3c-Gk-mZFnnvA#D2iJ5ts`o$%gxurmn zRQ=+-#OzevwA><~U{NxJt6u^!T0cG>sJJ9PUaz3?7Kcr4eoARhsvXEd#UQge7yv<4 BFvS1> diff --git a/src/snake/toolkit/analysis/__pycache__/stats.cpython-310.pyc b/src/snake/toolkit/analysis/__pycache__/stats.cpython-310.pyc deleted file mode 100644 index 459d21307cf15c1c03c16e628f7e6bf4ba1944c1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3743 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 diff --git a/src/snake/toolkit/cli/__pycache__/__init__.cpython-310.pyc b/src/snake/toolkit/cli/__pycache__/__init__.cpython-310.pyc deleted file mode 100644 index d7b853c80902b243b963d36eb48db3d684d1e8bb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 209 zcmd1j<>g`kf_}f*>6$?LF^Gc<7=auIATH(r5-AK(3@MDk44O<;N=nZ8xw(mXDGENB zd8rDXc_pbuX^F|H3TgR83c-Gk-mZFnnvA#DTX}Lu}!J=dcSHC1bKPNl0L_awvQ$Ic)sG%f2 ZUaz3?7Kcr4eoARhsvXFY#US%J7yyjlH>3an diff --git a/src/snake/toolkit/cli/__pycache__/acquisition.cpython-310.pyc b/src/snake/toolkit/cli/__pycache__/acquisition.cpython-310.pyc deleted file mode 100644 index 24ad1d0869a5f0f97c3575a103aa09afbe3d3a11..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2533 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 diff --git a/src/snake/toolkit/reconstructors/__pycache__/__init__.cpython-310.pyc b/src/snake/toolkit/reconstructors/__pycache__/__init__.cpython-310.pyc deleted file mode 100644 index 201eb824a3b8fad46ca8996bcc7d8c1a122d5c1f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 420 zcmY*Vu};G<5VaGB7Su{GbK~{O0*SE_bjxCy*bP?gIM@!T`~)As#>OvsW#Si@ zIK$BPBtPA|dw2G;olZ{>#M|<{B^aTvMD`;Cas|hq0|-5_M diff --git a/src/snake/toolkit/reconstructors/__pycache__/base.cpython-310.pyc b/src/snake/toolkit/reconstructors/__pycache__/base.cpython-310.pyc deleted file mode 100644 index 6725b4c6adb67a49f6dc6fbf7edd763b31ad77d7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2400 zcmZuy&2JM&6rY)0+iQFMnUIha!nSJFx&>R6D)oX8G*qZ6@gWE*?PaxiX3fU?VP?lf zUO`n6uBcM42njBg`Y-LZC(ga~Q2O31X>GzJ^ZeeMH?!~KH*eBbt3hD=I({)ds1oug z3ag_6!gZM0??5TxId?g4)#0RV}ZY0aX(tGdu@{LiNwhx5zZ|)z8X_zS?VMG1k@aFB*=cRBb zjQ7(d2&WS~dv#C{uEWeWfe7MK$Rgtuvc_Cf`)d|GJblf{{5-142-X&cMN6(mGagh5 z%kvUH7M@o$JTFf9B0}EwyoU=vdbd*ZJf2QK-QPK`cQjC#5)2X&TK!HCl5g8{LQ059dpXxN2eC04rhqiYORX}Qr3a>t=t}QB} zCRzd0E48bHTfF{^xNY75U^Tf7P-^iu0H*|)){1^m0J8y3{i26(TB}0-?V*@U zk%>fQj(Q-RFacBq{zN!ZJY0lQa7U%ieF6W;d~{LVP#?LK^#F*l|n6KGM?bp z)1i+6LA$dH%wuvyUQtfrmmL`|$V>K`LQi1eq>=C35z1N2bzax9Gt4((30Bs$&Uj$T zZ8)?r!z4(Hy5~*s=0j?2&<>cyFG`H({fH|W9``Ykt z7@rR0*HW#>Q#zpeS1W+gq0F*5;seh?Y=p5t6^_;op&}dORQ(XoBM}3p1pi*jR1S>N z^-tgvAN0Sul8DdH=mL=Z;@KEh>;{`UEfVjhY$NF)!A4)0Je;Va<9U9PqzZZgbWOw` zw9dkepz{?qfZ{YvrbYEOFhWWUU+y45n8}Zj)RACTrG*4jD?df@U$ZGWM4j9Kf>Za$ z2J{J=*|baBbeCDIZ|<7f0vm1&9Z^@dFtMr0J=nE|di)T!9SyTw|B)X?c;y{m3V>)uhavG1D6AjFQWv;r-1DP_ zDESRc@OnGQ0KAuR2Nf&1)0ee374I2;35Gg}3=-I;43fy+GRFR~eqnFr*RVQ)xi+wP zI$4MVMHD?^uZ-8^gkrPE_ilqjD}k(l2wzdSbzi`?mAK5ASY|7Z>T>HMkHGL7nEINv znM8T8rICkSES@iiYB>j7m0%gba(Ux)y+x*BR#e~FXryVtRy+iStf75Jzf!|ka&G~z zSf;^OoGZ1HREi-qDSXcW)g?p`E2aCN;{hfdFLa{Hz|hGLMN?Q;%SZMa-uvu45R=$| RR>ZBX|GGxMy0yL4_!oOBSaARV diff --git a/src/snake/toolkit/reconstructors/__pycache__/fourier.cpython-310.pyc b/src/snake/toolkit/reconstructors/__pycache__/fourier.cpython-310.pyc deleted file mode 100644 index ac734046efd7fb6a24eabf0869b0116445b70dd8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1196 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 diff --git a/src/snake_fmri.egg-info/PKG-INFO b/src/snake_fmri.egg-info/PKG-INFO deleted file mode 100644 index 5e371734..00000000 --- a/src/snake_fmri.egg-info/PKG-INFO +++ /dev/null @@ -1,113 +0,0 @@ -Metadata-Version: 2.2 -Name: snake-fmri -Version: 0.0.1.dev280 -Summary: A simulator and validator of fMRI reconstruction methods. -Author-email: Pierre-Antoine Comby -License: Copyright 2023 SNAKE-fMRI Contributors - - Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - - 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -Project-URL: Homepage, https://github.com/paquiteau/simfmri -Project-URL: Bug Reports, https://github.com/paquiteau/simfmri/issues -Project-URL: Source, https://github.com/paquiteau/simfmri -Keywords: simulation,fMRI -Classifier: Development Status :: 3 - Alpha -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: MIT License -Classifier: Programming Language :: Python :: 3.10 -Classifier: Programming Language :: Python :: 3.11 -Classifier: Programming Language :: Python :: 3.12 -Requires-Python: >=3.10 -Description-Content-Type: text/markdown -License-File: LICENSE.txt -Requires-Dist: numpy -Requires-Dist: scipy -Requires-Dist: nilearn -Requires-Dist: pandas -Requires-Dist: scikit-image -Requires-Dist: brainweb-dl -Requires-Dist: mri-nufft -Requires-Dist: ismrmrd -Requires-Dist: hydra-core -Requires-Dist: hydra-callbacks -Requires-Dist: hydra-colorlog -Provides-Extra: dev -Requires-Dist: black; extra == "dev" -Requires-Dist: ruff; extra == "dev" -Requires-Dist: isort; extra == "dev" -Provides-Extra: test -Requires-Dist: pytest; extra == "test" -Requires-Dist: pytest-cov; extra == "test" -Requires-Dist: pytest-sugar; extra == "test" -Requires-Dist: pytest-xdist; extra == "test" -Provides-Extra: doc -Requires-Dist: myst-parser; extra == "doc" -Requires-Dist: sphinx-copybutton; extra == "doc" -Requires-Dist: sphinx-gallery; extra == "doc" -Requires-Dist: sphinx-book-theme; extra == "doc" -Requires-Dist: matplotlib; extra == "doc" -Requires-Dist: pysap-fmri; extra == "doc" -Requires-Dist: ipywidgets; extra == "doc" -Provides-Extra: toolkit -Requires-Dist: matplotlib; extra == "toolkit" -Requires-Dist: pysap-fmri; extra == "toolkit" - -# SNAKE-fMRI: Simulator from neuro-activation to K-space Exploration - - - -

A Simulator from Neurovascular coupling to Acquisition of K-space data for Exploration of fMRI Technique

- - -[![Test](https://github.com/paquiteau/snake-fmri/actions/workflows/test.yml/badge.svg)](https://github.com/paquiteau/snake-fmri/actions/workflows/test.yml) -[![deploy-docs](https://github.com/paquiteau/snake-fmri/actions/workflows/deploy-docs.yml/badge.svg)](https://paquiteau.github.io/snake-fmri) -[![HAL](https://img.shields.io/badge/preprint-04533862-purple?logo=HAL&logoColor=white)](https://hal.science/hal-04533862) - -[![python](https://img.shields.io/badge/python-3.10%2B-blue?logo=python&logoColor=blue)](https://pypi.org/project/snake-fmri) -![black](https://img.shields.io/badge/code--style-black-black) -![ruff](https://img.shields.io/badge/lint-ruff-purple?logo=stackblitz&logoColor=yellow) - - - -This package provides a simulation and reconstruction framework for fMRI data. It is designed to be used for benchmarking and testing of fMRI reconstruction methods. - - -## Installation -### Requirements -- A working Python 3.10 environment or higher -- Optional: a working CUDA environment for NUFFT accelerations. See [mri-nufft](https://github.com/mind-inria/mri-nufft) for details. SNAKE works best with a fast GPU NUFFT Backend such as [cufinufft](https://github.com/flatironinstitute/finufft) or [gpuNUFFT](https://github.com/chaithyagr/gpuNUFFT) - - -### from PyPA (soon) - -It is recommended to install the SNAKE toolkit on top of the core runtime (the toolkit contains reconstructors, statistical analysis tool and the CLI to run experiments). - -``` sh -pip install snake-fmri[toolkit] -``` - -Some Reconstructors requires extra dependencies such as [pysap-fmri](https://github.com/paquiteau/pysap-fmri) or [patch-denoising](https://github.com/paquiteau/patch-denoising) - - -### Development version - -``` sh -git clone git@github.com:paquiteau/snake-fmri -cd snake-fmri -pip install -e .[test,dev,doc,toolkit] -``` - - -## Getting Started - -Documentation is available at https://paquiteau.github.io/snake-fmri - -To get started, you can check the examples gallery: https://paquiteau/github.io/snake-fmri/examples diff --git a/src/snake_fmri.egg-info/SOURCES.txt b/src/snake_fmri.egg-info/SOURCES.txt deleted file mode 100644 index 8ee0d290..00000000 --- a/src/snake_fmri.egg-info/SOURCES.txt +++ /dev/null @@ -1,100 +0,0 @@ -.gitignore -LICENSE.txt -README.md -pyproject.toml -sparkling-3d.bin -.github/workflows/deploy-docs.yml -.github/workflows/tags-release.yaml -.github/workflows/test.yml -docs/api.rst -docs/conf.py -docs/extend-snake.md -docs/getting_started.md -docs/how-does-it-works.md -docs/index.md -docs/mrd-simulation.md -docs/_static/logos/snake-fmriV2-logo.png -docs/_static/logos/snake-fmriV2-logo_dark.png -docs/_templates/autosummary/base.rst -docs/_templates/autosummary/class.rst -docs/_templates/autosummary/function.rst -docs/_templates/autosummary/module.rst -docs/misc/contributors.md -docs/misc/development.md -docs/misc/license.md -examples/README.md -examples/conftest.py -examples/example_EPI_2D.py -examples/example_T2s_EPI.py -examples/example_anat_EPI.py -examples/example_generate_phantom.py -examples/example_gpu_anat_spirals.py -examples/example_gpu_anat_spirals_slice.py -src/cli-conf/__init__.py -src/cli-conf/config.yaml -src/cli-conf/scenario1-EVI.yaml -src/cli-conf/scenario1.yaml -src/cli-conf/scenario2-multi.yaml -src/cli-conf/scenario2-noise.yaml -src/cli-conf/scenario2.yaml -src/cli-conf/scenario3-tpz.yaml -src/cli-conf/scenario3.yaml -src/snake/__init__.py -src/snake/_meta.py -src/snake/_version.py -src/snake/core/__init__.py -src/snake/core/parallel.py -src/snake/core/simulation.py -src/snake/core/smaps.py -src/snake/core/engine/__init__.py -src/snake/core/engine/base.py -src/snake/core/engine/cartesian.py -src/snake/core/engine/nufft.py -src/snake/core/engine/utils.py -src/snake/core/handlers/__init__.py -src/snake/core/handlers/base.py -src/snake/core/handlers/noise.py -src/snake/core/handlers/utils.py -src/snake/core/handlers/activations/__init__.py -src/snake/core/handlers/activations/activations.py -src/snake/core/handlers/activations/bold.py -src/snake/core/handlers/activations/roi.py -src/snake/core/handlers/motion/__init__.py -src/snake/core/handlers/motion/image.py -src/snake/core/handlers/motion/utils.py -src/snake/core/phantom/__init__.py -src/snake/core/phantom/dynamic.py -src/snake/core/phantom/shepp_logan.py -src/snake/core/phantom/static.py -src/snake/core/phantom/utils.py -src/snake/core/phantom/data/__init__.py -src/snake/core/phantom/data/tissues_properties_1T5.csv -src/snake/core/phantom/data/tissues_properties_7T.csv -src/snake/core/sampling/__init__.py -src/snake/core/sampling/base.py -src/snake/core/sampling/factories.py -src/snake/core/sampling/samplers.py -src/snake/mrd_utils/__init__.py -src/snake/mrd_utils/loader.py -src/snake/mrd_utils/utils.py -src/snake/mrd_utils/writer.py -src/snake/toolkit/__init__.py -src/snake/toolkit/plotting.py -src/snake/toolkit/analysis/metrics.py -src/snake/toolkit/analysis/stats.py -src/snake/toolkit/cli/__init__.py -src/snake/toolkit/cli/acquisition.py -src/snake/toolkit/cli/config.py -src/snake/toolkit/cli/main.py -src/snake/toolkit/cli/reconstruction.py -src/snake/toolkit/reconstructors/__init__.py -src/snake/toolkit/reconstructors/base.py -src/snake/toolkit/reconstructors/fourier.py -src/snake/toolkit/reconstructors/pysap.py -src/snake_fmri.egg-info/PKG-INFO -src/snake_fmri.egg-info/SOURCES.txt -src/snake_fmri.egg-info/dependency_links.txt -src/snake_fmri.egg-info/entry_points.txt -src/snake_fmri.egg-info/requires.txt -src/snake_fmri.egg-info/top_level.txt -tests/test_snake.py \ No newline at end of file diff --git a/src/snake_fmri.egg-info/dependency_links.txt b/src/snake_fmri.egg-info/dependency_links.txt deleted file mode 100644 index 8b137891..00000000 --- a/src/snake_fmri.egg-info/dependency_links.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/snake_fmri.egg-info/entry_points.txt b/src/snake_fmri.egg-info/entry_points.txt deleted file mode 100644 index 9edc5c07..00000000 --- a/src/snake_fmri.egg-info/entry_points.txt +++ /dev/null @@ -1,4 +0,0 @@ -[console_scripts] -snake-acq = snake.toolkit.cli.acquisition:acquisition_cli -snake-main = snake.toolkit.cli.main:main_cli -snake-rec = snake.toolkit.cli.reconstruction:reconstruction_cli diff --git a/src/snake_fmri.egg-info/requires.txt b/src/snake_fmri.egg-info/requires.txt deleted file mode 100644 index 53914332..00000000 --- a/src/snake_fmri.egg-info/requires.txt +++ /dev/null @@ -1,35 +0,0 @@ -numpy -scipy -nilearn -pandas -scikit-image -brainweb-dl -mri-nufft -ismrmrd -hydra-core -hydra-callbacks -hydra-colorlog - -[dev] -black -ruff -isort - -[doc] -myst-parser -sphinx-copybutton -sphinx-gallery -sphinx-book-theme -matplotlib -pysap-fmri -ipywidgets - -[test] -pytest -pytest-cov -pytest-sugar -pytest-xdist - -[toolkit] -matplotlib -pysap-fmri diff --git a/src/snake_fmri.egg-info/top_level.txt b/src/snake_fmri.egg-info/top_level.txt deleted file mode 100644 index c8026f82..00000000 --- a/src/snake_fmri.egg-info/top_level.txt +++ /dev/null @@ -1,2 +0,0 @@ -cli-conf -snake From 2442e66c7e5f2f0a04b1873a1b5816c49db1ea6b Mon Sep 17 00:00:00 2001 From: alineyyy Date: Thu, 30 Jan 2025 16:52:18 +0100 Subject: [PATCH 05/15] remove useless changes --- src/cli-conf/scenario2.yaml | 13 +++++++++++-- src/snake/toolkit/cli/config.py | 2 +- src/snake/toolkit/cli/reconstruction.py | 2 +- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/cli-conf/scenario2.yaml b/src/cli-conf/scenario2.yaml index 59386cf8..5d5d039d 100644 --- a/src/cli-conf/scenario2.yaml +++ b/src/cli-conf/scenario2.yaml @@ -52,7 +52,16 @@ engine: nufft_backend: "stacked-gpunufft" reconstructors: # adjoint: - # nufft_backend: "stacked-gpunufft"/snake-fmri + # nufft_backend: "stacked-gpunufft" + # density_compensation: "pipe" + sequential: + nufft_backend: "stacked-gpunufft" + density_compensation: false + restart_strategy: WARM + max_iter_per_frame: 50 + wavelet: "sym4" + + @@ -78,4 +87,4 @@ hydra: latest_run: _target_: hydra_callbacks.LatestRunLink run_base_dir: ${result_dir}/outputs - multirun_base_dir: ${result_dir}/multirun + multirun_base_dir: ${result_dir}/multirun \ No newline at end of file diff --git a/src/snake/toolkit/cli/config.py b/src/snake/toolkit/cli/config.py index 39d2a4e2..7611cf82 100644 --- a/src/snake/toolkit/cli/config.py +++ b/src/snake/toolkit/cli/config.py @@ -125,5 +125,5 @@ def cleanup_cuda() -> None: def make_hydra_cli(fun: callable) -> callable: """Create a Hydra CLI for the function.""" return hydra.main( - version_base=None, config_path="../../../cli-conf", config_name="scenario2-2d" + version_base=None, config_path="../../../cli-conf", config_name="config" )(fun) diff --git a/src/snake/toolkit/cli/reconstruction.py b/src/snake/toolkit/cli/reconstruction.py index b6519af5..ab456d89 100644 --- a/src/snake/toolkit/cli/reconstruction.py +++ b/src/snake/toolkit/cli/reconstruction.py @@ -53,7 +53,7 @@ def reconstruction(cfg: DictConfig) -> None: # array = Reconstructor.reconstruct(dataloader, sim_conf) with DataLoader(cfg.filename) as data_loader: for name, rec in cfg.reconstructors.items(): - rec_str = str(rec) # FIXME Also use parameters of reconstructors maybe just name??? + rec_str = str(rec) # FIXME Also use parameters of reconstructors data_rec_file = Path(f"data_rec_{rec_str}.npy") log.info(f"Using {name} reconstructor") rec.setup(sim_conf) From ebd8bb6debe201eab71178138ff3c6bd64df0d6b Mon Sep 17 00:00:00 2001 From: alineyyy Date: Fri, 31 Jan 2025 17:22:19 +0100 Subject: [PATCH 06/15] load from mrd + 2d adjoint reconstructor --- src/cli-conf/scenario2-2d.yaml | 93 +++++++++++++++++++++++ src/snake/core/engine/base.py | 12 ++- src/snake/mrd_utils/loader.py | 10 +++ src/snake/mrd_utils/writer.py | 6 +- src/snake/toolkit/cli/__init__.py | 2 +- src/snake/toolkit/cli/config.py | 2 +- src/snake/toolkit/cli/reconstruction.py | 2 +- src/snake/toolkit/reconstructors/pysap.py | 35 ++++++--- 8 files changed, 146 insertions(+), 16 deletions(-) create mode 100644 src/cli-conf/scenario2-2d.yaml diff --git a/src/cli-conf/scenario2-2d.yaml b/src/cli-conf/scenario2-2d.yaml new file mode 100644 index 00000000..23f721db --- /dev/null +++ b/src/cli-conf/scenario2-2d.yaml @@ -0,0 +1,93 @@ +# This files contains the configuration to reproduce the scenario 1 of the Snkf paper. + +defaults: + - base_config + - handlers: + - activation-block + - sampler: + - stack-of-spiral + - reconstructors: + - adjoint + #- sequential + - _self_ + +cache_dir: ${oc.env:PWD}/cache +result_dir: results/scenario2 +filename: ${cache_dir}/scenario2_2d_${engine.model}_${engine.snr}_${sampler.stack-of-spiral.constant}_${sampler.stack-of-spiral.accelz}.mrd + +sim_conf: + max_sim_time: 360 + seq: {TR: 50, TE: 25, FA: 12} + hardware: + n_coils: 1 + dwell_time_ms: 0.001 + shape: [60, 72, 60] + fov_mm: [181.0, 217.0, 181.0] + +phantom: + name: brainweb + sub_id: 4 + tissue_file: "tissue_7T" + +handlers: + activation-block: + event_name: block_on + block_on: 20 # seconds + block_off: 20 #seconds + duration: 360 # seconds + #delta_r2s: 1000 # millisecond^-1 + +sampler: + stack-of-spiral: + acsz: 1 + accelz: 1 + nb_revolutions: 10 + constant: true + spiral_name: "galilean" + +engine: + n_jobs: 1 + chunk_size: 10 + model: "simple" + snr: 10000 + nufft_backend: "gpuNUFFT" + slice_2d: true + +reconstructors: + adjoint: + nufft_backend: "gpuNUFFT" + density_compensation: "pipe" + # sequential: + # nufft_backend: "gpuNUFFT" + # density_compensation: false + # restart_strategy: WARM + # max_iter_per_frame: 50 + # wavelet: "sym4" + + + + + +hydra: + job: + chdir: true + + run: + dir: ${result_dir}/outputs/${hydra.job.name}/${now:%Y-%m-%d_%H-%M-%S} + sweep: + dir: ${result_dir}/multirun/${hydra.job.name}/${now:%Y-%m-%d_%H-%M-%S} + subdir: ${hydra.job.num} + + callbacks: + # gather_files: + # _target_: hydra_callbacks.MultiRunGatherer + # aggregator: + # _partial_: true + # _target_: snkf.cli.utils.aggregate_results + + log_job: + _target_: hydra.experimental.callbacks.LogJobReturnCallback + latest_run: + _target_: hydra_callbacks.LatestRunLink + run_base_dir: ${result_dir}/outputs + multirun_base_dir: ${result_dir}/multirun diff --git a/src/snake/core/engine/base.py b/src/snake/core/engine/base.py index e958045a..ab602ce0 100644 --- a/src/snake/core/engine/base.py +++ b/src/snake/core/engine/base.py @@ -209,7 +209,17 @@ def __call__( `_job_model_simple` methods. """ # Create the base dataset - make_base_mrd(filename, sampler, phantom, sim_conf, handlers, smaps, coil_cov, self.model, self.slice_2d) + make_base_mrd( + filename, + sampler, + phantom, + sim_conf, + handlers, + smaps, + coil_cov, + self.model, + self.slice_2d, + ) # Guesstimate the workload if worker_chunk_size <= 0: diff --git a/src/snake/mrd_utils/loader.py b/src/snake/mrd_utils/loader.py index 01401633..8981d5b5 100644 --- a/src/snake/mrd_utils/loader.py +++ b/src/snake/mrd_utils/loader.py @@ -211,6 +211,16 @@ def n_shots(self) -> int: """ return self.header.encoding[0].encodingLimits.kspace_encoding_step_1.maximum + @property + def engine_model(self) -> str: + """Get the engine model.""" + return self.header.userParameters.userParameterString[0].value + + @property + def slice_2d(self) -> bool: + """Is the slice 2D.""" + return bool(self.header.userParameters.userParameterString[1].value) + ############# # Get data # ############# diff --git a/src/snake/mrd_utils/writer.py b/src/snake/mrd_utils/writer.py index 7b04ab0b..3c62f6dc 100644 --- a/src/snake/mrd_utils/writer.py +++ b/src/snake/mrd_utils/writer.py @@ -22,7 +22,9 @@ log = logging.getLogger(__name__) -def get_mrd_header(sim_conf: SimConfig, engine: str, model: str, slice_2d: bool) -> mrd.xsd.ismrmrdHeader: +def get_mrd_header( + sim_conf: SimConfig, engine: str, model: str, slice_2d: bool +) -> mrd.xsd.ismrmrdHeader: """Create a MRD Header for snake-fmri data.""" H = mrd.xsd.ismrmrdHeader() # Experimental conditions @@ -85,7 +87,7 @@ def get_mrd_header(sim_conf: SimConfig, engine: str, model: str, slice_2d: bool) ("engine_model", model), ("slice_2d", str(slice_2d)), ] - ] + ], ) return H diff --git a/src/snake/toolkit/cli/__init__.py b/src/snake/toolkit/cli/__init__.py index 785d8312..af96346d 100644 --- a/src/snake/toolkit/cli/__init__.py +++ b/src/snake/toolkit/cli/__init__.py @@ -1 +1 @@ -""""Command Line Interface for SNAKE.""" +""" "Command Line Interface for SNAKE.""" diff --git a/src/snake/toolkit/cli/config.py b/src/snake/toolkit/cli/config.py index 7611cf82..39d2a4e2 100644 --- a/src/snake/toolkit/cli/config.py +++ b/src/snake/toolkit/cli/config.py @@ -125,5 +125,5 @@ def cleanup_cuda() -> None: def make_hydra_cli(fun: callable) -> callable: """Create a Hydra CLI for the function.""" return hydra.main( - version_base=None, config_path="../../../cli-conf", config_name="config" + version_base=None, config_path="../../../cli-conf", config_name="scenario2-2d" )(fun) diff --git a/src/snake/toolkit/cli/reconstruction.py b/src/snake/toolkit/cli/reconstruction.py index ab456d89..3df1d7b4 100644 --- a/src/snake/toolkit/cli/reconstruction.py +++ b/src/snake/toolkit/cli/reconstruction.py @@ -57,7 +57,7 @@ def reconstruction(cfg: DictConfig) -> None: data_rec_file = Path(f"data_rec_{rec_str}.npy") log.info(f"Using {name} reconstructor") rec.setup(sim_conf) - rec_data = rec.reconstruct(data_loader, sim_conf) + rec_data = rec.reconstruct(data_loader, sim_conf, data_loader.slice_2d) log.info(f"Reconstruction done with {name}") # Save the reconstruction np.save(data_rec_file, rec_data) diff --git a/src/snake/toolkit/reconstructors/pysap.py b/src/snake/toolkit/reconstructors/pysap.py index 9022d525..39552b79 100644 --- a/src/snake/toolkit/reconstructors/pysap.py +++ b/src/snake/toolkit/reconstructors/pysap.py @@ -73,18 +73,20 @@ def setup(self, sim_conf: SimConfig) -> None: """Initialize Reconstructor.""" pass - def reconstruct(self, data_loader: MRDLoader, sim_conf: SimConfig) -> NDArray: + def reconstruct( + self, data_loader: MRDLoader, sim_conf: SimConfig, slice_2d: bool + ) -> NDArray: """Reconstruct data with zero-filled method.""" with data_loader: if isinstance(data_loader, CartesianFrameDataLoader): - return self._reconstruct_cartesian(data_loader, sim_conf) + return self._reconstruct_cartesian(data_loader, sim_conf, slice_2d) elif isinstance(data_loader, NonCartesianFrameDataLoader): - return self._reconstruct_nufft(data_loader, sim_conf) + return self._reconstruct_nufft(data_loader, sim_conf, slice_2d) else: raise ValueError("Unknown dataloader") def _reconstruct_cartesian( - self, data_loader: CartesianFrameDataLoader, sim_conf: SimConfig + self, data_loader: CartesianFrameDataLoader, sim_conf: SimConfig, slice_2d ) -> NDArray: smaps = data_loader.get_smaps() if smaps is None and data_loader.n_coils > 1: @@ -114,7 +116,6 @@ def _reconstruct_cartesian( ): idx for idx in range(data_loader.n_frames) } - for future in as_completed(futures): future.result() pbar.update(1) @@ -126,16 +127,21 @@ def _reconstruct_cartesian( return final_images def _reconstruct_nufft( - self, data_loader: NonCartesianFrameDataLoader, sim_conf: SimConfig + self, data_loader: NonCartesianFrameDataLoader, sim_conf: SimConfig, slice_2d ) -> NDArray: """Reconstruct data with nufft method.""" from mrinufft import get_operator smaps = data_loader.get_smaps() - + shape = data_loader.shape traj, kspace_data = data_loader.get_kspace_frame(0) + + if slice_2d: + shape = data_loader.shape[:2] + traj = traj.reshape(data_loader.n_shots, -1, traj.shape[-1])[0, :, :2] + kwargs = dict( - shape=data_loader.shape, + shape=shape, n_coils=data_loader.n_coils, smaps=smaps, ) @@ -146,6 +152,7 @@ def _reconstruct_nufft( kwargs["density"] = self.density_compensation if "stacked" in self.nufft_backend: kwargs["z_index"] = "auto" + nufft_operator = get_operator( self.nufft_backend, samples=traj, @@ -158,8 +165,16 @@ def _reconstruct_nufft( for i in tqdm(range(data_loader.n_frames)): traj, data = data_loader.get_kspace_frame(i) - nufft_operator.samples = traj - final_images[i] = abs(nufft_operator.adj_op(data)) + if slice_2d: + nufft_operator.samples = traj.reshape( + data_loader.n_shots, -1, traj.shape[-1] + )[0, :, :2] + data = np.reshape(data, (data.shape[0], data_loader.n_shots, -1)) + for j in range(data.shape[1]): + final_images[i, :, :, j] = abs(nufft_operator.adj_op(data[:, j])) + else: + nufft_operator.samples = traj + final_images[i] = abs(nufft_operator.adj_op(data)) return final_images From 54671dd592f672cdf5984893cf97547698614219 Mon Sep 17 00:00:00 2001 From: alineyyy Date: Sat, 1 Feb 2025 14:51:19 +0100 Subject: [PATCH 07/15] update some changes --- src/cli-conf/scenario2-2d.yaml | 3 +-- src/snake/mrd_utils/loader.py | 2 +- src/snake/toolkit/cli/__init__.py | 2 +- src/snake/toolkit/cli/config.py | 2 +- src/snake/toolkit/cli/reconstruction.py | 2 +- src/snake/toolkit/reconstructors/pysap.py | 16 +++++++--------- 6 files changed, 12 insertions(+), 15 deletions(-) diff --git a/src/cli-conf/scenario2-2d.yaml b/src/cli-conf/scenario2-2d.yaml index 23f721db..011a3785 100644 --- a/src/cli-conf/scenario2-2d.yaml +++ b/src/cli-conf/scenario2-2d.yaml @@ -1,4 +1,4 @@ -# This files contains the configuration to reproduce the scenario 1 of the Snkf paper. +# This files contains the configuration to produce the scenario 2 of the Snkf paper but with a 2D slice acquisition and reconstruction. defaults: - base_config @@ -35,7 +35,6 @@ handlers: block_on: 20 # seconds block_off: 20 #seconds duration: 360 # seconds - #delta_r2s: 1000 # millisecond^-1 sampler: stack-of-spiral: diff --git a/src/snake/mrd_utils/loader.py b/src/snake/mrd_utils/loader.py index 8981d5b5..648b2f03 100644 --- a/src/snake/mrd_utils/loader.py +++ b/src/snake/mrd_utils/loader.py @@ -218,7 +218,7 @@ def engine_model(self) -> str: @property def slice_2d(self) -> bool: - """Is the slice 2D.""" + """Is the acquisiton run on 2D slices.""" return bool(self.header.userParameters.userParameterString[1].value) ############# diff --git a/src/snake/toolkit/cli/__init__.py b/src/snake/toolkit/cli/__init__.py index af96346d..c359c561 100644 --- a/src/snake/toolkit/cli/__init__.py +++ b/src/snake/toolkit/cli/__init__.py @@ -1 +1 @@ -""" "Command Line Interface for SNAKE.""" +"""Command Line Interface for SNAKE.""" diff --git a/src/snake/toolkit/cli/config.py b/src/snake/toolkit/cli/config.py index 39d2a4e2..7611cf82 100644 --- a/src/snake/toolkit/cli/config.py +++ b/src/snake/toolkit/cli/config.py @@ -125,5 +125,5 @@ def cleanup_cuda() -> None: def make_hydra_cli(fun: callable) -> callable: """Create a Hydra CLI for the function.""" return hydra.main( - version_base=None, config_path="../../../cli-conf", config_name="scenario2-2d" + version_base=None, config_path="../../../cli-conf", config_name="config" )(fun) diff --git a/src/snake/toolkit/cli/reconstruction.py b/src/snake/toolkit/cli/reconstruction.py index 3df1d7b4..ab456d89 100644 --- a/src/snake/toolkit/cli/reconstruction.py +++ b/src/snake/toolkit/cli/reconstruction.py @@ -57,7 +57,7 @@ def reconstruction(cfg: DictConfig) -> None: data_rec_file = Path(f"data_rec_{rec_str}.npy") log.info(f"Using {name} reconstructor") rec.setup(sim_conf) - rec_data = rec.reconstruct(data_loader, sim_conf, data_loader.slice_2d) + rec_data = rec.reconstruct(data_loader, sim_conf) log.info(f"Reconstruction done with {name}") # Save the reconstruction np.save(data_rec_file, rec_data) diff --git a/src/snake/toolkit/reconstructors/pysap.py b/src/snake/toolkit/reconstructors/pysap.py index 39552b79..8e35665d 100644 --- a/src/snake/toolkit/reconstructors/pysap.py +++ b/src/snake/toolkit/reconstructors/pysap.py @@ -73,20 +73,18 @@ def setup(self, sim_conf: SimConfig) -> None: """Initialize Reconstructor.""" pass - def reconstruct( - self, data_loader: MRDLoader, sim_conf: SimConfig, slice_2d: bool - ) -> NDArray: + def reconstruct(self, data_loader: MRDLoader, sim_conf: SimConfig) -> NDArray: """Reconstruct data with zero-filled method.""" with data_loader: if isinstance(data_loader, CartesianFrameDataLoader): - return self._reconstruct_cartesian(data_loader, sim_conf, slice_2d) + return self._reconstruct_cartesian(data_loader, sim_conf) elif isinstance(data_loader, NonCartesianFrameDataLoader): - return self._reconstruct_nufft(data_loader, sim_conf, slice_2d) + return self._reconstruct_nufft(data_loader, sim_conf) else: raise ValueError("Unknown dataloader") def _reconstruct_cartesian( - self, data_loader: CartesianFrameDataLoader, sim_conf: SimConfig, slice_2d + self, data_loader: CartesianFrameDataLoader, sim_conf: SimConfig ) -> NDArray: smaps = data_loader.get_smaps() if smaps is None and data_loader.n_coils > 1: @@ -127,7 +125,7 @@ def _reconstruct_cartesian( return final_images def _reconstruct_nufft( - self, data_loader: NonCartesianFrameDataLoader, sim_conf: SimConfig, slice_2d + self, data_loader: NonCartesianFrameDataLoader, sim_conf: SimConfig ) -> NDArray: """Reconstruct data with nufft method.""" from mrinufft import get_operator @@ -136,7 +134,7 @@ def _reconstruct_nufft( shape = data_loader.shape traj, kspace_data = data_loader.get_kspace_frame(0) - if slice_2d: + if data_loader.slice_2d: shape = data_loader.shape[:2] traj = traj.reshape(data_loader.n_shots, -1, traj.shape[-1])[0, :, :2] @@ -165,7 +163,7 @@ def _reconstruct_nufft( for i in tqdm(range(data_loader.n_frames)): traj, data = data_loader.get_kspace_frame(i) - if slice_2d: + if data_loader.slice_2d: nufft_operator.samples = traj.reshape( data_loader.n_shots, -1, traj.shape[-1] )[0, :, :2] From 57705b3cf0e1c0ff83d6c21789141b777e05f745 Mon Sep 17 00:00:00 2001 From: alineyyy Date: Sat, 1 Feb 2025 16:37:54 +0100 Subject: [PATCH 08/15] rotated spiral sampler --- src/snake/core/sampling/__init__.py | 2 + src/snake/core/sampling/samplers.py | 73 ++++++++++++++++++++++++++++- 2 files changed, 74 insertions(+), 1 deletion(-) diff --git a/src/snake/core/sampling/__init__.py b/src/snake/core/sampling/__init__.py index ad86234f..b763f9db 100644 --- a/src/snake/core/sampling/__init__.py +++ b/src/snake/core/sampling/__init__.py @@ -4,6 +4,7 @@ from .samplers import ( EPI3dAcquisitionSampler, StackOfSpiralSampler, + RotatedStackOfSpiralSampler, NonCartesianAcquisitionSampler, EVI3dAcquisitionSampler, LoadTrajectorySampler, @@ -15,5 +16,6 @@ "EPI3dAcquisitionSampler", "EVI3dAcquisitionSampler", "StackOfSpiralSampler", + "RotatedStackOfSpiralSampler", "NonCartesianAcquisitionSampler", ] diff --git a/src/snake/core/sampling/samplers.py b/src/snake/core/sampling/samplers.py index 42575795..0e586a44 100644 --- a/src/snake/core/sampling/samplers.py +++ b/src/snake/core/sampling/samplers.py @@ -15,6 +15,7 @@ stack_spiral_factory, stacked_epi_factory, evi_factory, + rotate_trajectory, ) from snake.mrd_utils.utils import ACQ from snake._meta import batched, EnvConfig @@ -217,7 +218,77 @@ def _single_frame(self, sim_conf: SimConfig) -> NDArray: data = np.maximum(data, -0.5) return data - +class RotatedStackOfSpiralSampler(NonCartesianAcquisitionSampler): + """ + Spiral 2D Acquisition Handler to generate k-space data. + Parameters + ---------- + acsz: float | int + Number/ proportion of lines to be acquired in the center of k-space. + accelz: int + Acceleration factor for the rest of the lines. + directionz: Literal["center-out", "random"] + Direction of the acquisition. Either "center-out" or "random". + pdfz: Literal["gaussian", "uniform"] + Probability density function of the sampling. Either "gaussian" or "uniform". + obs_ms: int + Time spent to acquire a single shot + nb_revolutions: int + Number of revolutions of the spiral. + in_out: bool + If true, the spiral is acquired with a double join pattern from/to the periphery + **kwargs: + Extra arguments (smaps, n_jobs, backend etc...) + """ + __sampler_name__ = "stack-of-spiral" + acsz: float | int + accelz: int + orderz: VDSorder = VDSorder.TOP_DOWN + nb_revolutions: int = 10 + spiral_name: str = "archimedes" + pdfz: VDSpdf = VDSpdf.GAUSSIAN + constant: bool = False + in_out: bool = True + rotate_angle: AngleRotation = AngleRotation.ZERO + rotate_frame_angle: AngleRotation = AngleRotation.ZERO + obs_time_ms: int = 30 + n_shot_slices: int = 1 + + def fix_angle_rotation(self, frame, angle): + for traj in frame: + for rotated_traj in rotate_trajectory((traj,), angle): + yield rotated_traj + + def get_next_frame(self, sim_conf): + base_frame = self._single_frame(sim_conf) + self._frame_index = 0 + if self.constant or self.rotate_frame_angle == 0: + return base_frame + else: + self._frame_index += 1 + base_frame_gen = (traj[None,...] for traj in base_frame) + rotated_frame = self.fix_angle_rotation(base_frame_gen, self.rotate_frame_angle*self._frame_index) + return np.concatenate([traj.astype(np.float32) for traj in rotated_frame], axis=0) + + def _single_frame(self, sim_conf: SimConfig) -> NDArray: + """Generate the sampling pattern.""" + n_samples = int(self.obs_time_ms / sim_conf.hardware.dwell_time_ms) + single_frame = stack_spiral_factory( + shape=sim_conf.shape, + accelz=self.accelz, + acsz=self.acsz, + n_samples=n_samples, + nb_revolutions=self.nb_revolutions, + pdfz=self.pdfz, + orderz=self.orderz, + spiral=self.spiral_name, + rotate_angle=self.rotate_angle, + in_out=self.in_out, + n_shot_slices=self.n_shot_slices, + rng=sim_conf.rng, + ) + return single_frame + class StackOfSpiralSampler(NonCartesianAcquisitionSampler): """ Spiral 2D Acquisition Handler to generate k-space data. From dd449e9f2f6d0e2a9bf98acd080de1de7ae137be Mon Sep 17 00:00:00 2001 From: alineyyy Date: Mon, 3 Feb 2025 11:06:55 +0100 Subject: [PATCH 09/15] ruff --- examples/example_gpu_anat_spirals_slice.py | 1 - src/snake/core/engine/cartesian.py | 1 - src/snake/core/sampling/samplers.py | 7 ++++--- src/snake/core/simulation.py | 1 - src/snake/mrd_utils/loader.py | 2 +- src/snake/toolkit/cli/acquisition.py | 4 +++- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/examples/example_gpu_anat_spirals_slice.py b/examples/example_gpu_anat_spirals_slice.py index 84b755a4..c7a7e225 100644 --- a/examples/example_gpu_anat_spirals_slice.py +++ b/examples/example_gpu_anat_spirals_slice.py @@ -13,7 +13,6 @@ # %% # Imports -import numpy as np import matplotlib.pyplot as plt from snake.core.simulation import SimConfig, default_hardware, GreConfig diff --git a/src/snake/core/engine/cartesian.py b/src/snake/core/engine/cartesian.py index ded70f6d..186b71f1 100644 --- a/src/snake/core/engine/cartesian.py +++ b/src/snake/core/engine/cartesian.py @@ -1,6 +1,5 @@ """Acquisition engine for Cartesian trajectories.""" -from typing import Any from collections.abc import Sequence from copy import deepcopy diff --git a/src/snake/core/sampling/samplers.py b/src/snake/core/sampling/samplers.py index 42575795..405856c5 100644 --- a/src/snake/core/sampling/samplers.py +++ b/src/snake/core/sampling/samplers.py @@ -1,7 +1,6 @@ """Samplers generate kspace trajectories.""" from __future__ import annotations -from typing import Literal import ismrmrd as mrd import numpy as np from numpy.typing import NDArray @@ -32,7 +31,8 @@ class NonCartesianAcquisitionSampler(BaseSampler): obs_time_ms: int Time spent to acquire a single shot in_out: bool - If true, the trajectory is acquired with a double join pattern from/to the periphery + If true, the trajectory is acquired with a double join pattern + from/to the periphery ndim: int Number of dimensions of the trajectory (2 or 3) """ @@ -198,7 +198,8 @@ class LoadTrajectorySampler(NonCartesianAcquisitionSampler): obs_time_ms: int Time spent to acquire a single shot in_out: bool - If true, the trajectory is acquired with a double join pattern from/to the periphery + If true, the trajectory is acquired with a double join pattern + from/to the periphery """ __sampler_name__ = "load-trajectory" diff --git a/src/snake/core/simulation.py b/src/snake/core/simulation.py index 181ff414..f14898aa 100644 --- a/src/snake/core/simulation.py +++ b/src/snake/core/simulation.py @@ -28,7 +28,6 @@ def _repr_html_(obj: Any, vertical: bool = True) -> str: '' f"{class_name}" ] - from typing import get_type_hints from dataclasses import fields resolved_hints = obj.__annotations__ diff --git a/src/snake/mrd_utils/loader.py b/src/snake/mrd_utils/loader.py index 648b2f03..5cbf7ac5 100644 --- a/src/snake/mrd_utils/loader.py +++ b/src/snake/mrd_utils/loader.py @@ -218,7 +218,7 @@ def engine_model(self) -> str: @property def slice_2d(self) -> bool: - """Is the acquisiton run on 2D slices.""" + """Is the acquisition run on 2D slices.""" return bool(self.header.userParameters.userParameterString[1].value) ############# diff --git a/src/snake/toolkit/cli/acquisition.py b/src/snake/toolkit/cli/acquisition.py index 6d902b19..1d79ce8a 100644 --- a/src/snake/toolkit/cli/acquisition.py +++ b/src/snake/toolkit/cli/acquisition.py @@ -51,7 +51,9 @@ def acquisition(cfg: ConfigSNAKE) -> None: kwargs = {} if engine_klass.__engine_name__ == "NUFFT": kwargs["nufft_backend"] = cfg.engine.nufft_backend - engine = engine_klass(model=cfg.engine.model, snr=cfg.engine.snr, slice_2d=cfg.engine.slice_2d) # type: ignore + engine = engine_klass( + model=cfg.engine.model, snr=cfg.engine.snr, slice_2d=cfg.engine.slice_2d + ) # type: ignore engine( cfg.filename, From 9473a0973f4d9736553802bffc78b3089e59c353 Mon Sep 17 00:00:00 2001 From: alineyyy Date: Sat, 1 Feb 2025 16:37:54 +0100 Subject: [PATCH 10/15] rotated spiral sampler --- src/snake/core/sampling/__init__.py | 2 + src/snake/core/sampling/samplers.py | 73 ++++++++++++++++++++++++++++- 2 files changed, 74 insertions(+), 1 deletion(-) diff --git a/src/snake/core/sampling/__init__.py b/src/snake/core/sampling/__init__.py index ad86234f..b763f9db 100644 --- a/src/snake/core/sampling/__init__.py +++ b/src/snake/core/sampling/__init__.py @@ -4,6 +4,7 @@ from .samplers import ( EPI3dAcquisitionSampler, StackOfSpiralSampler, + RotatedStackOfSpiralSampler, NonCartesianAcquisitionSampler, EVI3dAcquisitionSampler, LoadTrajectorySampler, @@ -15,5 +16,6 @@ "EPI3dAcquisitionSampler", "EVI3dAcquisitionSampler", "StackOfSpiralSampler", + "RotatedStackOfSpiralSampler", "NonCartesianAcquisitionSampler", ] diff --git a/src/snake/core/sampling/samplers.py b/src/snake/core/sampling/samplers.py index 405856c5..575b490c 100644 --- a/src/snake/core/sampling/samplers.py +++ b/src/snake/core/sampling/samplers.py @@ -14,6 +14,7 @@ stack_spiral_factory, stacked_epi_factory, evi_factory, + rotate_trajectory, ) from snake.mrd_utils.utils import ACQ from snake._meta import batched, EnvConfig @@ -218,7 +219,77 @@ def _single_frame(self, sim_conf: SimConfig) -> NDArray: data = np.maximum(data, -0.5) return data - +class RotatedStackOfSpiralSampler(NonCartesianAcquisitionSampler): + """ + Spiral 2D Acquisition Handler to generate k-space data. + Parameters + ---------- + acsz: float | int + Number/ proportion of lines to be acquired in the center of k-space. + accelz: int + Acceleration factor for the rest of the lines. + directionz: Literal["center-out", "random"] + Direction of the acquisition. Either "center-out" or "random". + pdfz: Literal["gaussian", "uniform"] + Probability density function of the sampling. Either "gaussian" or "uniform". + obs_ms: int + Time spent to acquire a single shot + nb_revolutions: int + Number of revolutions of the spiral. + in_out: bool + If true, the spiral is acquired with a double join pattern from/to the periphery + **kwargs: + Extra arguments (smaps, n_jobs, backend etc...) + """ + __sampler_name__ = "stack-of-spiral" + acsz: float | int + accelz: int + orderz: VDSorder = VDSorder.TOP_DOWN + nb_revolutions: int = 10 + spiral_name: str = "archimedes" + pdfz: VDSpdf = VDSpdf.GAUSSIAN + constant: bool = False + in_out: bool = True + rotate_angle: AngleRotation = AngleRotation.ZERO + rotate_frame_angle: AngleRotation = AngleRotation.ZERO + obs_time_ms: int = 30 + n_shot_slices: int = 1 + + def fix_angle_rotation(self, frame, angle): + for traj in frame: + for rotated_traj in rotate_trajectory((traj,), angle): + yield rotated_traj + + def get_next_frame(self, sim_conf): + base_frame = self._single_frame(sim_conf) + self._frame_index = 0 + if self.constant or self.rotate_frame_angle == 0: + return base_frame + else: + self._frame_index += 1 + base_frame_gen = (traj[None,...] for traj in base_frame) + rotated_frame = self.fix_angle_rotation(base_frame_gen, self.rotate_frame_angle*self._frame_index) + return np.concatenate([traj.astype(np.float32) for traj in rotated_frame], axis=0) + + def _single_frame(self, sim_conf: SimConfig) -> NDArray: + """Generate the sampling pattern.""" + n_samples = int(self.obs_time_ms / sim_conf.hardware.dwell_time_ms) + single_frame = stack_spiral_factory( + shape=sim_conf.shape, + accelz=self.accelz, + acsz=self.acsz, + n_samples=n_samples, + nb_revolutions=self.nb_revolutions, + pdfz=self.pdfz, + orderz=self.orderz, + spiral=self.spiral_name, + rotate_angle=self.rotate_angle, + in_out=self.in_out, + n_shot_slices=self.n_shot_slices, + rng=sim_conf.rng, + ) + return single_frame + class StackOfSpiralSampler(NonCartesianAcquisitionSampler): """ Spiral 2D Acquisition Handler to generate k-space data. From 879fee236c0b79e2752f2616855a8d7856e395f6 Mon Sep 17 00:00:00 2001 From: alineyyy Date: Mon, 3 Feb 2025 13:09:05 +0100 Subject: [PATCH 11/15] ruff --- src/snake/core/sampling/samplers.py | 32 ++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/src/snake/core/sampling/samplers.py b/src/snake/core/sampling/samplers.py index 575b490c..870b191c 100644 --- a/src/snake/core/sampling/samplers.py +++ b/src/snake/core/sampling/samplers.py @@ -19,7 +19,7 @@ from snake.mrd_utils.utils import ACQ from snake._meta import batched, EnvConfig from mrinufft.io import read_trajectory - +from collections.abc import Generator class NonCartesianAcquisitionSampler(BaseSampler): """ @@ -222,6 +222,7 @@ def _single_frame(self, sim_conf: SimConfig) -> NDArray: class RotatedStackOfSpiralSampler(NonCartesianAcquisitionSampler): """ Spiral 2D Acquisition Handler to generate k-space data. + Parameters ---------- acsz: float | int @@ -241,6 +242,7 @@ class RotatedStackOfSpiralSampler(NonCartesianAcquisitionSampler): **kwargs: Extra arguments (smaps, n_jobs, backend etc...) """ + __sampler_name__ = "stack-of-spiral" acsz: float | int accelz: int @@ -254,22 +256,32 @@ class RotatedStackOfSpiralSampler(NonCartesianAcquisitionSampler): rotate_frame_angle: AngleRotation = AngleRotation.ZERO obs_time_ms: int = 30 n_shot_slices: int = 1 - - def fix_angle_rotation(self, frame, angle): + frame_index: int = 0 + + def fix_angle_rotation( + self, + frame: Generator[np.ndarray, None, None], + angle: AngleRotation | float = 0 + ) -> Generator[np.ndarray, None, None]: + """Rotate the trajectory by a given angle.""" for traj in frame: - for rotated_traj in rotate_trajectory((traj,), angle): - yield rotated_traj + yield from rotate_trajectory((traj,), angle) - def get_next_frame(self, sim_conf): + def get_next_frame(self, sim_conf: SimConfig) -> NDArray: + """Generate the next rotated frame.""" base_frame = self._single_frame(sim_conf) - self._frame_index = 0 if self.constant or self.rotate_frame_angle == 0: return base_frame else: - self._frame_index += 1 + self.frame_index += 1 + print(self.frame_index) base_frame_gen = (traj[None,...] for traj in base_frame) - rotated_frame = self.fix_angle_rotation(base_frame_gen, self.rotate_frame_angle*self._frame_index) - return np.concatenate([traj.astype(np.float32) for traj in rotated_frame], axis=0) + rotated_frame = self.fix_angle_rotation( + base_frame_gen, self.rotate_frame_angle*self.frame_index + ) + return np.concatenate( + [traj.astype(np.float32) for traj in rotated_frame], axis=0 + ) def _single_frame(self, sim_conf: SimConfig) -> NDArray: """Generate the sampling pattern.""" From bc091388fa22b776e7fbea36995091f77cf2ee05 Mon Sep 17 00:00:00 2001 From: alineyyy Date: Mon, 3 Feb 2025 15:54:07 +0100 Subject: [PATCH 12/15] update yaml for rotation scenario --- src/cli-conf/scenario2-2d.yaml | 11 +++++++++-- src/snake/core/sampling/samplers.py | 14 +++++++------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/cli-conf/scenario2-2d.yaml b/src/cli-conf/scenario2-2d.yaml index 011a3785..c145e439 100644 --- a/src/cli-conf/scenario2-2d.yaml +++ b/src/cli-conf/scenario2-2d.yaml @@ -5,7 +5,7 @@ defaults: - handlers: - activation-block - sampler: - - stack-of-spiral + - rotated-stack-of-spiral - reconstructors: - adjoint #- sequential @@ -43,7 +43,14 @@ sampler: nb_revolutions: 10 constant: true spiral_name: "galilean" - + rotated-stack-of-spiral: + acsz: 1 + accelz: 1 + nb_revolutions: 10 + constant: false + spiral_name: "galilean" + rotate_frame_angle: 0 + engine: n_jobs: 1 chunk_size: 10 diff --git a/src/snake/core/sampling/samplers.py b/src/snake/core/sampling/samplers.py index cf957a36..8656791f 100644 --- a/src/snake/core/sampling/samplers.py +++ b/src/snake/core/sampling/samplers.py @@ -14,8 +14,7 @@ stack_spiral_factory, stacked_epi_factory, evi_factory, - rotate_trajectory, - rotate_trajectory, + rotate_trajectory ) from snake.mrd_utils.utils import ACQ from snake._meta import batched, EnvConfig @@ -244,7 +243,7 @@ class RotatedStackOfSpiralSampler(NonCartesianAcquisitionSampler): Extra arguments (smaps, n_jobs, backend etc...) """ - __sampler_name__ = "stack-of-spiral" + __sampler_name__ = "rotated-stack-of-spiral" acsz: float | int accelz: int orderz: VDSorder = VDSorder.TOP_DOWN @@ -254,7 +253,7 @@ class RotatedStackOfSpiralSampler(NonCartesianAcquisitionSampler): constant: bool = False in_out: bool = True rotate_angle: AngleRotation = AngleRotation.ZERO - rotate_frame_angle: AngleRotation = AngleRotation.ZERO + rotate_frame_angle: AngleRotation | int = 0 obs_time_ms: int = 30 n_shot_slices: int = 1 frame_index: int = 0 @@ -266,7 +265,8 @@ def fix_angle_rotation( ) -> Generator[np.ndarray, None, None]: """Rotate the trajectory by a given angle.""" for traj in frame: - yield from rotate_trajectory((traj,), angle) + yield from rotate_trajectory((x for x in [traj]), angle) + def get_next_frame(self, sim_conf: SimConfig) -> NDArray: """Generate the next rotated frame.""" @@ -275,10 +275,10 @@ def get_next_frame(self, sim_conf: SimConfig) -> NDArray: return base_frame else: self.frame_index += 1 - print(self.frame_index) + rotate_frame_angle = np.pi*(self.rotate_frame_angle/180) base_frame_gen = (traj[None,...] for traj in base_frame) rotated_frame = self.fix_angle_rotation( - base_frame_gen, self.rotate_frame_angle*self.frame_index + base_frame_gen, float(rotate_frame_angle*self.frame_index) ) return np.concatenate( [traj.astype(np.float32) for traj in rotated_frame], axis=0 From ac5474ed2c41c558872d88088fbdd9365618e0a9 Mon Sep 17 00:00:00 2001 From: alineyyy Date: Mon, 3 Feb 2025 16:14:22 +0100 Subject: [PATCH 13/15] ruff --- src/snake/core/sampling/samplers.py | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/snake/core/sampling/samplers.py b/src/snake/core/sampling/samplers.py index 8656791f..c4888b98 100644 --- a/src/snake/core/sampling/samplers.py +++ b/src/snake/core/sampling/samplers.py @@ -14,13 +14,14 @@ stack_spiral_factory, stacked_epi_factory, evi_factory, - rotate_trajectory + rotate_trajectory, ) from snake.mrd_utils.utils import ACQ from snake._meta import batched, EnvConfig from mrinufft.io import read_trajectory from collections.abc import Generator + class NonCartesianAcquisitionSampler(BaseSampler): """ Base class for non-cartesian acquisition samplers. @@ -219,6 +220,7 @@ def _single_frame(self, sim_conf: SimConfig) -> NDArray: data = np.maximum(data, -0.5) return data + class RotatedStackOfSpiralSampler(NonCartesianAcquisitionSampler): """ Spiral 2D Acquisition Handler to generate k-space data. @@ -259,31 +261,28 @@ class RotatedStackOfSpiralSampler(NonCartesianAcquisitionSampler): frame_index: int = 0 def fix_angle_rotation( - self, - frame: Generator[np.ndarray, None, None], - angle: AngleRotation | float = 0 - ) -> Generator[np.ndarray, None, None]: + self, frame: Generator[np.ndarray, None, None], angle: AngleRotation | float = 0 + ) -> Generator[np.ndarray, None, None]: """Rotate the trajectory by a given angle.""" for traj in frame: yield from rotate_trajectory((x for x in [traj]), angle) - - def get_next_frame(self, sim_conf: SimConfig) -> NDArray: + def get_next_frame(self, sim_conf: SimConfig) -> NDArray: """Generate the next rotated frame.""" base_frame = self._single_frame(sim_conf) if self.constant or self.rotate_frame_angle == 0: return base_frame else: self.frame_index += 1 - rotate_frame_angle = np.pi*(self.rotate_frame_angle/180) - base_frame_gen = (traj[None,...] for traj in base_frame) + rotate_frame_angle = np.pi * (self.rotate_frame_angle / 180) + base_frame_gen = (traj[None, ...] for traj in base_frame) rotated_frame = self.fix_angle_rotation( - base_frame_gen, float(rotate_frame_angle*self.frame_index) - ) + base_frame_gen, float(rotate_frame_angle * self.frame_index) + ) return np.concatenate( [traj.astype(np.float32) for traj in rotated_frame], axis=0 - ) - + ) + def _single_frame(self, sim_conf: SimConfig) -> NDArray: """Generate the sampling pattern.""" n_samples = int(self.obs_time_ms / sim_conf.hardware.dwell_time_ms) @@ -302,7 +301,8 @@ def _single_frame(self, sim_conf: SimConfig) -> NDArray: rng=sim_conf.rng, ) return single_frame - + + class StackOfSpiralSampler(NonCartesianAcquisitionSampler): """ Spiral 2D Acquisition Handler to generate k-space data. From 664751d6086ed0060c4d3426817311f1cf5a023a Mon Sep 17 00:00:00 2001 From: alineyyy Date: Mon, 3 Feb 2025 17:03:09 +0100 Subject: [PATCH 14/15] inherited class --- src/cli-conf/scenario2-2d.yaml | 3 +- src/snake/core/sampling/samplers.py | 106 +++++++++------------------- 2 files changed, 35 insertions(+), 74 deletions(-) diff --git a/src/cli-conf/scenario2-2d.yaml b/src/cli-conf/scenario2-2d.yaml index c145e439..317475eb 100644 --- a/src/cli-conf/scenario2-2d.yaml +++ b/src/cli-conf/scenario2-2d.yaml @@ -35,6 +35,7 @@ handlers: block_on: 20 # seconds block_off: 20 #seconds duration: 360 # seconds + delta_r2s: 1000 # millisecond^-1 sampler: stack-of-spiral: @@ -50,7 +51,7 @@ sampler: constant: false spiral_name: "galilean" rotate_frame_angle: 0 - + engine: n_jobs: 1 chunk_size: 10 diff --git a/src/snake/core/sampling/samplers.py b/src/snake/core/sampling/samplers.py index c4888b98..51237619 100644 --- a/src/snake/core/sampling/samplers.py +++ b/src/snake/core/sampling/samplers.py @@ -221,7 +221,7 @@ def _single_frame(self, sim_conf: SimConfig) -> NDArray: return data -class RotatedStackOfSpiralSampler(NonCartesianAcquisitionSampler): +class StackOfSpiralSampler(NonCartesianAcquisitionSampler): """ Spiral 2D Acquisition Handler to generate k-space data. @@ -245,7 +245,8 @@ class RotatedStackOfSpiralSampler(NonCartesianAcquisitionSampler): Extra arguments (smaps, n_jobs, backend etc...) """ - __sampler_name__ = "rotated-stack-of-spiral" + __sampler_name__ = "stack-of-spiral" + acsz: float | int accelz: int orderz: VDSorder = VDSorder.TOP_DOWN @@ -255,38 +256,13 @@ class RotatedStackOfSpiralSampler(NonCartesianAcquisitionSampler): constant: bool = False in_out: bool = True rotate_angle: AngleRotation = AngleRotation.ZERO - rotate_frame_angle: AngleRotation | int = 0 obs_time_ms: int = 30 n_shot_slices: int = 1 - frame_index: int = 0 - - def fix_angle_rotation( - self, frame: Generator[np.ndarray, None, None], angle: AngleRotation | float = 0 - ) -> Generator[np.ndarray, None, None]: - """Rotate the trajectory by a given angle.""" - for traj in frame: - yield from rotate_trajectory((x for x in [traj]), angle) - - def get_next_frame(self, sim_conf: SimConfig) -> NDArray: - """Generate the next rotated frame.""" - base_frame = self._single_frame(sim_conf) - if self.constant or self.rotate_frame_angle == 0: - return base_frame - else: - self.frame_index += 1 - rotate_frame_angle = np.pi * (self.rotate_frame_angle / 180) - base_frame_gen = (traj[None, ...] for traj in base_frame) - rotated_frame = self.fix_angle_rotation( - base_frame_gen, float(rotate_frame_angle * self.frame_index) - ) - return np.concatenate( - [traj.astype(np.float32) for traj in rotated_frame], axis=0 - ) def _single_frame(self, sim_conf: SimConfig) -> NDArray: """Generate the sampling pattern.""" n_samples = int(self.obs_time_ms / sim_conf.hardware.dwell_time_ms) - single_frame = stack_spiral_factory( + return stack_spiral_factory( shape=sim_conf.shape, accelz=self.accelz, acsz=self.acsz, @@ -300,64 +276,48 @@ def _single_frame(self, sim_conf: SimConfig) -> NDArray: n_shot_slices=self.n_shot_slices, rng=sim_conf.rng, ) - return single_frame -class StackOfSpiralSampler(NonCartesianAcquisitionSampler): +class RotatedStackOfSpiralSampler(StackOfSpiralSampler): """ Spiral 2D Acquisition Handler to generate k-space data. Parameters ---------- - acsz: float | int - Number/ proportion of lines to be acquired in the center of k-space. - accelz: int - Acceleration factor for the rest of the lines. - directionz: Literal["center-out", "random"] - Direction of the acquisition. Either "center-out" or "random". - pdfz: Literal["gaussian", "uniform"] - Probability density function of the sampling. Either "gaussian" or "uniform". - obs_ms: int - Time spent to acquire a single shot - nb_revolutions: int - Number of revolutions of the spiral. - in_out: bool - If true, the spiral is acquired with a double join pattern from/to the periphery + rotate_frame_angle: AngleRotation | int + Angle of rotation of the frame. + frame_index: int + Index of the frame. **kwargs: Extra arguments (smaps, n_jobs, backend etc...) """ - __sampler_name__ = "stack-of-spiral" + __sampler_name__ = "rotated-stack-of-spiral" + rotate_frame_angle: AngleRotation | int = 0 + frame_index: int = 0 - acsz: float | int - accelz: int - orderz: VDSorder = VDSorder.TOP_DOWN - nb_revolutions: int = 10 - spiral_name: str = "archimedes" - pdfz: VDSpdf = VDSpdf.GAUSSIAN - constant: bool = False - in_out: bool = True - rotate_angle: AngleRotation = AngleRotation.ZERO - obs_time_ms: int = 30 - n_shot_slices: int = 1 + def fix_angle_rotation( + self, frame: Generator[np.ndarray, None, None], angle: AngleRotation | float = 0 + ) -> Generator[np.ndarray, None, None]: + """Rotate the trajectory by a given angle.""" + for traj in frame: + yield from rotate_trajectory((x for x in [traj]), angle) - def _single_frame(self, sim_conf: SimConfig) -> NDArray: - """Generate the sampling pattern.""" - n_samples = int(self.obs_time_ms / sim_conf.hardware.dwell_time_ms) - return stack_spiral_factory( - shape=sim_conf.shape, - accelz=self.accelz, - acsz=self.acsz, - n_samples=n_samples, - nb_revolutions=self.nb_revolutions, - pdfz=self.pdfz, - orderz=self.orderz, - spiral=self.spiral_name, - rotate_angle=self.rotate_angle, - in_out=self.in_out, - n_shot_slices=self.n_shot_slices, - rng=sim_conf.rng, - ) + def get_next_frame(self, sim_conf: SimConfig) -> NDArray: + """Generate the next rotated frame.""" + base_frame = self._single_frame(sim_conf) + if self.constant or self.rotate_frame_angle == 0: + return base_frame + else: + self.frame_index += 1 + rotate_frame_angle = np.pi * (self.rotate_frame_angle / 180) + base_frame_gen = (traj[None, ...] for traj in base_frame) + rotated_frame = self.fix_angle_rotation( + base_frame_gen, float(rotate_frame_angle * self.frame_index) + ) + return np.concatenate( + [traj.astype(np.float32) for traj in rotated_frame], axis=0 + ) class EPI3dAcquisitionSampler(BaseSampler): From 48218fa5d2613827aae79c0e545169164a5fc904 Mon Sep 17 00:00:00 2001 From: alineyyy Date: Tue, 4 Feb 2025 14:09:04 +0100 Subject: [PATCH 15/15] update density comp while rotation --- src/snake/toolkit/cli/config.py | 2 +- src/snake/toolkit/reconstructors/pysap.py | 15 ++++++++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/snake/toolkit/cli/config.py b/src/snake/toolkit/cli/config.py index 7611cf82..39d2a4e2 100644 --- a/src/snake/toolkit/cli/config.py +++ b/src/snake/toolkit/cli/config.py @@ -125,5 +125,5 @@ def cleanup_cuda() -> None: def make_hydra_cli(fun: callable) -> callable: """Create a Hydra CLI for the function.""" return hydra.main( - version_base=None, config_path="../../../cli-conf", config_name="config" + version_base=None, config_path="../../../cli-conf", config_name="scenario2-2d" )(fun) diff --git a/src/snake/toolkit/reconstructors/pysap.py b/src/snake/toolkit/reconstructors/pysap.py index d2e3049a..051fb984 100644 --- a/src/snake/toolkit/reconstructors/pysap.py +++ b/src/snake/toolkit/reconstructors/pysap.py @@ -8,6 +8,7 @@ import numpy as np from numpy.typing import NDArray +from mrinufft.density import get_density # Local imports from snake.mrd_utils import ( @@ -155,9 +156,15 @@ def _reconstruct_nufft( kwargs["density"] = None else: kwargs["density"] = self.density_compensation + method = self.density_compensation if "stacked" in self.nufft_backend: kwargs["z_index"] = "auto" + if isinstance(method, str): + method = get_density(method) + if not callable(method): + raise ValueError(f"Unknown density method: {method}") + nufft_operator = get_operator( self.nufft_backend, samples=traj, @@ -171,9 +178,11 @@ def _reconstruct_nufft( for i in tqdm(range(data_loader.n_frames)): traj, data = data_loader.get_kspace_frame(i) if data_loader.slice_2d: - nufft_operator.samples = traj.reshape( - data_loader.n_shots, -1, traj.shape[-1] - )[0, :, :2] + traj = traj.reshape(data_loader.n_shots, -1, traj.shape[-1]) + nufft_operator.samples = traj[0, :, :2] + nufft_operator.density = method( + traj[:, :, :2], shape, backend=self.nufft_backend + ) data = np.reshape(data, (data.shape[0], data_loader.n_shots, -1)) for j in range(data.shape[1]): final_images[i, :, :, j] = abs(nufft_operator.adj_op(data[:, j]))