rapidtide 2.9.5__py3-none-any.whl → 3.1.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (405) hide show
  1. cloud/gmscalc-HCPYA +1 -1
  2. cloud/mount-and-run +2 -0
  3. cloud/rapidtide-HCPYA +3 -3
  4. rapidtide/Colortables.py +538 -38
  5. rapidtide/OrthoImageItem.py +1094 -51
  6. rapidtide/RapidtideDataset.py +1709 -114
  7. rapidtide/__init__.py +0 -8
  8. rapidtide/_version.py +4 -4
  9. rapidtide/calccoherence.py +242 -97
  10. rapidtide/calcnullsimfunc.py +240 -140
  11. rapidtide/calcsimfunc.py +314 -129
  12. rapidtide/correlate.py +1211 -389
  13. rapidtide/data/examples/src/testLD +56 -0
  14. rapidtide/data/examples/src/test_findmaxlag.py +2 -2
  15. rapidtide/data/examples/src/test_mlregressallt.py +32 -17
  16. rapidtide/data/examples/src/testalign +1 -1
  17. rapidtide/data/examples/src/testatlasaverage +35 -7
  18. rapidtide/data/examples/src/testboth +21 -0
  19. rapidtide/data/examples/src/testcifti +11 -0
  20. rapidtide/data/examples/src/testdelayvar +13 -0
  21. rapidtide/data/examples/src/testdlfilt +25 -0
  22. rapidtide/data/examples/src/testfft +35 -0
  23. rapidtide/data/examples/src/testfileorfloat +37 -0
  24. rapidtide/data/examples/src/testfmri +94 -27
  25. rapidtide/data/examples/src/testfuncs +3 -3
  26. rapidtide/data/examples/src/testglmfilt +8 -6
  27. rapidtide/data/examples/src/testhappy +84 -51
  28. rapidtide/data/examples/src/testinitdelay +19 -0
  29. rapidtide/data/examples/src/testmodels +33 -0
  30. rapidtide/data/examples/src/testnewrefine +26 -0
  31. rapidtide/data/examples/src/testnoiseamp +21 -0
  32. rapidtide/data/examples/src/testppgproc +17 -0
  33. rapidtide/data/examples/src/testrefineonly +22 -0
  34. rapidtide/data/examples/src/testretro +26 -13
  35. rapidtide/data/examples/src/testretrolagtcs +16 -0
  36. rapidtide/data/examples/src/testrolloff +11 -0
  37. rapidtide/data/examples/src/testsimdata +45 -28
  38. rapidtide/data/models/model_cnn_pytorch/loss.png +0 -0
  39. rapidtide/data/models/model_cnn_pytorch/loss.txt +1 -0
  40. rapidtide/data/models/model_cnn_pytorch/model.pth +0 -0
  41. rapidtide/data/models/model_cnn_pytorch/model_meta.json +68 -0
  42. rapidtide/data/models/model_cnn_pytorch_fulldata/loss.png +0 -0
  43. rapidtide/data/models/model_cnn_pytorch_fulldata/loss.txt +1 -0
  44. rapidtide/data/models/model_cnn_pytorch_fulldata/model.pth +0 -0
  45. rapidtide/data/models/model_cnn_pytorch_fulldata/model_meta.json +80 -0
  46. rapidtide/data/models/model_cnnbp_pytorch_fullldata/loss.png +0 -0
  47. rapidtide/data/models/model_cnnbp_pytorch_fullldata/loss.txt +1 -0
  48. rapidtide/data/models/model_cnnbp_pytorch_fullldata/model.pth +0 -0
  49. rapidtide/data/models/model_cnnbp_pytorch_fullldata/model_meta.json +138 -0
  50. rapidtide/data/models/model_cnnfft_pytorch_fulldata/loss.png +0 -0
  51. rapidtide/data/models/model_cnnfft_pytorch_fulldata/loss.txt +1 -0
  52. rapidtide/data/models/model_cnnfft_pytorch_fulldata/model.pth +0 -0
  53. rapidtide/data/models/model_cnnfft_pytorch_fulldata/model_meta.json +128 -0
  54. rapidtide/data/models/model_ppgattention_pytorch_w128_fulldata/loss.png +0 -0
  55. rapidtide/data/models/model_ppgattention_pytorch_w128_fulldata/loss.txt +1 -0
  56. rapidtide/data/models/model_ppgattention_pytorch_w128_fulldata/model.pth +0 -0
  57. rapidtide/data/models/model_ppgattention_pytorch_w128_fulldata/model_meta.json +49 -0
  58. rapidtide/data/models/model_revised_tf2/model.keras +0 -0
  59. rapidtide/data/models/{model_serdar → model_revised_tf2}/model_meta.json +1 -1
  60. rapidtide/data/models/model_serdar2_tf2/model.keras +0 -0
  61. rapidtide/data/models/{model_serdar2 → model_serdar2_tf2}/model_meta.json +1 -1
  62. rapidtide/data/models/model_serdar_tf2/model.keras +0 -0
  63. rapidtide/data/models/{model_revised → model_serdar_tf2}/model_meta.json +1 -1
  64. rapidtide/data/reference/HCP1200v2_MTT_2mm.nii.gz +0 -0
  65. rapidtide/data/reference/HCP1200v2_binmask_2mm.nii.gz +0 -0
  66. rapidtide/data/reference/HCP1200v2_csf_2mm.nii.gz +0 -0
  67. rapidtide/data/reference/HCP1200v2_gray_2mm.nii.gz +0 -0
  68. rapidtide/data/reference/HCP1200v2_graylaghist.json +7 -0
  69. rapidtide/data/reference/HCP1200v2_graylaghist.tsv.gz +0 -0
  70. rapidtide/data/reference/HCP1200v2_laghist.json +7 -0
  71. rapidtide/data/reference/HCP1200v2_laghist.tsv.gz +0 -0
  72. rapidtide/data/reference/HCP1200v2_mask_2mm.nii.gz +0 -0
  73. rapidtide/data/reference/HCP1200v2_maxcorr_2mm.nii.gz +0 -0
  74. rapidtide/data/reference/HCP1200v2_maxtime_2mm.nii.gz +0 -0
  75. rapidtide/data/reference/HCP1200v2_maxwidth_2mm.nii.gz +0 -0
  76. rapidtide/data/reference/HCP1200v2_negmask_2mm.nii.gz +0 -0
  77. rapidtide/data/reference/HCP1200v2_timepercentile_2mm.nii.gz +0 -0
  78. rapidtide/data/reference/HCP1200v2_white_2mm.nii.gz +0 -0
  79. rapidtide/data/reference/HCP1200v2_whitelaghist.json +7 -0
  80. rapidtide/data/reference/HCP1200v2_whitelaghist.tsv.gz +0 -0
  81. rapidtide/data/reference/JHU-ArterialTerritoriesNoVent-LVL1-seg2.xml +131 -0
  82. rapidtide/data/reference/JHU-ArterialTerritoriesNoVent-LVL1-seg2_regions.txt +60 -0
  83. rapidtide/data/reference/JHU-ArterialTerritoriesNoVent-LVL1-seg2_space-MNI152NLin6Asym_2mm.nii.gz +0 -0
  84. rapidtide/data/reference/JHU-ArterialTerritoriesNoVent-LVL1_space-MNI152NLin2009cAsym_2mm.nii.gz +0 -0
  85. rapidtide/data/reference/JHU-ArterialTerritoriesNoVent-LVL1_space-MNI152NLin2009cAsym_2mm_mask.nii.gz +0 -0
  86. rapidtide/data/reference/JHU-ArterialTerritoriesNoVent-LVL1_space-MNI152NLin6Asym_2mm_mask.nii.gz +0 -0
  87. rapidtide/data/reference/JHU-ArterialTerritoriesNoVent-LVL2_space-MNI152NLin6Asym_2mm_mask.nii.gz +0 -0
  88. rapidtide/data/reference/MNI152_T1_1mm_Brain_FAST_seg.nii.gz +0 -0
  89. rapidtide/data/reference/MNI152_T1_1mm_Brain_Mask.nii.gz +0 -0
  90. rapidtide/data/reference/MNI152_T1_2mm_Brain_FAST_seg.nii.gz +0 -0
  91. rapidtide/data/reference/MNI152_T1_2mm_Brain_Mask.nii.gz +0 -0
  92. rapidtide/decorators.py +91 -0
  93. rapidtide/dlfilter.py +2553 -414
  94. rapidtide/dlfiltertorch.py +5201 -0
  95. rapidtide/externaltools.py +328 -13
  96. rapidtide/fMRIData_class.py +178 -0
  97. rapidtide/ffttools.py +168 -0
  98. rapidtide/filter.py +2704 -1462
  99. rapidtide/fit.py +2361 -579
  100. rapidtide/genericmultiproc.py +197 -0
  101. rapidtide/happy_supportfuncs.py +3255 -548
  102. rapidtide/helper_classes.py +590 -1181
  103. rapidtide/io.py +2569 -468
  104. rapidtide/linfitfiltpass.py +784 -0
  105. rapidtide/makelaggedtcs.py +267 -97
  106. rapidtide/maskutil.py +555 -25
  107. rapidtide/miscmath.py +867 -137
  108. rapidtide/multiproc.py +217 -44
  109. rapidtide/patchmatch.py +752 -0
  110. rapidtide/peakeval.py +32 -32
  111. rapidtide/ppgproc.py +2205 -0
  112. rapidtide/qualitycheck.py +353 -40
  113. rapidtide/refinedelay.py +854 -0
  114. rapidtide/refineregressor.py +939 -0
  115. rapidtide/resample.py +725 -204
  116. rapidtide/scripts/__init__.py +1 -0
  117. rapidtide/scripts/{adjustoffset → adjustoffset.py} +7 -2
  118. rapidtide/scripts/{aligntcs → aligntcs.py} +7 -2
  119. rapidtide/scripts/{applydlfilter → applydlfilter.py} +7 -2
  120. rapidtide/scripts/applyppgproc.py +28 -0
  121. rapidtide/scripts/{atlasaverage → atlasaverage.py} +7 -2
  122. rapidtide/scripts/{atlastool → atlastool.py} +7 -2
  123. rapidtide/scripts/{calcicc → calcicc.py} +7 -2
  124. rapidtide/scripts/{calctexticc → calctexticc.py} +7 -2
  125. rapidtide/scripts/{calcttest → calcttest.py} +7 -2
  126. rapidtide/scripts/{ccorrica → ccorrica.py} +7 -2
  127. rapidtide/scripts/delayvar.py +28 -0
  128. rapidtide/scripts/{diffrois → diffrois.py} +7 -2
  129. rapidtide/scripts/{endtidalproc → endtidalproc.py} +7 -2
  130. rapidtide/scripts/{fdica → fdica.py} +7 -2
  131. rapidtide/scripts/{filtnifti → filtnifti.py} +7 -2
  132. rapidtide/scripts/{filttc → filttc.py} +7 -2
  133. rapidtide/scripts/{fingerprint → fingerprint.py} +20 -16
  134. rapidtide/scripts/{fixtr → fixtr.py} +7 -2
  135. rapidtide/scripts/{gmscalc → gmscalc.py} +7 -2
  136. rapidtide/scripts/{happy → happy.py} +7 -2
  137. rapidtide/scripts/{happy2std → happy2std.py} +7 -2
  138. rapidtide/scripts/{happywarp → happywarp.py} +8 -4
  139. rapidtide/scripts/{histnifti → histnifti.py} +7 -2
  140. rapidtide/scripts/{histtc → histtc.py} +7 -2
  141. rapidtide/scripts/{glmfilt → linfitfilt.py} +7 -4
  142. rapidtide/scripts/{localflow → localflow.py} +7 -2
  143. rapidtide/scripts/{mergequality → mergequality.py} +7 -2
  144. rapidtide/scripts/{pairproc → pairproc.py} +7 -2
  145. rapidtide/scripts/{pairwisemergenifti → pairwisemergenifti.py} +7 -2
  146. rapidtide/scripts/{physiofreq → physiofreq.py} +7 -2
  147. rapidtide/scripts/{pixelcomp → pixelcomp.py} +7 -2
  148. rapidtide/scripts/{plethquality → plethquality.py} +7 -2
  149. rapidtide/scripts/{polyfitim → polyfitim.py} +7 -2
  150. rapidtide/scripts/{proj2flow → proj2flow.py} +7 -2
  151. rapidtide/scripts/{rankimage → rankimage.py} +7 -2
  152. rapidtide/scripts/{rapidtide → rapidtide.py} +7 -2
  153. rapidtide/scripts/{rapidtide2std → rapidtide2std.py} +7 -2
  154. rapidtide/scripts/{resamplenifti → resamplenifti.py} +7 -2
  155. rapidtide/scripts/{resampletc → resampletc.py} +7 -2
  156. rapidtide/scripts/retrolagtcs.py +28 -0
  157. rapidtide/scripts/retroregress.py +28 -0
  158. rapidtide/scripts/{roisummarize → roisummarize.py} +7 -2
  159. rapidtide/scripts/{runqualitycheck → runqualitycheck.py} +7 -2
  160. rapidtide/scripts/{showarbcorr → showarbcorr.py} +7 -2
  161. rapidtide/scripts/{showhist → showhist.py} +7 -2
  162. rapidtide/scripts/{showstxcorr → showstxcorr.py} +7 -2
  163. rapidtide/scripts/{showtc → showtc.py} +7 -2
  164. rapidtide/scripts/{showxcorr_legacy → showxcorr_legacy.py} +8 -8
  165. rapidtide/scripts/{showxcorrx → showxcorrx.py} +7 -2
  166. rapidtide/scripts/{showxy → showxy.py} +7 -2
  167. rapidtide/scripts/{simdata → simdata.py} +7 -2
  168. rapidtide/scripts/{spatialdecomp → spatialdecomp.py} +7 -2
  169. rapidtide/scripts/{spatialfit → spatialfit.py} +7 -2
  170. rapidtide/scripts/{spatialmi → spatialmi.py} +7 -2
  171. rapidtide/scripts/{spectrogram → spectrogram.py} +7 -2
  172. rapidtide/scripts/stupidramtricks.py +238 -0
  173. rapidtide/scripts/{synthASL → synthASL.py} +7 -2
  174. rapidtide/scripts/{tcfrom2col → tcfrom2col.py} +7 -2
  175. rapidtide/scripts/{tcfrom3col → tcfrom3col.py} +7 -2
  176. rapidtide/scripts/{temporaldecomp → temporaldecomp.py} +7 -2
  177. rapidtide/scripts/{testhrv → testhrv.py} +1 -1
  178. rapidtide/scripts/{threeD → threeD.py} +7 -2
  179. rapidtide/scripts/{tidepool → tidepool.py} +7 -2
  180. rapidtide/scripts/{variabilityizer → variabilityizer.py} +7 -2
  181. rapidtide/simFuncClasses.py +2113 -0
  182. rapidtide/simfuncfit.py +312 -108
  183. rapidtide/stats.py +579 -247
  184. rapidtide/tests/.coveragerc +27 -6
  185. rapidtide-2.9.5.data/scripts/fdica → rapidtide/tests/cleanposttest +4 -6
  186. rapidtide/tests/happycomp +9 -0
  187. rapidtide/tests/resethappytargets +1 -1
  188. rapidtide/tests/resetrapidtidetargets +1 -1
  189. rapidtide/tests/resettargets +1 -1
  190. rapidtide/tests/runlocaltest +3 -3
  191. rapidtide/tests/showkernels +1 -1
  192. rapidtide/tests/test_aliasedcorrelate.py +4 -4
  193. rapidtide/tests/test_aligntcs.py +1 -1
  194. rapidtide/tests/test_calcicc.py +1 -1
  195. rapidtide/tests/test_cleanregressor.py +184 -0
  196. rapidtide/tests/test_congrid.py +70 -81
  197. rapidtide/tests/test_correlate.py +1 -1
  198. rapidtide/tests/test_corrpass.py +4 -4
  199. rapidtide/tests/test_delayestimation.py +54 -59
  200. rapidtide/tests/test_dlfiltertorch.py +437 -0
  201. rapidtide/tests/test_doresample.py +2 -2
  202. rapidtide/tests/test_externaltools.py +69 -0
  203. rapidtide/tests/test_fastresampler.py +9 -5
  204. rapidtide/tests/test_filter.py +96 -57
  205. rapidtide/tests/test_findmaxlag.py +50 -19
  206. rapidtide/tests/test_fullrunhappy_v1.py +15 -10
  207. rapidtide/tests/test_fullrunhappy_v2.py +19 -13
  208. rapidtide/tests/test_fullrunhappy_v3.py +28 -13
  209. rapidtide/tests/test_fullrunhappy_v4.py +30 -11
  210. rapidtide/tests/test_fullrunhappy_v5.py +62 -0
  211. rapidtide/tests/test_fullrunrapidtide_v1.py +61 -7
  212. rapidtide/tests/test_fullrunrapidtide_v2.py +27 -15
  213. rapidtide/tests/test_fullrunrapidtide_v3.py +28 -8
  214. rapidtide/tests/test_fullrunrapidtide_v4.py +16 -8
  215. rapidtide/tests/test_fullrunrapidtide_v5.py +15 -6
  216. rapidtide/tests/test_fullrunrapidtide_v6.py +142 -0
  217. rapidtide/tests/test_fullrunrapidtide_v7.py +114 -0
  218. rapidtide/tests/test_fullrunrapidtide_v8.py +66 -0
  219. rapidtide/tests/test_getparsers.py +158 -0
  220. rapidtide/tests/test_io.py +59 -18
  221. rapidtide/tests/{test_glmpass.py → test_linfitfiltpass.py} +10 -10
  222. rapidtide/tests/test_mi.py +1 -1
  223. rapidtide/tests/test_miscmath.py +1 -1
  224. rapidtide/tests/test_motionregress.py +5 -5
  225. rapidtide/tests/test_nullcorr.py +6 -9
  226. rapidtide/tests/test_padvec.py +216 -0
  227. rapidtide/tests/test_parserfuncs.py +101 -0
  228. rapidtide/tests/test_phaseanalysis.py +1 -1
  229. rapidtide/tests/test_rapidtideparser.py +59 -53
  230. rapidtide/tests/test_refinedelay.py +296 -0
  231. rapidtide/tests/test_runmisc.py +5 -5
  232. rapidtide/tests/test_sharedmem.py +60 -0
  233. rapidtide/tests/test_simroundtrip.py +132 -0
  234. rapidtide/tests/test_simulate.py +1 -1
  235. rapidtide/tests/test_stcorrelate.py +4 -2
  236. rapidtide/tests/test_timeshift.py +2 -2
  237. rapidtide/tests/test_valtoindex.py +1 -1
  238. rapidtide/tests/test_zRapidtideDataset.py +5 -3
  239. rapidtide/tests/utils.py +10 -9
  240. rapidtide/tidepoolTemplate.py +88 -70
  241. rapidtide/tidepoolTemplate.ui +60 -46
  242. rapidtide/tidepoolTemplate_alt.py +88 -53
  243. rapidtide/tidepoolTemplate_alt.ui +62 -52
  244. rapidtide/tidepoolTemplate_alt_qt6.py +921 -0
  245. rapidtide/tidepoolTemplate_big.py +1125 -0
  246. rapidtide/tidepoolTemplate_big.ui +2386 -0
  247. rapidtide/tidepoolTemplate_big_qt6.py +1129 -0
  248. rapidtide/tidepoolTemplate_qt6.py +793 -0
  249. rapidtide/util.py +1389 -148
  250. rapidtide/voxelData.py +1048 -0
  251. rapidtide/wiener.py +138 -25
  252. rapidtide/wiener2.py +114 -8
  253. rapidtide/workflows/adjustoffset.py +107 -5
  254. rapidtide/workflows/aligntcs.py +86 -3
  255. rapidtide/workflows/applydlfilter.py +231 -89
  256. rapidtide/workflows/applyppgproc.py +540 -0
  257. rapidtide/workflows/atlasaverage.py +309 -48
  258. rapidtide/workflows/atlastool.py +130 -9
  259. rapidtide/workflows/calcSimFuncMap.py +490 -0
  260. rapidtide/workflows/calctexticc.py +202 -10
  261. rapidtide/workflows/ccorrica.py +123 -15
  262. rapidtide/workflows/cleanregressor.py +415 -0
  263. rapidtide/workflows/delayvar.py +1268 -0
  264. rapidtide/workflows/diffrois.py +84 -6
  265. rapidtide/workflows/endtidalproc.py +149 -9
  266. rapidtide/workflows/fdica.py +197 -17
  267. rapidtide/workflows/filtnifti.py +71 -4
  268. rapidtide/workflows/filttc.py +76 -5
  269. rapidtide/workflows/fitSimFuncMap.py +578 -0
  270. rapidtide/workflows/fixtr.py +74 -4
  271. rapidtide/workflows/gmscalc.py +116 -6
  272. rapidtide/workflows/happy.py +1242 -480
  273. rapidtide/workflows/happy2std.py +145 -13
  274. rapidtide/workflows/happy_parser.py +277 -59
  275. rapidtide/workflows/histnifti.py +120 -4
  276. rapidtide/workflows/histtc.py +85 -4
  277. rapidtide/workflows/{glmfilt.py → linfitfilt.py} +128 -14
  278. rapidtide/workflows/localflow.py +329 -29
  279. rapidtide/workflows/mergequality.py +80 -4
  280. rapidtide/workflows/niftidecomp.py +323 -19
  281. rapidtide/workflows/niftistats.py +178 -8
  282. rapidtide/workflows/pairproc.py +99 -5
  283. rapidtide/workflows/pairwisemergenifti.py +86 -3
  284. rapidtide/workflows/parser_funcs.py +1488 -56
  285. rapidtide/workflows/physiofreq.py +139 -12
  286. rapidtide/workflows/pixelcomp.py +211 -9
  287. rapidtide/workflows/plethquality.py +105 -23
  288. rapidtide/workflows/polyfitim.py +159 -19
  289. rapidtide/workflows/proj2flow.py +76 -3
  290. rapidtide/workflows/rankimage.py +115 -8
  291. rapidtide/workflows/rapidtide.py +1833 -1919
  292. rapidtide/workflows/rapidtide2std.py +101 -3
  293. rapidtide/workflows/rapidtide_parser.py +607 -372
  294. rapidtide/workflows/refineDelayMap.py +249 -0
  295. rapidtide/workflows/refineRegressor.py +1215 -0
  296. rapidtide/workflows/regressfrommaps.py +308 -0
  297. rapidtide/workflows/resamplenifti.py +86 -4
  298. rapidtide/workflows/resampletc.py +92 -4
  299. rapidtide/workflows/retrolagtcs.py +442 -0
  300. rapidtide/workflows/retroregress.py +1501 -0
  301. rapidtide/workflows/roisummarize.py +176 -7
  302. rapidtide/workflows/runqualitycheck.py +72 -7
  303. rapidtide/workflows/showarbcorr.py +172 -16
  304. rapidtide/workflows/showhist.py +87 -3
  305. rapidtide/workflows/showstxcorr.py +161 -4
  306. rapidtide/workflows/showtc.py +172 -10
  307. rapidtide/workflows/showxcorrx.py +250 -62
  308. rapidtide/workflows/showxy.py +186 -16
  309. rapidtide/workflows/simdata.py +418 -112
  310. rapidtide/workflows/spatialfit.py +83 -8
  311. rapidtide/workflows/spatialmi.py +252 -29
  312. rapidtide/workflows/spectrogram.py +306 -33
  313. rapidtide/workflows/synthASL.py +157 -6
  314. rapidtide/workflows/tcfrom2col.py +77 -3
  315. rapidtide/workflows/tcfrom3col.py +75 -3
  316. rapidtide/workflows/tidepool.py +3829 -666
  317. rapidtide/workflows/utils.py +45 -19
  318. rapidtide/workflows/utils_doc.py +293 -0
  319. rapidtide/workflows/variabilityizer.py +118 -5
  320. {rapidtide-2.9.5.dist-info → rapidtide-3.1.3.dist-info}/METADATA +30 -223
  321. rapidtide-3.1.3.dist-info/RECORD +393 -0
  322. {rapidtide-2.9.5.dist-info → rapidtide-3.1.3.dist-info}/WHEEL +1 -1
  323. rapidtide-3.1.3.dist-info/entry_points.txt +65 -0
  324. rapidtide-3.1.3.dist-info/top_level.txt +2 -0
  325. rapidtide/calcandfitcorrpairs.py +0 -262
  326. rapidtide/data/examples/src/testoutputsize +0 -45
  327. rapidtide/data/models/model_revised/model.h5 +0 -0
  328. rapidtide/data/models/model_serdar/model.h5 +0 -0
  329. rapidtide/data/models/model_serdar2/model.h5 +0 -0
  330. rapidtide/data/reference/ASPECTS_nlin_asym_09c_2mm.nii.gz +0 -0
  331. rapidtide/data/reference/ASPECTS_nlin_asym_09c_2mm_mask.nii.gz +0 -0
  332. rapidtide/data/reference/ATTbasedFlowTerritories_split_nlin_asym_09c_2mm.nii.gz +0 -0
  333. rapidtide/data/reference/ATTbasedFlowTerritories_split_nlin_asym_09c_2mm_mask.nii.gz +0 -0
  334. rapidtide/data/reference/HCP1200_binmask_2mm_2009c_asym.nii.gz +0 -0
  335. rapidtide/data/reference/HCP1200_lag_2mm_2009c_asym.nii.gz +0 -0
  336. rapidtide/data/reference/HCP1200_mask_2mm_2009c_asym.nii.gz +0 -0
  337. rapidtide/data/reference/HCP1200_negmask_2mm_2009c_asym.nii.gz +0 -0
  338. rapidtide/data/reference/HCP1200_sigma_2mm_2009c_asym.nii.gz +0 -0
  339. rapidtide/data/reference/HCP1200_strength_2mm_2009c_asym.nii.gz +0 -0
  340. rapidtide/glmpass.py +0 -434
  341. rapidtide/refine_factored.py +0 -641
  342. rapidtide/scripts/retroglm +0 -23
  343. rapidtide/workflows/glmfrommaps.py +0 -202
  344. rapidtide/workflows/retroglm.py +0 -643
  345. rapidtide-2.9.5.data/scripts/adjustoffset +0 -23
  346. rapidtide-2.9.5.data/scripts/aligntcs +0 -23
  347. rapidtide-2.9.5.data/scripts/applydlfilter +0 -23
  348. rapidtide-2.9.5.data/scripts/atlasaverage +0 -23
  349. rapidtide-2.9.5.data/scripts/atlastool +0 -23
  350. rapidtide-2.9.5.data/scripts/calcicc +0 -22
  351. rapidtide-2.9.5.data/scripts/calctexticc +0 -23
  352. rapidtide-2.9.5.data/scripts/calcttest +0 -22
  353. rapidtide-2.9.5.data/scripts/ccorrica +0 -23
  354. rapidtide-2.9.5.data/scripts/diffrois +0 -23
  355. rapidtide-2.9.5.data/scripts/endtidalproc +0 -23
  356. rapidtide-2.9.5.data/scripts/filtnifti +0 -23
  357. rapidtide-2.9.5.data/scripts/filttc +0 -23
  358. rapidtide-2.9.5.data/scripts/fingerprint +0 -593
  359. rapidtide-2.9.5.data/scripts/fixtr +0 -23
  360. rapidtide-2.9.5.data/scripts/glmfilt +0 -24
  361. rapidtide-2.9.5.data/scripts/gmscalc +0 -22
  362. rapidtide-2.9.5.data/scripts/happy +0 -25
  363. rapidtide-2.9.5.data/scripts/happy2std +0 -23
  364. rapidtide-2.9.5.data/scripts/happywarp +0 -350
  365. rapidtide-2.9.5.data/scripts/histnifti +0 -23
  366. rapidtide-2.9.5.data/scripts/histtc +0 -23
  367. rapidtide-2.9.5.data/scripts/localflow +0 -23
  368. rapidtide-2.9.5.data/scripts/mergequality +0 -23
  369. rapidtide-2.9.5.data/scripts/pairproc +0 -23
  370. rapidtide-2.9.5.data/scripts/pairwisemergenifti +0 -23
  371. rapidtide-2.9.5.data/scripts/physiofreq +0 -23
  372. rapidtide-2.9.5.data/scripts/pixelcomp +0 -23
  373. rapidtide-2.9.5.data/scripts/plethquality +0 -23
  374. rapidtide-2.9.5.data/scripts/polyfitim +0 -23
  375. rapidtide-2.9.5.data/scripts/proj2flow +0 -23
  376. rapidtide-2.9.5.data/scripts/rankimage +0 -23
  377. rapidtide-2.9.5.data/scripts/rapidtide +0 -23
  378. rapidtide-2.9.5.data/scripts/rapidtide2std +0 -23
  379. rapidtide-2.9.5.data/scripts/resamplenifti +0 -23
  380. rapidtide-2.9.5.data/scripts/resampletc +0 -23
  381. rapidtide-2.9.5.data/scripts/retroglm +0 -23
  382. rapidtide-2.9.5.data/scripts/roisummarize +0 -23
  383. rapidtide-2.9.5.data/scripts/runqualitycheck +0 -23
  384. rapidtide-2.9.5.data/scripts/showarbcorr +0 -23
  385. rapidtide-2.9.5.data/scripts/showhist +0 -23
  386. rapidtide-2.9.5.data/scripts/showstxcorr +0 -23
  387. rapidtide-2.9.5.data/scripts/showtc +0 -23
  388. rapidtide-2.9.5.data/scripts/showxcorr_legacy +0 -536
  389. rapidtide-2.9.5.data/scripts/showxcorrx +0 -23
  390. rapidtide-2.9.5.data/scripts/showxy +0 -23
  391. rapidtide-2.9.5.data/scripts/simdata +0 -23
  392. rapidtide-2.9.5.data/scripts/spatialdecomp +0 -23
  393. rapidtide-2.9.5.data/scripts/spatialfit +0 -23
  394. rapidtide-2.9.5.data/scripts/spatialmi +0 -23
  395. rapidtide-2.9.5.data/scripts/spectrogram +0 -23
  396. rapidtide-2.9.5.data/scripts/synthASL +0 -23
  397. rapidtide-2.9.5.data/scripts/tcfrom2col +0 -23
  398. rapidtide-2.9.5.data/scripts/tcfrom3col +0 -23
  399. rapidtide-2.9.5.data/scripts/temporaldecomp +0 -23
  400. rapidtide-2.9.5.data/scripts/threeD +0 -236
  401. rapidtide-2.9.5.data/scripts/tidepool +0 -23
  402. rapidtide-2.9.5.data/scripts/variabilityizer +0 -23
  403. rapidtide-2.9.5.dist-info/RECORD +0 -357
  404. rapidtide-2.9.5.dist-info/top_level.txt +0 -86
  405. {rapidtide-2.9.5.dist-info → rapidtide-3.1.3.dist-info/licenses}/LICENSE +0 -0
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env python
2
2
  # -*- coding: utf-8 -*-
