melage 0.0.65__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 (501) hide show
  1. melage/__init__.py +16 -0
  2. melage/cli.py +4 -0
  3. melage/graphics/GLGraphicsItem.py +286 -0
  4. melage/graphics/GLViewWidget.py +595 -0
  5. melage/graphics/Transform3D.py +55 -0
  6. melage/graphics/__init__.py +8 -0
  7. melage/graphics/functions.py +101 -0
  8. melage/graphics/items/GLAxisItem.py +149 -0
  9. melage/graphics/items/GLGridItem.py +178 -0
  10. melage/graphics/items/GLPolygonItem.py +77 -0
  11. melage/graphics/items/GLScatterPlotItem.py +135 -0
  12. melage/graphics/items/GLVolumeItem.py +280 -0
  13. melage/graphics/items/GLVolumeItem_b.py +237 -0
  14. melage/graphics/items/__init__.py +0 -0
  15. melage/graphics/shaders.py +202 -0
  16. melage/main.py +270 -0
  17. melage/requirements22.txt +25 -0
  18. melage/requirements_old.txt +28 -0
  19. melage/resource/0circle.png +0 -0
  20. melage/resource/0circle_faded.png +0 -0
  21. melage/resource/3d.png +0 -0
  22. melage/resource/3d.psd +0 -0
  23. melage/resource/3dFaded.png +0 -0
  24. melage/resource/Eraser.png +0 -0
  25. melage/resource/EraserFaded.png +0 -0
  26. melage/resource/EraserX.png +0 -0
  27. melage/resource/EraserXFaded.png +0 -0
  28. melage/resource/Eraser_icon.svg +79 -0
  29. melage/resource/Hand.png +0 -0
  30. melage/resource/HandIcons_0.png +0 -0
  31. melage/resource/Hand_IX.png +0 -0
  32. melage/resource/Hand_IXFaded.png +0 -0
  33. melage/resource/Handsqueezed.png +0 -0
  34. melage/resource/Handwriting (copy).png +0 -0
  35. melage/resource/Handwriting.png +0 -0
  36. melage/resource/HandwritingMinus.png +0 -0
  37. melage/resource/HandwritingMinusX.png +0 -0
  38. melage/resource/HandwritingPlus.png +0 -0
  39. melage/resource/HandwritingPlusX.png +0 -0
  40. melage/resource/Move_icon.svg +8 -0
  41. melage/resource/PngItem_2422924.png +0 -0
  42. melage/resource/about.png +0 -0
  43. melage/resource/about_logo.png +0 -0
  44. melage/resource/about_logo0.png +0 -0
  45. melage/resource/action_check.png +0 -0
  46. melage/resource/action_check_OFF.png +0 -0
  47. melage/resource/arrow).png +0 -0
  48. melage/resource/arrow.png +0 -0
  49. melage/resource/arrowFaded.png +0 -0
  50. melage/resource/arrow_org.png +0 -0
  51. melage/resource/arrow_org.png.png +0 -0
  52. melage/resource/arrows.png +0 -0
  53. melage/resource/authors.mp4 +0 -0
  54. melage/resource/box.png +0 -0
  55. melage/resource/check-image-icon-0.jpg +0 -0
  56. melage/resource/circle.png +0 -0
  57. melage/resource/circle_faded.png +0 -0
  58. melage/resource/circle_or.png +0 -0
  59. melage/resource/close.png +0 -0
  60. melage/resource/close_bg.png +0 -0
  61. melage/resource/color/Simple.txt +18 -0
  62. melage/resource/color/Tissue.txt +24 -0
  63. melage/resource/color/Tissue12.txt +27 -0
  64. melage/resource/color/albert_LUT.txt +102 -0
  65. melage/resource/color/mcrib_LUT.txt +102 -0
  66. melage/resource/color/pediatric1.txt +29 -0
  67. melage/resource/color/pediatric1_old.txt +27 -0
  68. melage/resource/color/pediatric2.txt +87 -0
  69. melage/resource/color/pediatric3.txt +29 -0
  70. melage/resource/color/pediatrics (copy).csv +103 -0
  71. melage/resource/color/tissue_seg.txt +4 -0
  72. melage/resource/contour.png +0 -0
  73. melage/resource/contour.svg +2 -0
  74. melage/resource/contourFaded.png +0 -0
  75. melage/resource/contourX.png +0 -0
  76. melage/resource/contourXFaded.png +0 -0
  77. melage/resource/dti.png +0 -0
  78. melage/resource/dti0.png +0 -0
  79. melage/resource/dti222.png +0 -0
  80. melage/resource/dti_or.png +0 -0
  81. melage/resource/eco.png +0 -0
  82. melage/resource/eco22.png +0 -0
  83. melage/resource/eco_old.png +0 -0
  84. melage/resource/eco_or.png +0 -0
  85. melage/resource/eco_or2.png +0 -0
  86. melage/resource/eco_seg.png +0 -0
  87. melage/resource/eco_seg_old.png +0 -0
  88. melage/resource/export.png +0 -0
  89. melage/resource/hand-grab-icon-10.jpg +0 -0
  90. melage/resource/hand-grab-icon-25.jpg +0 -0
  91. melage/resource/info.png +0 -0
  92. melage/resource/line.png +0 -0
  93. melage/resource/linefaded.png +0 -0
  94. melage/resource/load.png +0 -0
  95. melage/resource/main.ico +0 -0
  96. melage/resource/manual_images/3D_rightc.png +0 -0
  97. melage/resource/manual_images/3D_rightc_goto.png +0 -0
  98. melage/resource/manual_images/3D_rightc_paint.png +0 -0
  99. melage/resource/manual_images/3D_rightc_paint_draw1.png +0 -0
  100. melage/resource/manual_images/3D_rightc_paint_draw2.png +0 -0
  101. melage/resource/manual_images/3D_rightc_paint_render.png +0 -0
  102. melage/resource/manual_images/3D_rightc_paint_render2.png +0 -0
  103. melage/resource/manual_images/3D_rightc_paint_render3.png +0 -0
  104. melage/resource/manual_images/3D_rightc_paint_render4.png +0 -0
  105. melage/resource/manual_images/3D_rightc_paint_render5.png +0 -0
  106. melage/resource/manual_images/3D_rightc_paint_render6.png +0 -0
  107. melage/resource/manual_images/3D_rightc_seg.png +0 -0
  108. melage/resource/manual_images/exit_toolbar.png +0 -0
  109. melage/resource/manual_images/load_image_file.png +0 -0
  110. melage/resource/manual_images/load_image_file_openp.png +0 -0
  111. melage/resource/manual_images/main_page.png +0 -0
  112. melage/resource/manual_images/menu_file.png +0 -0
  113. melage/resource/manual_images/menu_file_export.png +0 -0
  114. melage/resource/manual_images/menu_file_import.png +0 -0
  115. melage/resource/manual_images/menu_file_settings.png +0 -0
  116. melage/resource/manual_images/menu_file_ss.png +0 -0
  117. melage/resource/manual_images/open_save_load.png +0 -0
  118. melage/resource/manual_images/panning_toolbar.png +0 -0
  119. melage/resource/manual_images/segmentation_toolbar.png +0 -0
  120. melage/resource/manual_images/tab_mri.png +0 -0
  121. melage/resource/manual_images/tab_us.png +0 -0
  122. melage/resource/manual_images/tabs.png +0 -0
  123. melage/resource/manual_images/toolbar_tools.png +0 -0
  124. melage/resource/manual_images/tools_basic.png +0 -0
  125. melage/resource/manual_images/tools_bet.png +0 -0
  126. melage/resource/manual_images/tools_cs.png +0 -0
  127. melage/resource/manual_images/tools_deepbet.png +0 -0
  128. melage/resource/manual_images/tools_imageinfo.png +0 -0
  129. melage/resource/manual_images/tools_maskO.png +0 -0
  130. melage/resource/manual_images/tools_masking.png +0 -0
  131. melage/resource/manual_images/tools_n4b.png +0 -0
  132. melage/resource/manual_images/tools_resize.png +0 -0
  133. melage/resource/manual_images/tools_ruler.png +0 -0
  134. melage/resource/manual_images/tools_seg.png +0 -0
  135. melage/resource/manual_images/tools_threshold.png +0 -0
  136. melage/resource/manual_images/tools_tools.png +0 -0
  137. melage/resource/manual_images/widget_color.png +0 -0
  138. melage/resource/manual_images/widget_color_add.png +0 -0
  139. melage/resource/manual_images/widget_color_add2.png +0 -0
  140. melage/resource/manual_images/widget_color_additional.png +0 -0
  141. melage/resource/manual_images/widget_images.png +0 -0
  142. melage/resource/manual_images/widget_images2.png +0 -0
  143. melage/resource/manual_images/widget_images3.png +0 -0
  144. melage/resource/manual_images/widget_marker.png +0 -0
  145. melage/resource/manual_images/widget_mri.png +0 -0
  146. melage/resource/manual_images/widget_mri2.png +0 -0
  147. melage/resource/manual_images/widget_segintensity.png +0 -0
  148. melage/resource/manual_images/widget_tab_mutualview.png +0 -0
  149. melage/resource/manual_images/widget_tab_mutualview2.png +0 -0
  150. melage/resource/manual_images/widget_table.png +0 -0
  151. melage/resource/manual_images/widget_table2.png +0 -0
  152. melage/resource/manual_images/widget_us.png +0 -0
  153. melage/resource/melage_top.ico +0 -0
  154. melage/resource/melage_top.png +0 -0
  155. melage/resource/melage_top0.png +0 -0
  156. melage/resource/melage_top1.png +0 -0
  157. melage/resource/melage_top4.png +0 -0
  158. melage/resource/mri (copy).png +0 -0
  159. melage/resource/mri.png +0 -0
  160. melage/resource/mri0.png +0 -0
  161. melage/resource/mri000.png +0 -0
  162. melage/resource/mri22.png +0 -0
  163. melage/resource/mri_big.png +0 -0
  164. melage/resource/mri_old.png +0 -0
  165. melage/resource/mri_seg.png +0 -0
  166. melage/resource/mri_seg_old.png +0 -0
  167. melage/resource/new.png +0 -0
  168. melage/resource/open.png +0 -0
  169. melage/resource/open2.png +0 -0
  170. melage/resource/pan.png +0 -0
  171. melage/resource/pencil.png +0 -0
  172. melage/resource/pencilFaded.png +0 -0
  173. melage/resource/points.png +0 -0
  174. melage/resource/pointsFaded.png +0 -0
  175. melage/resource/rotate.png +0 -0
  176. melage/resource/ruler.png +0 -0
  177. melage/resource/rulerFaded.png +0 -0
  178. melage/resource/s.png +0 -0
  179. melage/resource/s.psd +0 -0
  180. melage/resource/save.png +0 -0
  181. melage/resource/saveas.png +0 -0
  182. melage/resource/seg_mri.png +0 -0
  183. melage/resource/seg_mri2.png +0 -0
  184. melage/resource/settings.png +0 -0
  185. melage/resource/synch.png +0 -0
  186. melage/resource/synchFaded.png +0 -0
  187. melage/resource/theme/rc/.keep +1 -0
  188. melage/resource/theme/rc/arrow_down.png +0 -0
  189. melage/resource/theme/rc/arrow_down@2x.png +0 -0
  190. melage/resource/theme/rc/arrow_down_disabled.png +0 -0
  191. melage/resource/theme/rc/arrow_down_disabled@2x.png +0 -0
  192. melage/resource/theme/rc/arrow_down_focus.png +0 -0
  193. melage/resource/theme/rc/arrow_down_focus@2x.png +0 -0
  194. melage/resource/theme/rc/arrow_down_pressed.png +0 -0
  195. melage/resource/theme/rc/arrow_down_pressed@2x.png +0 -0
  196. melage/resource/theme/rc/arrow_left.png +0 -0
  197. melage/resource/theme/rc/arrow_left@2x.png +0 -0
  198. melage/resource/theme/rc/arrow_left_disabled.png +0 -0
  199. melage/resource/theme/rc/arrow_left_disabled@2x.png +0 -0
  200. melage/resource/theme/rc/arrow_left_focus.png +0 -0
  201. melage/resource/theme/rc/arrow_left_focus@2x.png +0 -0
  202. melage/resource/theme/rc/arrow_left_pressed.png +0 -0
  203. melage/resource/theme/rc/arrow_left_pressed@2x.png +0 -0
  204. melage/resource/theme/rc/arrow_right.png +0 -0
  205. melage/resource/theme/rc/arrow_right@2x.png +0 -0
  206. melage/resource/theme/rc/arrow_right_disabled.png +0 -0
  207. melage/resource/theme/rc/arrow_right_disabled@2x.png +0 -0
  208. melage/resource/theme/rc/arrow_right_focus.png +0 -0
  209. melage/resource/theme/rc/arrow_right_focus@2x.png +0 -0
  210. melage/resource/theme/rc/arrow_right_pressed.png +0 -0
  211. melage/resource/theme/rc/arrow_right_pressed@2x.png +0 -0
  212. melage/resource/theme/rc/arrow_up.png +0 -0
  213. melage/resource/theme/rc/arrow_up@2x.png +0 -0
  214. melage/resource/theme/rc/arrow_up_disabled.png +0 -0
  215. melage/resource/theme/rc/arrow_up_disabled@2x.png +0 -0
  216. melage/resource/theme/rc/arrow_up_focus.png +0 -0
  217. melage/resource/theme/rc/arrow_up_focus@2x.png +0 -0
  218. melage/resource/theme/rc/arrow_up_pressed.png +0 -0
  219. melage/resource/theme/rc/arrow_up_pressed@2x.png +0 -0
  220. melage/resource/theme/rc/base_icon.png +0 -0
  221. melage/resource/theme/rc/base_icon@2x.png +0 -0
  222. melage/resource/theme/rc/base_icon_disabled.png +0 -0
  223. melage/resource/theme/rc/base_icon_disabled@2x.png +0 -0
  224. melage/resource/theme/rc/base_icon_focus.png +0 -0
  225. melage/resource/theme/rc/base_icon_focus@2x.png +0 -0
  226. melage/resource/theme/rc/base_icon_pressed.png +0 -0
  227. melage/resource/theme/rc/base_icon_pressed@2x.png +0 -0
  228. melage/resource/theme/rc/branch_closed.png +0 -0
  229. melage/resource/theme/rc/branch_closed@2x.png +0 -0
  230. melage/resource/theme/rc/branch_closed_disabled.png +0 -0
  231. melage/resource/theme/rc/branch_closed_disabled@2x.png +0 -0
  232. melage/resource/theme/rc/branch_closed_focus.png +0 -0
  233. melage/resource/theme/rc/branch_closed_focus@2x.png +0 -0
  234. melage/resource/theme/rc/branch_closed_pressed.png +0 -0
  235. melage/resource/theme/rc/branch_closed_pressed@2x.png +0 -0
  236. melage/resource/theme/rc/branch_end.png +0 -0
  237. melage/resource/theme/rc/branch_end@2x.png +0 -0
  238. melage/resource/theme/rc/branch_end_disabled.png +0 -0
  239. melage/resource/theme/rc/branch_end_disabled@2x.png +0 -0
  240. melage/resource/theme/rc/branch_end_focus.png +0 -0
  241. melage/resource/theme/rc/branch_end_focus@2x.png +0 -0
  242. melage/resource/theme/rc/branch_end_pressed.png +0 -0
  243. melage/resource/theme/rc/branch_end_pressed@2x.png +0 -0
  244. melage/resource/theme/rc/branch_line.png +0 -0
  245. melage/resource/theme/rc/branch_line@2x.png +0 -0
  246. melage/resource/theme/rc/branch_line_disabled.png +0 -0
  247. melage/resource/theme/rc/branch_line_disabled@2x.png +0 -0
  248. melage/resource/theme/rc/branch_line_focus.png +0 -0
  249. melage/resource/theme/rc/branch_line_focus@2x.png +0 -0
  250. melage/resource/theme/rc/branch_line_pressed.png +0 -0
  251. melage/resource/theme/rc/branch_line_pressed@2x.png +0 -0
  252. melage/resource/theme/rc/branch_more.png +0 -0
  253. melage/resource/theme/rc/branch_more@2x.png +0 -0
  254. melage/resource/theme/rc/branch_more_disabled.png +0 -0
  255. melage/resource/theme/rc/branch_more_disabled@2x.png +0 -0
  256. melage/resource/theme/rc/branch_more_focus.png +0 -0
  257. melage/resource/theme/rc/branch_more_focus@2x.png +0 -0
  258. melage/resource/theme/rc/branch_more_pressed.png +0 -0
  259. melage/resource/theme/rc/branch_more_pressed@2x.png +0 -0
  260. melage/resource/theme/rc/branch_open.png +0 -0
  261. melage/resource/theme/rc/branch_open@2x.png +0 -0
  262. melage/resource/theme/rc/branch_open_disabled.png +0 -0
  263. melage/resource/theme/rc/branch_open_disabled@2x.png +0 -0
  264. melage/resource/theme/rc/branch_open_focus.png +0 -0
  265. melage/resource/theme/rc/branch_open_focus@2x.png +0 -0
  266. melage/resource/theme/rc/branch_open_pressed.png +0 -0
  267. melage/resource/theme/rc/branch_open_pressed@2x.png +0 -0
  268. melage/resource/theme/rc/checkbox_checked.png +0 -0
  269. melage/resource/theme/rc/checkbox_checked0.png +0 -0
  270. melage/resource/theme/rc/checkbox_checked@2x.png +0 -0
  271. melage/resource/theme/rc/checkbox_checked@2x0.png +0 -0
  272. melage/resource/theme/rc/checkbox_checked@2x000.png.png +0 -0
  273. melage/resource/theme/rc/checkbox_checked_disabled.png +0 -0
  274. melage/resource/theme/rc/checkbox_checked_disabled0.png +0 -0
  275. melage/resource/theme/rc/checkbox_checked_disabled@2x.png +0 -0
  276. melage/resource/theme/rc/checkbox_checked_disabled@2x0.png +0 -0
  277. melage/resource/theme/rc/checkbox_checked_focus.png +0 -0
  278. melage/resource/theme/rc/checkbox_checked_focus0.png +0 -0
  279. melage/resource/theme/rc/checkbox_checked_focus@2x.png +0 -0
  280. melage/resource/theme/rc/checkbox_checked_focus@2x0.png +0 -0
  281. melage/resource/theme/rc/checkbox_checked_pressed.png +0 -0
  282. melage/resource/theme/rc/checkbox_checked_pressed0.png +0 -0
  283. melage/resource/theme/rc/checkbox_checked_pressed@2x.png +0 -0
  284. melage/resource/theme/rc/checkbox_checked_pressed@2x0.png +0 -0
  285. melage/resource/theme/rc/checkbox_indeterminate.png +0 -0
  286. melage/resource/theme/rc/checkbox_indeterminate@2x.png +0 -0
  287. melage/resource/theme/rc/checkbox_indeterminate_disabled.png +0 -0
  288. melage/resource/theme/rc/checkbox_indeterminate_disabled@2x.png +0 -0
  289. melage/resource/theme/rc/checkbox_indeterminate_focus.png +0 -0
  290. melage/resource/theme/rc/checkbox_indeterminate_focus@2x.png +0 -0
  291. melage/resource/theme/rc/checkbox_indeterminate_pressed.png +0 -0
  292. melage/resource/theme/rc/checkbox_indeterminate_pressed@2x.png +0 -0
  293. melage/resource/theme/rc/checkbox_unchecked.png +0 -0
  294. melage/resource/theme/rc/checkbox_unchecked0.png +0 -0
  295. melage/resource/theme/rc/checkbox_unchecked00.png +0 -0
  296. melage/resource/theme/rc/checkbox_unchecked@2x.png +0 -0
  297. melage/resource/theme/rc/checkbox_unchecked@2x0.png +0 -0
  298. melage/resource/theme/rc/checkbox_unchecked@2x00.png +0 -0
  299. melage/resource/theme/rc/checkbox_unchecked_disabled.png +0 -0
  300. melage/resource/theme/rc/checkbox_unchecked_disabled0.png +0 -0
  301. melage/resource/theme/rc/checkbox_unchecked_disabled00.png +0 -0
  302. melage/resource/theme/rc/checkbox_unchecked_disabled@2x.png +0 -0
  303. melage/resource/theme/rc/checkbox_unchecked_disabled@2x0.png +0 -0
  304. melage/resource/theme/rc/checkbox_unchecked_disabled@2x00.png +0 -0
  305. melage/resource/theme/rc/checkbox_unchecked_focus.png +0 -0
  306. melage/resource/theme/rc/checkbox_unchecked_focus0.png +0 -0
  307. melage/resource/theme/rc/checkbox_unchecked_focus00.png +0 -0
  308. melage/resource/theme/rc/checkbox_unchecked_focus@2x.png +0 -0
  309. melage/resource/theme/rc/checkbox_unchecked_focus@2x0.png +0 -0
  310. melage/resource/theme/rc/checkbox_unchecked_focus@2x00.png +0 -0
  311. melage/resource/theme/rc/checkbox_unchecked_pressed.png +0 -0
  312. melage/resource/theme/rc/checkbox_unchecked_pressed0.png +0 -0
  313. melage/resource/theme/rc/checkbox_unchecked_pressed00.png +0 -0
  314. melage/resource/theme/rc/checkbox_unchecked_pressed@2x.png +0 -0
  315. melage/resource/theme/rc/checkbox_unchecked_pressed@2x0.png +0 -0
  316. melage/resource/theme/rc/checkbox_unchecked_pressed@2x00.png +0 -0
  317. melage/resource/theme/rc/line_horizontal.png +0 -0
  318. melage/resource/theme/rc/line_horizontal@2x.png +0 -0
  319. melage/resource/theme/rc/line_horizontal_disabled.png +0 -0
  320. melage/resource/theme/rc/line_horizontal_disabled@2x.png +0 -0
  321. melage/resource/theme/rc/line_horizontal_focus.png +0 -0
  322. melage/resource/theme/rc/line_horizontal_focus@2x.png +0 -0
  323. melage/resource/theme/rc/line_horizontal_pressed.png +0 -0
  324. melage/resource/theme/rc/line_horizontal_pressed@2x.png +0 -0
  325. melage/resource/theme/rc/line_vertical.png +0 -0
  326. melage/resource/theme/rc/line_vertical@2x.png +0 -0
  327. melage/resource/theme/rc/line_vertical_disabled.png +0 -0
  328. melage/resource/theme/rc/line_vertical_disabled@2x.png +0 -0
  329. melage/resource/theme/rc/line_vertical_focus.png +0 -0
  330. melage/resource/theme/rc/line_vertical_focus@2x.png +0 -0
  331. melage/resource/theme/rc/line_vertical_pressed.png +0 -0
  332. melage/resource/theme/rc/line_vertical_pressed@2x.png +0 -0
  333. melage/resource/theme/rc/radio_checked.png +0 -0
  334. melage/resource/theme/rc/radio_checked@2x.png +0 -0
  335. melage/resource/theme/rc/radio_checked_disabled.png +0 -0
  336. melage/resource/theme/rc/radio_checked_disabled@2x.png +0 -0
  337. melage/resource/theme/rc/radio_checked_focus.png +0 -0
  338. melage/resource/theme/rc/radio_checked_focus@2x.png +0 -0
  339. melage/resource/theme/rc/radio_checked_pressed.png +0 -0
  340. melage/resource/theme/rc/radio_checked_pressed@2x.png +0 -0
  341. melage/resource/theme/rc/radio_unchecked.png +0 -0
  342. melage/resource/theme/rc/radio_unchecked@2x.png +0 -0
  343. melage/resource/theme/rc/radio_unchecked_disabled.png +0 -0
  344. melage/resource/theme/rc/radio_unchecked_disabled@2x.png +0 -0
  345. melage/resource/theme/rc/radio_unchecked_focus.png +0 -0
  346. melage/resource/theme/rc/radio_unchecked_focus@2x.png +0 -0
  347. melage/resource/theme/rc/radio_unchecked_pressed.png +0 -0
  348. melage/resource/theme/rc/radio_unchecked_pressed@2x.png +0 -0
  349. melage/resource/theme/rc/toolbar_move_horizontal.png +0 -0
  350. melage/resource/theme/rc/toolbar_move_horizontal@2x.png +0 -0
  351. melage/resource/theme/rc/toolbar_move_horizontal_disabled.png +0 -0
  352. melage/resource/theme/rc/toolbar_move_horizontal_disabled@2x.png +0 -0
  353. melage/resource/theme/rc/toolbar_move_horizontal_focus.png +0 -0
  354. melage/resource/theme/rc/toolbar_move_horizontal_focus@2x.png +0 -0
  355. melage/resource/theme/rc/toolbar_move_horizontal_pressed.png +0 -0
  356. melage/resource/theme/rc/toolbar_move_horizontal_pressed@2x.png +0 -0
  357. melage/resource/theme/rc/toolbar_move_vertical.png +0 -0
  358. melage/resource/theme/rc/toolbar_move_vertical@2x.png +0 -0
  359. melage/resource/theme/rc/toolbar_move_vertical_disabled.png +0 -0
  360. melage/resource/theme/rc/toolbar_move_vertical_disabled@2x.png +0 -0
  361. melage/resource/theme/rc/toolbar_move_vertical_focus.png +0 -0
  362. melage/resource/theme/rc/toolbar_move_vertical_focus@2x.png +0 -0
  363. melage/resource/theme/rc/toolbar_move_vertical_pressed.png +0 -0
  364. melage/resource/theme/rc/toolbar_move_vertical_pressed@2x.png +0 -0
  365. melage/resource/theme/rc/toolbar_separator_horizontal.png +0 -0
  366. melage/resource/theme/rc/toolbar_separator_horizontal@2x.png +0 -0
  367. melage/resource/theme/rc/toolbar_separator_horizontal_disabled.png +0 -0
  368. melage/resource/theme/rc/toolbar_separator_horizontal_disabled@2x.png +0 -0
  369. melage/resource/theme/rc/toolbar_separator_horizontal_focus.png +0 -0
  370. melage/resource/theme/rc/toolbar_separator_horizontal_focus@2x.png +0 -0
  371. melage/resource/theme/rc/toolbar_separator_horizontal_pressed.png +0 -0
  372. melage/resource/theme/rc/toolbar_separator_horizontal_pressed@2x.png +0 -0
  373. melage/resource/theme/rc/toolbar_separator_vertical.png +0 -0
  374. melage/resource/theme/rc/toolbar_separator_vertical@2x.png +0 -0
  375. melage/resource/theme/rc/toolbar_separator_vertical_disabled.png +0 -0
  376. melage/resource/theme/rc/toolbar_separator_vertical_disabled@2x.png +0 -0
  377. melage/resource/theme/rc/toolbar_separator_vertical_focus.png +0 -0
  378. melage/resource/theme/rc/toolbar_separator_vertical_focus@2x.png +0 -0
  379. melage/resource/theme/rc/toolbar_separator_vertical_pressed.png +0 -0
  380. melage/resource/theme/rc/toolbar_separator_vertical_pressed@2x.png +0 -0
  381. melage/resource/theme/rc/transparent.png +0 -0
  382. melage/resource/theme/rc/transparent@2x.png +0 -0
  383. melage/resource/theme/rc/transparent_disabled.png +0 -0
  384. melage/resource/theme/rc/transparent_disabled@2x.png +0 -0
  385. melage/resource/theme/rc/transparent_focus.png +0 -0
  386. melage/resource/theme/rc/transparent_focus@2x.png +0 -0
  387. melage/resource/theme/rc/transparent_pressed.png +0 -0
  388. melage/resource/theme/rc/transparent_pressed@2x.png +0 -0
  389. melage/resource/theme/rc/window_close.png +0 -0
  390. melage/resource/theme/rc/window_close@2x.png +0 -0
  391. melage/resource/theme/rc/window_close_disabled.png +0 -0
  392. melage/resource/theme/rc/window_close_disabled@2x.png +0 -0
  393. melage/resource/theme/rc/window_close_focus.png +0 -0
  394. melage/resource/theme/rc/window_close_focus@2x.png +0 -0
  395. melage/resource/theme/rc/window_close_pressed.png +0 -0
  396. melage/resource/theme/rc/window_close_pressed@2x.png +0 -0
  397. melage/resource/theme/rc/window_grip.png +0 -0
  398. melage/resource/theme/rc/window_grip@2x.png +0 -0
  399. melage/resource/theme/rc/window_grip_disabled.png +0 -0
  400. melage/resource/theme/rc/window_grip_disabled@2x.png +0 -0
  401. melage/resource/theme/rc/window_grip_focus.png +0 -0
  402. melage/resource/theme/rc/window_grip_focus@2x.png +0 -0
  403. melage/resource/theme/rc/window_grip_pressed.png +0 -0
  404. melage/resource/theme/rc/window_grip_pressed@2x.png +0 -0
  405. melage/resource/theme/rc/window_minimize.png +0 -0
  406. melage/resource/theme/rc/window_minimize@2x.png +0 -0
  407. melage/resource/theme/rc/window_minimize_disabled.png +0 -0
  408. melage/resource/theme/rc/window_minimize_disabled@2x.png +0 -0
  409. melage/resource/theme/rc/window_minimize_focus.png +0 -0
  410. melage/resource/theme/rc/window_minimize_focus@2x.png +0 -0
  411. melage/resource/theme/rc/window_minimize_pressed.png +0 -0
  412. melage/resource/theme/rc/window_minimize_pressed@2x.png +0 -0
  413. melage/resource/theme/rc/window_undock.png +0 -0
  414. melage/resource/theme/rc/window_undock@2x.png +0 -0
  415. melage/resource/theme/rc/window_undock_disabled.png +0 -0
  416. melage/resource/theme/rc/window_undock_disabled@2x.png +0 -0
  417. melage/resource/theme/rc/window_undock_focus.png +0 -0
  418. melage/resource/theme/rc/window_undock_focus@2x.png +0 -0
  419. melage/resource/theme/rc/window_undock_pressed.png +0 -0
  420. melage/resource/theme/rc/window_undock_pressed@2x.png +0 -0
  421. melage/resource/theme/style.qss +2223 -0
  422. melage/resource/tract.png +0 -0
  423. melage/resource/view1.png +0 -0
  424. melage/resource/view1_eco.png +0 -0
  425. melage/resource/view1_mri.png +0 -0
  426. melage/resource/view1_seg.png +0 -0
  427. melage/resource/view2.png +0 -0
  428. melage/resource/view2_seg.png +0 -0
  429. melage/resource/w.png +0 -0
  430. melage/resource/zoom_in.png +0 -0
  431. melage/resource/zoom_inFaded.png +0 -0
  432. melage/resource/zoom_out.png +0 -0
  433. melage/resource/zoom_outFaded.png +0 -0
  434. melage/some_notes.txt +3 -0
  435. melage/utils/DispalyIm.py +2788 -0
  436. melage/utils/GMM.py +720 -0
  437. melage/utils/Shaders_120.py +257 -0
  438. melage/utils/Shaders_330.py +314 -0
  439. melage/utils/Shaders_bu.py +314 -0
  440. melage/utils/__init__0.py +7 -0
  441. melage/utils/brain_extraction_helper.py +234 -0
  442. melage/utils/custom_QScrollBar.py +61 -0
  443. melage/utils/glScientific.py +1554 -0
  444. melage/utils/glScientific_bc.py +1585 -0
  445. melage/utils/readData.py +1061 -0
  446. melage/utils/registration.py +512 -0
  447. melage/utils/source_folder.py +18 -0
  448. melage/utils/utils.py +3808 -0
  449. melage/version.txt +1 -0
  450. melage/widgets/ApplyMask.py +212 -0
  451. melage/widgets/ChangeSystem.py +152 -0
  452. melage/widgets/DeepLModels/InfantSegment/Unet.py +464 -0
  453. melage/widgets/DeepLModels/NPP/dataset/mri_dataset_affine.py +149 -0
  454. melage/widgets/DeepLModels/NPP/models/checkpoints/npp_v1.pth.py +0 -0
  455. melage/widgets/DeepLModels/NPP/models/losses.py +146 -0
  456. melage/widgets/DeepLModels/NPP/models/model.py +272 -0
  457. melage/widgets/DeepLModels/NPP/models/utils.py +303 -0
  458. melage/widgets/DeepLModels/NPP/npp.py +116 -0
  459. melage/widgets/DeepLModels/NPP/requirements.txt +8 -0
  460. melage/widgets/DeepLModels/NPP/train/train.py +116 -0
  461. melage/widgets/DeepLModels/Unet3DAtt.py +657 -0
  462. melage/widgets/DeepLModels/Unet3D_basic.py +648 -0
  463. melage/widgets/DeepLModels/new_unet.py +652 -0
  464. melage/widgets/DeepLModels/new_unet_old.py +639 -0
  465. melage/widgets/DeepLModels/new_unet_old2.py +658 -0
  466. melage/widgets/HistImage.py +153 -0
  467. melage/widgets/ImageThresholding.py +222 -0
  468. melage/widgets/MaskOperations.py +147 -0
  469. melage/widgets/N4Dialog.py +241 -0
  470. melage/widgets/Segmentation/FCM.py +1553 -0
  471. melage/widgets/Segmentation/__init__.py +588 -0
  472. melage/widgets/Segmentation/utils.py +417 -0
  473. melage/widgets/SemiAutoSeg.py +666 -0
  474. melage/widgets/Synthstrip.py +141 -0
  475. melage/widgets/__init__0.py +5 -0
  476. melage/widgets/about.py +246 -0
  477. melage/widgets/activation.py +437 -0
  478. melage/widgets/activator.py +147 -0
  479. melage/widgets/be_dl.py +409 -0
  480. melage/widgets/be_dl_unet3d.py +441 -0
  481. melage/widgets/brain_extraction.py +855 -0
  482. melage/widgets/brain_extraction_dl.py +887 -0
  483. melage/widgets/brain_extraction_dl_bu.py +869 -0
  484. melage/widgets/colorwidget.py +100 -0
  485. melage/widgets/dockWidgets.py +2005 -0
  486. melage/widgets/enhanceImWidget.py +109 -0
  487. melage/widgets/fileDialog_widget.py +275 -0
  488. melage/widgets/iminfo.py +346 -0
  489. melage/widgets/mainwindow_widget.py +6775 -0
  490. melage/widgets/melageAbout.py +123 -0
  491. melage/widgets/openglWidgets.py +556 -0
  492. melage/widgets/registrationWidget.py +342 -0
  493. melage/widgets/repeat_widget.py +74 -0
  494. melage/widgets/screenshot_widget.py +138 -0
  495. melage/widgets/settings_widget.py +77 -0
  496. melage/widgets/tranformationWidget.py +275 -0
  497. melage-0.0.65.dist-info/METADATA +742 -0
  498. melage-0.0.65.dist-info/RECORD +501 -0
  499. melage-0.0.65.dist-info/WHEEL +5 -0
  500. melage-0.0.65.dist-info/entry_points.txt +2 -0
  501. melage-0.0.65.dist-info/top_level.txt +1 -0
