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,1554 @@
1
+ # -*- coding: utf-8 -*-
2
+ __author__= 'Bahram Jafrasteh'
3
+ import numpy as np
4
+ import sys
5
+ sys.path.append('../')
6
+ from melage.graphics import GLViewWidget, GLAxisItem, GLScatterPlotItem, GLGridItem, GLVolumeItem, GLPolygonItem
7
+ from OpenGL.GL import *
8
+ from collections import defaultdict
9
+ from PyQt5.QtWidgets import QApplication, QWidget, QMenu, QAction, QSlider, QFileDialog
10
+ from PyQt5.QtGui import QVector3D, QMatrix4x4
11
+ from PyQt5.QtCore import Qt
12
+ import cv2
13
+ from scipy.ndimage import gaussian_filter
14
+
15
+ #from utils.polygontessellator import PolygonTessellator
16
+ from melage.utils.utils import ConvertPointsToPolygons, ConvertPToPolygons, fillInsidePol, Polygon, LargestCC
17
+ from PyQt5.QtCore import pyqtSignal
18
+ from functools import partial
19
+
20
+ class glScientific(GLViewWidget):
21
+ """
22
+
23
+ """
24
+ point3dpos=pyqtSignal(object, object) #qt signal
25
+ update_3dview = pyqtSignal(object, object) # qt signal
26
+ update_cmap = pyqtSignal(object, bool)
27
+
28
+ def __init__(self, colorsCombinations, parent = None, id =0, source_directory=''):
29
+ """
30
+
31
+ :param colorsCombinations: a dictionary containing color information
32
+ :param parent: parent
33
+ :param id: id of the GL
34
+ :param source_directory: source folder
35
+ """
36
+
37
+ super( glScientific, self).__init__(parent)
38
+ self.traces = dict()
39
+ #self = gl.GLViewWidget()
40
+ #self.installEventFilter()
41
+ self.id = id
42
+ self._lastZ = 1
43
+ #self._image = None
44
+ self._renderMode = 'Img'
45
+ self._threshold = 0
46
+ self._artistic = False
47
+ self.initiate_actions()
48
+ self._updatePaint = True
49
+ self._gotoLoc = False
50
+ self.colorsCombinations = colorsCombinations
51
+ self.totalPolyItems = []
52
+ self.maxXYZ = [100, 100, 100]
53
+ self._excluded_inds = np.zeros((100,100,100), bool)
54
+ self.setWindowTitle('3D view')
55
+ self._enabledPolygon = False
56
+ #self.setGeometry(0, 110, 600, 600)
57
+ self.setGeometry(0,0,1000,1000)
58
+ self.el_az_dis.connect(
59
+ lambda points : self.emit_viewport(points)
60
+ )
61
+ self._indices = None
62
+ self._rendered = 'seg'
63
+ self._numPolys = 0
64
+ self.totalpolys = defaultdict(list)
65
+ self.totalpolys_camer = defaultdict(list)
66
+
67
+ self._sPoints = []
68
+ self.intensityImg = 0.1
69
+ self.intensitySeg = 1.0
70
+ self.totalItems = defaultdict(list)
71
+ self.totalItems['axis'] = []
72
+ self.totalItems['polys'] = []
73
+ self.colorInd = 9876#len(self.colorsCombinations)
74
+ self.colorInds= [9876]
75
+ self.setContextMenuPolicy(Qt.CustomContextMenu) # enable right click
76
+
77
+ self.customContextMenuRequested.connect(self.ShowContextMenu)
78
+
79
+ self.createGridAxis(self.maxXYZ)
80
+ self.source_dir = source_directory
81
+ self.GLV = GLVolumeItem(sliceDensity=1, smooth=True, glOptions='translucent',
82
+ intensity_seg = self.intensitySeg)
83
+ self.GLSC = GLScatterPlotItem(pxMode=True, size=5)
84
+ self.GLPl = GLPolygonItem()
85
+ #self.GLV.smooth = True
86
+ self._UseScatter = False
87
+
88
+ self._verticalSlider_1 = QSlider(self)
89
+ self._verticalSlider_1.setOrientation(Qt.Vertical)
90
+ self._verticalSlider_1.setObjectName("verticalSlider_6")
91
+ self._verticalSlider_1.setRange(1, 50)
92
+ self._verticalSlider_1.setValue(1)
93
+ self._verticalSlider_1.setVisible(False)
94
+ #self.label_1 = QLabel(self)
95
+ #self.label_1.setAlignment(Qt.AlignCenter)
96
+ #self.label_1.setObjectName("label_1")
97
+ #self._verticalSlider_1.valueChanged.connect(self.label_1.setNum)
98
+ self._verticalSlider_1.valueChanged.connect(self.threshold_change)
99
+
100
+ self._seg_im = None
101
+
102
+ #self.opts['bgcolor'] = [0.5, 1, 0.0, 1]
103
+ self.opts['bgcolor'] = [0.05, 0.05, 0.05, 1]#[0.3, 0.3, 0.3, 1] # background color
104
+
105
+ def threshold_change(self, value):
106
+ """
107
+ Threshold in 3D rendering
108
+ :param value:
109
+ :return:
110
+ """
111
+ if self._rendered != 'image':
112
+ self._verticalSlider_1.setValue(1)
113
+ return
114
+ self._threshold = value
115
+ self.update_cmap_image(self._lastmap_type,reset=False)
116
+ #self.cmap_image(self._lastmap_type,reset=False)
117
+
118
+
119
+
120
+
121
+ def take_screenshot(self):
122
+ """
123
+ Take screenshot from 3D rendering
124
+ :return:
125
+ """
126
+ if self._seg_im is None:
127
+ return
128
+ filters = "png(*.png)"
129
+ opts = QFileDialog.DontUseNativeDialog
130
+ fileObj = QFileDialog.getSaveFileName(self, "Open File", self.source_dir, filters, options=opts)
131
+ if fileObj[0] == '':
132
+ return
133
+ filename = fileObj[0] + '.png'
134
+ init_width, init_height = self.width(), self.height()
135
+ maxhw = max(init_width, init_height)
136
+ width, height = init_width, init_height
137
+ while maxhw <3000:
138
+ width, height = width*1.5, height*1.5
139
+ maxhw = max(width, height)
140
+ self.setFixedWidth(int(width))
141
+ self.setFixedHeight(int(height))
142
+ maxhw = max(self.width(), self.height())
143
+ #self.setGeometry()
144
+ self.removeItem('scatter_total')
145
+ self.GLV.setData(self._seg_im, self._artistic)
146
+ self.GLV.setDepthValue(10)
147
+ self.addItem(self.GLV, 'vol_total')
148
+ self.showEvent(0)
149
+ maxhw = max(self.width(), self.height())
150
+ img = glReadPixels(0, 0, maxhw, maxhw, GL_RGB, GL_FLOAT)
151
+ img = img[::-1]
152
+ img = img[:self.height(), :self.width(), :]
153
+ from matplotlib.image import imsave
154
+
155
+ imsave(filename, img)
156
+ self.setFixedWidth(init_width)
157
+ self.setFixedHeight(init_height)
158
+
159
+ def initiate_actions(self):
160
+ """
161
+
162
+ :return:
163
+ """
164
+ self.axis_action = QAction("Axis")
165
+ self.axis_action.setCheckable(True)
166
+ self.axis_action.setChecked(False)
167
+ self.axis_action.triggered.connect(self.axis_status)
168
+
169
+
170
+ self.goto_action = QAction("GoTo")
171
+ self.goto_action.setCheckable(True)
172
+ self.goto_action.setChecked(False)
173
+ self.goto_action.triggered.connect(self.goto_status)
174
+
175
+ self.grid_action = QAction("Grid")
176
+ self.grid_action.setCheckable(True)
177
+ self.grid_action.setChecked(False)
178
+ self.grid_action.triggered.connect(self.grid_status)
179
+
180
+
181
+
182
+ self.seg_action = QAction("Show Seg.")
183
+ self.seg_action.setCheckable(True)
184
+ self.seg_action.setChecked(False)
185
+ self.seg_action.triggered.connect(self.seg_status)
186
+
187
+ self.im_seg_action = QAction("Show Img+Seg")
188
+ self.im_seg_action.setCheckable(True)
189
+ self.im_seg_action.setChecked(False)
190
+ self.im_seg_action.triggered.connect(self.im_seg_status)
191
+
192
+
193
+
194
+ self.screenshot_action = QAction("ScreenShot")
195
+ self.screenshot_action.triggered.connect(self.take_screenshot)
196
+
197
+ self.draw_action = QAction("Draw")
198
+ self.draw_action.setCheckable(True)
199
+ self.draw_action.setChecked(False)
200
+ self.draw_action.triggered.connect(self.draw_status)
201
+
202
+
203
+ #self.draw_art = QAction("Artistic")
204
+ #self.draw_art.setCheckable(True)
205
+ #self.draw_art.setChecked(False)
206
+ #self.draw_art.triggered.connect(self.draw_art_action)
207
+
208
+ self.clear_action = QAction("Show Total")
209
+ self.clear_action.triggered.connect(self.showTotal)
210
+
211
+
212
+
213
+ def showTotal(self):
214
+ """
215
+ Show all the part of image in 3D
216
+ :return:
217
+ """
218
+ self._excluded_inds[:] = False
219
+ self._artistic = False
220
+ self.update_3dview.emit(True, None)
221
+
222
+
223
+ def remove_painting(self):
224
+ """
225
+ Excluding 3D ares from demonstration
226
+ :return:
227
+ """
228
+ def filledPoly(poly):
229
+ """
230
+ Fill inside polygons
231
+ Args:
232
+ poly:
233
+
234
+ Returns:
235
+
236
+ """
237
+ from matplotlib.path import Path
238
+
239
+ try:
240
+ coords = np.array(poly.exterior.coords)
241
+
242
+ p = Path(coords)
243
+ xmin, ymin, xmax, ymax = poly.bounds
244
+ x = np.arange(np.floor(xmin), np.ceil(xmax), 1)
245
+ y = np.arange(np.floor(ymin), np.ceil(ymax), 1)
246
+ points = np.transpose([np.tile(x, len(y)), np.repeat(y, len(x))])
247
+ ind_points = p.contains_points(points)
248
+ selected_points = points[ind_points]
249
+
250
+ return selected_points
251
+ except:
252
+ return []
253
+ def adjustVals(selected):
254
+ for i in [0,1,2]:
255
+ ind = selected[:,i]>=self.maxXYZ[i]
256
+ selected[ind, i] = self.maxXYZ[i]-1
257
+ ind = selected[:,i]<=0
258
+ selected[ind, i] = 1
259
+ return selected
260
+ def findIndices(vls):
261
+ pl = Polygon(vls)
262
+ if not pl.is_valid:
263
+ pls = ConvertPToPolygons(vls)
264
+ for ij, pl in enumerate(pls):
265
+ if ij == 0:
266
+ #pl = spline_points(pl)
267
+ selected_points = filledPoly(pl)
268
+ else:
269
+ #pl = spline_points(pl)
270
+ n_points = filledPoly(pl)
271
+ selected_points = np.vstack([selected_points, n_points])
272
+ else:
273
+ #pl = spline_points(pl)
274
+ selected_points = filledPoly(pl)
275
+ return selected_points
276
+ if len(self.totalpolys[0])<5:
277
+ return
278
+ if 'vol_total' in self.items:
279
+ self.SubUpdateSegScatterItem()
280
+ else:
281
+ return
282
+ #points = self._compute_coordinates(self.mousePos)
283
+ if 'scatter_total' in self.items:
284
+
285
+ self.removeItem('scatter_total')
286
+ self.GLV.setData(self._seg_im, self._artistic)
287
+ self.GLV.setDepthValue(20)
288
+ self.addItem(self.GLV, 'vol_total')
289
+
290
+ invM = np.linalg.inv(self.mvpProj.reshape((4, 4)).transpose())
291
+ xmax, ymax, zmax = self.maxCoord
292
+ filled_polygon = np.array(self._sPoints)
293
+ filled_polygon = findIndices(filled_polygon)
294
+ filled_polygon = np.concatenate([filled_polygon, np.ones((len(filled_polygon), 2))], 1)
295
+ filled_polygon[:, 0] = 2 * filled_polygon[:,0] / self.width() - 1
296
+ filled_polygon[:, 1] = 1 - 2 * filled_polygon[:,1] / self.height()
297
+ filled_polygon[:, 3] = 1
298
+ filled_polygon[:, 2] = 2 * 1- 1
299
+
300
+
301
+
302
+ Tpoints = []
303
+ #self._z[self._z>0].min(), #self._z[self._z<1].max()
304
+ opt=1e-4
305
+ #round(self._z[self._z < 1].max() + 0.0001, 4)
306
+ for z in np.arange(0.9985- 0.0006, round(self._z[self._z < 1].max() + 0.0001, 4), 1e-6):
307
+ A = filled_polygon.copy()
308
+ A[:, 2] = 2 * z - 1
309
+
310
+ Tpoints = np.matmul(invM,
311
+ A.T).T
312
+ Tpoints /= Tpoints[:, 3, None]
313
+ # Tpoints = Tpoints.astype('int')
314
+
315
+ selected = Tpoints.astype('int')[:, :3]
316
+
317
+
318
+ selected[:, 2] = self.maxXYZ[0] - selected[:, 2]
319
+ selected[:, 0] = self.maxXYZ[2] - selected[:, 0]
320
+
321
+ ind = 0
322
+ for j, xyzm in enumerate([zmax, ymax, xmax]):
323
+ ind += ((selected[:, j] < xyzm) * (selected[:, j] >= 0))
324
+ ind = ind >= 3
325
+ selected = selected[ind, :]
326
+ selected = selected[:, [2, 1, 0]]
327
+
328
+ self._excluded_inds[selected[:, 0], selected[:, 1], selected[:, 2]] = True
329
+
330
+
331
+ #from scipy.ndimage import binary_fill_holes
332
+ #self._excluded_inds = binary_fill_holes(self._excluded_inds)
333
+ self._indices = (self._indices.astype('int')- self._excluded_inds.astype('int'))>0
334
+ self._seg_im[self._excluded_inds, :] = 0
335
+
336
+ #print('removing')
337
+ self.clear_points()
338
+ self.GLV.setData(self._seg_im, self._artistic)
339
+ self.GLV.update()
340
+ return
341
+
342
+
343
+ def clear_points(self):
344
+ """
345
+ Clear information
346
+ :return:
347
+ """
348
+ self.totalpolys = defaultdict(list)
349
+ self.totalpolys_camer = defaultdict(list)
350
+ self._numPolys = 0
351
+ self._lastZ=1
352
+ self.GLPl.update_points(self.totalpolys)
353
+ self.update()
354
+
355
+
356
+ def paintGL(self, region=None, viewport=None, useItemNames=False):
357
+ """
358
+ Paint GL
359
+ :param region:
360
+ :param viewport:
361
+ :param useItemNames:
362
+ :return:
363
+ """
364
+ super(glScientific, self).paintGL()
365
+ elev = self.opts['elevation'] #* np.pi/180.
366
+ azim = self.opts['azimuth'] #* np.pi/180.
367
+ #print(elev, azim)
368
+
369
+ def _endIMage(self, x, y, z, tol=10): # to check if we are at the end of the image
370
+ zmax, xmax, ymax = self.maxCoord
371
+ zmax, xmax, ymax = zmax+tol, ymax+tol, xmax+tol
372
+ endIm = False
373
+ if x<-tol:
374
+ endIm = True
375
+ x = -tol
376
+ elif x>xmax:
377
+ endIm = True
378
+ x = xmax
379
+ if y <-tol:
380
+ endIm = True
381
+ y = -tol
382
+ elif y > ymax:
383
+ endIm = True
384
+ y = ymax
385
+ if z <-tol:
386
+ endIm = True
387
+ z = -tol
388
+ elif z > zmax:
389
+ endIm = True
390
+ z = zmax
391
+ return endIm, x, y, z
392
+
393
+ def mouseReleaseEvent(self, a0) -> None:
394
+ """
395
+ Mouse events
396
+ :param a0:
397
+ :return:
398
+ """
399
+ if self._enabledPolygon:
400
+ if len(self._sPoints)==0:
401
+ return
402
+ self.totalpolys[self._numPolys].append(self.totalpolys[self._numPolys][0])
403
+ self._sPoints.append(self._sPoints[0])
404
+
405
+ if self.GLV._ax==0:
406
+ self.totalpolys_camer[self._numPolys] = ['sagittal', self.GLV._d]
407
+ elif self.GLV._ax == 1:
408
+ self.totalpolys_camer[self._numPolys] = ['coronal', self.GLV._d]
409
+ elif self.GLV._ax == 2:
410
+ self.totalpolys_camer[self._numPolys] = ['axial', self.GLV._d]
411
+ self._numPolys = 0
412
+ self.GLPl.update_points(self.totalpolys)
413
+
414
+ #polygonC = ConvertPointsToPolygons(self.totalpolys[self._numPolys], width=0)
415
+ #if polygonC.is_valid:
416
+ # Mpl = ConvertPToPolygons(self.totalpolys[self._numPolys])
417
+ try:
418
+ self.remove_painting()
419
+ except Exception as e:
420
+ print(e)
421
+ self._sPoints = []
422
+ self._enabledPolygon = False
423
+ self.draw_action.setChecked(False)
424
+
425
+
426
+ if 'scatter_total' in self.items:
427
+
428
+ self.removeItem('scatter_total')
429
+ self.GLV.setData(self._seg_im, self._artistic)
430
+ self.GLV.setDepthValue(20)
431
+ self.addItem(self.GLV, 'vol_total')
432
+
433
+ def _custom_viewMatrix(self, distance):
434
+ tr = QMatrix4x4()
435
+ tr.translate( 0.0, 0.0, -distance)
436
+ tr.rotate(self.opts['elevation']-90, 1, 0, 0)
437
+ tr.rotate(self.opts['azimuth']+90, 0, 0, -1)
438
+ center = self.opts['center']
439
+ tr.translate(-center.x(), -center.y(), -center.z())
440
+ return tr
441
+
442
+ def _custom_projectionMatrix(self, dist):
443
+
444
+ dpr = self.devicePixelRatio()
445
+ region = (0, 0, self.width() * dpr, self.height() * dpr)
446
+
447
+ x0, y0, w, h = self.getViewport()
448
+
449
+ nearClip = dist * 0.001
450
+ farClip = dist * 1000.
451
+
452
+ r = nearClip * np.tan(self.opts['fov'] * 0.5 * np.pi / 180.)
453
+ t = r * h / w
454
+
455
+ ## Note that X0 and width in these equations must be the values used in viewport
456
+ left = r * ((region[0] - x0) * (2.0 / w) - 1)
457
+ right = r * ((region[0] + region[2] - x0) * (2.0 / w) - 1)
458
+ bottom = t * ((region[1] - y0) * (2.0 / h) - 1)
459
+ top = t * ((region[1] + region[3] - y0) * (2.0 / h) - 1)
460
+
461
+ tr = QMatrix4x4()
462
+ tr.frustum(left, right, bottom, top, nearClip, farClip)
463
+ return tr
464
+
465
+ def _compute_coordinates(self, ev, z=None):
466
+ if z is None:
467
+ self.showEvent(0)
468
+ z = glReadPixels(ev.x(), self.height() - ev.y(), 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT)[0][0]
469
+ if z == 0:
470
+ return [0,0,0,0]
471
+ if z==1:
472
+ z=self._lastZ
473
+ #a = np.argwhere(self._z != 1)
474
+ #_y, _x = self.height() - ev.y(), ev.x()
475
+ #ind = np.abs(a-np.array([_y, _x])).sum(-1).argmin()
476
+ #z = self._z[a[ind][0], a[ind][1]]
477
+ self._lastZ = z
478
+
479
+
480
+
481
+ #per = np.array(self.m.copyDataTo()).reshape((4, 4)).transpose().flatten()
482
+ #zFar = 0.5 * per[14] * (1.0 - ((per[10] - 1.0) / (per[10] + 1.0)))
483
+ # zNear = zFar * (per[10] + 1.0) / (per[10] - 1.0)
484
+
485
+ # z = (2.0 * z) - 1.0
486
+ # z = (2.0 * zNear * zFar) / (zFar + zNear - (z * (zFar - zNear)))
487
+
488
+ ndcx = 2 * self.mousePos.x() / self.width() - 1
489
+ ndcy = 1 - 2 * self.mousePos.y() / self.height()
490
+ a= [self.mousePos.x(), self.mousePos.y()]
491
+
492
+ #z=0.998
493
+
494
+ invM = np.linalg.inv(self.mvpProj.reshape((4, 4)).transpose())
495
+
496
+ points = np.matmul(invM,
497
+ np.array([ndcx, ndcy, 2 * z - 1, 1]))
498
+ points /= points[3]
499
+ return points,a
500
+
501
+ def mouseMoveEvent(self, ev):
502
+ #print(self.opts['azimuth'], self.opts['elevation'])
503
+ if not hasattr(self, 'mousePos'):
504
+ return
505
+ diff = ev.pos() - self.mousePos
506
+ self.mousePos = ev.pos()
507
+ if self._enabledPolygon:
508
+
509
+ #self.SubUpdateSegScatterItem()
510
+
511
+ #z = self._z[self.height()-ev.y(), ev.x()]
512
+ z=1.0
513
+ points, _ = self._compute_coordinates(ev, z=z)
514
+ #points[0] -= 1
515
+ #points[-1] -= 1
516
+ # points[1] -= 1
517
+ #points[2] = self.maxXYZ[2] - points[2]
518
+ #points[0] = self.maxXYZ[2] - points[0]
519
+ p1, xo = self._compute_coordinates(ev, 1)
520
+
521
+ # self.points = []
522
+ x,y, z, _ = points
523
+ if z == 0:
524
+ return
525
+ endIm = self._endIMage(x, y, z)
526
+
527
+ if endIm[0]:
528
+ # update x and y
529
+ #return
530
+ x = endIm[1]
531
+ y = endIm[2]
532
+ z = endIm[3]
533
+ endIm2 = self._endIMage(p1[0], p1[2], p1[3])
534
+ self._sPoints.append(xo)
535
+ #if not endIm2[0]:
536
+ # self._sPoints.append(p1)
537
+ self.totalpolys[self._numPolys].append([x, y, z])
538
+ if len(self.totalpolys[self._numPolys]) > 2:
539
+ self.GLPl.update_points(self.totalpolys)
540
+ self.addItem(self.GLPl, 'pol_total')
541
+ self.GLPl.setDepthValue(100)
542
+ #if 'scatter_total' in self.items:
543
+ # self.removeItem('scatter_total')
544
+ # self.GLV.setData(self._seg_im)
545
+ # self.GLV.setDepthValue(0)
546
+ # self.addItem(self.GLV, 'vol_total')
547
+
548
+ else:
549
+ if ev.buttons() == Qt.LeftButton:
550
+ if (ev.modifiers() & Qt.ControlModifier):
551
+ self.pan(diff.x(), diff.y(), 0, relative='view')
552
+ else:
553
+ self.orbit(-diff.x(), diff.y())
554
+ elif ev.buttons() == Qt.MidButton:
555
+ if (ev.modifiers() & Qt.ControlModifier):
556
+ self.pan(diff.x(), 0, diff.y(), relative='view-upright')
557
+ else:
558
+ self.pan(diff.x(), diff.y(), 0, relative='view-upright')
559
+ self.point3dpos.emit([self.opts['elevation'], self.opts['azimuth'], self.opts['distance']],None)
560
+ def emit_viewport(self, points):
561
+ self.point3dpos.emit(points, None)
562
+
563
+ def mousePressEvent(self, ev):
564
+ """
565
+ By Bahram Jafrasteh
566
+ :param ev:
567
+ :return:
568
+ """
569
+ #self.opts['azimuth'] = 0
570
+ #self.opts['elevation'] = 0
571
+
572
+ self.mousePos = ev.localPos()
573
+ if not (self._gotoLoc or self._enabledPolygon):
574
+ return
575
+
576
+ if ev.button()==Qt.RightButton:
577
+ return
578
+ if 'vol_total' in self.items:
579
+ self.SubUpdateSegScatterItem()
580
+ else:
581
+ return
582
+ points, _ = self._compute_coordinates(ev)
583
+
584
+ #points[1] -= 1
585
+ #print(points)
586
+
587
+ if self._enabledPolygon:
588
+ #self.addItem(self.GLPl, 'pol_total')
589
+ #self.points = []
590
+ #points[2] = self.maxXYZ[2] - points[2]
591
+ #points[0] = self.maxXYZ[2] - points[0]
592
+ p1, xo = self._compute_coordinates(ev, 1)
593
+ self._sPoints = []
594
+ self.totalpolys[self._numPolys] =[]
595
+ if points[-2] == 0:
596
+ return
597
+ #print(points)
598
+ x, y, z , _=points
599
+ endIm = self._endIMage(x, y, z)
600
+ if endIm[0]:
601
+ # update x and y
602
+ x = endIm[1]
603
+ y = endIm[2]
604
+ z = endIm[3]
605
+ endIm2 = self._endIMage(p1[0], p1[2], p1[3])
606
+ #if not endIm2[0]:
607
+ # self._sPoints.append(p1)
608
+
609
+ self._sPoints.append(xo)
610
+ self.totalpolys[self._numPolys].append([x, y, z])
611
+ if len(self.totalpolys[self._numPolys])>1:
612
+ self.GLPl.update_points(self.totalpolys)
613
+
614
+
615
+
616
+ #print(points)
617
+ elif self._gotoLoc:
618
+ #points[0] -= 1
619
+ #points[-1] -= 1
620
+ points[2] = self.maxXYZ[0] - points[2]
621
+ points[0] = self.maxXYZ[2] - points[0]
622
+ if self.GLV._ax==0:
623
+ windowName = 'sagittal'
624
+ elif self.GLV._ax == 1:
625
+ windowName = 'coronal'
626
+ elif self.GLV._ax == 2:
627
+ windowName = 'axial'
628
+ self.point3dpos.emit(points, windowName)
629
+ else:
630
+ self.point3dpos.emit(points, None)
631
+ #self.updateSegVolItem(self._seg_im, None)
632
+ if 'scatter_total' in self.items:
633
+
634
+ self.removeItem('scatter_total')
635
+ self.GLV.setData(self._seg_im, self._artistic)
636
+ self.GLV.setDepthValue(20)
637
+ self.addItem(self.GLV, 'vol_total')
638
+
639
+
640
+
641
+ """
642
+
643
+ def changedata(self):
644
+ self._artistic = False
645
+ if self._UseScatter:
646
+ self._UseScatter=False
647
+ #self.paint(self._seg_im)
648
+ self.SubUpdateSegScatterItem()
649
+ elif not self._UseScatter:
650
+ self._UseScatter=True
651
+
652
+ self.update()
653
+ """
654
+ def _localUpdate(self):
655
+
656
+ self.removeItem('scatter_total')
657
+ if self._seg_im is not None:
658
+ self.GLV.setData(self._seg_im.copy(), self._artistic)
659
+ else:
660
+ self.GLV.data = None
661
+ self.GLV.setDepthValue(20)
662
+ self.addItem(self.GLV, 'vol_total')
663
+
664
+ def draw_art_action(self, selected_action_name):
665
+ # Uncheck all other actions
666
+ for action_name, action in self.action_objects.items():
667
+ if action_name != selected_action_name:
668
+ action.setChecked(False)
669
+ else:
670
+ action.setChecked(True)
671
+
672
+ # Set the artistic value based on the selected action
673
+ self._artistic = selected_action_name
674
+
675
+ # Perform updates based on action states
676
+ if self.seg_action.isChecked() or self.im_seg_action.isChecked():
677
+ self.update_3dview.emit(True, None)
678
+ elif hasattr(self, '_lastmap_type'):
679
+ self.update_cmap_image(self._lastmap_type, True)
680
+ self.update()
681
+
682
+ def draw_status(self, value):
683
+ try:
684
+ if not value:
685
+ self.removeItem('pol_total')
686
+ self.totalpolys = defaultdict(list)
687
+ totalpolys_camer = defaultdict(list)
688
+ self.GLPl.update_points(self.totalpolys)
689
+ self._enabledPolygon = value
690
+ else:
691
+ self.GLV.setDepthValue(0)
692
+ self._enabledPolygon = value
693
+
694
+
695
+ """
696
+
697
+ if self.GLV._ax==0: #sagittal
698
+ if self.GLV._d==1:
699
+ self.opts['elevation'] = 0
700
+ self.opts['azimuth'] = 0
701
+ else:
702
+ self.opts['elevation'] = 0
703
+ self.opts['azimuth'] = -180
704
+ elif self.GLV._ax==1:#coronal
705
+ if self.GLV._d == 1:
706
+ self.opts['elevation'] = 0
707
+ self.opts['azimuth'] = 90
708
+ else:
709
+ self.opts['elevation'] = 0
710
+ self.opts['azimuth'] = -90
711
+ elif self.GLV._ax==2:#axial
712
+ if self.GLV._d == 1:
713
+ self.opts['elevation'] = 90
714
+ self.opts['azimuth'] = 0
715
+ else:
716
+ self.opts['elevation'] = -90
717
+ self.opts['azimuth'] = 0
718
+ """
719
+ self.SubUpdateSegScatterItem()
720
+ self.showEvent(0)
721
+ self._z = glReadPixels(0, 0, self.height(),self.width(), GL_DEPTH_COMPONENT, GL_FLOAT)
722
+ if 'scatter_total' in self.items:
723
+ self.removeItem('scatter_total')
724
+ self.GLV.setData(self._seg_im, self._artistic)
725
+ self.GLV.setDepthValue(0)
726
+ self.addItem(self.GLV, 'vol_total')
727
+ except Exception as e:
728
+ print(e)
729
+ def axis_status(self, value):
730
+ if not value:
731
+ self.removeItem('ax')
732
+ else:
733
+ self.addItem(self.ax,'ax')
734
+ self.axis_action.setChecked(True)
735
+
736
+ def grid_status(self, value):
737
+ if not value:
738
+ self.removeItem('xyz')
739
+ else:
740
+ self.addItem(self.gx, 'xyz')
741
+ self.grid_action.setChecked(True)
742
+ def artistic_status(self, value):
743
+ self._artistic = True
744
+ if not value:
745
+ self._artistic = False
746
+ self._localUpdate()
747
+
748
+
749
+ def im_seg_status(self, value):
750
+ self.seg_action.setChecked(False)
751
+ if value:
752
+ self._renderMode = 'Seg'
753
+ self._threshold=0
754
+ self.im_seg_action.setChecked(True)
755
+ self.update_3dview.emit(True, None)
756
+
757
+
758
+ #self.removeItem('vol_total')
759
+
760
+ else:
761
+ self._renderMode = 'Img'
762
+ self.im_seg_action.setChecked(False)
763
+
764
+ self.removeItem('vol_total')
765
+ self.paintGL()
766
+
767
+
768
+
769
+ def seg_status(self, value):
770
+ self.im_seg_action.setChecked(False)
771
+
772
+ if value:
773
+ self._renderMode = 'Seg'
774
+ self._threshold=0
775
+
776
+ self.seg_action.setChecked(True)
777
+ self.update_3dview.emit(True, None)
778
+
779
+ else:
780
+ self._renderMode = 'Img'
781
+ self.seg_action.setChecked(False)
782
+ self.removeItem('vol_total')
783
+ self.paintGL()
784
+ #if hasattr(self, 'GLV'):
785
+ # self.GLV.smooth = value
786
+ # self.GLV._needUpload = True
787
+ # self._localUpdate()
788
+ # self.paintGL()
789
+
790
+
791
+ def goto_status(self, value):
792
+ self._gotoLoc = value
793
+ if not value:
794
+ self.point3dpos.emit(np.array([0,0,0,1]),None)
795
+
796
+
797
+ def changeBG(self, cl):
798
+ self.opts['bgcolor'] = cl
799
+ self._localUpdate()
800
+ self.paintGL()
801
+
802
+
803
+ def update_cmap_image(self, map_type, reset=True):
804
+ self.update_cmap.emit(map_type, reset)
805
+
806
+ def cmap_image(self, _image, map_type, reset=True):
807
+ #if self._image is None:
808
+ # return
809
+ if reset:
810
+ self._threshold = 0
811
+ self._renderMode = 'Seg'
812
+ self.seg_action.setChecked(False)
813
+ self.im_seg_action.setChecked(False)
814
+ self._verticalSlider_1.setVisible(True)
815
+ mask = _image<=(_image.max()*self._threshold/100)
816
+ if map_type=='original':
817
+ cm = np.repeat(_image[...,None], 4, -1)
818
+ else:
819
+ import matplotlib.pyplot as plt
820
+ cm = plt.get_cmap(map_type, lut=256)
821
+ cm = cm(_image / _image.max()) * 255.0
822
+ #if map_type!='gist_rainbow_r':
823
+ # cm[...,3]=self._image
824
+ self.removeItem('vol_total')
825
+
826
+ self._seg_im = cm
827
+ self._seg_im[mask,:]=0
828
+ #if self._indices is not None:
829
+ self._indices = (1-mask.astype('int'))>0
830
+ self._indices = (self._indices.astype('int') - self._excluded_inds.astype('int')) > 0
831
+ self._seg_im[self._excluded_inds,:]=0
832
+ self.GLV.setData(self._seg_im, self._artistic)
833
+ self.GLV.setDepthValue(20)
834
+ self.addItem(self.GLV, 'vol_total')
835
+ self.paintGL()
836
+ self._lastmap_type = map_type
837
+ self._rendered = 'image'
838
+
839
+ def ShowContextMenu(self, pos):
840
+ # Main Edit Menu
841
+ menu = QMenu("Edit")
842
+
843
+ # Submenu for Background Colors
844
+ self.bgColorMenu = QMenu('Background Color')
845
+
846
+ grc = QAction('Gray')
847
+ gc = QAction("Green")
848
+ oc = QAction("Orange")
849
+ pc = QAction("Pink")
850
+ vc = QAction("Violet")
851
+ rc = QAction("Red")
852
+ bc = QAction("Blue")
853
+ wc = QAction("White")
854
+ yc = QAction("Yellow")
855
+ blc = QAction("Black")
856
+
857
+ gc.triggered.connect(partial(self.changeBG, [0.5, 1, 0.0, 1]))
858
+ oc.triggered.connect(partial(self.changeBG, [1, 0.7, 0.1, 1]))
859
+ pc.triggered.connect(partial(self.changeBG, [1, 0.41, 0.79, 1]))
860
+
861
+ vc.triggered.connect(partial(self.changeBG, [0.93, 0.51, 0.93, 1]))
862
+ wc.triggered.connect(partial(self.changeBG, [1., 1., 1., 1]))#[0.96, 0.96, 0.86, 1]
863
+ rc.triggered.connect(partial(self.changeBG, [0.98, 0.5, 0.44, 1]))
864
+ bc.triggered.connect(partial(self.changeBG, [0.25, 0.87, 0.82, 1]))
865
+ yc.triggered.connect(partial(self.changeBG, [1, 0.87, 0.0, 1]))
866
+ blc.triggered.connect(partial(self.changeBG, [0.05, 0.05, 0.05, 1]))
867
+ grc.triggered.connect(partial(self.changeBG, [0.3, 0.3, 0.3, 1]))
868
+ self.bgColorMenu.addAction(gc)
869
+ self.bgColorMenu.addAction(grc)
870
+ self.bgColorMenu.addAction(rc)
871
+ self.bgColorMenu.addAction(bc)
872
+ self.bgColorMenu.addAction(vc)
873
+ self.bgColorMenu.addAction(wc)
874
+ self.bgColorMenu.addAction(oc)
875
+ self.bgColorMenu.addAction(pc)
876
+ self.bgColorMenu.addAction(yc)
877
+ self.bgColorMenu.addAction(blc)
878
+
879
+
880
+ # Submenu for Image Rendering/Colormap Options
881
+ self.imageRenderMenu = QMenu("Image Render")
882
+
883
+ gis_rainbow = QAction("RainBow")
884
+ gis_rainbow.triggered.connect(partial(self.update_cmap_image, 'gist_rainbow_r'))
885
+
886
+ gray = QAction("Gray")
887
+ gray.triggered.connect(partial(self.update_cmap_image, 'gray_r'))
888
+
889
+ original = QAction("Original")
890
+ original.triggered.connect(partial(self.update_cmap_image, 'original'))
891
+
892
+ jet = QAction("JET")
893
+ jet.triggered.connect(partial(self.update_cmap_image, 'jet_r'))
894
+
895
+ CMRmap = QAction("gnuplot")
896
+ CMRmap.triggered.connect(partial(self.update_cmap_image, 'gnuplot2'))
897
+
898
+ gnuplot_r = QAction("gnuplot2")
899
+ gnuplot_r.triggered.connect(partial(self.update_cmap_image, 'gnuplot_r'))
900
+ self.imageRenderMenu.addAction(gis_rainbow)
901
+ self.imageRenderMenu.addAction(gray)
902
+ self.imageRenderMenu.addAction(jet)
903
+ self.imageRenderMenu.addAction(CMRmap)
904
+ self.imageRenderMenu.addAction(gnuplot_r)
905
+ self.imageRenderMenu.addAction(original)
906
+
907
+
908
+ # Submenu for dividing the image
909
+ self.CutMenu = QMenu('Cut')
910
+
911
+ # Define the action names and labels in a list
912
+ self.actions = [
913
+ ('cut_remove_half_action', 'Remove Right Half'),
914
+ ('cut_remove_left_half_action', 'Remove Left Half'),
915
+ ('cut_remove_top_half_action', 'Remove Top Half'),
916
+ ('cut_remove_bottom_half_action', 'Remove Bottom Half'),
917
+ ('cut_remove_front_half_action', 'Remove Front Half'),
918
+ ('cut_remove_back_half_action', 'Remove Back Half'),
919
+ ('cut_remove_quarter_action', 'Remove Top-Right Quarter'),
920
+ ('cut_remove_eighth_action', 'Remove Top-Right Front Eighth')
921
+ ]
922
+
923
+ # Create actions dynamically
924
+ self.action_objects = {}
925
+ for action_name, label in self.actions:
926
+ action = QAction(label)
927
+ action.setCheckable(True)
928
+ action.setChecked(False)
929
+ action.triggered.connect(partial(self.draw_art_action, action_name))
930
+ self.CutMenu.addAction(action)
931
+ self.action_objects[action_name] = action
932
+
933
+
934
+
935
+
936
+ # Submenu for Segmentation Options
937
+ self.segmentationMenu = QMenu('Segmentation')
938
+ self.segmentationMenu.addAction(self.im_seg_action)
939
+ self.segmentationMenu.addAction(self.seg_action)
940
+
941
+ # Submenu for Drawing Options
942
+ self.paintingMenu = QMenu('Painting')
943
+ self.paintingMenu.addAction(self.draw_action)
944
+ #self.paintingMenu.addAction(self.draw_art)
945
+ self.paintingMenu.addAction(self.clear_action)
946
+ self.paintingMenu.addMenu(self.imageRenderMenu) # Nested menu for image rendering
947
+
948
+ # View Options (Axis, Grid, Slice)
949
+ self.viewMenu = QMenu("View Options")
950
+ self.viewMenu.addAction(self.axis_action)
951
+ self.viewMenu.addAction(self.grid_action)
952
+
953
+
954
+ # Actions directly in the main menu
955
+ menu.addMenu(self.bgColorMenu) # Background Color
956
+ menu.addMenu(self.paintingMenu) # Painting and Image Rendering
957
+ menu.addMenu(self.segmentationMenu) # Segmentation
958
+ menu.addMenu(self.viewMenu) # View Options
959
+ menu.addMenu(self.CutMenu)
960
+ menu.addAction(self.screenshot_action) # Screenshot
961
+ menu.addAction(self.goto_action) # GoTo
962
+
963
+
964
+ menu.exec_(self.mapToGlobal(pos))
965
+
966
+
967
+
968
+ def changeAxis(self, polygon, axis):
969
+ if axis == 'coronal':
970
+ polygon = polygon[:, [0, 2, 1]]
971
+ # polygon = np.flipud(polygon)
972
+ polygon[:, 0] = self.maxXYZ[2] - polygon[:, 0]
973
+ polygon[:, 2] = self.maxXYZ[0] - polygon[:, 2]
974
+ elif axis == 'sagittal':
975
+ polygon = polygon[:, [2, 0, 1]]
976
+ #polygon[:, 1] = self.maxXYZ[2] - polygon[:, 1]
977
+ polygon[:, 2] = self.maxXYZ[0] - polygon[:, 2]
978
+ #polygon[:,0] = -polygon[:,0]
979
+ #polygon[:,2] = -polygon[:,2]
980
+ elif axis == 'axial':
981
+ polygon = polygon[:, [0, 1, 2]]
982
+ polygon[:, 0] = self.maxXYZ[2] - polygon[:, 0]
983
+ #polygon[:, 2] = self.maxXYZ[2] - polygon[:, 2]
984
+ return polygon
985
+
986
+
987
+ def updateSegSlice(self, imSeg, edges, currentWidnowName, sliceNum):
988
+ """
989
+ :param totalPs: keys of total points
990
+ :param changedIndice: indices of key name
991
+ :return:
992
+ """
993
+ minimum_area = 2
994
+ if currentWidnowName.lower() == 'coronal':
995
+ subim = imSeg[:,sliceNum,:]
996
+ d = np.where(subim > 0)
997
+ contours, hierarchy = cv2.findContours(image=subim.astype(np.uint8), mode=cv2.RETR_TREE,
998
+ method=cv2.CHAIN_APPROX_NONE)
999
+ if len(contours)==0:
1000
+ item = GLScatterPlotItem(pos=np.empty(shape=(0,3), dtype=np.int64), color=np.empty(shape=(0,4), dtype=np.float64), pxMode=True, size=5)
1001
+ self.addItem(item, 'scatter_{}_{}'.format(currentWidnowName, sliceNum))
1002
+ return
1003
+ else:
1004
+ cnts = []
1005
+ i = 0
1006
+ for contour in contours:
1007
+ if cv2.contourArea(contour)<minimum_area:
1008
+ continue
1009
+ cnt = contour.squeeze()
1010
+ val = subim[cnt[0, 1], cnt[0, 0]]
1011
+ if val > 150:
1012
+ val -= 150
1013
+ subc = subim[cnt[:, 1], cnt[:, 0]]
1014
+ if sum(subc>150)>0:
1015
+ subc[subc>150] = subc[subc>150] - 150
1016
+ subim[cnt[:, 1], cnt[:, 0]] = subc
1017
+ cnts.append([cnt, val])
1018
+ subim[cnt[:, 1], cnt[:, 0]] = 150+subim[cnt[0, 1], cnt[0, 0]]
1019
+ print(np.unique(subim))
1020
+ print(i)
1021
+ i+=1
1022
+ print('')
1023
+ #cnt = contours[0].squeeze()
1024
+
1025
+ #subim[cnt[:, 1], cnt[:, 0]] = 150+subim[cnt[0, 1], cnt[0, 0]]
1026
+ points = np.vstack((d[0], np.repeat(sliceNum,len(d[0])), d[1])).transpose([1,0])[:,[2,1,0]]
1027
+ #cnts = np.vstack((cnt[:, 1], np.repeat(sliceNum, cnt.shape[0]), cnt[:, 0] )).transpose([1, 0])[:, [2, 1, 0]]
1028
+ elif currentWidnowName.lower() == 'sagittal':
1029
+ subim = imSeg[:,:,sliceNum]
1030
+ d = np.where(subim > 0)
1031
+ contours, hierarchy = cv2.findContours(image=subim.astype(np.uint8), mode=cv2.RETR_TREE,
1032
+ method=cv2.CHAIN_APPROX_NONE)
1033
+ if len(contours)==0:
1034
+ item = GLScatterPlotItem(pos=np.empty(shape=(0,3), dtype=np.int64), color=np.empty(shape=(0,4), dtype=np.float64), pxMode=True, size=5)
1035
+ self.addItem(item, 'scatter_{}_{}'.format(currentWidnowName, sliceNum))
1036
+ return
1037
+ else:
1038
+ cnts = []
1039
+ for contour in contours:
1040
+ if cv2.contourArea(contour)<minimum_area:
1041
+ continue
1042
+ cnt = contour.squeeze()
1043
+ val = subim[cnt[0, 1], cnt[0, 0]]
1044
+ if val>150:
1045
+ val -= 150
1046
+ d = subim[cnt[:, 1], cnt[:, 0]]
1047
+ if sum(d>150)>0:
1048
+ d[d>150] = d[d>150] - 150
1049
+ subim[cnt[:, 1], cnt[:, 0]] = d
1050
+ cnts.append([cnt, val] )
1051
+ subim[cnt[:, 1], cnt[:, 0]] = 150+subim[cnt[0, 1], cnt[0, 0]]
1052
+ points = np.vstack((d[0], d[1],np.repeat(sliceNum,len(d[0])))).transpose([1,0])[:,[2,1,0]]
1053
+ #cnts = np.vstack((cnt[:, 1], cnt[:, 0], np.repeat(sliceNum, cnt.shape[0]))).transpose([1, 0])[:, [2, 1, 0]]
1054
+ elif currentWidnowName.lower() == 'axial':
1055
+ subim = imSeg[sliceNum,:,:]
1056
+ d = np.where(subim > 0)
1057
+ contours, hierarchy = cv2.findContours(image=subim.astype(np.uint8), mode=cv2.RETR_TREE,
1058
+ method=cv2.CHAIN_APPROX_NONE)
1059
+ if len(contours)==0:
1060
+ item = GLScatterPlotItem(pos=np.empty(shape=(0,3), dtype=np.int64), color=np.empty(shape=(0,4), dtype=np.float64), pxMode=True, size=5)
1061
+ self.addItem(item, 'scatter_{}_{}'.format(currentWidnowName, sliceNum))
1062
+ return
1063
+ else:
1064
+ cnts = []
1065
+ for contour in contours:
1066
+ if cv2.contourArea(contour)<minimum_area:
1067
+ continue
1068
+ cnt = contour.squeeze()
1069
+ val = subim[cnt[0, 1], cnt[0, 0]]
1070
+ if val > 150:
1071
+ val -= 150
1072
+ d = subim[cnt[:, 1], cnt[:, 0]]
1073
+ if sum(d>150)>0:
1074
+ d[d>150] = d[d>150] - 150
1075
+ subim[cnt[:, 1], cnt[:, 0]] = d
1076
+ cnts.append([cnt, val])
1077
+ subim[cnt[:, 1], cnt[:, 0]] = 150+subim[cnt[0, 1], cnt[0, 0]]
1078
+ #cnt = contours[0].squeeze()
1079
+ #subim[cnt[:, 1], cnt[:, 0]] = 150+subim[cnt[0, 1], cnt[0, 0]]
1080
+ points = np.vstack((np.repeat(sliceNum,len(d[0])),d[0], d[1])).transpose([1,0])[:,[2,1,0]]
1081
+ #cnts = np.vstack((np.repeat(sliceNum, cnt.shape[0]), cnt[:, 1], cnt[:, 0] )).transpose([1, 0])[:, [2, 1, 0]]
1082
+
1083
+
1084
+ #d = np.where(imSeg>0)
1085
+ #if d[0].shape[0]<=1:
1086
+ #return
1087
+ #points = np.vstack((d[0], d[1], d[2])).transpose([1, 0])[:,[2,1,0]]
1088
+
1089
+ points[:, 0] = self.maxXYZ[2] - points[:, 0]
1090
+ points[:, 2] = self.maxXYZ[0] - points[:, 2]
1091
+
1092
+ #cnts[:, 0] = self.maxXYZ[2] - cnts[:, 0]
1093
+ #cnts[:, 2] = self.maxXYZ[0] - cnts[:, 2]
1094
+
1095
+
1096
+ """
1097
+ if windowName == 'coronal':
1098
+ points[:, 0] = self.maxXYZ[2] - points[:, 0]
1099
+ points[:, 2] = self.maxXYZ[0] - points[:, 2]
1100
+ elif windowName == 'sagittal':
1101
+ points[:, 2] = self.maxXYZ[0] - points[:, 2]
1102
+ elif windowName == 'axial':
1103
+ points[:, 0] = self.maxXYZ[2] - points[:, 0]
1104
+ """
1105
+ colors = np.zeros((points.shape[0], 4))
1106
+ #colors[:, 3] = imSeg[tuple(zip(d))].squeeze()
1107
+ #colors[:, 2] = data[tuple(zip(d))].squeeze()
1108
+ #colors[:, 1] = data[tuple(zip(d))].squeeze()
1109
+ colorsInd = subim[tuple(zip(d))].transpose().squeeze()
1110
+ for cl in np.unique(colorsInd[colorsInd<=150]):
1111
+ if cl == 0:
1112
+ continue
1113
+ ind = colorsInd == cl
1114
+ colorval = self.colorsCombinations[int(cl)]
1115
+ colors[ind,:] =colorval
1116
+
1117
+ ind_edge = colorsInd == cl+150
1118
+ colorval_edge = (0.,0.,0.,1.0)
1119
+ colors[ind_edge, :] = colorval_edge
1120
+ for cnt0 in cnts:
1121
+ cnt, cl = cnt0
1122
+ subim[cnt[:, 1], cnt[:, 0]] = cl
1123
+ #colors[:,0] = 255.0
1124
+ #colors = colors/255.0
1125
+ item = GLScatterPlotItem(pos=points, color = colors, pxMode=True, size=5)
1126
+ self.addItem(item, 'scatter_{}_{}'.format(currentWidnowName, sliceNum))
1127
+
1128
+ return
1129
+
1130
+
1131
+ def updateSegVolItem(self, imSeg = None, imOrg = None, currentWidnowName=None, sliceNum = None):
1132
+ """
1133
+ :param totalPs: keys of total points
1134
+ :param changedIndice: indices of key name
1135
+ :return:
1136
+ """
1137
+ self.removeItem('scatter_total')
1138
+ d = np.where(imSeg>0)
1139
+ if d[0].shape[0]<=1:
1140
+ return
1141
+ self.maxXYZ_current = [d[0].max(),d[1].max(),d[2].max()]
1142
+
1143
+ self.minXYZ_current = [d[0].min(),d[1].min(),d[2].min()]
1144
+ if d[0].shape[0]<=1:
1145
+ self.removeItem('scatter_total')
1146
+ return
1147
+
1148
+
1149
+ """
1150
+ if windowName == 'coronal':
1151
+ points[:, 0] = self.maxXYZ[2] - points[:, 0]
1152
+ points[:, 2] = self.maxXYZ[0] - points[:, 2]
1153
+ elif windowName == 'sagittal':
1154
+ points[:, 2] = self.maxXYZ[0] - points[:, 2]
1155
+ elif windowName == 'axial':
1156
+ points[:, 0] = self.maxXYZ[2] - points[:, 0]
1157
+ """
1158
+
1159
+ #colors[:, 3] = imSeg[tuple(zip(d))].squeeze()
1160
+ #colors[:, 2] = data[tuple(zip(d))].squeeze()
1161
+ #colors[:, 1] = data[tuple(zip(d))].squeeze()
1162
+ colorsInd = imSeg[tuple(zip(d))].squeeze()
1163
+ uq = np.unique(colorsInd)
1164
+ if 9876 not in self.colorInds: # len(self.colorsCombinations):
1165
+ selected_ud = self.colorInds
1166
+ else:
1167
+ selected_ud = uq
1168
+ _seg_im = np.zeros((*imSeg.shape, 4))
1169
+ indics = 0
1170
+ for cl in uq:
1171
+ if cl in selected_ud:
1172
+ ind = imSeg == cl
1173
+ indics += ind
1174
+ try:
1175
+ colorval = self.colorsCombinations[int(cl)]
1176
+ _seg_im[ind, :] = colorval
1177
+ except:
1178
+ print('Index {} does not have a representative color.'.format(int(cl)))
1179
+ #colors[:,0] = 255.0
1180
+ #colors = colors/255.0
1181
+ #if self._indices is None:
1182
+ self._indices = indics>self._threshold
1183
+ self._rendered = 'seg'
1184
+ self._verticalSlider_1.setVisible(False)
1185
+ _seg_im *= 255
1186
+ _seg_im[self._excluded_inds,:]=0
1187
+ #im_or = np.repeat(imOrg[..., None], [4], axis=-1)
1188
+ #im_or[indics<=0,:]=0
1189
+ #a = self.intensitySeg * _seg_im + (1 - self.intensitySeg) * im_or
1190
+
1191
+ if self.im_seg_action.isChecked():
1192
+ cm = np.repeat(imOrg[..., None], 4, -1)
1193
+ mask = imOrg <= (imOrg.max() * self._threshold / 100)
1194
+
1195
+ cm_rgb = cm[...,:3]/255.0
1196
+ #cm_rgb[imSeg>0,:]=0 # remove segmented ROIs from the original image
1197
+ cm_alpha = cm[...,3]/255.0
1198
+
1199
+ seg_rgb = _seg_im[...,:3]/255.0
1200
+ seg_alpha = _seg_im[..., 3]/ 255.0
1201
+
1202
+ user_threshold = self.intensityImg
1203
+ #cm_alpha *= user_threshold if user_threshold else 0.02
1204
+ """
1205
+
1206
+
1207
+ # Calculate the gradient along each dimension (x, y, z)
1208
+ gradients = np.gradient(cm[..., :3], axis=(0, 1, 2))
1209
+
1210
+ # Compute the gradient magnitude
1211
+ gradient_magnitude = np.sqrt(sum(g ** 2 for g in gradients)).mean(axis=-1)
1212
+
1213
+ gradient_magnitude = gaussian_filter(gradient_magnitude, sigma=2)
1214
+
1215
+ # Normalize the gradient magnitude to [0, 1]
1216
+ gradient_magnitude = (gradient_magnitude - gradient_magnitude.min()) / (
1217
+ gradient_magnitude.max() - gradient_magnitude.min()
1218
+ )
1219
+ gradient_magnitude*=0.5
1220
+ # Adjust alpha based on the gradient magnitude
1221
+ #cm_alpha *= (gradient_magnitude ** 2) # Emphasize significant gradients more
1222
+ """
1223
+ cm_alpha*=self.intensityImg
1224
+
1225
+ #seg_alpha *= 1.3 # linear
1226
+ seg_alpha = np.sqrt(seg_alpha) # non linear
1227
+
1228
+ composite_alpha = cm_alpha + seg_alpha *(1-cm_alpha)
1229
+
1230
+ composite_alpha_clipped = np.clip(composite_alpha, a_min=1e-10, a_max=None)
1231
+ composite_rgb = (cm_rgb * cm_alpha[..., np.newaxis] + seg_rgb * seg_alpha[..., np.newaxis] * (
1232
+ 1 - cm_alpha[..., np.newaxis])) / composite_alpha_clipped[..., np.newaxis]
1233
+ composite_rgb[composite_alpha == 0] = 0
1234
+ composite_alpha[composite_alpha == 0] = 1
1235
+ _seg_im = np.concatenate((composite_rgb*255.0, composite_alpha[..., np.newaxis] * 255), axis=-1)
1236
+ _seg_im[mask,:] = 0
1237
+ #self._seg_im = _seg_im
1238
+ #self.GLV.setData(_seg_im, self._artistic)
1239
+
1240
+ self._seg_im = _seg_im
1241
+ self.GLV.setData(_seg_im, self._artistic)
1242
+
1243
+ self.GLV.setDepthValue(20)
1244
+ self.addItem(self.GLV, 'vol_total')
1245
+
1246
+ return
1247
+
1248
+
1249
+
1250
+ def SubUpdateSegScatterItem(self):
1251
+ if self._seg_im is None:
1252
+ return
1253
+ if self._indices is None:
1254
+ self._indices = self._image>0
1255
+ self.removeItem('vol_total')
1256
+ d = np.where(self._indices)
1257
+ if d[0].shape[0]<=1:
1258
+ return
1259
+ points = np.vstack((d[0], d[1], d[2])).transpose([1, 0]) # [:,[2,1,0]]
1260
+
1261
+ points[:, 0] = self.maxXYZ[0] - points[:, 0] # axial
1262
+ points[:, 2] = self.maxXYZ[2] - points[:, 2] # sagittal
1263
+ # points[:, 1] = self.maxXYZ[1] - points[:, 1]#coronal
1264
+ points = points[:, [2, 1, 0]]
1265
+ colors = self._seg_im[self._indices]/255.0
1266
+
1267
+ self.GLSC.setData(pos=points, color = colors, pxMode=True, size=5)
1268
+ self.addItem(self.GLSC, 'scatter_total')
1269
+
1270
+ def updateSegScatterItem(self, imSeg, windowName):
1271
+ """
1272
+ :param totalPs: keys of total points
1273
+ :param changedIndice: indices of key name
1274
+ :return:
1275
+ """
1276
+ self.removeItem('vol_total')
1277
+
1278
+ d = np.where(imSeg>0)
1279
+ if d[0].shape[0]<=1:
1280
+ self.removeItem('scatter_total')
1281
+ return
1282
+ points = np.vstack((d[0], d[1], d[2])).transpose([1, 0])#[:,[2,1,0]]
1283
+
1284
+ points[:, 0] = self.maxXYZ[0] - points[:, 0]#axial
1285
+ points[:, 2] = self.maxXYZ[2] - points[:, 2]#sagittal
1286
+ #points[:, 1] = self.maxXYZ[1] - points[:, 1]#coronal
1287
+ points = points[:,[2,1,0]]
1288
+
1289
+ """
1290
+ if windowName == 'coronal':
1291
+ points[:, 0] = self.maxXYZ[2] - points[:, 0]
1292
+ points[:, 2] = self.maxXYZ[0] - points[:, 2]
1293
+ elif windowName == 'sagittal':
1294
+ points[:, 2] = self.maxXYZ[0] - points[:, 2]
1295
+ elif windowName == 'axial':
1296
+ points[:, 0] = self.maxXYZ[2] - points[:, 0]
1297
+ """
1298
+ colors = np.ones((points.shape[0], 4))*10000
1299
+ #colors[:, 3] = imSeg[tuple(zip(d))].squeeze()
1300
+ #colors[:, 2] = data[tuple(zip(d))].squeeze()
1301
+ #colors[:, 1] = data[tuple(zip(d))].squeeze()
1302
+ colorsInd = imSeg[tuple(zip(d))].squeeze()
1303
+ uq = np.unique(colorsInd)
1304
+ if 9876 not in self.colorInds: # len(self.colorsCombinations):
1305
+ selected_ud = self.colorInds
1306
+ else:
1307
+ selected_ud = uq
1308
+
1309
+ for cl in uq:
1310
+ if cl == 0:
1311
+ continue
1312
+ if cl in selected_ud:
1313
+ ind = colorsInd == cl
1314
+ try:
1315
+ colorval = self.colorsCombinations[int(cl)]
1316
+ colors[ind,:] =colorval
1317
+ except:
1318
+ print('Index {} does not have a representative color.'.format(int(cl)))
1319
+ #colors[:,0] = 255.0
1320
+ #colors = colors/255.0
1321
+ ind_non_zero = colors.sum(1)!=10000*4
1322
+ self.GLSC.setData(pos=points[ind_non_zero, :], color = colors[ind_non_zero, :], pxMode=True, size=5)
1323
+ self.addItem(self.GLSC, 'scatter_total')
1324
+ return
1325
+ if len(changedIndice)== 0:
1326
+ return
1327
+
1328
+ for axis in totalPs.keys():
1329
+ for Pls in totalPs[axis].keys():
1330
+ for key in totalPs[axis][Pls].keys():
1331
+ keyName = str(axis) + '_' + str(Pls) + '_' + str(key)
1332
+ if keyName in changedIndice:
1333
+ ind = changedIndice.index(keyName)
1334
+ self.removeItem(keyName)
1335
+ polyg, color = totalPs[axis][Pls][key]
1336
+ polygon = np.array(list(polyg.exterior.coords))
1337
+ polygon = self.changeAxis(polygon, axis)
1338
+ keyName = str(axis) + '_' + str(Pls) + '_' + str(key)
1339
+ polygon = np.array(PolygonTessellator().tessellate(polygon))
1340
+ self.addSegItem(polygon, keyName, color)
1341
+ changedIndice.pop(ind)
1342
+ if len(changedIndice) != 0:
1343
+ for keyName in changedIndice:
1344
+ self.removeItem(keyName)
1345
+
1346
+
1347
+
1348
+
1349
+ #def paint(self, imSeg = None, edges = None, currentWidnowName=None, sliceNum = None):
1350
+ def paint(self, imSeg = None, im = None, currentWidnowName=None, sliceNum = None):
1351
+ if not self._updatePaint:
1352
+ return
1353
+ if not self._renderMode.lower()=='seg':
1354
+ return
1355
+ if not (self.seg_action.isChecked() or self.im_seg_action.isChecked()):
1356
+ return
1357
+ #self._seg_im = imSeg
1358
+ #if imSeg is not None:
1359
+ #if currentWidnowName is None:
1360
+ #if self._UseScatter:
1361
+ # self.updateSegScatterItem(imSeg, currentWidnowName)
1362
+ #else:
1363
+
1364
+ self.updateSegVolItem(imSeg, im, currentWidnowName)
1365
+ #else:
1366
+ # self.updateSegSlice(imSeg, edges, currentWidnowName, sliceNum)
1367
+
1368
+ if self.isVisible():
1369
+ self.show()
1370
+
1371
+
1372
+ def load_paint(self, imSeg):
1373
+
1374
+ if hasattr(self,'items_names'):
1375
+ if len(self.items_names)>3:
1376
+ try:
1377
+ total_items = list(set(self.items_names) - set(['scatter_total', 'xyz', 'ax']))
1378
+ for item in total_items:
1379
+ _, currentWidnowName, sliceNum = item.split('_')
1380
+ sliceNum = int(sliceNum)
1381
+ self.updateSegSlice(imSeg, [], currentWidnowName, sliceNum)
1382
+ delattr(self, 'items_names')
1383
+ self.update()
1384
+ except:
1385
+ self.paint(imSeg, None)
1386
+ else:
1387
+ self.paint(imSeg, None)
1388
+ if hasattr(self, 'items_names'):
1389
+ delattr(self, 'items_names')
1390
+
1391
+
1392
+ def createGridAxis(self, maxcoord):
1393
+ self.removeItem('vol_total')
1394
+ #maxcoord = self.testTest()
1395
+ ############# create the background grids #############
1396
+ self.setMaxCoords(maxcoord)
1397
+
1398
+ #self._seg_im = np.zeros((*maxcoord,1)).squeeze()
1399
+ if len(self.totalItems['axis']) != 0:
1400
+ self.removeItem(self.totalItems['axis'][0])
1401
+ self.removeItem(self.totalItems['axis'][1])
1402
+ #self.removeItem(self.totalItems['axis'][2])
1403
+ #self.removeItem(self.totalItems['axis'][3])
1404
+ del self.totalItems['axis']
1405
+ zmax, ymax, xmax = maxcoord
1406
+ self.maxXYZ = [zmax, ymax, xmax]
1407
+ self._excluded_inds = np.zeros((self.maxXYZ[0],self.maxXYZ[1],self.maxXYZ[2]), bool)
1408
+ self._excluded_inds[:]=False
1409
+ xvals = np.arange(0, xmax + xmax/10, xmax/5).astype(np.int64)
1410
+ yvals = np.arange(0, ymax + ymax/10, ymax/5).astype(np.int64)
1411
+ zvals = np.arange(0, zmax + zmax/10, zmax/5).astype(np.int64)
1412
+
1413
+ self.maxXYZ = [zmax, ymax, xmax]
1414
+ self.maxXYZ_current = [zmax, ymax, xmax]
1415
+ self.minXYZ_current = [0, 0, 0]
1416
+ #xvals = -np.arange(0, xmax + xmax/5, xmax/5).astype("int")[::-1]
1417
+ #yvals = -np.arange(0, ymax + ymax/5, ymax/5).astype("int")[::-1]
1418
+ #zvals = -np.arange(0, zmax + zmax/5, zmax/5).astype("int")[::-1]
1419
+
1420
+ zmax = zvals[-1]; ymax = yvals[-1]; xmax=xvals[-1]
1421
+ zmin = zvals[0];ymin = yvals[0];xmin = xvals[0]
1422
+ self.gx = GLGridItem(glOptions='translucent', color=[0,0,0,1])
1423
+ self.gx.setGrid(xvals, yvals, zvals )
1424
+ self.gx.setDepthValue(0)
1425
+
1426
+
1427
+
1428
+
1429
+
1430
+ #gx.translate(-zmax, 0, 0)
1431
+ #gx.rotate(90, 0, 1, 0)
1432
+ #gx.translate(0, 0, zmax)
1433
+ if self.grid_action.isChecked():
1434
+ self.totalItems['axis'].append('xyz')
1435
+ self.addItem(self.gx, 'xyz')
1436
+
1437
+ #imxz = np.zeros((xmax, zmax,3))
1438
+ #Imxz = GLImageItem(imxz, color=[1,1,0,1], program=self.program)
1439
+ #Imxz.rotate(90,0,1,0)
1440
+ #self.addItem(Imxz, 'imxz')
1441
+
1442
+ #gy = gl.GLGridItem(glOptions='opaque', program=self.program)
1443
+ #gy.rotate(90, 1, 0, 0)
1444
+ #gy.setGrid(xvals, zvals)
1445
+ #self.totalItems['axis'].append('y')
1446
+ #self.addItem(gy, 'y')
1447
+
1448
+ #gz = gl.GLGridItem(glOptions='opaque', program=self.program)
1449
+ #gz.setGrid(xvals, yvals)
1450
+ #self.totalItems['axis'].append('z')
1451
+ #self.addItem(gz, 'z')
1452
+
1453
+ ############# axis #############
1454
+ self.ax = GLAxisItem(antialias=True, glOptions='translucent')
1455
+ self.ax.setDepthValue(0)
1456
+ self.ax.setGLViewWidget(self)
1457
+ #ax.setSize(0, xmax, 0, ymax, 0, zmax)
1458
+ self.ax.setSize(xmin, xmax, ymin,ymax, zmin, zmax)
1459
+ self.ax.setOriging(maxcoord[2]/2,maxcoord[1]/2,maxcoord[0]/2)
1460
+ if self.axis_action.isChecked():
1461
+ self.totalItems['axis'].append('ax')
1462
+ self.addItem(self.ax, 'ax')
1463
+
1464
+ # Switch to 'nearly' orthographic projection.
1465
+ #self.opts['distance'] = 40000
1466
+ self.opts['fov'] = 45
1467
+ self.opts['elevation'] = 45
1468
+ self.opts['azimuth'] = 45
1469
+
1470
+ self.setCameraPosition(pos=QVector3D(maxcoord[2]/2,maxcoord[1]/2,maxcoord[0]/2), rotation=(0,0,1,1),
1471
+ distance= max(xmax, ymax, zmax))
1472
+ #distance=np.sqrt(maxcoord[0]**2+maxcoord[1]**2+maxcoord[2]**2),
1473
+ #)
1474
+ self.totalPolyItems = []
1475
+
1476
+ self._enabledPolygon = False
1477
+ self._indices = None
1478
+ self._rendered = 'seg'
1479
+ self._numPolys = 0
1480
+ self.totalpolys = defaultdict(list)
1481
+ self.totalpolys_camer = defaultdict(list)
1482
+
1483
+
1484
+
1485
+
1486
+
1487
+
1488
+ # Start Qt event loop unless running in interactive mode.
1489
+ class Ui_Main0():
1490
+ NumRows = 2
1491
+ NumColumns = 3
1492
+
1493
+ def __init__(self):
1494
+ super(Ui_Main0, self).__init__()
1495
+
1496
+ self.glWidgets = []
1497
+
1498
+ def setupUi(self, Main):
1499
+ Main.resize(2000, 1800)
1500
+ self.centralwidget = QWidget(Main)
1501
+ self.centralwidget.setEnabled(True)
1502
+ self.v = glScientific(self.centralwidget)
1503
+
1504
+
1505
+ import pickle
1506
+ #with open('dictionary', 'wb') as output:
1507
+ # pickle.dump(self.colorsCombinations, output, pickle.HIGHEST_PROTOCOL)
1508
+ with open('dictionary', 'rb') as output:
1509
+ r = pickle.load(output)
1510
+
1511
+ self.v.colorsCombinations = r
1512
+ self.v.colorInds = [85,45]
1513
+ #v.animation()
1514
+
1515
+ class MainWindow0(QWidget, Ui_Main0):
1516
+ def __init__(self, *args, obj=None, **kwargs):
1517
+ super(MainWindow0, self).__init__(*args, **kwargs)
1518
+ #QtGui.QWidget.__init__(self)
1519
+ self.setupUi(self)
1520
+ from nibabel import load
1521
+ #nii = load('inp.nii')
1522
+ #data = np.squeeze(nii.get_data())
1523
+
1524
+ data = np.load('aa.npy')
1525
+ data = data.astype("float") # Typecast to float
1526
+ #data = data[:, :, ::-1]
1527
+ self.v._renderMode = 'seg'
1528
+ self.v._excluded_inds = np.zeros_like(data).astype('bool')
1529
+ self.v._excluded_inds[:] = False
1530
+ self.v.createGridAxis(list(data.shape))
1531
+ self.v.paint(data)
1532
+ self.v.show()
1533
+
1534
+ data = np.rot90(data, axes=(1, 2))# x
1535
+ data = np.rot90(data, axes=(0, 2)) #y
1536
+ data = np.rot90(data, axes=(0, 1)) # z
1537
+
1538
+ #data = np.load('ab.npy')
1539
+ #data = data.astype("float") # Typecast to float
1540
+
1541
+
1542
+
1543
+
1544
+
1545
+ if __name__ == '__main__':
1546
+ app = QApplication(sys.argv)
1547
+
1548
+ window = MainWindow0()
1549
+
1550
+ #window.show()
1551
+ sys.exit(app.exec_())
1552
+
1553
+
1554
+