3
3
  #
4
- # Copyright 2016-2024 Blaise Frederick
4
+ # Copyright 2016-2025 Blaise Frederick
5
5
  #
6
6
  # Licensed under the Apache License, Version 2.0 (the "License");
7
7
  # you may not use this file except in compliance with the License.
@@ -19,12 +19,12 @@
19
19
  """
20
20
  A widget for orthographically displaying 3 and 4 dimensional data
21
21
  """
22
-
23
- import copy
24
22
  import os
23
+ from typing import Any
25
24
 
26
25
  import numpy as np
27
26
  import pyqtgraph as pg
27
+ from numpy.typing import NDArray
28
28
  from pyqtgraph.Qt import QtCore, QtGui, QtWidgets
29
29
 
30
30
  try:
@@ -34,8 +34,69 @@ try:
34
34
  except ImportError:
35
35
  PILexists = False
36
36
 
37
-
38
- def newColorbar(left, top, impixpervoxx, impixpervoxy, imgsize):
37
+ try:
38
+ from PySide6.QtCore import __version__
39
+ except ImportError:
40
+ try:
41
+ from PyQt6.QtCore import QT_VERSION_STR
42
+ except ImportError:
43
+ pyqtbinding = "pyqt5"
44
+ else:
45
+ pyqtbinding = "pyqt6"
46
+ else:
47
+ pyqtbinding = "pyside6"
48
+ print(f"using {pyqtbinding=}")
49
+
50
+
51
+ def newColorbar(
52
+ left: float, top: float, impixpervoxx: float, impixpervoxy: float, imgsize: int
53
+ ) -> tuple[Any, Any, Any, NDArray[np.float64]]:
54
+ """
55
+ Create a colorbar widget with foreground and background image items for plotting.
56
+
57
+ This function generates a colorbar using PyGraphQt (pg) components, including
58
+ a foreground and background `ImageItem`, a `ViewBox` for layout control, and
59
+ a 2D array of color values. The colorbar is scaled and positioned according
60
+ to the provided parameters.
61
+
62
+ Parameters
63
+ ----------
64
+ left : float
65
+ The x-coordinate of the top-left corner of the colorbar in the scene.
66
+ top : float
67
+ The y-coordinate of the top-left corner of the colorbar in the scene.
68
+ impixpervoxx : float
69
+ Scaling factor for the horizontal axis (pixel per unit in x-direction).
70
+ impixpervoxy : float
71
+ Scaling factor for the vertical axis (pixel per unit in y-direction).
72
+ imgsize : int
73
+ The size of the colorbar image in pixels, used to determine dimensions.
74
+
75
+ Returns
76
+ -------
77
+ tuple[Any, Any, Any, NDArray[np.float64]]
78
+ A tuple containing:
79
+ - `thecolorbarfgwin`: The foreground `ImageItem` for the colorbar.
80
+ - `thecolorbarbgwin`: The background `ImageItem` for the colorbar.
81
+ - `theviewbox`: The `ViewBox` that contains the colorbar items.
82
+ - `colorbarvals`: A 2D NumPy array of shape `(cb_xdim, cb_ydim)` with
83
+ color values ranging from 0.0 to 1.0, used for rendering the colorbar.
84
+
85
+ Notes
86
+ -----
87
+ The colorbar uses a linear gradient from black (0.0) to white (1.0) along the
88
+ vertical axis. The horizontal dimension is set to 1/10th of `imgsize`, and
89
+ the vertical dimension equals `imgsize`. The `ViewBox` is configured to disable
90
+ auto-ranging and mouse interaction.
91
+
92
+ Examples
93
+ --------
94
+ >>> fg_item, bg_item, view_box, color_vals = newColorbar(
95
+ ... left=100, top=50, impixpervoxx=1.0, impixpervoxy=1.0, imgsize=256
96
+ ... )
97
+ >>> view_box.addItem(fg_item)
98
+ >>> view_box.addItem(bg_item)
99
+ """
39
100
  cb_xdim = imgsize // 10