@@ -0,0 +1,1061 @@
1
+
2
+ __AUTHOR__ = 'Bahram Jafrasteh'
3
+
4
+ import sys
5
+ sys.path.append('..')
6
+ from melage.utils.utils import Item, Item_equal, normalize_mri, convert_to_ras, make_affine, fast_split_min_dim, get_size_minDim, guess_num_image_index
7
+ import SimpleITK as sitk
8
+ from datetime import datetime
9
+ import numpy as np
10
+ import nibabel as nib
11
+ import re
12
+ import os
13
+
14
+ class readData():
15
+ """
16
+ This is the main file to read images
17
+ """
18
+ def __init__(self, only_metadata = False, type='t1', target_system='IPL'):#target_system='IPL'):
19
+ """
20
+ :param only_metadata: if only metadat needs to be read
21
+ :param type: data tyoe
22
+ :param target_system: target system to show
23
+ """
24
+ self.metadata_dict = dict() #metada dictionary
25
+ self.phi_angles = np.zeros(shape=(0,0)) # phi angle related to vol files in GE
26
+ self.theta_angles = np.zeros(shape=(0,0)) # phi angle related to vol files in GE
27
+ self.only_metadata = only_metadata
28
+ self.success = False
29
+ self.tract = None# if tractography file is available
30
+ self.s2c = False # sagittal to coronal
31
+ self.rotationMat = np.eye(4) # roation matrix
32
+ self.metadata = {}
33
+ self.npEdge = []
34
+ self._npSeg = None
35
+ self.type = type
36
+ #if type=='t1':
37
+ # self.target_system = target_system#'IPL'
38
+ #elif type == 'eco':
39
+ self.target_system = target_system#'PLI'#'SPR'#'ARI'
40
+
41
+
42
+
43
+ def grid_date_gen(self, arr, dim_axial, dim_sagital, dim_coronal, bModeRadius):
44
+ """
45
+ This function related to reading GE ultrasound data (VOL not compressed)
46
+ :param arr:
47
+ :param dim_axial:
48
+ :param dim_sagital:
49
+ :param dim_coronal:
50
+ :param bModeRadius:
51
+ :return:
52
+ """
53
+ x_r = 0
54
+ rs = np.array(
55
+ [(self.metadata_dict['Offset_Spacing'] + i) * self.metadata_dict['Resolution'] for i in range(dim_coronal)])
56
+ for k in range(dim_axial):
57
+ thetas = np.repeat(self.theta_angles[k] - np.pi / 2.0, dim_coronal)
58
+ for j in range(dim_sagital):
59
+ phis = np.repeat(self.phi_angles[j] - np.pi / 2.0, dim_coronal)
60
+ arr[x_r*dim_coronal:(x_r+1)*dim_coronal, 0] = rs * np.sin(phis) # coronal
61
+ arr[x_r*dim_coronal:(x_r+1)*dim_coronal, 1] = -(rs * np.cos(phis) - bModeRadius) * np.sin(thetas) # sagital
62
+ arr[x_r*dim_coronal:(x_r+1)*dim_coronal, 2] = bModeRadius * (1 - np.cos(thetas)) + rs * np.cos(phis) * np.cos(thetas) # axial
63
+ #arr[:,j,k, 0] = rs * np.sin(phis) # coronal
64
+ #arr[:,j,k, 1] = -(rs * np.cos(phis) - bModeRadius) * np.sin(thetas) # sagital
65
+ #arr[:,j,k, 2] = bModeRadius * (1 - np.cos(thetas)) + rs * np.cos(phis) * np.cos(thetas) # axial
66
+ x_r += 1
67
+ return arr
68
+ def read_cartesian(self, f, data_size):
69
+ " This function related to reading GE ultrasound data (VOL not compressed)"
70
+ raise ValueError('No Implemented yet')
71
+
72
+
73
+
74
+ def manuallySetIms(self, type):
75
+ """
76
+ Manually set image
77
+ :param type:
78
+ :return:
79
+ """
80
+ if hasattr(self, 'header'):
81
+ hdr = self.header
82
+ else:
83
+ hdr = nib.Nifti1Header()
84
+ hdr['dim'] = np.array([3, self.npImage.shape[2], self.npImage.shape[1], self.npImage.shape[0], 1, 1, 1, 1])
85
+
86
+ if hasattr(self, 'affine'):
87
+ if self.s2c and hasattr(self, '_imChanged_affine'):
88
+ affine = self._imChanged_affine
89
+ else:
90
+ affine = self.affine
91
+ else:
92
+ affine = np.eye(4)
93
+ affine[:-1, -1] = np.array(self.ImOrigin)
94
+ np.fill_diagonal(affine[:-1, :-1], self.ImSpacing)
95
+
96
+ data = self.npImage
97
+ self._imChanged = nib.Nifti1Image(data, affine, hdr)
98
+ self._imChanged.header.set_zooms(np.array(self.ImSpacing))
99
+ transform, self.source_system = convert_to_ras(self._imChanged.affine, self.target_system)
100
+ self._imChanged = self._imChanged.as_reoriented(transform)
101
+ self.im = self._imChanged.__class__(self._imChanged.dataobj[:], self._imChanged.affine, self._imChanged.header)
102
+ if hasattr(self, 'npImages'):
103
+ self.ims = nib.Nifti1Image(self.npImages, affine, hdr)
104
+ self.ims = self.ims.as_reoriented(transform)
105
+
106
+
107
+ def read_non_cartesian(self, f, data_size):
108
+ " This function related to reading GE ultrasound data (VOL not compressed)"
109
+ from vtk.util import numpy_support
110
+ import vtk
111
+
112
+ total_voxels = self.metadata_dict['Coronal_Dimension']*self.metadata_dict['Sagittal_Dimension']*self.metadata_dict['Axial_Dimension']
113
+ #data_points_arr = np.zeros(shape=(self.metadata_dict['Coronal_Dimension'], self.metadata_dict['Sagittal_Dimension'], self.metadata_dict['Axial_Dimension'],3))
114
+ data_points_arr = np.zeros(shape=(total_voxels,3))
115
+ data_points = vtk.vtkPoints()
116
+ StructuredGrid = vtk.vtkStructuredGrid()
117
+ assert (len(self.phi_angles) == self.metadata_dict['Sagittal_Dimension'])
118
+ assert (len(self.theta_angles) == self.metadata_dict['Axial_Dimension'])
119
+ assert (data_size == total_voxels)
120
+ bModeRadius = -self.metadata_dict['Offset_Radius'] * self.metadata_dict['Resolution']
121
+
122
+ data_points_arr = self.grid_date_gen(data_points_arr,
123
+ self.metadata_dict['Axial_Dimension'],
124
+ self.metadata_dict['Sagittal_Dimension'],
125
+ self.metadata_dict['Coronal_Dimension'],
126
+ bModeRadius)
127
+ data_points_vtk = numpy_support.numpy_to_vtk(num_array=data_points_arr, deep=True, array_type=vtk.VTK_DOUBLE)
128
+ data_points.SetData(data_points_vtk)
129
+
130
+ StructuredGrid.SetPoints(data_points)
131
+ StructuredGrid.SetExtent(
132
+ 0, self.metadata_dict['Coronal_Dimension'] -1,
133
+ 0, self.metadata_dict['Sagittal_Dimension']-1,
134
+ 0, self.metadata_dict['Axial_Dimension']-1
135
+ )
136
+
137
+ # read bytes
138
+ byte_voxel_values = f.read(data_size)
139
+ # convert to voxel values
140
+ array_voxel_values = np.asarray([int(i) for i in byte_voxel_values])
141
+ # numpy to vtk int array
142
+ voxel_values = numpy_support.numpy_to_vtk(num_array=array_voxel_values.ravel(), deep=True, array_type=vtk.VTK_DOUBLE)
143
+ # set voxel name
144
+ voxel_values.SetName('VoxelIntensity')
145
+ # assign cell data
146
+ StructuredGrid.GetPointData().AddArray(voxel_values)
147
+ StructuredGrid.GetPointData().SetActiveAttribute('VoxelIntensity', vtk.vtkDataSetAttributes.SCALARS)
148
+ #StructuredGrid.GetPointData().SetScalars(voxel_values)
149
+
150
+ # bounds
151
+ Cartesian_Bounds = StructuredGrid.GetBounds()
152
+
153
+ outputSpacing = [0.3, 0.3, 0.3]
154
+ volumeDims = [int(np.ceil((Cartesian_Bounds[1] - Cartesian_Bounds[0]) / outputSpacing[0])),
155
+ int(np.ceil((Cartesian_Bounds[3] - Cartesian_Bounds[2]) / outputSpacing[1])),
156
+ int(np.ceil((Cartesian_Bounds[5] - Cartesian_Bounds[4]) / outputSpacing[2]))]
157
+ ImageResampler = vtk.vtkResampleToImage()
158
+ ImageResampler.SetInputDataObject(StructuredGrid)
159
+ ImageResampler.SetSamplingDimensions(volumeDims)
160
+ ImageResampler.Update()
161
+ self.VtkImage = ImageResampler.GetOutput()
162
+ if self.VtkImage.GetPointData().RemoveArray('vtkValidPointMask') is not None:
163
+ self.VtkImage.GetPointData().RemoveArray('vtkValidPointMask')
164
+
165
+
166
+
167
+ self.ImExtent = self.VtkImage.GetExtent()
168
+
169
+ self.ImSpacing = self.VtkImage.GetSpacing()
170
+
171
+ self.ImOrigin = self.VtkImage.GetOrigin()
172
+
173
+ self.ImEnd = np.zeros(shape=(3,))
174
+ self.ImCenter = np.zeros(shape=(3,))
175
+ for i in range(3):
176
+ self.ImEnd[i] = self.ImOrigin[i] + (self.ImExtent[i*2+1]-self.ImExtent[i*2])*self.ImSpacing[i]
177
+
178
+ self.ImCenter[0] = self.ImOrigin[0] + self.ImSpacing[0] * 0.5 * (self.ImExtent[0] + self.ImExtent[1])
179
+ self.ImCenter[1] = self.ImOrigin[1] + self.ImSpacing[1] * 0.5 * (self.ImExtent[2] + self.ImExtent[3])
180
+ self.ImCenter[2] = self.ImOrigin[2] + self.ImSpacing[2] * 0.5 * (self.ImExtent[4] + self.ImExtent[5])
181
+ self.metadata_dict['ImCenter'] = self.ImCenter.tolist()
182
+ self.metadata_dict['ImEnd'] = self.ImEnd.tolist()
183
+ self.metadata_dict['ImOrigin'] = self.ImOrigin
184
+ self.metadata_dict['ImSpacing'] = self.ImSpacing
185
+ self.metadata_dict['ImExtent'] = self.ImExtent
186
+
187
+ def get_metadata(self):
188
+ """
189
+ Get metadat
190
+ :return:
191
+ """
192
+ return self.metadata_dict
193
+ def get_vtkImage(self):
194
+ """ Get VTK images"""
195
+ return self.VtkImage
196
+
197
+
198
+ def changeImData(self, im, axis =[2, 1, 0]):
199
+ """
200
+ Chamge image information
201
+ :param im:
202
+ :param axis:
203
+ :return:
204
+ """
205
+ data = im.get_fdata()
206
+ self.npImage = normalize_mri(data).astype(np.uint8)
207
+
208
+
209
+
210
+ def changeData(self, type, axis =[2, 1, 0], imchange=False, state= True, npSeg=None):
211
+ """
212
+ Change image data in case of changing sagittal to coronal or vice versa
213
+ :param type:
214
+ :param axis:
215
+ :param imchange:
216
+ :param state:
217
+ :param npSeg:
218
+ :return:
219
+ """
220
+ if self.target_system=='IPL' and state:
221
+ return
222
+
223
+ transpose_axis_inv = axis
224
+ if state:
225
+ transform, _ = convert_to_ras(self.im.affine, target='SRA')
226
+ self.s2c = True
227
+ else:
228
+ transform, _ = convert_to_ras(self.im.affine, self.target_system)
229
+ self.s2c = False
230
+
231
+ im = self.im.as_reoriented(transform)
232
+ self.ImDirection = nib.aff2axcodes(im.affine)
233
+ self.ImExtent = (0, im.header['dim'][transpose_axis_inv[0]+1], 0,
234
+ im.header['dim'][transpose_axis_inv[1]+1], 0,
235
+ im.header['dim'][transpose_axis_inv[2]+1])
236
+ self.ImSpacing = im.header['pixdim'][1:4][transpose_axis_inv]
237
+ self.metadata = {key: im.header[key] for key in im.header.keys()}
238
+ self.metadata['rot_axial'] = 0
239
+ self.metadata['rot_sagittal'] = 0
240
+ self.metadata['rot_coronal'] = 0
241
+
242
+ self.ImOrigin = np.array([self.metadata['qoffset_x'].item(),
243
+ self.metadata['qoffset_y'].item(),
244
+ self.metadata['qoffset_z'].item()])[transpose_axis_inv] #qoffset_x, qoffset_y, qoffset_z
245
+ self.ImEnd = np.zeros(shape=(3,))
246
+ self.ImCenter = np.zeros(shape=(3,))
247
+ for i in range(3):
248
+ self.ImEnd[i] = self.ImOrigin[i] + (self.ImExtent[i * 2 + 1] - self.ImExtent[i * 2]) * self.ImSpacing[i]
249
+
250
+ self.ImCenter[0] = self.ImOrigin[0] + self.ImSpacing[0] * 0.5 * (self.ImExtent[0] + self.ImExtent[1])
251
+ self.ImCenter[1] = self.ImOrigin[1] + self.ImSpacing[1] * 0.5 * (self.ImExtent[2] + self.ImExtent[3])
252
+ self.ImCenter[2] = self.ImOrigin[2] + self.ImSpacing[2] * 0.5 * (self.ImExtent[4] + self.ImExtent[5])
253
+
254
+ if imchange:
255
+ self._imChanged = im
256
+ self._imChanged_affine = im.affine
257
+ self.npImage = im.get_fdata()
258
+ if npSeg is not None:
259
+ self.npSeg = npSeg.as_reoriented(transform).get_fdata()
260
+ else:
261
+ self.npSeg = np.zeros_like(self.npImage)
262
+
263
+
264
+ def updateData(self, im, rotm, type):
265
+ """
266
+ update image data
267
+ :param im:
268
+ :param rotm:
269
+ :param type:
270
+ :return:
271
+ """
272
+ if type == 't1':
273
+ data = im
274
+ elif type == 'eco':
275
+ data = im
276
+
277
+ self.npImage = normalize_mri(data).astype(np.uint8)
278
+ self.rotationMat = rotm
279
+ if type=='t1':
280
+ self.npSeg = np.zeros_like(self.npImage).astype('int')
281
+
282
+
283
+ def GetParams(self):
284
+ """
285
+ Get parameters for saving the changes
286
+ :return:
287
+ """
288
+ return ['basefile']
289
+
290
+
291
+ def readNRRD(self, file, type='eco'):
292
+ """
293
+ Read NRRD image data (This function should be checked)
294
+ :param file:
295
+ :param type:
296
+ :return:
297
+ """
298
+ import nrrd
299
+ import nibabel as nib
300
+ data, header = nrrd.read(file)
301
+ if 'space directions' in header and 'space origin' in header:
302
+ directions = np.array(header['space directions'])
303
+ origin = np.array(header['space origin'])
304
+ affine = np.eye(4)
305
+ affine[:3, :3] = directions
306
+ affine[:3, 3] = origin
307
+ else:
308
+ affine = np.eye(4) # fallback
309
+ self.im = nib.Nifti1Image(data, affine)
310
+ self._read_sub_nifti()
311
+ found_image_data = True
312
+ found_meta_data = False
313
+ file_path, file_extension = os.path.splitext(file)
314
+ self.basefile = os.path.basename(file)
315
+ if os.path.isfile(file_path + '.json'):
316
+ found_meta_data = True
317
+ if found_image_data:
318
+ self.success = True
319
+ self.set_metadata()
320
+ self.read_pars()
321
+
322
+ return [found_meta_data, found_image_data, 'Success']
323
+
324
+ def UpdateAnotherDim(self, dim_active=0): # just in case of 4 dimensional image
325
+ """
326
+ This function have been implemented to show four dimensional images suchs fmri or dwi
327
+ :param dim_active:
328
+ :return:
329
+ """
330
+ if not hasattr(self, 'ims') or dim_active<0:
331
+ return
332
+ #if self.target_system!='IPL':
333
+ if self.target_system!='RAS':
334
+ return
335
+ #from nibabel.funcs import four_to_three
336
+ min_dim, num_dims = guess_num_image_index(self.ims)
337
+ self.im = fast_split_min_dim(self.ims, min_dim, desired_index=dim_active) # select the first image
338
+ #self.im = four_to_three(self.ims)[dim_active]
339
+ if hasattr(self, 'bvals_dwi') and hasattr(self, 'bvecs_dwi'):
340
+ self._fileDicom = self._fileDicom_base + 'B_{}_Bvec_{}'.format(self.bvals_dwi[dim_active], np.round(self.bvecs_dwi[dim_active],2))+'.dcm'
341
+ spacing = self.im.header['pixdim'][1:4]
342
+ minSpacing = 1.0#np.min(spacing)
343
+ if max(abs(np.min(spacing)-spacing))/3.0> 0.01: # check if need resampling
344
+ self._resampling(spacing, minSpacing)
345
+ transform, self.source_system = convert_to_ras(self.im.affine, target=self.target_system)
346
+ self.im = self.im.as_reoriented(transform)
347
+ found_image_data = True
348
+ found_meta_data = False
349
+ if found_image_data:
350
+ self.success = True
351
+ self.set_metadata()
352
+ self.read_pars()
353
+ return [found_meta_data, found_image_data, 'Success']
354
+
355
+
356
+ def _changeCoordSystem(self, target):
357
+ """
358
+ Changing coordinate system of image
359
+ :param target:
360
+ :return:
361
+ """
362
+ if not hasattr(self, 'npSeg'):
363
+ return False
364
+ if not hasattr(self.im, 'affine'):
365
+ return False
366
+ affine_previous = self.im.affine.copy()
367
+ transform, source_system = convert_to_ras(self.im.affine, target=target)
368
+ if source_system== target:
369
+ return False
370
+ self.im = self.im.as_reoriented(transform)
371
+ self.set_metadata()
372
+ self.read_pars(reset_seg=False)
373
+ if self.npSeg.max()>0:
374
+ im_tm = nib.Nifti1Image(self.npSeg, affine_previous, dtype=np.int64)
375
+ im_tm = im_tm.as_reoriented(transform)
376
+ self.npSeg = im_tm.get_fdata()
377
+ else:
378
+ self.npSeg = np.zeros_like(self.npImage).astype('int')
379
+ if not hasattr(self, 'source_system'):
380
+ self.source_system = source_system
381
+ return True
382
+
383
+
384
+ def readDicomDirectory(self, file, type='econ'):
385
+ """
386
+ Reading a dicom directory
387
+ :param file:
388
+ :param type:
389
+ :return:
390
+ """
391
+ from pydicom.filereader import dcmread
392
+ from pydicom.filereader import read_dicomdir
393
+ dicom_dir = read_dicomdir(file)
394
+ base_dir = os.path.dirname(file)
395
+ # go through the patient record and print information
396
+ series_DESC_total = []
397
+ size_total = []
398
+ file_total = []
399
+ for series in dicom_dir.patient_records[0].children[0].children:
400
+
401
+ image_records = series.children
402
+
403
+ image_filenames = [os.path.join(base_dir, *image_rec.ReferencedFileID)
404
+ for image_rec in image_records]
405
+ file_reader = sitk.ImageFileReader()
406
+ base_dir_c = os.path.dirname(image_filenames[0])
407
+ if not os.path.isfile(image_filenames[0]):
408
+ continue
409
+
410
+ file_reader.SetFileName(image_filenames[0])
411
+ file_reader.ReadImageInformation()
412
+ try:
413
+ series_ID, r, c, series_DESC ='', 0, 0, 'Image'
414
+ for i, el in enumerate(['0020|000e', '0028|0010', '0028|0011', '0008|103e']):
415
+ if el in file_reader.GetMetaDataKeys():
416
+ read = file_reader.GetMetaData(el)
417
+ if i == 0:
418
+ series_ID = read
419
+ elif i == 1:
420
+ r = int(read)
421
+ elif i == 2:
422
+ c = int(read)
423
+ elif i == 3:
424
+ series_DESC = read
425
+
426
+ sorted_file_names = sitk.ImageSeriesReader.GetGDCMSeriesFileNames(base_dir_c, series_ID)
427
+ series_DESC_total.append(series_DESC)
428
+ size_total.append([r, c, len(sorted_file_names)])
429
+ file_total.append(sorted_file_names)
430
+
431
+ except:
432
+ continue
433
+
434
+ from melage.utils.utils import create_combo_box_new
435
+ combo = create_combo_box_new(series_DESC_total, size_total)
436
+ if combo.exec_() == combo.accept:
437
+ ind_sel = combo.selectedInd
438
+ ind_sel = combo.selectedInd
439
+ return self.readDICOM(file_total[ind_sel][0], type, ind_series=ind_sel)
440
+
441
+ def _find_equal_sizeImages(self, sorted_file_names, file_reader):
442
+ # find equal size images in the directory
443
+ dics = dict()
444
+ file_reader.LoadPrivateTagsOn()
445
+ seens = []
446
+ echotimes = dict()
447
+ seens_sizes = []
448
+ r = 0
449
+
450
+ while True:
451
+
452
+ l = sorted_file_names[r]
453
+ r += 1
454
+
455
+ file_reader.SetFileName(l)
456
+ file_reader.ReadImageInformation()
457
+
458
+ try:
459
+ #size = (int(file_reader.GetMetaData('0028|0010')),int(file_reader.GetMetaData('0028|0011')))
460
+ size = file_reader.GetSize()
461
+ #print(file_reader.GetMetaData('07a1|103e'), file_reader.GetMetaData('07a5|1060'), file_reader.GetMetaData('0020|1041'))
462
+
463
+ if size not in dics:
464
+ dics[size] = list()
465
+ echotimes[size] = []
466
+ #if len(dics[size])>45:
467
+ # print('a')
468
+
469
+ key = '07a1|103e' if '07a1|103e' in file_reader.GetMetaDataKeys() else '0020|0013'
470
+ val = file_reader.GetMetaData(key) if key in file_reader.GetMetaDataKeys() else ''
471
+ echotimes[size].append(float(val) if val != '' else 0)
472
+
473
+ dics[size].append(l)
474
+ except:
475
+ print('')
476
+ pass
477
+ if r >= len(sorted_file_names):
478
+ break
479
+
480
+ if self._dicom_image_type=='diffusion' and not any([el==1 for el in size]):
481
+ if '0008|103e' in file_reader.GetMetaDataKeys():
482
+ series_DESC = file_reader.GetMetaData('0008|103e')
483
+ self._fileDicom = series_DESC
484
+ return self._read_dwi_images(dics, echotimes)
485
+
486
+ from melage.utils.utils import show_message_box, create_combo_box_new
487
+ if len(dics.keys())>1:
488
+ #show_message_box('There are {} readable files in the directory'.format(len(nib_ims)))
489
+ series_desc_t = []
490
+ sizes = []
491
+ for key in dics.keys():
492
+ fl = dics[key][0]
493
+ file_reader.SetFileName(fl)
494
+ file_reader.ReadImageInformation()
495
+ if '0008|103e' in file_reader.GetMetaDataKeys():
496
+ series_DESC = file_reader.GetMetaData('0008|103e')
497
+ else:
498
+ series_DESC = 'Image'
499
+ series_desc_t.append(series_DESC)
500
+ sizes.append(key)
501
+ combo = create_combo_box_new(series_desc_t, sizes)
502
+ if combo.exec_()==combo.accept:
503
+ ind_sel = combo.selectedInd
504
+ ind_sel = combo.selectedInd
505
+ elif len(dics.keys())==1:
506
+ ind_sel = 0
507
+ if '0008|103e' in file_reader.GetMetaDataKeys():
508
+ series_DESC = file_reader.GetMetaData('0008|103e')
509
+ else:
510
+ series_DESC = 'Image'
511
+ series_desc_t = [series_DESC]
512
+ sizes = [size]
513
+ else:
514
+ #show_message_box('The directory does not contain dicom or is not readable')
515
+ return [False, False, 'No file']
516
+
517
+ if ind_sel is None:
518
+ show_message_box('The directory does not contain dicom or is not readable')
519
+ return [False, False, 'No file']
520
+
521
+ ind_key = sizes[ind_sel]
522
+ time_s = echotimes[ind_key]
523
+
524
+ imgs = dics[ind_key]
525
+ if len(time_s)>1:
526
+ lst = list(np.argsort(time_s))
527
+ this_set = [imgs[l] for l in lst]
528
+ else:
529
+ this_set = imgs
530
+ im = sitk.ReadImage(this_set)
531
+ affine = make_affine(im)
532
+ nib_im =nib.Nifti1Image(sitk.GetArrayFromImage(im).transpose(), affine)
533
+ self._fileDicom = series_desc_t[ind_sel]+'.dcm'
534
+ return nib_im
535
+
536
+ def _read_dwi_images(self, dics, echotimes):
537
+ """
538
+ If the file is detected as dwi read it
539
+ :param dics:
540
+ :param echotimes:
541
+ :return:
542
+ """
543
+ from melage.utils.utils import norm_dti
544
+ from pydicom.filereader import dcmread
545
+ Ln = [dics[key] for key in dics.keys()]
546
+ ech = [echotimes[key] for key in echotimes.keys()]
547
+ ind_m = np.argmin([len(a) for a in Ln])
548
+ ind_ma = np.argmax([len(a) for a in Ln])
549
+ if ind_m == ind_ma and len(Ln)>1:
550
+ ind_m = np.argmin([list(dics.keys())[1][0], list(dics.keys())[0][0]])
551
+ ind_ma = np.argmax([list(dics.keys())[1][0], list(dics.keys())[0][0]])
552
+ image_indices = Ln[ind_m]
553
+ echotimes = ech[ind_ma]
554
+ image_bvec = Ln[ind_ma]
555
+ num_images = len(image_bvec)//len(image_indices)
556
+ indices_bvec = np.arange(0, len(image_bvec), num_images)
557
+ bvals = dict()
558
+ bvecs_total = dict()
559
+ r = 0
560
+ images = []
561
+ for l in image_indices:
562
+ ds_bvec = dcmread(image_bvec[indices_bvec[r]], stop_before_pixels=True)
563
+ this_set = image_bvec[r*num_images:(r+1)*num_images]
564
+ if len(echotimes)>=len(image_bvec):
565
+ lst = list(np.argsort(echotimes[r * num_images:(r + 1) * num_images]))
566
+ this_set = [this_set[l] for l in lst]
567
+ images.append(this_set)
568
+ try:
569
+ bvec = ds_bvec[0x52009230].value[0][0x002111fe].value[0][0x00211146].value
570
+ except:
571
+ bvec = [0, 0, 0]
572
+
573
+ ds = dcmread(l, stop_before_pixels=True)
574
+ ds.decode()
575
+ bval_str = ds[0x00180024].value # (0043,1039) for GE
576
+ bval = int(float(re.findall(r'\d+', bval_str)[0])) # find all numbers
577
+ bvals[r] = bval
578
+ size = (ds[0x00280010].value, ds[0x00280011].value)
579
+
580
+ ####### Read BVAL
581
+ acqu_matrix = None
582
+ if 0x00181310 in ds:
583
+ acqu_matrix = ds[0x00181310].value # acquisition matrix
584
+ phase_encoding_dir = ds[0x00181312].value # either ROW or COLUMNs *For CANON and GE can be useful
585
+ image_position = ds[0x00200032].value # It is the location in mm from the origin of the RCS.#
586
+ pixel_resolution = ds[0x00280030].value
587
+ image_orientation_xy = ds[0x00200037].value
588
+ # [float(i) for i in re.findall(r"\d+\.\d+", file_reader.GetMetaData('0020|0037'))]
589
+ read_v = norm_dti(image_orientation_xy[:3])
590
+ phase_v = norm_dti(image_orientation_xy[3:])
591
+ slice_v = norm_dti(np.cross(read_v, phase_v))
592
+ PatientPosition = ds[0x00185100].value # HFS # if not HFS warning
593
+ bvec_new = norm_dti([np.dot(read_v, bvec), np.dot(phase_v, bvec), np.dot(slice_v, bvec)])
594
+ if bvec_new[1]!=0:
595
+ bvec_new[1] = -bvec_new[1]
596
+ bvecs_total[r] = bvec_new
597
+ r += 1
598
+
599
+ num_image = len(dics.keys())
600
+ ast = []
601
+
602
+ if len(Ln)==1:
603
+ print('Guessing mosaic...')
604
+ for img in images:
605
+ ig = sitk.ReadImage(img)
606
+ a = sitk.GetArrayFromImage(ig).transpose()
607
+ if len(Ln) == 1 and acqu_matrix is not None:
608
+ acqu_matrix = [el for el in acqu_matrix if el!=0]
609
+ h = a.shape[0] // acqu_matrix[0]
610
+ w = a.shape[1] // acqu_matrix[-1]
611
+ nh = a.shape[0] // h
612
+ nw = a.shape[1] // w
613
+ if h * w * nh * nw <= a.shape[0] * a.shape[1] and (w>1 or h>1):
614
+ b = np.zeros((nh, nw, h * w))
615
+ r = 0
616
+ for i in range(h):
617
+ st = i * nw
618
+ ft = (i + 1) * nw
619
+ for j in range(w):
620
+ b[..., r] = a[j * nh:(j + 1) * nh, st:ft].squeeze()
621
+ r += 1
622
+ a = b
623
+ if a.ndim==3:
624
+ if a.shape[-1]!=1:
625
+ a = a[...,None]
626
+ ast.append(a)
627
+
628
+ affine = make_affine(ig)
629
+ ast = np.block(ast)
630
+ nib_im = nib.Nifti1Image(ast, affine)
631
+ self.bvals_dwi = [bvals[key] for key in bvals.keys()]
632
+ self.bvecs_dwi = np.array([bvecs_total[key] for key in bvecs_total.keys()])
633
+ return nib_im
634
+
635
+ def _resampling(self, spacing, minSpacing):
636
+ """
637
+ Resample image to desired spacing
638
+ :param spacing:
639
+ :param minSpacing:
640
+ :return:
641
+ """
642
+ from melage.utils.utils import resize_window
643
+ window = resize_window()
644
+ window.label_current_spc.setText('{:.3f},{:.3f},{:.3f}'.format(spacing[0], spacing[1], spacing[2]))
645
+ window.label_new_spc.setValue(minSpacing)
646
+ window.exec_()
647
+ if window._status:
648
+ newSpacing = window.label_new_spc.value()
649
+ method='spline'
650
+ if window.radioButton_1.isChecked():
651
+ method = 'linear'
652
+ from melage.utils.utils import resample_to_spacing
653
+ self.im = resample_to_spacing(self.im, newSpacing, method)
654
+ #print('resampling')
655
+
656
+ def readDICOM(self, file, type='eco', ind_series=0):
657
+ """
658
+ Read DICOM image
659
+ :param file:
660
+ :param type:
661
+ :return:
662
+ """
663
+ from pydicom.filereader import dcmread
664
+
665
+ if file.split('/')[-1].lower()=='dicomdir':
666
+ return self.readDicomDirectory(file, type)
667
+ file_reader = sitk.ImageFileReader()
668
+ reader = sitk.ImageSeriesReader()
669
+ folder_in = os.path.dirname(file)
670
+ series_IDs = reader.GetGDCMSeriesIDs(folder_in)
671
+ if len(series_IDs)-1<ind_series:
672
+ ind_series = len(series_IDs)-1
673
+ series_file_names = reader.GetGDCMSeriesFileNames(folder_in, series_IDs[ind_series])
674
+ file_reader.SetFileName(series_file_names[0])
675
+ file_reader.ReadImageInformation()
676
+ file_reader.LoadPrivateTagsOn()
677
+ self._Manufacturer = ''
678
+ if '0008|0070' in file_reader.GetMetaDataKeys():
679
+ self._Manufacturer = file_reader.GetMetaData('0008|0070')
680
+ self._dicom_image_type = ''
681
+ if '0008|0008' in file_reader.GetMetaDataKeys():
682
+ tag_imt = file_reader.GetMetaData('0008|0008').split("\\")
683
+ if len(tag_imt)>=3:
684
+ self._dicom_image_type = tag_imt[2].lower()
685
+
686
+ try:
687
+ series_ID = file_reader.GetMetaData('0020|000e')
688
+ try:
689
+ series_DESC = file_reader.GetMetaData('0008|103e')
690
+ except:
691
+ series_DESC = 'Image'
692
+ sorted_file_names = sitk.ImageSeriesReader.GetGDCMSeriesFileNames(folder_in, series_ID)
693
+ except:
694
+ single_file_mode = True
695
+ sorted_file_names = [file]
696
+
697
+ a = dcmread(file)
698
+ self.im_metadata = [[a[key].name, a[key].value] for key in a.keys()
699
+ if a[key].name not in ['Pixel Data', 'Overlay Data']]
700
+ del a
701
+ self.ims = self._find_equal_sizeImages(sorted_file_names, file_reader)
702
+
703
+ if self.ims.ndim==4:
704
+ #from nibabel.funcs import four_to_three
705
+ #nib_images = four_to_three(self.ims)
706
+ min_dim, self._num_dims = guess_num_image_index(self.ims)
707
+ self.im = fast_split_min_dim(self.ims, min_dim, desired_index=0)
708
+ if type=='eco' and self._num_dims>1:
709
+ index_used = [r for r, l in enumerate(self.ims.shape) if l == 3 or l == 1]
710
+ affine = self.ims.affine
711
+ header = self.ims.header
712
+ image = self.ims.get_fdata()
713
+ image = np.swapaxes(image, index_used[0], -1)
714
+ image = image.mean(-1)
715
+ self.ims = nib.Nifti1Image(image, affine, header=header)
716
+ nib_images = [self.ims]
717
+ self.im = self.ims
718
+ else:
719
+ #self.im = nib_images[0] # select the first image
720
+ if hasattr(self, 'bvals_dwi') and hasattr(self, 'bvecs_dwi'):
721
+ self._fileDicom_base = self._fileDicom
722
+ self._fileDicom = self._fileDicom_base+'B_{}_Bvec_{}'.format(self.bvals_dwi[0], np.round(self.bvecs_dwi[0],2))+'.dcm'
723
+ if self._num_dims>1:
724
+ transform, _ = convert_to_ras(self.ims.affine, target=self.target_system)
725
+ self.npImages = self.ims.as_reoriented(transform).get_fdata()
726
+ else:
727
+ delattr(self, 'ims')
728
+ else:
729
+ self.im = self.ims
730
+ delattr(self, 'ims')
731
+
732
+ self.im_metadata = {key: self.im.header[key] for key in self.im.header.keys()}
733
+ self.im_metadata['Affine'] = self.im.affine
734
+ self._read_sub_nifti()
735
+
736
+ found_image_data = True
737
+ found_meta_data = False
738
+ file_path, file_extension = os.path.splitext(file)
739
+ self.basefile = os.path.basename(file)
740
+ if os.path.isfile(file_path + '.json'):
741
+ found_meta_data = True
742
+ if found_image_data:
743
+ self.success = True
744
+ self.set_metadata()
745
+ self.read_pars()
746
+
747
+ return [found_meta_data, found_image_data, 'Success']
748
+
749
+ def set_metadata(self):
750
+ """
751
+ Set meta data for the file being read
752
+ :return:
753
+ """
754
+ self.metadata = {key: self.im.header[key] for key in self.im.header.keys()}
755
+ self.metadata['rot_axial'] = 0
756
+ self.metadata['rot_sagittal'] = 0
757
+ self.metadata['rot_coronal'] = 0
758
+
759
+
760
+ def _read_sub_nifti(self):
761
+ spacing = self.im.header['pixdim'][1:4]
762
+ minSpacing = 1.0#np.min(spacing)
763
+ self.set_metadata()
764
+
765
+ if max(abs(np.min(spacing)-spacing))/3.0> 0.01: # check if need resampling
766
+ self._resampling(spacing, minSpacing)
767
+
768
+ transform, self.source_system = convert_to_ras(self.im.affine, target=self.target_system)
769
+ self.header = self.im.header
770
+ self.im = self.im.as_reoriented(transform)
771
+ self.im_metadata = {key: self.im.header[key] for key in self.im.header.keys()}
772
+ self.im_metadata['Affine'] = self.im.affine
773
+
774
+
775
+ def readNIFTI(self, file, type = 'eco'):
776
+ """
777
+ Read file with nifti format
778
+ :param file:
779
+ :param type:
780
+ :return:
781
+ """
782
+ ims = nib.load(file) # read image
783
+
784
+ dtype = ims.get_data_dtype()
785
+ if len(dtype)>0:
786
+ print('structured array :{}'.format(dtype))
787
+ imsg = ims.get_fdata()
788
+ imsg = imsg.view((imsg.dtype[0], len(imsg.dtype.names)))
789
+ ims = nib.Nifti1Image(imsg, ims.affine, ims.header)
790
+
791
+ self.ims = ims
792
+
793
+ if self.ims.ndim==4:
794
+ #from nibabel.funcs import four_to_three
795
+ min_dim, self._num_dims = guess_num_image_index(self.ims)
796
+ #nib_images, num_dims = fast_split_min_dim(self.ims)
797
+ #self.im = nib_images[0] # select the first image
798
+ if self._num_dims>1:
799
+ transform, _ = convert_to_ras(self.ims.affine, target=self.target_system)
800
+ #self.npImages = self.ims.as_reoriented(transform).get_fdata()
801
+ self.im = fast_split_min_dim(self.ims, min_dim, desired_index=0) # select the first image
802
+ else:
803
+ self.im = fast_split_min_dim(self.ims, min_dim, desired_index=0) # select the first image
804
+ delattr(self, 'ims')
805
+ elif self.ims.ndim==5 or self.ims.ndim==3:
806
+ self.im = self.ims
807
+ delattr(self, 'ims')
808
+ else:
809
+ return
810
+ if file.split('.')[-1] != 'gz' and file.split('.')[-1] != 'nii' :#'delta' in self.im.header: # TODO: newly update from August 21, 2024
811
+ self.im = nib.Nifti1Image(self.im.get_fdata(), self.im.affine)
812
+ #self.im_metadata = [[key, self.im.header[key]] for key in self.im.header.keys()]
813
+ #self.im_metadata.append(['Affine', self.im.affine])
814
+ self.im_metadata = {key: self.im.header[key] for key in self.im.header.keys()}
815
+ self.im_metadata['Affine'] = self.im.affine
816
+
817
+ self._read_sub_nifti()
818
+ found_image_data = True
819
+ found_meta_data = False
820
+ file_path, file_extension = os.path.splitext(file)
821
+ self.basefile = os.path.basename(file)
822
+ if os.path.isfile(file_path + '.json'):
823
+ found_meta_data = True
824
+ if found_image_data:
825
+ self.success = True
826
+ self.read_pars()
827
+ return [found_meta_data, found_image_data, 'Success']
828
+
829
+ def read_pars(self, reset_seg=True, adjust_for_show=True):
830
+ """
831
+
832
+ :param reset_seg: if True segmentation is removed
833
+ :return:
834
+ """
835
+ # assing image parameters
836
+ self._imChanged = self.im.__class__(self.im.dataobj[:], self.im.affine, self.im.header)
837
+
838
+ #self.affine, shape = get_affine_shape(self.im)
839
+ self.affine = self.im.affine
840
+ #self.header = self.im.header
841
+
842
+ data = self.im.get_fdata()
843
+ if adjust_for_show:
844
+ data = data.transpose(2, 1, 0)[::-1, ::-1, ::-1]
845
+
846
+ if data.ndim == 5 and data.shape[-1]==1:
847
+ data = data.squeeze()
848
+ if data.ndim == 4:
849
+ is_rgb = np.where([el == 3 for el in data.shape])[0]
850
+ if len(is_rgb)>0:
851
+ dim_act = is_rgb[0]
852
+ data = np.mean(data,dim_act)
853
+
854
+ self.npImage = normalize_mri(data).astype(np.uint8)
855
+ if reset_seg:
856
+ self.npSeg = np.zeros_like(self.npImage).astype('int')
857
+ #self.npEdge = np.empty((0,3))
858
+
859
+ self.ImDirection = nib.aff2axcodes(self.im.affine)
860
+ #transpose_axis_inv = [2,1,0]#self.transpose_axis[::-1]
861
+ transpose_axis_inv = [0,1,2]
862
+ self.ImExtent = (0, self.im.header['dim'][transpose_axis_inv[0]+1], 0,
863
+ self.im.header['dim'][transpose_axis_inv[1]+1], 0,
864
+ self.im.header['dim'][transpose_axis_inv[2]+1])
865
+
866
+ self.ImSpacing = self.im.header['pixdim'][1:4][transpose_axis_inv]
867
+ self.ImOrigin = np.array([self.metadata['qoffset_x'].item(),
868
+ self.metadata['qoffset_y'].item(),
869
+ self.metadata['qoffset_z'].item()])[transpose_axis_inv] #qoffset_x, qoffset_y, qoffset_z
870
+ self.ImEnd = np.zeros(shape=(3,))
871
+ self.ImCenter = np.zeros(shape=(3,))
872
+ for i in range(3):
873
+ self.ImEnd[i] = self.ImOrigin[i] + (self.ImExtent[i * 2 + 1] - self.ImExtent[i * 2]) * self.ImSpacing[i]
874
+
875
+ self.ImCenter[0] = self.ImOrigin[0] + self.ImSpacing[0] * 0.5 * (self.ImExtent[0] + self.ImExtent[1])
876
+ self.ImCenter[1] = self.ImOrigin[1] + self.ImSpacing[1] * 0.5 * (self.ImExtent[2] + self.ImExtent[3])
877
+ self.ImCenter[2] = self.ImOrigin[2] + self.ImSpacing[2] * 0.5 * (self.ImExtent[4] + self.ImExtent[5])
878
+
879
+
880
+
881
+ def readKretz(self, file):
882
+ """
883
+ Read Kretz GE healthcare
884
+ :param file:
885
+ :return:
886
+ """
887
+ import struct
888
+
889
+ kretz_identifier = b"KRETZFILE 1.0 "
890
+ found_image_data = False
891
+ found_meta_data = False
892
+ if file == '':
893
+ return [found_meta_data, found_image_data, "No file"]
894
+ with open(file, 'rb') as f:
895
+ byte = f.read(16)
896
+ if byte != kretz_identifier:
897
+ return [found_meta_data, found_image_data, "Not a kretz file"]
898
+ while byte:
899
+ Item.tagcl = f.read(2)
900
+ if not Item.tagcl:
901
+ break
902
+ # label_names = ["Patient Name", "Patient ID", "Height","Width","Channels","Resoloution",
903
+ # "Time", "Hospital","Device","TIB","Technology","MI","TIS","Ultrasound Machine"]
904
+ Item.tagel = f.read(2)
905
+ Item.size = f.read(4)
906
+ data_size = struct.unpack('I', Item.size)[0] # get data size
907
+ if Item_equal(Item, (0xC000, 0x0001)): # read coronal dimension
908
+ found_meta_data = True
909
+ dim_coronal = struct.unpack('H', f.read(data_size))[0]
910
+ self.metadata_dict['Coronal_Dimension'] = dim_coronal
911
+
912
+ elif Item_equal(Item, (0xC000, 0x0002)):# read sagital dimension
913
+ found_meta_data = True
914
+ dim_sagital = struct.unpack('H', f.read(data_size))[0]
915
+ self.metadata_dict['Sagittal_Dimension'] = dim_sagital
916
+ elif Item_equal(Item, (0xC000, 0x0003)):# read axial dimension
917
+ found_meta_data = True
918
+ dim_axial = struct.unpack('H', f.read(data_size))[0]
919
+ self.metadata_dict['Axial_Dimension'] = dim_axial
920
+ elif Item_equal(Item, (0xC100, 0x0001)):# read resolution
921
+ found_meta_data = True
922
+ resolution = struct.unpack('d', f.read(data_size))[0]
923
+ self.metadata_dict['Resolution'] = resolution*1000
924
+ elif Item_equal(Item, (0xC300, 0x0002)): # read phi angles
925
+ assert (int(data_size / 8) == dim_sagital)
926
+ data_in = f.read(data_size)
927
+ if data_size%8 != 0:
928
+ return [found_meta_data, found_image_data, "Phi angles are not readable"]
929
+ self.phi_angles = np.resize(self.phi_angles, (dim_sagital,))
930
+ for i in range(dim_sagital):
931
+ self.phi_angles[i] = struct.unpack('d', data_in[i * 8:(i + 1) * 8])[0]
932
+ elif Item_equal(Item, (0xC200, 0x0001)): # offset spacing
933
+ found_meta_data = True
934
+ offset_spacing = struct.unpack('d', f.read(data_size))[0]
935
+ self.metadata_dict['Offset_Spacing'] = offset_spacing
936
+ elif Item_equal(Item, (0xC200, 0x0002)):# offset radius
937
+ found_meta_data = True
938
+ offset_radius = struct.unpack('d', f.read(data_size))[0]
939
+ self.metadata_dict['Offset_Radius'] = offset_radius
940
+ elif Item_equal(Item, (0xC300, 0x0001)): # theta angles should be 215
941
+ assert (int(data_size/8)==dim_axial)
942
+ data_in = f.read(data_size)
943
+ if data_size%8 != 0:
944
+ return [found_meta_data, found_image_data, "Theta angles are not readable"]
945
+ self.theta_angles = np.resize(self.theta_angles, (dim_axial,))
946
+ for i in range(dim_axial):
947
+ self.theta_angles[i] = struct.unpack('d', data_in[i * 8:(i + 1) * 8])[0]
948
+ elif Item_equal(Item, (0x0010, 0x0022)): # cartesian spacing
949
+ found_meta_data = True
950
+ CartesianSpacing = struct.unpack('d', f.read(data_size))[0]
951
+ self.metadata_dict['Cartesian_Spacing'] = CartesianSpacing
952
+ elif Item_equal(Item, (0x0110, 0x0001)): # patient id
953
+ found_meta_data = True
954
+ P_ID = f.read(data_size).decode('iso-8859-1').replace('\x00', '')
955
+ self.metadata_dict['Patient_ID'] = P_ID
956
+ elif Item_equal(Item,(0x0110, 0x0002)): # patient name
957
+ found_meta_data = True
958
+ P_name = f.read(data_size).decode('iso-8859-1').replace('\x00', '')
959
+ self.metadata_dict['Patient_Name'] = P_name
960
+ elif Item_equal(Item,(0x0140, 0x0003)): # study date
961
+ found_meta_data = True
962
+ study_date = f.read(data_size).decode('iso-8859-1').replace('\x00', '')
963
+ study_date = datetime.strptime(study_date, '%Y%m%d').strftime('%d/%b/%Y')
964
+ self.metadata_dict['Study_Date'] = study_date
965
+ elif Item_equal(Item,(0x0140, 0x0004)): # study time
966
+ found_meta_data = True
967
+ study_time = f.read(data_size).decode('iso-8859-1').replace('\x00', '')
968
+ study_time = datetime.strptime(study_time, '%H%M%S').strftime('%I:%M%p')
969
+ self.metadata_dict['Study_Time'] = study_time
970
+ elif Item_equal(Item,(0x0110, 0x0003)): # birth date
971
+ found_meta_data = True
972
+ birth_date = f.read(data_size).decode('iso-8859-1').replace('\x00', '')
973
+ birth_date = datetime.strptime(birth_date, '%Y%m%d').strftime('%d/%b/%Y')
974
+ self.metadata_dict['Birth_Date'] = birth_date
975
+ elif Item_equal(Item,(0x0120, 0x0001)): # Hospital name
976
+ found_meta_data = True
977
+ hospital_name = f.read(data_size).decode('iso-8859-1').replace('\x00', '')
978
+ self.metadata_dict['Hospital_Name'] = hospital_name
979
+ elif Item_equal(Item, (0x0130, 0x0001)): # device
980
+ found_meta_data = True
981
+ device_name = f.read(data_size).decode('iso-8859-1').replace('\x00', '')
982
+ self.metadata_dict['Ultrasound_Device'] = device_name
983
+ elif Item_equal(Item, (0x0140, 0x0002)): # tech
984
+ found_meta_data = True
985
+ tech_name = f.read(data_size).decode('iso-8859-1').replace('\x00', '')
986
+ self.metadata_dict['Technology'] = tech_name
987
+ elif Item_equal(Item, (0x0150, 0x0013)): # velocity
988
+ found_meta_data = True
989
+ velocity = f.read(data_size).decode('iso-8859-1').replace('\x00', '')
990
+ self.metadata_dict['Velocity'] = velocity
991
+ elif Item_equal(Item, (0x0150, 0x0014)): # velocity
992
+ found_meta_data = True
993
+ velocity = f.read(data_size).decode('iso-8859-1').replace('\x00', '')
994
+ self.metadata_dict['Velocity2'] = velocity
995
+ elif Item_equal(Item, (0x0150, 0x0018)): # length
996
+ found_meta_data = True
997
+ length = f.read(data_size).decode('iso-8859-1').replace('\x00', '')
998
+ self.metadata_dict['Length'] = length
999
+ elif Item_equal(Item, (0x150, 0x29)): # Ultra sound machine
1000
+ found_meta_data = True
1001
+ UltrasoundMachine = f.read(data_size).decode('iso-8859-1').replace('\x00', '').replace('\x99', '')
1002
+ self.metadata_dict['Ultrasound_Machine'] = UltrasoundMachine
1003
+ elif Item_equal(Item, (0x0150, 0x002A)): # TIs
1004
+ found_meta_data = True
1005
+ TIs = f.read(data_size).decode('iso-8859-1').replace('\x00', '')
1006
+ if len(TIs.split(' '))<2:
1007
+ self.metadata_dict['TIs'] = TIs
1008
+ else:
1009
+ self.metadata_dict['TIs'] = float(TIs.split(' ')[1])
1010
+ elif Item_equal(Item, (0x0150, 0x002B)): # MI
1011
+ found_meta_data = True
1012
+ MI = f.read(data_size).decode('iso-8859-1').replace('\x00', '')
1013
+ self.metadata_dict['MI'] = float(MI.split(' ')[1])
1014
+ elif Item_equal(Item, (0x0150, 0x0038)): # thermal index for bone
1015
+ found_meta_data = True
1016
+ TIB = f.read(data_size).decode('iso-8859-1').replace('\x00', '')
1017
+ if len(TIB.split(' '))<2:
1018
+ self.metadata_dict['TIb'] = TIB
1019
+ else:
1020
+ self.metadata_dict['TIb'] = float(TIB.split(' ')[1])
1021
+ elif Item_equal(Item, (0xD000, 0x0001)): # image data
1022
+ found_image_data = True
1023
+ if not self.only_metadata:
1024
+ if len(self.phi_angles)==0 or len(self.theta_angles)==0:
1025
+ self.read_cartesian(f, data_size)
1026
+ else:
1027
+ self.read_non_cartesian(f, data_size)
1028
+ else:
1029
+ d = f.read(data_size)
1030
+ debug = False
1031
+ if debug:
1032
+ print(Item.tagcl)
1033
+ print(Item.tagel)
1034
+ if data_size == 2:
1035
+ print(struct.unpack('H', d)[0])
1036
+ elif data_size == 1:
1037
+ print(struct.unpack('b', d)[0])
1038
+ elif data_size == 4:
1039
+ print(struct.unpack('I', d)[0])
1040
+ elif data_size%8==0:
1041
+ n = int(data_size/8)
1042
+ print([struct.unpack('d', d[i * 8:(i + 1) * 8])[0] for i in range(n)])
1043
+ else:
1044
+ print(d)
1045
+ if found_meta_data and found_image_data:
1046
+ self.success = True
1047
+ import vtk
1048
+ nifit_writer = vtk.vtkNIFTIImageWriter()
1049
+ nifit_writer.SetInputData(self.VtkImage)
1050
+ new_file = '/'.join(file.split('.')[:-1])+'.nii.gz'
1051
+ nifit_writer.SetFileName(new_file)
1052
+ nifit_writer.Write()
1053
+ return self.readNIFTI(new_file, type=type)
1054
+ #self.npEdge = np.empty((0, 3))
1055
+ return [False, False, 'Failed']
1056
+
1057
+ if __name__ == "__main__":
1058
+ import os
1059
+ cd = 'folder'
1060
+ a = readData()
1061
+ a.readNIFTI(os.path.join(cd, 'test.nii.gz'), 'mri')