40
101
  cb_ydim = imgsize
41
102
  theviewbox = pg.ViewBox(enableMouse=False)
@@ -68,7 +129,65 @@ def newColorbar(left, top, impixpervoxx, impixpervoxy, imgsize):
68
129
  return thecolorbarfgwin, thecolorbarbgwin, theviewbox, colorbarvals
69
130
 
70
131
 
71
- def newViewWindow(view, left, top, impixpervoxx, impixpervoxy, imgsize, enableMouse=False):
132
+ def setupViewWindow(
133
+ view: Any,
134
+ left: float,
135
+ top: float,
136
+ impixpervoxx: float,
137
+ impixpervoxy: float,
138
+ imgsize: int,
139
+ enableMouse: bool = False,
140
+ ) -> tuple[Any, Any, Any, Any, Any]:
141
+ """
142
+ Set up a view window with background and foreground image items, and crosshair lines.
143
+
144
+ This function configures a PyGraphQt view box with specified image transformation
145
+ parameters and adds background and foreground image items along with vertical and
146
+ horizontal crosshair lines for visualization purposes.
147
+
148
+ Parameters
149
+ ----------
150
+ view : Any
151
+ The parent view object to which the view box will be added.
152
+ left : float
153
+ The x-coordinate offset for the image transformation.
154
+ top : float
155
+ The y-coordinate offset for the image transformation.
156
+ impixpervoxx : float
157
+ The scaling factor for the horizontal axis of the image.
158
+ impixpervoxy : float
159
+ The scaling factor for the vertical axis of the image.
160
+ imgsize : int
161
+ The size of the image in pixels, used to set the view range.
162
+ enableMouse : bool, optional
163
+ Whether to enable mouse interaction with the view box. Default is False.
164
+
165
+ Returns
166
+ -------
167
+ tuple[Any, Any, Any, Any, Any]
168
+ A tuple containing:
169
+ - theviewfgwin: The foreground image item.
170
+ - theviewbgwin: The background image item.
171
+ - theviewvLine: The vertical crosshair line.
172
+ - theviewhLine: The horizontal crosshair line.
173
+ - theviewbox: The configured view box object.
174
+
175
+ Notes
176
+ -----
177
+ The view box is locked to a 1:1 aspect ratio and initialized with a gray background.
178
+ The transformation applied to both image items includes translation and scaling
179
+ to align the image properly within the view.
180
+
181
+ Examples
182
+ --------
183
+ >>> import pyqtgraph as pg
184
+ >>> from PyQt5 import QtCore, QtGui
185
+ >>> view = pg.GraphicsLayoutWidget()
186
+ >>> fgwin, bgwin, vline, hline, vbox = setupViewWindow(
187
+ ... view, 0, 0, 1.0, 1.0, 256, enableMouse=True
188
+ ... )
189
+ """
190
+
72
191
  theviewbox = view.addViewBox(enableMouse=enableMouse, enableMenu=False, lockAspect=1.0)
73
192
  theviewbox.setAspectLocked()
74
193
  theviewbox.setRange(QtCore.QRectF(0, 0, imgsize, imgsize), padding=0.0, disableAutoRange=True)
@@ -104,19 +223,72 @@ class OrthoImageItem(QtWidgets.QWidget):
104
223
 
105
224
  def __init__(
106
225
  self,
107
- map,
108
- axview,
109
- corview,
110
- sagview,
111
- enableMouse=False,
112
- button=None,
113
- imgsize=64,
114
- arrangement=0,
115
- bgmap=None,
116
- verbose=0,
117
- ):
226
+ map: Any,
227
+ axview: Any,
228
+ corview: Any,
229
+ sagview: Any,
230
+ enableMouse: bool = False,
231
+ button: Any | None = None,
232
+ imgsize: int = 64,
233
+ arrangement: int = 0,
234
+ bgmap: Any | None = None,
235
+ verbose: int = 0,
236
+ ) -> None:
237
+ """
238
+ Initialize the OrthoImageItem widget for displaying 3D medical images in orthogonal views.
239
+
240
+ This constructor sets up the necessary attributes and configurations for rendering
241
+ a 3D image volume in three orthogonal views (axial, coronal, and sagittal) using
242
+ PyQt and PySide. It handles coordinate transformations, view setup, and mouse interaction
243
+ if enabled.
244
+
245
+ Parameters
246
+ ----------
247
+ map : Any
248
+ The 3D image data map object containing image dimensions and voxel information.
249
+ axview : Any
250
+ The axial view widget (e.g., a PySide QGraphicsView).
251
+ corview : Any
252
+ The coronal view widget (e.g., a PySide QGraphicsView).
253
+ sagview : Any
254
+ The sagittal view widget (e.g., a PySide QGraphicsView).
255
+ enableMouse : bool, optional
256
+ Whether to enable mouse interaction for navigating the views, by default False.
257
+ button : Any | None, optional
258
+ Mouse button used for interaction, by default None.
259
+ imgsize : int, optional
260
+ Size of the image display in pixels, by default 64.
261
+ arrangement : int, optional
262
+ Layout arrangement for the views, by default 0.
263
+ bgmap : Any | None, optional
264
+ Background image map for overlay, by default None.
265
+ verbose : int, optional
266
+ Verbosity level for printing debug information, by default 0.
267
+
268
+ Returns
269
+ -------
270
+ None
271
+ This method initializes the object and does not return any value.
272
+
273
+ Notes
274
+ -----
275
+ The method performs coordinate transformations to map voxel indices to physical space
276
+ and sets up the view ranges and layouts for each of the three orthogonal views.
277
+ If `enableMouse` is True, mouse event handlers are attached to allow navigation.
278
+
279
+ Examples
280
+ --------
281
+ >>> ortho_item = OrthoImageItem(
282
+ ... map=volume_map,
283
+ ... axview=axial_view,
284
+ ... corview=coronal_view,
285
+ ... sagview=sagittal_view,
286
+ ... enableMouse=True
287
+ ... )
288
+ """
118
289
  QtWidgets.QWidget.__init__(self)
119
290
  self.map = map
291
+ self.mapname = self.map.label
120
292
  self.bgmap = bgmap
121
293
  self.axview = axview
122
294
  self.corview = corview
@@ -146,9 +318,21 @@ class OrthoImageItem(QtWidgets.QWidget):
146
318
  self.offsetx = self.imgsize * (0.5 - self.xfov / (2.0 * self.maxfov))
147
319
  self.offsety = self.imgsize * (0.5 - self.yfov / (2.0 * self.maxfov))
148
320
  self.offsetz = self.imgsize * (0.5 - self.zfov / (2.0 * self.maxfov))
321
+ self.axviewbox = None
322
+ self.corviewbox = None
323
+ self.sagviewbox = None
324
+ self.axviewwin = None
325
+ self.corviewwin = None
326
+ self.sagviewwin = None
327
+ self.axviewbgwin = None
328
+ self.corviewbgwin = None
329
+ self.sagviewbgwin = None
330
+ self.debug = True
331
+ self.arrangement = arrangement
149
332
 
150
333
  if self.verbose > 1:
151
- print("OrthoImageItem intialization:")
334
+ print("OrthoImageItem initialization:")
335
+ print(" Map name:", self.mapname)
152
336
  print(" Dimensions:", self.xdim, self.ydim, self.zdim)
153
337
  print(" Voxel sizes:", self.xsize, self.ysize, self.zsize)
154
338
  print(" FOVs:", self.xfov, self.yfov, self.zfov)
@@ -162,7 +346,6 @@ class OrthoImageItem(QtWidgets.QWidget):
162
346
  print(" Offsets:", self.offsetx, self.offsety, self.offsetz)
163
347
  self.buttonisdown = False
164
348
 
165
- self.arrangement = arrangement
166
349
  self.axview.setBackground(None)
167
350
  self.axview.setRange(padding=0.0)
168
351
  self.axview.ci.layout.setContentsMargins(0, 0, 0, 0)
@@ -182,7 +365,7 @@ class OrthoImageItem(QtWidgets.QWidget):
182
365
  self.axviewvLine,
183
366
  self.axviewhLine,
184
367
  self.axviewbox,
185
- ) = newViewWindow(
368
+ ) = setupViewWindow(
186
369
  self.axview,
187
370
  self.offsetx,
188
371
  self.offsety,
@@ -197,7 +380,7 @@ class OrthoImageItem(QtWidgets.QWidget):
197
380
  self.corviewvLine,
198
381
  self.corviewhLine,
199
382
  self.corviewbox,
200
- ) = newViewWindow(
383
+ ) = setupViewWindow(
201
384
  self.corview,
202
385
  self.offsetx,
203
386
  self.offsetz,
@@ -212,7 +395,7 @@ class OrthoImageItem(QtWidgets.QWidget):
212
395
  self.sagviewvLine,
213
396
  self.sagviewhLine,
214
397
  self.sagviewbox,
215
- ) = newViewWindow(
398
+ ) = setupViewWindow(
216
399
  self.sagview,
217
400
  self.offsety,
218
401
  self.offsetz,
@@ -236,16 +419,128 @@ class OrthoImageItem(QtWidgets.QWidget):
236
419
  self.enableView()
237
420
  self.updateAllViews()
238
421
 
239
- def xvox2pix(self, xpos):
422
+ def xvox2pix(self, xpos: int) -> int:
423
+ """
424
+ Convert voxel position to pixel position along x-axis.
425
+
426
+ Parameters
427
+ ----------
428
+ xpos : int
429
+ Voxel position along x-axis to be converted to pixel coordinates.
430
+
431
+ Returns
432
+ -------
433
+ int
434
+ Corresponding pixel position along x-axis.
435
+
436
+ Notes
437
+ -----
438
+ This function performs a linear transformation from voxel coordinates to pixel coordinates
439
+ using the formula: pixel = offsetx + impixpervoxx * voxel_position
440
+
441
+ Examples
442
+ --------
443
+ >>> obj.xvox2pix(10)
444
+ 15
445
+ >>> obj.xvox2pix(0)
446
+ 5
447
+ """
240
448
  return int(np.round(self.offsetx + self.impixpervoxx * xpos))
241
449
 
242
- def yvox2pix(self, ypos):
450
+ def yvox2pix(self, ypos: int) -> int:
451
+ """
452
+ Convert voxel y-coordinate to pixel y-coordinate.
453
+
454
+ This function transforms a y-coordinate from voxel space to pixel space using
455
+ the transformation parameters stored in the object.
456
+
457
+ Parameters
458
+ ----------
459
+ ypos : int
460
+ Y-coordinate in voxel space to be converted to pixel space.
461
+
462
+ Returns
463
+ -------
464
+ int
465
+ Y-coordinate in pixel space corresponding to the input voxel y-coordinate.
466
+
467
+ Notes
468
+ -----
469
+ The conversion follows the formula: pixel_y = offsety + impixpervoxy * voxel_y
470
+ where offsety and impixpervoxy are attributes of the object.
471
+
472
+ Examples
473
+ --------
474
+ >>> obj = MyClass()
475
+ >>> obj.offsety = 10
476
+ >>> obj.impixpervoxy = 2.5
477
+ >>> obj.yvox2pix(4)
478
+ 20
479
+ """
243
480
  return int(np.round(self.offsety + self.impixpervoxy * ypos))
244
481
 
245
- def zvox2pix(self, zpos):
482
+ def zvox2pix(self, zpos: int) -> int:
483
+ """
484
+ Convert z-voxel position to pixel position.
485
+
486
+ This function transforms a z-coordinate in voxel space to its corresponding
487
+ position in pixel space using the camera's offset and pixel-per-voxel ratio.
488
+
489
+ Parameters
490
+ ----------
491
+ zpos : int
492
+ Z-coordinate in voxel space to be converted to pixel space.
493
+
494
+ Returns
495
+ -------
496
+ int
497
+ Corresponding z-position in pixel space.
498
+
499
+ Notes
500
+ -----
501
+ The conversion follows the formula: pixel_position = offsetz + impixpervoxz * zpos
502
+ where:
503
+ - offsetz: base offset in pixel space
504
+ - impixpervoxz: pixels per voxel in z-direction
505
+
506
+ Examples
507
+ --------
508
+ >>> zvox2pix(10)
509
+ 150
510
+ """
246
511
  return int(np.round(self.offsetz + self.impixpervoxz * zpos))
247
512
 
248
- def xpix2vox(self, xpix):
513
+ def xpix2vox(self, xpix: float) -> int:
514
+ """
515
+ Convert pixel coordinate to voxel coordinate in x-direction.
516
+
517
+ This function transforms a pixel coordinate in the x-direction to its
518
+ corresponding voxel coordinate, taking into account the image offset and
519
+ pixel-to-voxel conversion factors.
520
+
521
+ Parameters
522
+ ----------
523
+ xpix : float
524
+ The pixel coordinate in x-direction to be converted to voxel coordinate.
525
+
526
+ Returns
527
+ -------
528
+ int
529
+ The corresponding voxel coordinate in x-direction, clamped to the
530
+ valid range [0, self.xdim-1].
531
+
532
+ Notes
533
+ -----
534
+ The conversion is performed using the formula: voxel = (pixel - offset) / pixels_per_voxel.
535
+ Edge cases are handled by clamping values to the valid voxel range.
536
+
537
+ Examples
538
+ --------
539
+ >>> # Assuming self.offsetx = 10, self.impixpervoxx = 2.0, self.xdim = 100
540
+ >>> result = self.xpix2vox(20.0)
541
+ >>> print(result)
542
+ 5
543
+ """
249
544
  thepos = (xpix - self.offsetx) / self.impixpervoxx
250
545
  if thepos > self.xdim - 1:
251
546
  thepos = self.xdim - 1
@@ -253,7 +548,36 @@ class OrthoImageItem(QtWidgets.QWidget):
253
548
  thepos = 0
254
549
  return int(np.round(thepos))
255
550
 
256
- def ypix2vox(self, ypix):
551
+ def ypix2vox(self, ypix: float) -> int:
552
+ """
553
+ Convert y pixel coordinate to voxel coordinate.
554
+
555
+ This function transforms a y pixel coordinate in the image space to
556
+ the corresponding voxel coordinate in the volume space, taking into
557
+ account the image offset and pixel spacing.
558
+
559
+ Parameters
560
+ ----------
561
+ ypix : float
562
+ Y pixel coordinate in image space
563
+
564
+ Returns
565
+ -------
566
+ int
567
+ Corresponding y voxel coordinate in volume space
568
+
569
+ Notes
570
+ -----
571
+ The conversion uses the formula: voxel = (pixel - offset) / pixels_per_voxel
572
+ Boundary conditions are enforced to ensure the result stays within valid
573
+ voxel range [0, ydim-1].
574
+
575
+ Examples
576
+ --------
577
+ >>> # Assuming self.offsety = 10, self.impixpervoxy = 2.0, self.ydim = 100
578
+ >>> ypix2vox(12) # Returns 1
579
+ >>> ypix2vox(200) # Returns 99 (clamped to maximum valid voxel)
580
+ """
257
581
  thepos = (ypix - self.offsety) / self.impixpervoxy
258
582
  if thepos > self.ydim - 1:
259
583
  thepos = self.ydim - 1
@@ -261,7 +585,40 @@ class OrthoImageItem(QtWidgets.QWidget):
261
585
  thepos = 0
262
586
  return int(np.round(thepos))
263
587
 
264
- def zpix2vox(self, zpix):
588
+ def zpix2vox(self, zpix: float) -> int:
589
+ """
590
+ Convert z-pixel coordinate to z-voxel coordinate.
591
+
592
+ This function transforms a z-pixel coordinate to the corresponding z-voxel
593
+ coordinate by applying the inverse transformation using the offset and
594
+ pixel-per-voxel parameters.
595
+
596
+ Parameters
597
+ ----------
598
+ zpix : float
599
+ Z-pixel coordinate to be converted to voxel coordinate.
600
+
601
+ Returns
602
+ -------
603
+ int
604
+ Corresponding z-voxel coordinate. The result is clamped to the
605
+ valid range [0, self.zdim-1].
606
+
607
+ Notes
608
+ -----
609
+ The conversion is performed using the formula:
610
+ voxel = (zpix - offsetz) / impixpervoxz
611
+
612
+ If the resulting voxel coordinate exceeds the valid range [0, self.zdim-1],
613
+ it is clamped to the nearest boundary value.
614
+
615
+ Examples
616
+ --------
617
+ >>> # Assuming self.offsetz = 10, self.impixpervoxz = 2, self.zdim = 100
618
+ >>> zpix2vox(12) # Returns 1
619
+ >>> zpix2vox(10) # Returns 0
620
+ >>> zpix2vox(200) # Returns 99 (clamped to max)
621
+ """
265
622
  thepos = (zpix - self.offsetz) / self.impixpervoxz
266
623
  if thepos > self.zdim - 1:
267
624
  thepos = self.zdim - 1
@@ -269,7 +626,35 @@ class OrthoImageItem(QtWidgets.QWidget):
269
626
  thepos = 0
270
627
  return int(np.round(thepos))
271
628
 
272
- def updateAllViews(self):
629
+ def updateAllViews(self) -> None:
630
+ """
631
+ Update all three views (axial, coronal, and sagittal) of the visualization.
632
+
633
+ This function updates the axial, coronal, and sagittal views based on the current
634
+ position settings (`xpos`, `ypos`, `zpos`) and time index (`tpos`), using the
635
+ underlying data, mask, and background map if available. It also updates the
636
+ position lines in each view to reflect the current voxel coordinates.
637
+
638
+ Notes
639
+ -----
640
+ The function handles both 2D and 3D data depending on the value of `self.tdim`.
641
+ If `self.tdim == 1`, the data is treated as 2D; otherwise, it is treated as 3D
642
+ with a time dimension.
643
+
644
+ Parameters
645
+ ----------
646
+ None
647
+
648
+ Returns
649
+ -------
650
+ None
651
+ This function does not return any value.
652
+
653
+ Examples
654
+ --------
655
+ >>> updateAllViews()
656
+ Updates all three views (axial, coronal, sagittal) with current data and position.
657
+ """
273
658
  if self.tdim == 1:
274
659
  axdata = self.map.maskeddata[:, :, self.zpos]
275
660
  else:
@@ -322,17 +707,123 @@ class OrthoImageItem(QtWidgets.QWidget):
322
707
  self.sagviewvLine.setValue(self.yvox2pix(self.ypos))
323
708
  self.sagviewhLine.setValue(self.zvox2pix(self.zpos))
324
709
 
325
- def updateOneView(self, data, mask, background, theLUT, thefgwin, thebgwin):
710
+ def updateOneView(
711
+ self,
712
+ data: NDArray,
713
+ mask: NDArray,
714
+ background: NDArray | None,
715
+ theLUT: NDArray,
716
+ thefgwin: Any,
717
+ thebgwin: Any,
718
+ ) -> None:
719
+ """
720
+ Update the visualization view with processed data and optional background.
721
+
722
+ This function applies a lookup table to the input data, displays it in the
723
+ foreground window, and optionally displays a background image in the background window.
724
+
725
+ Parameters
726
+ ----------
727
+ data : NDArray
728
+ The main data array to be processed and displayed.
729
+ mask : NDArray
730
+ The mask array used for data processing.
731
+ background : NDArray | None
732
+ The background data array to be displayed, or None if no background.
733
+ theLUT : NDArray
734
+ The lookup table array used for color mapping.
735
+ thefgwin : Any
736
+ The foreground window object where the processed data will be displayed.
737
+ thebgwin : Any
738
+ The background window object where the background data will be displayed.
739
+
740
+ Returns
741
+ -------
742
+ None
743
+ This function does not return any value.
744
+
745
+ Notes
746
+ -----
747
+ The function applies the lookup table using `self.applyLUT` method and sets
748
+ the image in the foreground window with float data type. If background is
749
+ provided, it is displayed in the background window with automatic level
750
+ adjustment enabled.
751
+
752
+ Examples
753
+ --------
754
+ >>> updateOneView(data, mask, background, theLUT, fg_window, bg_window)
755
+ """
326
756
  im = self.applyLUT(data, mask, theLUT, self.map.dispmin, self.map.dispmax)
327
757
  thefgwin.setImage(im.astype("float"))
328
758
  if background is not None:
329
759
  thebgwin.setImage(background.astype("float"), autoLevels=True)
330
760
 
331
- def setMap(self, themap):
761
+ def setMap(self, themap: Any) -> None:
762
+ """
763
+ Set the map attribute and update related properties.
764
+
765
+ This method assigns the provided map to the instance and updates
766
+ the dimensionality and label properties based on the map's attributes.
767
+
768
+ Parameters
769
+ ----------
770
+ themap : Any
771
+ The map object to be assigned to the instance. Expected to have
772
+ attributes 'tdim' (dimensionality) and 'label' (name/label).
773
+
774
+ Returns
775
+ -------
776
+ None
777
+ This method does not return any value.
778
+
779
+ Notes
780
+ -----
781
+ The method assumes that the input map object has 'tdim' and 'label'
782
+ attributes. If these attributes are not present, an AttributeError
783
+ will be raised.
784
+
785
+ Examples
786
+ --------
787
+ >>> instance.setMap(my_map)
788
+ >>> print(instance.tdim)
789
+ 2
790
+ >>> print(instance.mapname)
791
+ 'my_map_label'
792
+ """
332
793
  self.map = themap
333
794
  self.tdim = self.map.tdim
334
-
335
- def enableView(self):
795
+ self.mapname = self.map.label
796
+
797
+ def enableView(self) -> None:
798
+ """
799
+ Enable and display all view components.
800
+
801
+ This method enables the main button and displays all three view components
802
+ (axial, coronal, and sagittal) by setting their visibility to True.
803
+
804
+ Parameters
805
+ ----------
806
+ self : object
807
+ The instance of the class containing the view components and button.
808
+
809
+ Returns
810
+ -------
811
+ None
812
+ This method does not return any value.
813
+
814
+ Notes
815
+ -----
816
+ The method first checks if the button exists before attempting to modify it.
817
+ If the button exists, it updates the button text with the map label and enables
818
+ the button. All three view components (axview, corview, and sagview) are then
819
+ made visible.
820
+
821
+ Examples
822
+ --------
823
+ >>> viewer = Viewer()
824
+ >>> viewer.enableView()
825
+ >>> # All view components are now visible and button is enabled
826
+ """
336
827
  if self.button is not None:
337
828
  self.button.setText(self.map.label)
338
829
  self.button.setDisabled(False)
@@ -341,7 +832,47 @@ class OrthoImageItem(QtWidgets.QWidget):
341
832
  self.corview.show()
342
833
  self.sagview.show()
343
834
 
344
- def applyLUT(self, theimage, mask, theLUT, dispmin, dispmax):
835
+ def applyLUT(
836
+ self, theimage: NDArray, mask: NDArray, theLUT: NDArray, dispmin: float, dispmax: float
837
+ ) -> NDArray:
838
+ """
839
+ Apply a lookup table to an image with optional masking and scaling.
840
+
841
+ This function maps image values to colors using a lookup table, applying
842
+ scaling based on the display range and masking invalid regions.
843
+
844
+ Parameters
845
+ ----------
846
+ theimage : NDArray
847
+ Input image array to be mapped using the lookup table
848
+ mask : NDArray
849
+ Mask array where values less than 1 will be set to transparent (alpha = 0)
850
+ theLUT : NDArray
851
+ Lookup table array for color mapping, typically with shape (N, 4) for RGBA values
852
+ dispmin : float
853
+ Minimum display value for scaling the input image
854
+ dispmax : float
855
+ Maximum display value for scaling the input image
856
+
857
+ Returns
858
+ -------
859
+ NDArray
860
+ Mapped image array with the same shape as input image, with colors applied
861
+ from the lookup table and masked regions set to transparent
862
+
863
+ Notes
864
+ -----
865
+ The function performs the following operations:
866
+ 1. Scales input image values to index range of the lookup table
867
+ 2. Clamps scaled values to valid lookup table indices
868
+ 3. Maps image values to colors using the lookup table
869
+ 4. Applies mask to set transparent pixels where mask < 1
870
+
871
+ Examples
872
+ --------
873
+ >>> # Apply LUT to image with display range [0, 255]
874
+ >>> result = applyLUT(image, mask, lut, 0.0, 255.0)
875
+ """
345
876
  offset = dispmin
346
877
  if dispmax - dispmin > 0:
347
878
  scale = len(theLUT) / (dispmax - dispmin)
@@ -354,7 +885,48 @@ class OrthoImageItem(QtWidgets.QWidget):
354
885
  mappeddata[:, :, 3][np.where(mask < 1)] = 0
355
886
  return mappeddata
356
887
 
357
- def updateCursors(self):
888
+ def updateCursors(self) -> None:
889
+ """
890
+ Update cursor positions in all view axes based on voxel coordinates.
891
+
892
+ This method converts voxel coordinates to pixel coordinates for each view
893
+ and updates the corresponding cursor lines in the axial, coronal, and
894
+ sagittal views.
895
+
896
+ Parameters
897
+ ----------
898
+ self : object
899
+ The instance containing the cursor update functionality
900
+
901
+ Returns
902
+ -------
903
+ None
904
+ This method does not return any value
905
+
906
+ Notes
907
+ -----
908
+ The method uses the following coordinate conversion methods:
909
+ - xvox2pix: converts x voxel coordinate to x pixel coordinate
910
+ - yvox2pix: converts y voxel coordinate to y pixel coordinate
911
+ - zvox2pix: converts z voxel coordinate to z pixel coordinate
912
+
913
+ The cursor lines are updated in the following views:
914
+ - axviewvLine: axial view vertical line
915
+ - axviewhLine: axial view horizontal line
916
+ - corviewvLine: coronal view vertical line
917
+ - corviewhLine: coronal view horizontal line
918
+ - sagviewvLine: sagittal view vertical line
919
+ - sagviewhLine: sagittal view horizontal line
920
+
921
+ Examples
922
+ --------
923
+ >>> viewer = Viewer()
924
+ >>> viewer.xpos = 10
925
+ >>> viewer.ypos = 15
926
+ >>> viewer.zpos = 20
927
+ >>> viewer.updateCursors()
928
+ >>> # Cursor positions updated in all three views
929
+ """
358
930
  xpix = self.xvox2pix(self.xpos)
359
931
  ypix = self.yvox2pix(self.ypos)
360
932
  zpix = self.zvox2pix(self.zpos)
@@ -365,60 +937,332 @@ class OrthoImageItem(QtWidgets.QWidget):
365
937
  self.sagviewvLine.setValue(ypix)
366
938
  self.sagviewhLine.setValue(zpix)
367
939
 
368
- def handlemouseup(self, event):
940
+ def handlemouseup(self, event: Any) -> None:
941
+ """
942
+ Handle mouse button up event.
943
+
944
+ This method is called when a mouse button is released. It updates the internal
945
+ state to reflect that the button is no longer pressed and refreshes all views
946
+ to ensure proper cursor representation and visual feedback.
947
+
948
+ Parameters
949
+ ----------
950
+ event : Any
951
+ The mouse event object containing information about the mouse button release.
952
+ This typically includes coordinates and button information.
953
+
954
+ Returns
955
+ -------
956
+ None
957
+ This method does not return any value.
958
+
959
+ Notes
960
+ -----
961
+ This method updates the cursor state and triggers updates across all connected views
962
+ to ensure consistent visual representation of the mouse state.
963
+
964
+ Examples
965
+ --------
966
+ >>> widget.handlemouseup(event)
967
+ >>> # Mouse button state updated and views refreshed
968
+ """
369
969
  self.buttonisdown = False
370
970
  self.updateCursors()
371
971
  self.updateAllViews()
372
972
 
373
- def handleaxmousemove(self, event):
973
+ def handleaxmousemove(self, event: Any) -> None:
974
+ """
975
+ Handle mouse move events for axis navigation.
976
+
977
+ This method is called when the mouse is moved while a button is pressed,
978
+ updating the position coordinates and triggering view updates.
979
+
980
+ Parameters
981
+ ----------
982
+ event : Any
983
+ Mouse event object containing position information. The event object
984
+ should have a `pos()` method that returns the mouse position.
985
+
986
+ Returns
987
+ -------
988
+ None
989
+ This method does not return any value.
990
+
991
+ Notes
992
+ -----
993
+ The method only processes mouse movement when `self.buttonisdown` is True.
994
+ Position coordinates are converted from pixel to voxel space using
995
+ `xpix2vox` and `ypix2vox` conversion methods. The image size is used to
996
+ properly map y-coordinates from pixel space to voxel space.
997
+
998
+ Examples
999
+ --------
1000
+ >>> # This method is typically called internally by the GUI framework
1001
+ >>> # when mouse events occur
1002
+ >>> self.handleaxmousemove(mouse_event)
1003
+ >>> # Updates self.xpos and self.ypos coordinates
1004
+ >>> # Triggers view updates and emits updated signal
1005
+ """
374
1006
  if self.buttonisdown:
375
1007
  self.xpos = self.xpix2vox(event.pos().x() - 1)
376
1008
  self.ypos = self.ypix2vox(self.imgsize - event.pos().y() + 1)
377
1009
  self.updateAllViews()
378
1010
  self.updated.emit()
379
1011
 
380
- def handlecormousemove(self, event):
1012
+ def handlecormousemove(self, event: Any) -> None:
1013
+ """
1014
+ Handle mouse move events for correlation function view navigation.
1015
+
1016
+ This method updates the x and z position coordinates based on mouse movement
1017
+ when a button is pressed. It converts pixel coordinates to voxel coordinates
1018
+ and triggers view updates and signal emission.
1019
+
1020
+ Parameters
1021
+ ----------
1022
+ event : Any
1023
+ Mouse event object containing position information. Expected to have
1024
+ a `pos()` method that returns a position object with `x()` and `y()` methods.
1025
+
1026
+ Returns
1027
+ -------
1028
+ None
1029
+ This method does not return any value.
1030
+
1031
+ Notes
1032
+ -----
1033
+ The method only processes mouse movement when `self.buttonisdown` is True.
1034
+ Pixel coordinates are converted to voxel coordinates using:
1035
+ - x position: `xpix2vox(event.pos().x() - 1)`
1036
+ - z position: `zpix2vox(self.imgsize - event.pos().y() + 1)`
1037
+
1038
+ Examples
1039
+ --------
1040
+ >>> # This method is typically called internally by the GUI framework
1041
+ >>> # when mouse events occur in the correlative view
1042
+ >>> handlecormousemove(mouse_event)
1043
+ """
381
1044
  if self.buttonisdown:
382
1045
  self.xpos = self.xpix2vox(event.pos().x() - 1)
383
1046
  self.zpos = self.zpix2vox(self.imgsize - event.pos().y() + 1)
384
1047
  self.updateAllViews()
385
1048
  self.updated.emit()
386
1049
 
387
- def handlesagmousemove(self, event):
1050
+ def handlesagmousemove(self, event: Any) -> None:
1051
+ """
1052
+ Handle mouse move events for sagittal view navigation.
1053
+
1054
+ This method updates the y and z position coordinates when the mouse is moved
1055
+ while the button is pressed, and triggers view updates and signals.
1056
+
1057
+ Parameters
1058
+ ----------
1059
+ event : Any
1060
+ Mouse event object containing position information. Expected to have
1061
+ a `pos()` method that returns a position object with `x()` and `y()` methods.
1062
+
1063
+ Returns
1064
+ -------
1065
+ None
1066
+ This method does not return any value.
1067
+
1068
+ Notes
1069
+ -----
1070
+ The method only processes mouse movement when `self.buttonisdown` is True.
1071
+ Position coordinates are converted from pixel to voxel space using
1072
+ `self.ypix2vox()` and `self.zpix2vox()` conversion methods.
1073
+
1074
+ Examples
1075
+ --------
1076
+ >>> self.handlesagmousemove(mouse_event)
1077
+ # Updates position coordinates and triggers view updates
1078
+ """
388
1079
  if self.buttonisdown:
389
1080
  self.ypos = self.ypix2vox(event.pos().x() - 1)
390
1081
  self.zpos = self.zpix2vox(self.imgsize - event.pos().y() + 1)
391
1082
  self.updateAllViews()
392
1083
  self.updated.emit()
393
1084
 
394
- def handleaxkey(self, event):
1085
+ def handleaxkey(self, event: Any) -> None:
1086
+ """
1087
+ Handle axis key events and update views.
1088
+
1089
+ This method is called when an axis key event occurs. It prints the event
1090
+ if verbose mode is enabled (verbose > 1), updates all views in the
1091
+ application, and emits an updated signal.
1092
+
1093
+ Parameters
1094
+ ----------
1095
+ event : Any
1096
+ The axis key event object containing event information and data.
1097
+
1098
+ Returns
1099
+ -------
1100
+ None
1101
+ This method does not return any value.
1102
+
1103
+ Notes
1104
+ -----
1105
+ This method is typically used as an event handler for axis key events.
1106
+ The verbose flag controls whether event information is printed to stdout.
1107
+
1108
+ Examples
1109
+ --------
1110
+ >>> # Typically called internally by event system
1111
+ >>> self.handleaxkey(some_event_object)
1112
+ >>> # Output will be printed if self.verbose > 1
1113
+ """
395
1114
  if self.verbose > 1:
396
1115
  print(event)
397
1116
  self.updateAllViews()
398
1117
  self.updated.emit()
399
1118
 
400
- def handleaxclick(self, event):
1119
+ def handleaxclick(self, event: Any) -> None:
1120
+ """
1121
+ Handle mouse click events on the axis.
1122
+
1123
+ This method processes mouse click events to convert pixel coordinates to voxel coordinates,
1124
+ updates the button state, and triggers view updates.
1125
+
1126
+ Parameters
1127
+ ----------
1128
+ event : Any
1129
+ Mouse event object containing position information. Expected to have a `pos()` method
1130
+ that returns a position object with `x()` and `y()` methods.
1131
+
1132
+ Returns
1133
+ -------
1134
+ None
1135
+ This method does not return any value.
1136
+
1137
+ Notes
1138
+ -----
1139
+ The method converts pixel coordinates to voxel coordinates using the following transformations:
1140
+ - x-coordinate: xpix2vox(event.pos().x() - 1)
1141
+ - y-coordinate: ypix2vox(self.imgsize - event.pos().y() + 1)
1142
+
1143
+ The y-coordinate transformation accounts for the difference between pixel coordinate systems
1144
+ where (0,0) is typically at the top-left corner, and voxel coordinate systems where (0,0)
1145
+ is at the bottom-left corner.
1146
+
1147
+ Examples
1148
+ --------
1149
+ >>> handleaxclick(event)
1150
+ # Processes the mouse click event and updates internal state
1151
+ """
401
1152
  self.xpos = self.xpix2vox(event.pos().x() - 1)
402
1153
  self.ypos = self.ypix2vox(self.imgsize - event.pos().y() + 1)
403
1154
  self.buttonisdown = True
404
1155
  self.updateAllViews()
405
1156
  self.updated.emit()
406
1157
 
407
- def handlecorclick(self, event):
1158
+ def handlecorclick(self, event: Any) -> None:
1159
+ """
1160
+ Handle mouse click event for coordinate conversion and view update.
1161
+
1162
+ This method processes mouse click events to convert pixel coordinates to voxel coordinates,
1163
+ updates the button state, and triggers view updates and signals.
1164
+
1165
+ Parameters
1166
+ ----------
1167
+ event : Any
1168
+ Mouse event object containing position information. Expected to have a `pos()` method
1169
+ that returns a point with `x()` and `y()` coordinate methods.
1170
+
1171
+ Returns
1172
+ -------
1173
+ None
1174
+ This method does not return any value.
1175
+
1176
+ Notes
1177
+ -----
1178
+ The method converts pixel coordinates to voxel coordinates using:
1179
+ - x coordinate: `xpix2vox(event.pos().x() - 1)`
1180
+ - z coordinate: `zpix2vox(self.imgsize - event.pos().y() + 1)`
1181
+
1182
+ The coordinate transformation accounts for pixel indexing differences and image orientation.
1183
+
1184
+ Examples
1185
+ --------
1186
+ >>> # Typical usage in event handling context
1187
+ >>> self.handlecorclick(mouse_event)
1188
+ >>> # Updates self.xpos, self.zpos, self.buttonisdown and triggers updates
1189
+ """
408
1190
  self.xpos = self.xpix2vox(event.pos().x() - 1)
409
1191
  self.zpos = self.zpix2vox(self.imgsize - event.pos().y() + 1)
410
1192
  self.buttonisdown = True
411
1193
  self.updateAllViews()
412
1194
  self.updated.emit()
413
1195
 
414
- def handlesagclick(self, event):
1196
+ def handlesagclick(self, event: Any) -> None:
1197
+ """
1198
+ Handle mouse click events for sagittal view navigation.
1199
+
1200
+ This method processes mouse click events in the sagittal view, converting pixel
1201
+ coordinates to voxel coordinates and updating the view accordingly.
1202
+
1203
+ Parameters
1204
+ ----------
1205
+ event : Any
1206
+ Mouse event object containing position information. Expected to have a
1207
+ `pos()` method that returns a position object with `x()` and `y()` methods.
1208
+
1209
+ Returns
1210
+ -------
1211
+ None
1212
+ This method does not return any value.
1213
+
1214
+ Notes
1215
+ -----
1216
+ The method updates internal position variables (ypos, zpos) and triggers
1217
+ view updates through the updateAllViews() method and updated.emit() signal.
1218
+ The pixel coordinates are adjusted by subtracting 1 from x and adding 1 to y
1219
+ for proper coordinate system alignment.
1220
+
1221
+ Examples
1222
+ --------
1223
+ >>> viewer = ImageViewer()
1224
+ >>> event = MouseEvent(pos=QPoint(100, 150))
1225
+ >>> viewer.handlesagclick(event)
1226
+ >>> print(viewer.ypos, viewer.zpos)
1227
+ (0.5, 0.75)
1228
+ """
415
1229
  self.ypos = self.ypix2vox(event.pos().x() - 1)
416
1230
  self.zpos = self.zpix2vox(self.imgsize - event.pos().y() + 1)
417
1231
  self.buttonisdown = True
418
1232
  self.updateAllViews()
419
1233
  self.updated.emit()
420
1234
 
421
- def setXYZpos(self, xpos, ypos, zpos, emitsignal=True):
1235
+ def setXYZpos(self, xpos: int, ypos: int, zpos: int, emitsignal: bool = True) -> None:
1236
+ """
1237
+ Set the XYZ position coordinates and update views.
1238
+
1239
+ Parameters
1240
+ ----------
1241
+ xpos : int
1242
+ The x-coordinate position value.
1243
+ ypos : int
1244
+ The y-coordinate position value.
1245
+ zpos : int
1246
+ The z-coordinate position value.
1247
+ emitsignal : bool, optional
1248
+ If True, emit the updated signal after position change (default is True).
1249
+
1250
+ Returns
1251
+ -------
1252
+ None
1253
+ This method does not return any value.
1254
+
1255
+ Notes
1256
+ -----
1257
+ This method converts all position parameters to integers and updates
1258
+ all views through the updateAllViews() call. The updated signal is
1259
+ only emitted when emitsignal is True.
1260
+
1261
+ Examples
1262
+ --------
1263
+ >>> obj.setXYZpos(10, 20, 30)
1264
+ >>> obj.setXYZpos(5, 15, 25, emitsignal=False)
1265
+ """
422
1266
  self.xpos = int(xpos)
423
1267
  self.ypos = int(ypos)
424
1268
  self.zpos = int(zpos)
@@ -426,7 +1270,37 @@ class OrthoImageItem(QtWidgets.QWidget):
426
1270
  if emitsignal:
427
1271
  self.updated.emit()
428
1272
 
429
- def setTpos(self, tpos, emitsignal=True):
1273
+ def setTpos(self, tpos: int, emitsignal: bool = True) -> None:
1274
+ """
1275
+ Set the current time position and update all views.
1276
+
1277
+ This method updates the internal time position counter and triggers
1278
+ view updates. If emitsignal is True, it also emits the updated signal.
1279
+
1280
+ Parameters
1281
+ ----------
1282
+ tpos : int
1283
+ The new time position to set. If tpos exceeds the maximum allowed
1284
+ time position (self.tdim - 1), it will be clamped to the maximum value.
1285
+ emitsignal : bool, optional
1286
+ If True, emit the updated signal after updating the time position.
1287
+ Default is True.
1288
+
1289
+ Returns
1290
+ -------
1291
+ None
1292
+ This method does not return any value.
1293
+
1294
+ Notes
1295
+ -----
1296
+ The time position is automatically clamped to the valid range [0, self.tdim - 1].
1297
+ This ensures that the time position never exceeds the dimension limits.
1298
+
1299
+ Examples
1300
+ --------
1301
+ >>> obj.setTpos(5)
1302
+ >>> obj.setTpos(10, emitsignal=False)
1303
+ """
430
1304
  if tpos > self.tdim - 1:
431
1305
  self.tpos = int(self.tdim - 1)
432
1306
  else:
@@ -436,13 +1310,103 @@ class OrthoImageItem(QtWidgets.QWidget):
436
1310
  if emitsignal:
437
1311
  self.updated.emit()
438
1312
 
439
- def getFocusVal(self):
1313
+ def getFocusVal(self) -> float:
1314
+ """
1315
+ Get the focus value at the current position.
1316
+
1317
+ This method retrieves the data value from the masked data array at the
1318
+ current position coordinates. The method handles both 3D and 4D data arrays
1319
+ by checking the time dimension.
1320
+
1321
+ Parameters
1322
+ ----------
1323
+ self : object
1324
+ The instance containing the data and position attributes.
1325
+
1326
+ Returns
1327
+ -------
1328
+ float
1329
+ The focus value at the current position. Returns a scalar value
1330
+ from the masked data array.
1331
+
1332
+ Notes
1333
+ -----
1334
+ The method uses the following attributes from the instance:
1335
+ - self.tdim: Time dimension flag (1 for 3D, >1 for 4D)
1336
+ - self.map.maskeddata: The data array containing the values
1337
+ - self.xpos, self.ypos, self.zpos, self.tpos: Position coordinates
1338
+
1339
+ Examples
1340
+ --------
1341
+ >>> value = obj.getFocusVal()
1342
+ >>> print(value)
1343
+ 0.567
1344
+ """
440
1345
  if self.tdim > 1:
441
1346
  return self.map.maskeddata[self.xpos, self.ypos, self.zpos, self.tpos]
442
1347
  else:
443
1348
  return self.map.maskeddata[self.xpos, self.ypos, self.zpos]
444
1349
 
445
- def saveandcomposite(self, square_img, fg_img, bg_img, name, savedir, scalefach, scalefacv):
1350
+ def saveandcomposite(
1351
+ self,
1352
+ square_img: Any,
1353
+ fg_img: Any,
1354
+ bg_img: Any,
1355
+ name: str,
1356
+ savedir: str,
1357
+ scalefach: float,
1358
+ scalefacv: float,
1359
+ ) -> None:
1360
+ """
1361
+ Save and composite image layers into a final output file.
1362
+
1363
+ This function saves individual image layers (square, foreground, and background)
1364
+ and composites them into a final image. If PIL is available, it performs
1365
+ additional operations such as flipping, scaling, and saving the composite
1366
+ as a JPEG file. Temporary files are removed after processing.
1367
+
1368
+ Parameters
1369
+ ----------
1370
+ square_img : Any
1371
+ The square image to be saved.
1372
+ fg_img : Any
1373
+ The foreground image to be saved and composited.
1374
+ bg_img : Any
1375
+ The background image to be saved and composited.
1376
+ name : str
1377
+ Base name for the output files.
1378
+ savedir : str
1379
+ Directory where output files will be saved.
1380
+ scalefach : float
1381
+ Horizontal scaling factor for the final image.
1382
+ scalefacv : float
1383
+ Vertical scaling factor for the final image.
1384
+
1385
+ Returns
1386
+ -------
1387
+ None
1388
+ This function does not return any value.
1389
+
1390
+ Notes
1391
+ -----
1392
+ - If PIL is available, the function will save the images in PNG format
1393
+ and composite them into a JPEG file.
1394
+ - Temporary files are deleted after processing.
1395
+ - The function uses `Image.NEAREST` for resizing to preserve pixel integrity.
1396
+ - Verbose logging is enabled based on `self.verbose` level.
1397
+
1398
+ Examples
1399
+ --------
1400
+ >>> saveandcomposite(
1401
+ ... square_img=square,
1402
+ ... fg_img=foreground,
1403
+ ... bg_img=background,
1404
+ ... name="test_image",
1405
+ ... savedir="/path/to/save",
1406
+ ... scalefach=1.0,
1407
+ ... scalefacv=1.0
1408
+ ... )
1409
+ """
446
1410
  if PILexists:
447
1411
  if self.verbose > 1:
448
1412
  print("using PIL to save ", name)
@@ -491,11 +1455,66 @@ class OrthoImageItem(QtWidgets.QWidget):
491
1455
  fg_img.save(os.path.join(savedir, name + "_fg.png"))
492
1456
  bg_img.save(os.path.join(savedir, name + "_bg.png"))
493
1457
 
494
- def saveDisp(self):
1458
+ def saveDisp(self) -> None:
1459
+ """
1460
+ Save display windows for axial, coronal, and sagittal views of the image data.
1461
+
1462
+ This function saves three orthogonal views (axial, coronal, and sagittal) of the
1463
+ image data to the specified directory. It also saves a colorbar and writes
1464
+ display limits to a text file. The saved images are composed using the
1465
+ `saveandcomposite` method, and the colorbar is generated using `newColorbar`.
1466
+
1467
+ Parameters
1468
+ ----------
1469
+ self : object
1470
+ The instance of the class containing this method. Expected to have attributes:
1471
+ - `verbose`: int, controls verbosity of output.
1472
+ - `map`: object with attributes:
1473
+ - `namebase`: str, base name for output files.
1474
+ - `name`: str, name of the map.
1475
+ - `theLUT`: lookup table for color mapping.
1476
+ - `dispmin`: float, minimum display value.
1477
+ - `dispmax`: float, maximum display value.
1478
+ - `impixpervoxx`, `impixpervoxy`, `impixpervoxz`: float, voxel sizes in each dimension.
1479
+ - `xdim`, `ydim`, `zdim`: int, dimensions of the image in each axis.
1480
+ - `xsize`, `ysize`, `zsize`: float, physical size per voxel in each axis.
1481
+ - `axviewwin`, `axviewbgwin`, `corviewwin`, `corviewbgwin`, `sagviewwin`, `sagviewbgwin`:
1482
+ ImageItem objects for the respective views.
1483
+ - `applyLUT`: method to apply lookup table to data.
1484
+ - `saveandcomposite`: method to composite and save image views.
1485
+
1486
+ Returns
1487
+ -------
1488
+ None
1489
+ This function does not return any value.
1490
+
1491
+ Notes
1492
+ -----
1493
+ - The function uses Qt bindings (PyQt5, PyQt6, or PySide6) to open a file dialog
1494
+ for selecting the output directory.
1495
+ - The saved images are named with the base name from `self.map.namebase` and
1496
+ appended with `_ax`, `_cor`, and `_sag` for the respective views.
1497
+ - A colorbar is generated but currently commented out in the code.
1498
+ - The display limits are saved to a file named `<namebase><name>_lims.txt`.
1499
+
1500
+ Examples
1501
+ --------
1502
+ Assuming `obj` is an instance of the class containing this method:
1503
+
1504
+ >>> obj.saveDisp()
1505
+ # Saves axial, coronal, and sagittal views to the selected directory.
1506
+ """
495
1507
  if self.verbose > 1:
496
1508
  print("saving main window")
497
1509
  mydialog = QtWidgets.QFileDialog()
498
- options = mydialog.Options()
1510
+ if pyqtbinding == "pyqt5":
1511
+ options = mydialog.Options()
1512
+ elif pyqtbinding == "pyqt6":
1513
+ options = mydialog.options()
1514
+ elif pyqtbinding == "pyside6":
1515
+ options = mydialog.options()
1516
+ else:
1517
+ print("unsupported qt binding")
499
1518
  thedir = str(
500
1519
  mydialog.getExistingDirectory(options=options, caption="Image output directory")
501
1520
  )
@@ -528,7 +1547,7 @@ class OrthoImageItem(QtWidgets.QWidget):
528
1547
  ) = newColorbar(0, 0, maximpervox, maximpervox, maxdim)
529
1548
  cbim = self.applyLUT(
530
1549
  colorbarvals,
531
- (colorbarvals * 0 + 1).astype("int"),
1550
+ np.ones_like(colorbarvals, "int"),
532
1551
  self.map.theLUT,
533
1552
  0.0,
534
1553
  1.0,
@@ -577,7 +1596,31 @@ class OrthoImageItem(QtWidgets.QWidget):
577
1596
  FILE.writelines(str(self.map.dispmin) + "\t" + str(self.map.dispmax))
578
1597
  # img_colorbar.save(thedir + self.map.name + '_colorbar.png')
579
1598
 
580
- def summarize(self):
1599
+ def summarize(self) -> None:
1600
+ """
1601
+ Summarize the orthoimage item information.
1602
+
1603
+ This method performs a summary operation on the orthoimage item, typically
1604
+ used to validate or prepare the item for further processing. When a map is
1605
+ associated with the item, it may perform additional operations or validation.
1606
+
1607
+ Notes
1608
+ -----
1609
+ The method currently contains a placeholder implementation that only checks
1610
+ if a map is set. In a complete implementation, this method would likely
1611
+ generate summary statistics, validate data integrity, or prepare the item
1612
+ for display or export operations.
1613
+
1614
+ Examples
1615
+ --------
1616
+ >>> item = OrthoImageItem()
1617
+ >>> item.summarize()
1618
+ # Performs summary operation on the item
1619
+
1620
+ See Also
1621
+ --------
1622
+ OrthoImageItem : Main class for orthoimage items
1623
+ """
581
1624
  if self.map is not None:
582
1625
  # print('OrthoImageItem[', self.map.name, ']: map is set')
583
1626
  pass