PaIRS-UniNa 0.2.5__cp313-cp313-win_amd64.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 (323) hide show
  1. PaIRS_UniNa/Calibration_Tab.py +331 -0
  2. PaIRS_UniNa/Changes.txt +110 -0
  3. PaIRS_UniNa/Custom_Top.py +303 -0
  4. PaIRS_UniNa/Explorer.py +3069 -0
  5. PaIRS_UniNa/FolderLoop.py +372 -0
  6. PaIRS_UniNa/Input_Tab.py +719 -0
  7. PaIRS_UniNa/Input_Tab_CalVi.py +788 -0
  8. PaIRS_UniNa/Input_Tab_tools.py +3023 -0
  9. PaIRS_UniNa/Log_Tab.py +110 -0
  10. PaIRS_UniNa/Output_Tab.py +924 -0
  11. PaIRS_UniNa/PaIRS.py +18 -0
  12. PaIRS_UniNa/PaIRS_PIV.py +873 -0
  13. PaIRS_UniNa/PaIRS_pypacks.py +1250 -0
  14. PaIRS_UniNa/Process_Tab.py +1757 -0
  15. PaIRS_UniNa/Process_Tab_CalVi.py +313 -0
  16. PaIRS_UniNa/Process_Tab_Disp.py +163 -0
  17. PaIRS_UniNa/Process_Tab_Min.py +120 -0
  18. PaIRS_UniNa/ResizePopup.py +55 -0
  19. PaIRS_UniNa/Saving_tools.py +296 -0
  20. PaIRS_UniNa/TabTools.py +1251 -0
  21. PaIRS_UniNa/Vis_Tab.py +2100 -0
  22. PaIRS_UniNa/Vis_Tab_CalVi.py +983 -0
  23. PaIRS_UniNa/Whatsnew.py +118 -0
  24. PaIRS_UniNa/_PaIRS_PIV.pyd +0 -0
  25. PaIRS_UniNa/__init__.py +6 -0
  26. PaIRS_UniNa/__main__.py +45 -0
  27. PaIRS_UniNa/addwidgets_ps.py +1125 -0
  28. PaIRS_UniNa/calib.py +1488 -0
  29. PaIRS_UniNa/calibView.py +826 -0
  30. PaIRS_UniNa/gPaIRS.py +3769 -0
  31. PaIRS_UniNa/gPalette.py +189 -0
  32. PaIRS_UniNa/icons/abort.png +0 -0
  33. PaIRS_UniNa/icons/about.png +0 -0
  34. PaIRS_UniNa/icons/align_all.png +0 -0
  35. PaIRS_UniNa/icons/announcement.png +0 -0
  36. PaIRS_UniNa/icons/automatic_levels_off.png +0 -0
  37. PaIRS_UniNa/icons/automatic_levels_on.png +0 -0
  38. PaIRS_UniNa/icons/automatic_off.png +0 -0
  39. PaIRS_UniNa/icons/automatic_on.png +0 -0
  40. PaIRS_UniNa/icons/automatic_size_off.png +0 -0
  41. PaIRS_UniNa/icons/automatic_size_on.png +0 -0
  42. PaIRS_UniNa/icons/axes.png +0 -0
  43. PaIRS_UniNa/icons/background.png +0 -0
  44. PaIRS_UniNa/icons/background_vectors.png +0 -0
  45. PaIRS_UniNa/icons/bin_off.png +0 -0
  46. PaIRS_UniNa/icons/bin_on.png +0 -0
  47. PaIRS_UniNa/icons/browse_file_c.png +0 -0
  48. PaIRS_UniNa/icons/browse_folder_c.png +0 -0
  49. PaIRS_UniNa/icons/brush_cursor.png +0 -0
  50. PaIRS_UniNa/icons/bugfix.png +0 -0
  51. PaIRS_UniNa/icons/cal_proc.png +0 -0
  52. PaIRS_UniNa/icons/cal_proc_off.png +0 -0
  53. PaIRS_UniNa/icons/cal_step.png +0 -0
  54. PaIRS_UniNa/icons/cal_step_off.png +0 -0
  55. PaIRS_UniNa/icons/calibrate.png +0 -0
  56. PaIRS_UniNa/icons/calibration_logo.png +0 -0
  57. PaIRS_UniNa/icons/change_folder.png +0 -0
  58. PaIRS_UniNa/icons/change_folder_off.png +0 -0
  59. PaIRS_UniNa/icons/checklist.png +0 -0
  60. PaIRS_UniNa/icons/clean.png +0 -0
  61. PaIRS_UniNa/icons/clean_run.png +0 -0
  62. PaIRS_UniNa/icons/close.png +0 -0
  63. PaIRS_UniNa/icons/close_all.png +0 -0
  64. PaIRS_UniNa/icons/close_project.png +0 -0
  65. PaIRS_UniNa/icons/close_workspace.png +0 -0
  66. PaIRS_UniNa/icons/colormap.png +0 -0
  67. PaIRS_UniNa/icons/colormaps/Accent.png +0 -0
  68. PaIRS_UniNa/icons/colormaps/BrBG.png +0 -0
  69. PaIRS_UniNa/icons/colormaps/Dark2.png +0 -0
  70. PaIRS_UniNa/icons/colormaps/PRGn.png +0 -0
  71. PaIRS_UniNa/icons/colormaps/Paired.png +0 -0
  72. PaIRS_UniNa/icons/colormaps/Pastel1.png +0 -0
  73. PaIRS_UniNa/icons/colormaps/Pastel2.png +0 -0
  74. PaIRS_UniNa/icons/colormaps/PiYG.png +0 -0
  75. PaIRS_UniNa/icons/colormaps/PuOr.png +0 -0
  76. PaIRS_UniNa/icons/colormaps/RdBu.png +0 -0
  77. PaIRS_UniNa/icons/colormaps/RdGy.png +0 -0
  78. PaIRS_UniNa/icons/colormaps/RdYlBu.png +0 -0
  79. PaIRS_UniNa/icons/colormaps/RdYlGn.png +0 -0
  80. PaIRS_UniNa/icons/colormaps/Set1.png +0 -0
  81. PaIRS_UniNa/icons/colormaps/Set2.png +0 -0
  82. PaIRS_UniNa/icons/colormaps/Set3.png +0 -0
  83. PaIRS_UniNa/icons/colormaps/Spectral.png +0 -0
  84. PaIRS_UniNa/icons/colormaps/Wistia.png +0 -0
  85. PaIRS_UniNa/icons/colormaps/afmhot.png +0 -0
  86. PaIRS_UniNa/icons/colormaps/autumn.png +0 -0
  87. PaIRS_UniNa/icons/colormaps/binary.png +0 -0
  88. PaIRS_UniNa/icons/colormaps/blackVector.png +0 -0
  89. PaIRS_UniNa/icons/colormaps/blueVector.png +0 -0
  90. PaIRS_UniNa/icons/colormaps/bone.png +0 -0
  91. PaIRS_UniNa/icons/colormaps/brg.png +0 -0
  92. PaIRS_UniNa/icons/colormaps/bwr.png +0 -0
  93. PaIRS_UniNa/icons/colormaps/cividis.png +0 -0
  94. PaIRS_UniNa/icons/colormaps/cool.png +0 -0
  95. PaIRS_UniNa/icons/colormaps/coolwarm.png +0 -0
  96. PaIRS_UniNa/icons/colormaps/copper.png +0 -0
  97. PaIRS_UniNa/icons/colormaps/cubehelix.png +0 -0
  98. PaIRS_UniNa/icons/colormaps/cyanVector.png +0 -0
  99. PaIRS_UniNa/icons/colormaps/flag.png +0 -0
  100. PaIRS_UniNa/icons/colormaps/gist_heat.png +0 -0
  101. PaIRS_UniNa/icons/colormaps/gray.png +0 -0
  102. PaIRS_UniNa/icons/colormaps/greenVector.png +0 -0
  103. PaIRS_UniNa/icons/colormaps/hot.png +0 -0
  104. PaIRS_UniNa/icons/colormaps/hsv.png +0 -0
  105. PaIRS_UniNa/icons/colormaps/inferno.png +0 -0
  106. PaIRS_UniNa/icons/colormaps/jet.png +0 -0
  107. PaIRS_UniNa/icons/colormaps/magentaVector.png +0 -0
  108. PaIRS_UniNa/icons/colormaps/magma.png +0 -0
  109. PaIRS_UniNa/icons/colormaps/ocean.png +0 -0
  110. PaIRS_UniNa/icons/colormaps/pink.png +0 -0
  111. PaIRS_UniNa/icons/colormaps/plasma.png +0 -0
  112. PaIRS_UniNa/icons/colormaps/prism.png +0 -0
  113. PaIRS_UniNa/icons/colormaps/rainbow.png +0 -0
  114. PaIRS_UniNa/icons/colormaps/redVector.png +0 -0
  115. PaIRS_UniNa/icons/colormaps/seismic.png +0 -0
  116. PaIRS_UniNa/icons/colormaps/spring.png +0 -0
  117. PaIRS_UniNa/icons/colormaps/summer.png +0 -0
  118. PaIRS_UniNa/icons/colormaps/tab10.png +0 -0
  119. PaIRS_UniNa/icons/colormaps/tab20.png +0 -0
  120. PaIRS_UniNa/icons/colormaps/tab20b.png +0 -0
  121. PaIRS_UniNa/icons/colormaps/tab20c.png +0 -0
  122. PaIRS_UniNa/icons/colormaps/terrain.png +0 -0
  123. PaIRS_UniNa/icons/colormaps/twilight.png +0 -0
  124. PaIRS_UniNa/icons/colormaps/viridis.png +0 -0
  125. PaIRS_UniNa/icons/colormaps/whiteVector.png +0 -0
  126. PaIRS_UniNa/icons/colormaps/winter.png +0 -0
  127. PaIRS_UniNa/icons/colormaps/yellowVector.png +0 -0
  128. PaIRS_UniNa/icons/common_region.png +0 -0
  129. PaIRS_UniNa/icons/common_region_off.png +0 -0
  130. PaIRS_UniNa/icons/completed.png +0 -0
  131. PaIRS_UniNa/icons/contourf_off.png +0 -0
  132. PaIRS_UniNa/icons/contourf_on.png +0 -0
  133. PaIRS_UniNa/icons/copy.png +0 -0
  134. PaIRS_UniNa/icons/copy_process.png +0 -0
  135. PaIRS_UniNa/icons/copy_process_off.png +0 -0
  136. PaIRS_UniNa/icons/copygrid.png +0 -0
  137. PaIRS_UniNa/icons/cursor_lamp.png +0 -0
  138. PaIRS_UniNa/icons/cut.png +0 -0
  139. PaIRS_UniNa/icons/cut_warnings.png +0 -0
  140. PaIRS_UniNa/icons/darkmode.png +0 -0
  141. PaIRS_UniNa/icons/debug_run.png +0 -0
  142. PaIRS_UniNa/icons/delete.png +0 -0
  143. PaIRS_UniNa/icons/deleteErr.png +0 -0
  144. PaIRS_UniNa/icons/disp_step.png +0 -0
  145. PaIRS_UniNa/icons/disp_step_off.png +0 -0
  146. PaIRS_UniNa/icons/down.png +0 -0
  147. PaIRS_UniNa/icons/edit_list.png +0 -0
  148. PaIRS_UniNa/icons/editing.png +0 -0
  149. PaIRS_UniNa/icons/example_list.png +0 -0
  150. PaIRS_UniNa/icons/find_all_planes.png +0 -0
  151. PaIRS_UniNa/icons/find_plane.png +0 -0
  152. PaIRS_UniNa/icons/flaticon_PaIRS.png +0 -0
  153. PaIRS_UniNa/icons/flaticon_PaIRS_beta.png +0 -0
  154. PaIRS_UniNa/icons/flaticon_PaIRS_download.png +0 -0
  155. PaIRS_UniNa/icons/flip_y_off.png +0 -0
  156. PaIRS_UniNa/icons/flip_y_on.png +0 -0
  157. PaIRS_UniNa/icons/focusErrr.png +0 -0
  158. PaIRS_UniNa/icons/gear.gif +0 -0
  159. PaIRS_UniNa/icons/gear.png +0 -0
  160. PaIRS_UniNa/icons/ger.png +0 -0
  161. PaIRS_UniNa/icons/greenv.png +0 -0
  162. PaIRS_UniNa/icons/guide.png +0 -0
  163. PaIRS_UniNa/icons/icon_CalVi.png +0 -0
  164. PaIRS_UniNa/icons/icon_PaIRS.png +0 -0
  165. PaIRS_UniNa/icons/import.png +0 -0
  166. PaIRS_UniNa/icons/import_set.png +0 -0
  167. PaIRS_UniNa/icons/information.png +0 -0
  168. PaIRS_UniNa/icons/input_logo.png +0 -0
  169. PaIRS_UniNa/icons/issue.png +0 -0
  170. PaIRS_UniNa/icons/laser_NTR.png +0 -0
  171. PaIRS_UniNa/icons/laser_TR_double.png +0 -0
  172. PaIRS_UniNa/icons/laser_TR_single.png +0 -0
  173. PaIRS_UniNa/icons/link.png +0 -0
  174. PaIRS_UniNa/icons/linked.png +0 -0
  175. PaIRS_UniNa/icons/loaded.png +0 -0
  176. PaIRS_UniNa/icons/loading_2.gif +0 -0
  177. PaIRS_UniNa/icons/log_logo.png +0 -0
  178. PaIRS_UniNa/icons/logo_CalVi.png +0 -0
  179. PaIRS_UniNa/icons/logo_CalVi_completo.png +0 -0
  180. PaIRS_UniNa/icons/logo_CalVi_party.png +0 -0
  181. PaIRS_UniNa/icons/logo_PaIRS.png +0 -0
  182. PaIRS_UniNa/icons/logo_PaIRS_completo.png +0 -0
  183. PaIRS_UniNa/icons/logo_PaIRS_download.png +0 -0
  184. PaIRS_UniNa/icons/logo_PaIRS_party_rect.png +0 -0
  185. PaIRS_UniNa/icons/logo_PaIRS_rect.png +0 -0
  186. PaIRS_UniNa/icons/logo_opaco.png +0 -0
  187. PaIRS_UniNa/icons/mask.png +0 -0
  188. PaIRS_UniNa/icons/measure.png +0 -0
  189. PaIRS_UniNa/icons/measure_off.png +0 -0
  190. PaIRS_UniNa/icons/min_proc.png +0 -0
  191. PaIRS_UniNa/icons/min_proc_off.png +0 -0
  192. PaIRS_UniNa/icons/min_step.png +0 -0
  193. PaIRS_UniNa/icons/min_step_off.png +0 -0
  194. PaIRS_UniNa/icons/minus.png +0 -0
  195. PaIRS_UniNa/icons/mirror_u.png +0 -0
  196. PaIRS_UniNa/icons/mirror_v.png +0 -0
  197. PaIRS_UniNa/icons/mirror_x.png +0 -0
  198. PaIRS_UniNa/icons/mirror_y.png +0 -0
  199. PaIRS_UniNa/icons/mtplt.png +0 -0
  200. PaIRS_UniNa/icons/new.png +0 -0
  201. PaIRS_UniNa/icons/new_workspace.png +0 -0
  202. PaIRS_UniNa/icons/news.png +0 -0
  203. PaIRS_UniNa/icons/normal_run.png +0 -0
  204. PaIRS_UniNa/icons/open.png +0 -0
  205. PaIRS_UniNa/icons/open_image.png +0 -0
  206. PaIRS_UniNa/icons/open_new_window.png +0 -0
  207. PaIRS_UniNa/icons/open_result.png +0 -0
  208. PaIRS_UniNa/icons/open_workspace.png +0 -0
  209. PaIRS_UniNa/icons/output_logo.png +0 -0
  210. PaIRS_UniNa/icons/paste_above.png +0 -0
  211. PaIRS_UniNa/icons/paste_below.png +0 -0
  212. PaIRS_UniNa/icons/pause.png +0 -0
  213. PaIRS_UniNa/icons/paused.png +0 -0
  214. PaIRS_UniNa/icons/piv_proc.png +0 -0
  215. PaIRS_UniNa/icons/piv_proc_off.png +0 -0
  216. PaIRS_UniNa/icons/piv_step.png +0 -0
  217. PaIRS_UniNa/icons/piv_step_off.png +0 -0
  218. PaIRS_UniNa/icons/plane.png +0 -0
  219. PaIRS_UniNa/icons/play.png +0 -0
  220. PaIRS_UniNa/icons/plus.png +0 -0
  221. PaIRS_UniNa/icons/process_logo.png +0 -0
  222. PaIRS_UniNa/icons/process_loop.png +0 -0
  223. PaIRS_UniNa/icons/project.png +0 -0
  224. PaIRS_UniNa/icons/pylog.png +0 -0
  225. PaIRS_UniNa/icons/python_warning.png +0 -0
  226. PaIRS_UniNa/icons/queue.png +0 -0
  227. PaIRS_UniNa/icons/quit.png +0 -0
  228. PaIRS_UniNa/icons/read.png +0 -0
  229. PaIRS_UniNa/icons/read_list.png +0 -0
  230. PaIRS_UniNa/icons/redo.png +0 -0
  231. PaIRS_UniNa/icons/redx.png +0 -0
  232. PaIRS_UniNa/icons/reset.png +0 -0
  233. PaIRS_UniNa/icons/reset_levels.png +0 -0
  234. PaIRS_UniNa/icons/resize_icon.png +0 -0
  235. PaIRS_UniNa/icons/restore.png +0 -0
  236. PaIRS_UniNa/icons/restore_undo.png +0 -0
  237. PaIRS_UniNa/icons/rotate_clock.png +0 -0
  238. PaIRS_UniNa/icons/rotate_counter.png +0 -0
  239. PaIRS_UniNa/icons/rotate_v_clock.png +0 -0
  240. PaIRS_UniNa/icons/rotate_v_counter.png +0 -0
  241. PaIRS_UniNa/icons/running.gif +0 -0
  242. PaIRS_UniNa/icons/running.png +0 -0
  243. PaIRS_UniNa/icons/running_warn.png +0 -0
  244. PaIRS_UniNa/icons/sandglass.png +0 -0
  245. PaIRS_UniNa/icons/save.png +0 -0
  246. PaIRS_UniNa/icons/save_and_stop.png +0 -0
  247. PaIRS_UniNa/icons/save_cfg.png +0 -0
  248. PaIRS_UniNa/icons/saveas.png +0 -0
  249. PaIRS_UniNa/icons/saveas_workspace.png +0 -0
  250. PaIRS_UniNa/icons/scale_all.png +0 -0
  251. PaIRS_UniNa/icons/scale_down.png +0 -0
  252. PaIRS_UniNa/icons/scale_up.png +0 -0
  253. PaIRS_UniNa/icons/scan_list.png +0 -0
  254. PaIRS_UniNa/icons/scan_path.png +0 -0
  255. PaIRS_UniNa/icons/search.png +0 -0
  256. PaIRS_UniNa/icons/showIW_off.png +0 -0
  257. PaIRS_UniNa/icons/showIW_on.png +0 -0
  258. PaIRS_UniNa/icons/show_all.png +0 -0
  259. PaIRS_UniNa/icons/sort.png +0 -0
  260. PaIRS_UniNa/icons/sort_reversed.png +0 -0
  261. PaIRS_UniNa/icons/spiv_proc.png +0 -0
  262. PaIRS_UniNa/icons/spiv_proc_off.png +0 -0
  263. PaIRS_UniNa/icons/star.png +0 -0
  264. PaIRS_UniNa/icons/step_inheritance.png +0 -0
  265. PaIRS_UniNa/icons/subMIN_off.png +0 -0
  266. PaIRS_UniNa/icons/subMIN_on.png +0 -0
  267. PaIRS_UniNa/icons/tom.png +0 -0
  268. PaIRS_UniNa/icons/trash.png +0 -0
  269. PaIRS_UniNa/icons/undo.png +0 -0
  270. PaIRS_UniNa/icons/unedited.png +0 -0
  271. PaIRS_UniNa/icons/unina_dii.png +0 -0
  272. PaIRS_UniNa/icons/uninitialized.png +0 -0
  273. PaIRS_UniNa/icons/unlink.png +0 -0
  274. PaIRS_UniNa/icons/unwrap_items.png +0 -0
  275. PaIRS_UniNa/icons/up.png +0 -0
  276. PaIRS_UniNa/icons/updating_import.gif +0 -0
  277. PaIRS_UniNa/icons/updating_pairs.gif +0 -0
  278. PaIRS_UniNa/icons/vectorColor.png +0 -0
  279. PaIRS_UniNa/icons/vettore.png +0 -0
  280. PaIRS_UniNa/icons/view.png +0 -0
  281. PaIRS_UniNa/icons/view_off.png +0 -0
  282. PaIRS_UniNa/icons/vis_logo.png +0 -0
  283. PaIRS_UniNa/icons/waiting_circle.png +0 -0
  284. PaIRS_UniNa/icons/warning.png +0 -0
  285. PaIRS_UniNa/icons/warning_circle.png +0 -0
  286. PaIRS_UniNa/icons/window.png +0 -0
  287. PaIRS_UniNa/icons/workspace.png +0 -0
  288. PaIRS_UniNa/icons/wrap_items.png +0 -0
  289. PaIRS_UniNa/icons/write_list.png +0 -0
  290. PaIRS_UniNa/listLib.py +303 -0
  291. PaIRS_UniNa/mtfPIV.py +256 -0
  292. PaIRS_UniNa/parForMulti.py +435 -0
  293. PaIRS_UniNa/parForWorkers.py +593 -0
  294. PaIRS_UniNa/pivParFor.py +235 -0
  295. PaIRS_UniNa/plt_util.py +141 -0
  296. PaIRS_UniNa/preProcParFor.py +155 -0
  297. PaIRS_UniNa/procTools.py +1391 -0
  298. PaIRS_UniNa/readcfg.py +52 -0
  299. PaIRS_UniNa/rqrdpckgs.txt +8 -0
  300. PaIRS_UniNa/stereoPivParFor.py +227 -0
  301. PaIRS_UniNa/tAVarie.py +215 -0
  302. PaIRS_UniNa/tabSplitter.py +612 -0
  303. PaIRS_UniNa/ui_Calibration_Tab.py +545 -0
  304. PaIRS_UniNa/ui_Custom_Top.py +296 -0
  305. PaIRS_UniNa/ui_Input_Tab.py +1101 -0
  306. PaIRS_UniNa/ui_Input_Tab_CalVi.py +1283 -0
  307. PaIRS_UniNa/ui_Log_Tab.py +263 -0
  308. PaIRS_UniNa/ui_Output_Tab.py +2362 -0
  309. PaIRS_UniNa/ui_Process_Tab.py +3810 -0
  310. PaIRS_UniNa/ui_Process_Tab_CalVi.py +1549 -0
  311. PaIRS_UniNa/ui_Process_Tab_Disp.py +1141 -0
  312. PaIRS_UniNa/ui_Process_Tab_Min.py +437 -0
  313. PaIRS_UniNa/ui_ResizePopup.py +204 -0
  314. PaIRS_UniNa/ui_Vis_Tab.py +1628 -0
  315. PaIRS_UniNa/ui_Vis_Tab_CalVi.py +1251 -0
  316. PaIRS_UniNa/ui_Whatsnew.py +132 -0
  317. PaIRS_UniNa/ui_gPairs.py +871 -0
  318. PaIRS_UniNa/ui_infoPaIRS.py +551 -0
  319. PaIRS_UniNa/whatsnew.txt +6 -0
  320. pairs_unina-0.2.5.dist-info/METADATA +151 -0
  321. pairs_unina-0.2.5.dist-info/RECORD +323 -0
  322. pairs_unina-0.2.5.dist-info/WHEEL +5 -0
  323. pairs_unina-0.2.5.dist-info/top_level.txt +2 -0
PaIRS_UniNa/Vis_Tab.py ADDED
@@ -0,0 +1,2100 @@
1
+ from .ui_Vis_Tab import*
2
+ from .Input_Tab_tools import *
3
+ from .Output_Tab import outType_dict
4
+ from .TabTools import*
5
+ if __package__ or "." in __name__:
6
+ import PaIRS_UniNa.PaIRS_PIV as PaIRS_lib
7
+ else:
8
+ if platform.system() == "Darwin":
9
+ sys.path.append('../lib/mac')
10
+ #sys.path.append('../lib')
11
+ else:
12
+ #sys.path.append('PaIRS_PIV')
13
+ sys.path.append('../lib')
14
+ sys.path.append('TpivPython/lib')
15
+ import PaIRS_PIV as PaIRS_lib # type: ignore
16
+
17
+ spin_tips={
18
+ 'min': 'Minimum level',
19
+ 'mean': 'Mean level',
20
+ 'max': 'Maximum level',
21
+ 'range': 'Level range',
22
+ 'xmin': 'Minimum x coordinate',
23
+ 'xmax': 'Maximum x coordinate',
24
+ 'ymin': 'Minimum y coordinate',
25
+ 'ymax' : 'Maximum y coordinate',
26
+ 'nclev': 'Number of color levels',
27
+ 'vecsize': 'Size of velocity vectors',
28
+ 'vecwid': 'Width of velocity vectors',
29
+ 'vecspac': 'Spacing of velocity vectors',
30
+ 'streamdens': 'Density of streamlines',
31
+ 'img': 'Image number',
32
+ 'frame': 'Frame number',
33
+ 'cam': 'Camera number',
34
+ 'it': 'Iteration number',
35
+ }
36
+ check_tips={}
37
+ radio_tips={}
38
+ line_edit_tips={}
39
+ button_tips={
40
+ 'tool_CollapBox_PlotTools': 'Open/close plot tools box',
41
+ 'CollapBox_PlotTools': 'Open/close plot tools box',
42
+ 'ShowIW': 'Show/hide interrogation windows',
43
+ 'SubMIN': 'Subtract minimum',
44
+ 'Contourf': 'Contour plot mode',
45
+ 'cmap': 'Colormap',
46
+ 'automatic_levels': 'Automatic levels',
47
+ 'automatic_sizes': 'Automatic sizes',
48
+ 'restore': 'Restore levels',
49
+ 'resize': 'Resize',
50
+ 'invert_y': 'Invert y axis',
51
+ 'left': 'Change page setting',
52
+ 'right': 'Change page setting',
53
+ 'qt_toolbar_ext_button': 'Plot interaction',
54
+ 'unit': 'Type of unit',
55
+ 'cvec': 'Color of vectors/streamlines',
56
+ 'view': 'Inspect pre-existing results',
57
+ 'ShowCR': 'Show common region',
58
+ 'dx_left': 'View zone moved to left',
59
+ 'dx_right': 'View zone moved to right',
60
+ 'dy_down': 'View zone moved down',
61
+ 'dy_up': 'View zone moved up',
62
+ 'FocusIW': 'Resize to interrogation window size',
63
+ }
64
+ combo_tips={
65
+ 'map_var': 'Map variable',
66
+ 'field_rep': 'Field representation',
67
+ }
68
+ Flag_VIS_DEBUG=False
69
+
70
+ FlagGenerateColormaps=False
71
+ FlagVerticalColormap=True
72
+ VIS_ColorMaps = {
73
+ 'main': ['gray','jet','viridis', 'cividis', 'inferno', 'hsv','brg'],
74
+ 'Miscellaneous': ['magma','plasma',
75
+ 'terrain', 'ocean','twilight', 'rainbow','cubehelix', 'prism','flag'],
76
+ 'Sequential': ['binary', 'bone', 'pink',
77
+ 'spring', 'summer', 'autumn', 'winter', 'cool',
78
+ 'Wistia', 'hot', 'afmhot', 'gist_heat', 'copper'],
79
+ 'Diverging': ['PiYG', 'PRGn', 'BrBG', 'PuOr', 'RdGy', 'RdBu', 'RdYlBu',
80
+ 'RdYlGn', 'Spectral', 'coolwarm', 'bwr', 'seismic'],
81
+ 'Qualitative': ['Pastel1', 'Pastel2', 'Paired', 'Accent', 'Dark2',
82
+ 'Set1', 'Set2', 'Set3', 'tab10', 'tab20', 'tab20b',
83
+ 'tab20c']
84
+ }
85
+ FlagGenerateColorvectors=False
86
+ VIS_VectorColors={
87
+ 'black': (0, 0, 0),
88
+ 'red': (1, 0, 0),
89
+ 'green': (0, 1, 0),
90
+ 'blue': (0, 0, 1),
91
+ 'cyan': (0, 1, 1),
92
+ 'magenta': (1, 0, 1),
93
+ 'yellow': (1, 1, 0),
94
+ 'white': (1, 1, 1),
95
+ }
96
+ nStepsSlider=1e5
97
+ nPixelsPerVector=10 #one vector each nPixelsPerVector pixels
98
+
99
+ class NamesPIV(TABpar):
100
+
101
+ def __init__(self,Process=ProcessTypes.null,Step=StepTypes.null):
102
+ self.setup(Process,Step)
103
+ super().__init__('OUTpar','Output')
104
+
105
+ def setup(self,Process,Step):
106
+ self.Process = Process
107
+ self.Step = Step
108
+
109
+ self.img='img'
110
+ self.dispMap='dispMap'
111
+ self.X='X'
112
+ self.Y='Y'
113
+ self.Z='Z'
114
+ self.x='x'
115
+ self.y='y'
116
+ self.z='z'
117
+ self.u='U'
118
+ self.v='V'
119
+ self.w='W'
120
+ self.Mod='Mod'
121
+ self.up='uu'
122
+ self.vp='vv'
123
+ self.wp='ww'
124
+ self.uvp='uv'
125
+ self.uwp='uw'
126
+ self.vwp='vw'
127
+ self.ZVort='ZVort'
128
+ self.dPar='dPar'
129
+ self.dOrt='dOrt'
130
+ self.sn='SN'
131
+ self.FCl='CC'
132
+ self.Info='Info'
133
+ allFields={}
134
+ for f,v in self.__dict__.items():
135
+ allFields[v]=f
136
+ self.allFields=allFields
137
+ self.combo_dict={
138
+ self.img: 'image intesity',
139
+ self.dispMap: 'disparity maps',
140
+ self.Mod: 'magnitude',
141
+ self.z: 'z',
142
+ self.u: 'U',
143
+ self.v: 'V',
144
+ self.w: 'W',
145
+ self.up: "<u'u'>",
146
+ self.vp: "<v'v'>",
147
+ self.wp: "<w'w'>",
148
+ self.uvp: "<u'v'>",
149
+ self.uwp: "<u'w'>",
150
+ self.vwp: "<v'w'>",
151
+ self.ZVort: "z-vorticity",
152
+ self.dPar: "epipolar || disp.",
153
+ self.dOrt: "epipolar ⊥ disp.",
154
+ self.sn: "S/N",
155
+ self.Info: "Info",
156
+ self.FCl: "CC"
157
+ }
158
+ self.combo_dict_keys={}
159
+ for k,v in self.combo_dict.items(): self.combo_dict_keys[v]=k
160
+ self.titles_dict={
161
+ self.img: 'intensity',
162
+ self.dispMap: 'disparity maps',
163
+ self.Mod: "velocity magnitude",
164
+ self.z: "z coordinate",
165
+ self.u: "x-velocity component",
166
+ self.v: "y-velocity component",
167
+ self.w: "z-velocity component",
168
+ self.up: "x normal Reynolds stress",
169
+ self.vp: "y normal Reynolds stress",
170
+ self.wp: "z normal Reynolds stress",
171
+ self.uvp: "xy tangential Reynolds stress",
172
+ self.uwp: "xz tangential Reynolds stress",
173
+ self.vwp: "yz tangential Reynolds stress",
174
+ self.ZVort: "z-vorticity component",
175
+ self.dPar: "epipolar parallel displacement",
176
+ self.dOrt: "epipolar orthogonal displacement",
177
+ self.sn: "signal-to-noise ratio",
178
+ self.Info: "outlier info",
179
+ self.FCl: "Correlation coefficient"
180
+ }
181
+ self.titles_cb_dict={
182
+ self.img: '',
183
+ self.dispMap: '',
184
+ self.Mod: "|Vel|",
185
+ self.z: "z",
186
+ self.u: "U",
187
+ self.v: "V",
188
+ self.w: "W",
189
+ self.up: "<u'u'>",
190
+ self.vp: "<v'v'>",
191
+ self.wp: "<w'w'>",
192
+ self.uvp: "<u'v'>",
193
+ self.uwp: "<u'w'>",
194
+ self.vwp: "<v'w'>",
195
+ self.dPar: "d par.",
196
+ self.dOrt: "d ort.",
197
+ self.ZVort: "ωz",
198
+ self.sn: "S/N",
199
+ self.Info: "i",
200
+ self.FCl: "CC"
201
+ }
202
+
203
+ self.fields=list(self.combo_dict)
204
+ self.combo_list=[self.combo_dict[f] for f in self.fields]
205
+ self.titles_list=[self.titles_dict[f] for f in self.fields]
206
+ self.titles_cb_list=[self.titles_cb_dict[f] for f in self.fields]
207
+
208
+ self.img_ind=[self.fields.index(f) for f in [self.img]]
209
+
210
+ # should start with x, y ,u ,v
211
+ if Step==StepTypes.disp:
212
+ self.instVel=[self.x,self.y,self.z,self.dPar,self.dOrt] #,self.FCl]
213
+ self.instVel_plot=[self.z,self.dPar,self.dOrt] #,self.FCl]
214
+ self.avgVel=copy.deepcopy(self.instVel)
215
+ self.avgVel_plot=copy.deepcopy(self.instVel_plot)
216
+ elif Step==StepTypes.spiv:
217
+ self.instVel=[self.x,self.y,self.z,self.u,self.v,self.w,self.FCl,self.Info,self.sn]
218
+ self.instVel_plot=[self.Mod,self.u,self.v,self.w,self.ZVort,self.FCl,self.Info,self.sn]
219
+ self.avgVel=[self.x,self.y,self.z,self.u,self.v,self.w,self.up,self.vp,self.wp,self.uvp,self.uwp,self.vwp,self.FCl,self.Info,self.sn]
220
+ self.avgVel_plot=[self.Mod,self.u,self.v,self.w,self.up,self.vp,self.wp,self.uvp,self.uwp,self.vwp,self.ZVort,self.FCl,self.Info,self.sn]
221
+ else: # for now should be StepTypes.piv
222
+ self.instVel=[self.x,self.y,self.u,self.v,self.FCl,self.Info,self.sn]
223
+ self.instVel_plot=[self.Mod,self.u,self.v,self.ZVort,self.FCl,self.Info,self.sn]
224
+ self.avgVel=[self.x,self.y,self.u,self.v,self.up,self.vp,self.uvp,self.FCl,self.Info,self.sn]
225
+ self.avgVel_plot=[self.Mod,self.u,self.v,self.up,self.vp,self.uvp,self.ZVort,self.FCl,self.Info,self.sn]
226
+
227
+ self.instVelFields=[self.allFields[f] for f in self.instVel ]
228
+ self.instVel_plot_ind=[self.fields.index(f) for f in self.instVel_plot if f in self.fields]
229
+ self.avgVelFields=[self.allFields[f] for f in self.avgVel ]
230
+ self.avgVel_plot_ind=[self.fields.index(f) for f in self.avgVel_plot if f in self.fields]
231
+
232
+ def pick(self,lista,indici):
233
+ return [lista[i] for i in indici]
234
+
235
+ class VISpar(TABpar):
236
+ FlagVis=True
237
+ FlagAutoLevels=True
238
+ FlagAutoSizes=True
239
+ class OUT(TABpar):
240
+ def __init__(self):
241
+ self.x = 0
242
+ self.y = 0
243
+ self.w = None
244
+ self.h = None
245
+ self.vecop = []
246
+
247
+ self.x_min = 0.0
248
+ self.x_max = 0.0
249
+ self.y_min = 0.0
250
+ self.y_max = 0.0
251
+
252
+ self.xres = 1
253
+ self.pixAR = 1
254
+
255
+ self.zconst = 0.0
256
+ self.xterm = 0.0
257
+ self.yterm = 0.0
258
+
259
+ super().__init__('VISpar.Out','Vis')
260
+
261
+ class PRO(TABpar):
262
+ def __init__(self):
263
+ WSize_init=[128, 64, 32]
264
+ WSpac_init=[ 32, 16, 8]
265
+ self.Vect=[copy.deepcopy(WSize_init),copy.deepcopy(WSpac_init),copy.deepcopy(WSize_init),copy.deepcopy(WSpac_init)]
266
+ self.FlagBordo=False
267
+ super().__init__('VISpar.Pro','Vis')
268
+
269
+ def __init__(self,Process=ProcessTypes.null,Step=StepTypes.null):
270
+ self.setup(Process,Step)
271
+ super().__init__('VISpar','Vis')
272
+ self.unchecked_fields+=['FlagAutomaticLevels','FlagAutomaticSizes','setPage']
273
+ self.uncopied_fields+=['graphics_fields']
274
+
275
+ def setup(self,Process,Step):
276
+ self.Process = Process
277
+ self.Step = Step
278
+ self.FlagView = False
279
+
280
+ self.img=-1
281
+ self.nimg=0
282
+ self.frame=1
283
+ self.it=1
284
+ self.cam=0
285
+ self.ncam=0
286
+
287
+ self.path=''
288
+ self.imList=[[[],[]]*self.ncam]
289
+ self.image_file=''
290
+ self.fres=[] #lambda k: ''
291
+ self.outPathRoot='' #useful in procOhtName(self.VISpar)
292
+ self.name_proc=''
293
+ self.result_file=''
294
+ self.FlagResult=False
295
+
296
+ fields_noGraphics=[f for f,_ in self.__dict__.items()]
297
+ self.type = 0
298
+ self.FlagMIN = False
299
+ self.FlagTR = False
300
+ self.LaserType = 0
301
+ self.Nit = 1
302
+ self.imListMin=[[[],[]]*self.ncam]
303
+
304
+ self.image_file_Min=''
305
+ self.image_file_Disp=''
306
+ self.result_file_Mean=''
307
+ self.image_file_Current=''
308
+ self.result_file_Current=''
309
+
310
+ self.FlagShowIW=False
311
+ self.FlagShowCR=False
312
+ self.FlagSubMIN=False
313
+ self.variable=''
314
+ self.variableKey=''
315
+ self.field_rep=0
316
+
317
+ self.FlagYInvert=[False,False]
318
+ self.FlagResetLevels=True
319
+ self.FlagResetSizes=True
320
+ self.setPage=0
321
+
322
+ namesPIV=NamesPIV()
323
+ img=namesPIV.img
324
+ dispMap=namesPIV.dispMap
325
+ self.vcolorMap={img: 'gray', dispMap: 'gray'}
326
+ self.colorMap='gray'
327
+ self.vvectorColor={img: 'green', dispMap: 'green'}
328
+ self.vectorColor='green'
329
+ self.vLim={img: 1, dispMap: 1}
330
+ self.vmin_default={img: 0, dispMap: 0}
331
+ self.vmax_default={img: 1, dispMap: 0}
332
+ self.vmean_default={img: 0.5, dispMap: 0.5}
333
+ self.vrange_default={img: 1, dispMap: 1}
334
+ self.vmin={img: 0, dispMap: 0}
335
+ self.vmax={img: 1, dispMap: 1}
336
+ self.vmean={img: 0.5, dispMap: 0.5}
337
+ self.vrange={img: 1, dispMap: 1}
338
+ self.min=0
339
+ self.max=1
340
+ self.mean=0.5
341
+ self.range=1
342
+
343
+ self.unit=[False,True]
344
+ self.size_default=[[0,1,0,1,1],[0,1,0,1,1]] #xmin,xmax,ymin,ymax,max vec spacing
345
+ self.size=[[0,1,0,1,1],[0,1,0,1,1]] #xmin,xmax,ymin,ymax,max vec spacing
346
+ self.xmin=0
347
+ self.xmax=1
348
+ self.ymin=0
349
+ self.ymax=1
350
+
351
+ self.nclev=30
352
+ self.vecsize=1
353
+ self.vecwid=1
354
+ self.vecspac=1
355
+ self.streamdens=1
356
+
357
+ self.FlagContourf=True
358
+
359
+ self.graphics_fields=[f for f,_ in self.__dict__.items() if f not in fields_noGraphics]
360
+
361
+ self.Out=self.OUT()
362
+ self.Pro=self.PRO()
363
+
364
+ self.FlagCAL = Process in ProcessTypes.threeCameras
365
+ self.calList = []
366
+ self.calEx = []
367
+
368
+ #self.FlagDISP = Step==StepTypes.disp
369
+ #self.dispFile = ''
370
+
371
+ def resF(self,i,string=''):
372
+ fres=self.fres
373
+ if not fres: return ''
374
+ outPathRoot=fres[0]
375
+ if string=='dispMap':
376
+ fold=os.path.dirname(self.outPathRoot)
377
+ rad=os.path.splitext(os.path.basename(self.outPathRoot))[0]
378
+ if rad[-1]!='_': rad+='_'
379
+ return myStandardRoot(os.path.join(fold, f'dispMap_rot_{rad}{i}.png'))
380
+ ndig=fres[1]
381
+ outExt=fres[2]
382
+ if type(i)==str:
383
+ return f"{outPathRoot}{i}{outExt}"
384
+ elif type(i)==int:
385
+ return f"{outPathRoot}{i:0{ndig:d}d}{outExt}"
386
+ else:
387
+ return ''
388
+
389
+ class Vis_Tab(gPaIRS_Tab):
390
+ class VIS_Tab_Signals(gPaIRS_Tab.Tab_Signals):
391
+ pass
392
+
393
+ def __init__(self,parent: QWidget =None, flagInit= __name__ == "__main__"):
394
+ super().__init__(parent,Ui_VisTab,VISpar)
395
+ self.signals=self.VIS_Tab_Signals(self)
396
+
397
+ #------------------------------------- Graphical interface: widgets
398
+ self.TABname='Vis'
399
+ self.ui: Ui_VisTab
400
+ self.Ptoolbar=None
401
+ self.addPlotToolBar()
402
+ self.ui.plot.axes.format_coord=lambda x,y: self.custom_format_coord(x,y)
403
+
404
+ self.ui.sliders=self.findChildren(QSlider)
405
+ for slider in (self.ui.slider_min,self.ui.slider_max,self.ui.slider_mean,self.ui.slider_range):
406
+ slider.setMinimum(0)
407
+ slider.setMaximum(nStepsSlider)
408
+ slider.setSingleStep(int(nStepsSlider/100))
409
+
410
+ #necessary to change the name and the order of the items
411
+ for g in list(globals()):
412
+ if '_items' in g or '_ord' in g or '_tips' in g:
413
+ #pri.Info.blue(f'Adding {g} to {self.name_tab}')
414
+ setattr(self,g,eval(g))
415
+
416
+ if __name__ == "__main__":
417
+ self.app=app
418
+ setAppGuiPalette(self)
419
+
420
+ #------------------------------------- Graphical interface: miscellanea
421
+ self.brush_cursor= QCursor(QPixmap(icons_path+"brush_cursor.png").scaled(24,24,mode=Qt.TransformationMode.SmoothTransformation))
422
+ self.FlagNormalCursor=True
423
+
424
+ self.img=None
425
+ self.imgshow=None
426
+ self.cb=None
427
+ self.orect=[]
428
+ self.xres=self.yres=1.0
429
+
430
+ self.map=None
431
+ self.contour=None
432
+ self.qui=None
433
+ self.stream=None
434
+ self.CR=None
435
+ self.RF=None
436
+
437
+ self.namesPIV=NamesPIV()
438
+
439
+ pri.Time.magenta('Colormap generation: start')
440
+ # Create the popup menu
441
+ self.colorMapMenu = QMenu(self)
442
+ # Add the colormap thumbnails to the menu
443
+ def on_colormap_selected(name):
444
+ self.VISpar.vcolorMap[self.VISpar.variableKey]=self.VISpar.colorMap=name
445
+ for k, colorMapClass in enumerate(VIS_ColorMaps):
446
+ if not k: menu=self.colorMapMenu
447
+ else: menu=self.colorMapMenu.addMenu(colorMapClass)
448
+ #for colormap in VIS_ColorMaps[colorMapClass]:
449
+ for colormap in VIS_ColorMaps[colorMapClass]:
450
+ imgMapPath=icons_path+'colormaps/'+colormap+'.png'
451
+ if os.path.exists(imgMapPath) and not FlagGenerateColormaps:
452
+ pixmap = QPixmap(imgMapPath)
453
+ else:
454
+ pixmap=create_colormap_image(colormap, 25, 50, FlagVerticalColormap, imgMapPath)
455
+ action = menu.addAction(QIcon(pixmap), ' '+colormap)
456
+ action.triggered.connect(lambda _, name=colormap: on_colormap_selected(name))
457
+ pri.Time.magenta('Colormap generation: end')
458
+
459
+ pri.Time.magenta('Vector color generation: start')
460
+ # Create the popup menu
461
+ self.vectorColorMenu = QMenu(self)
462
+ # Add the colormap thumbnails to the menu
463
+ def on_vectorcolor_selected(name):
464
+ self.VISpar.vvectorColor[self.VISpar.variableKey]=self.VISpar.vectorColor=name
465
+ for colorName, color in VIS_VectorColors.items():
466
+ menu=self.vectorColorMenu
467
+ #for colormap in VIS_ColorMaps[colorMapClass]:
468
+ imgMapPath=icons_path+'colormaps/'+colorName+'Vector.png'
469
+ if os.path.exists(imgMapPath) and not FlagGenerateColorvectors:
470
+ pixmap = QPixmap(imgMapPath)
471
+ else:
472
+ pixmap=create_arrow_pixmap(color, 50, 50, imgMapPath)
473
+ action = menu.addAction(QIcon(pixmap), ' '+colorName.lower())
474
+ action.triggered.connect(lambda _, name=colorName: on_vectorcolor_selected(name))
475
+ pri.Time.magenta('Vector color generation: end')
476
+
477
+ #------------------------------------- Declaration of parameters
478
+ self.VISpar_base=VISpar()
479
+ self.VISpar:VISpar=self.TABpar
480
+ self.VISpar_old:VISpar=self.TABpar_old
481
+
482
+ #------------------------------------- Callbacks
483
+ self.defineWidgets()
484
+ self.setupWid() #---------------- IMPORTANT
485
+
486
+ FlagPreventAddPrev_Slider=False
487
+ for n in ('min','max','mean','range','nclev','vecsize','vecwid','vecspac','streamdens'):
488
+ def defineSliderCallbackSet(n):
489
+ spin:QSpinBox=getattr(self.ui,'spin_'+n)
490
+ slider:QSlider=getattr(self.ui,'slider_'+n)
491
+
492
+ if n in ('min','max','mean','range'):
493
+ changingAction=lambda: self.sliderLevels_changing(spin,slider,FlagPreventAddPrev_Slider)
494
+ callback=self.wrappedCallback(spin_tips[n],changingAction)
495
+ action=lambda: self.spinLevels_action(spin)
496
+ elif n in ('nclev','vecsize','vecwid','vecspac','streamdens'):
497
+ changingAction=lambda: self.sliderFieldRep_changing(spin,slider,FlagPreventAddPrev_Slider)
498
+ callback=self.wrappedCallback(spin_tips[n],changingAction)
499
+ action=lambda: self.spinFieldRep_action(spin)
500
+ setting=lambda: self.slider_set(spin,slider)
501
+
502
+ slider.valueChanged.connect(callback)
503
+
504
+ if n in ('nclev','streamdens'):
505
+ def sliderMessage(s:QSlider):
506
+ if self.VISpar.field_rep==2:
507
+ tip = f"Release to repaint"
508
+ else: tip=""
509
+ QToolTip.showText(s.mapToGlobal(s.rect().topLeft()), tip)
510
+ slider.sliderPressed.connect(lambda: sliderMessage(slider))
511
+
512
+ setattr(self,'slider_'+n+'_callbcak',callback)
513
+ setattr(self,'spin_'+n+'_action',action)
514
+ setattr(self,'spin_'+n+'_set',setting)
515
+
516
+ defineSliderCallbackSet(n)
517
+
518
+
519
+ for k,n in enumerate(['xmin','xmax','ymin','ymax']):
520
+ def defineXYAction(k,n):
521
+ spin=getattr(self.ui,'spin_'+n)
522
+ action=lambda: self.spin_xy_action(spin,k)
523
+ setattr(self,'spin_'+n+'_action',action)
524
+ defineXYAction(k,n)
525
+
526
+ self.plot_callback=self.wrappedCallback('Plot interaction',self.updatingPlot)
527
+ self.ui.plot.addfuncrelease['fPlotCallback']=self.plot_callback
528
+
529
+ self.button_left_action=lambda: self.leftrightCallback(-1)
530
+ self.button_right_action=lambda: self.leftrightCallback(+1)
531
+
532
+ self.QS_copy2clipboard=QShortcut(QKeySequence('Ctrl+C'), self.ui.plot)
533
+ self.QS_copy2clipboard.activated.connect(self.ui.plot.copy2clipboard)
534
+ self.QS_copy2newfig=QShortcut(QKeySequence('Ctrl+D'), self.ui.plot)
535
+ self.QS_copy2newfig.activated.connect(lambda: self.ui.plot.copy2newfig(self.ui.name_var.toolTip()))
536
+ self.load_Img_callback=self.wrappedCallback('Loading image',self.loadImg)
537
+ self.load_Res_callback=self.wrappedCallback('Loading result',self.loadRes)
538
+
539
+ self.defineCallbacks()
540
+ self.spins_valueChanged=[self.ui.spin_img,self.ui.spin_frame,self.ui.spin_cam,self.ui.spin_it]
541
+ self.connectCallbacks()
542
+
543
+ self.defineSettings()
544
+ self.TABsettings.append(self.setMapVar)
545
+
546
+ self.adjustTABpar=self.adjustVISpar
547
+ self.setTABlayout=self.setVISlayout
548
+
549
+ self.FlagReset=True
550
+ self.FlagResetLevels=True
551
+ self.FlagResetSizes =True
552
+
553
+ self.image_file=''
554
+ self.image_raw=None
555
+ self.image=None
556
+ self.image_file_Min=''
557
+ self.image_Min_raw=None
558
+ self.image_Min=None
559
+ self.image_file_Disp=''
560
+ self.image_Disp_raw=None
561
+ self.image_Disp=None
562
+ self.nbits=0
563
+ self.result_file=''
564
+ self.result=None
565
+ self.result_file_Mean=''
566
+ self.result_Mean=None
567
+ self.image_file_Load=''
568
+ self.result_file_Load=''
569
+
570
+ self.image_Current_raw=None
571
+ self.image_Current=None
572
+ self.result_Current=None
573
+
574
+ self.FlagAddPrev=False
575
+
576
+ #------------------------------------- Initializing
577
+ if flagInit:
578
+ self.initialize()
579
+ #else:
580
+ # self.adjustTABpar()
581
+ # self.setTABpar(FlagBridge=False)
582
+
583
+ def addPlotToolBar(self):
584
+ if self.Ptoolbar:
585
+ self.Ptoolbar.setParent(None)
586
+ self.Ptoolbar = NavigationToolbar(self.ui.plot, self)
587
+ unwanted_buttons = ['Home','Back','Forward','Customize'] #'Subplots','Save'
588
+ for x in self.Ptoolbar.actions():
589
+ if x.text() in unwanted_buttons:
590
+ self.Ptoolbar.removeAction(x)
591
+ self.ui.lay_w_Plot.addWidget(self.Ptoolbar)
592
+
593
+ def initialize(self):
594
+ pri.Info.yellow(f'{"*"*20} VIS initialization {"*"*20}')
595
+ self.setExample()
596
+ self.adjustVISpar()
597
+ self.setVISlayout()
598
+ self.setTABpar(FlagBridge=False) #with bridge
599
+ self.add_TABpar('initialization')
600
+
601
+ def setExample(self):
602
+ if not basefold_DEBUG_VIS: return
603
+ imSet=ImageSet(path=basefold_DEBUG_VIS)
604
+
605
+ k1=0
606
+ k2=imSet.link[k1][0]
607
+ self.VISpar.path=imSet.path
608
+ self.VISpar.imList,_=imSet.genListsFromFrame([k1],[k2+1],imSet.ind_in[k1],imSet.nimg[k1],1,False)
609
+
610
+ outPath=myStandardPath(os.path.dirname(imSet.outFiles[outExt.piv][0]))
611
+ outSet=ImageSet(path=outPath,exts=list(outType_dict))
612
+
613
+ im_min_a=findFiles_sorted(outPath+'*a_min.*')
614
+ if im_min_a: self.VISpar.imListMin[0].append(im_min_a[0])
615
+ im_min_b=findFiles_sorted(outPath+'*b_min.*')
616
+ if im_min_b: self.VISpar.imListMin[0].append(im_min_b[0])
617
+ self.VISpar.fres=[outPath+outSet.fname[0][0],outSet.fname[0][1],outSet.fname[0][2]] #lambda i: outPath+outSet.nameF(outSet.fname[0],i)
618
+ self.VISpar.result_file_Mean=self.VISpar.resF('*').replace('_*','')
619
+ self.VISpar.img=1
620
+ self.VISpar.Out.FlagNone=True
621
+ return
622
+
623
+ #*************************************************** Adjusting parameters
624
+ def adjustVISpar(self):
625
+ self.VISpar.ncam=len(self.VISpar.imList)
626
+ if self.VISpar.ncam and not self.VISpar.cam: self.VISpar.cam=1
627
+ self.VISpar.nimg=len(self.VISpar.imList[0][0]) if len(self.VISpar.imList[0]) else 0 if self.VISpar.ncam else 0
628
+ if not self.VISpar.nimg and self.VISpar.img:
629
+ FlagResults=self.image_file_Min!='' or self.result_file_Mean!='' or self.image_file_Disp!=''
630
+ self.VISpar.img=0 if FlagResults else -1
631
+
632
+ FlagNewImage, FlagNewResult = self.adjustImport()
633
+
634
+ FlagNew=(not self.VISpar.type and FlagNewImage) or (self.VISpar.type==1 and FlagNewResult)
635
+ FlagDiff=self.VISpar.isDifferentFrom(self.VISpar_old,fields=['img','cam','frame']) or FlagNew
636
+
637
+ if (VISpar.FlagAutoLevels and (FlagNewImage or FlagNewResult)):
638
+ self.resetAllLevels()
639
+ if FlagDiff or self.FlagResetLevels:
640
+ self.FlagResetLevels=False
641
+ self.resetLevels()
642
+ elif self.FlagResetLevels:
643
+ self.FlagResetLevels=False
644
+ self.resetLevels()
645
+
646
+ if (VISpar.FlagAutoSizes and (FlagNewImage or FlagNewResult)):
647
+ self.resetAllXYLims()
648
+ if FlagDiff or self.FlagResetSizes:
649
+ self.FlagResetSizes=False
650
+ self.resetXYLims()
651
+ elif self.FlagResetSizes:
652
+ self.FlagResetSizes=False
653
+ self.resetXYLims()
654
+
655
+ self.adjustFieldRep()
656
+
657
+ def adjustImport(self):
658
+ self.VISpar.image_file=self.VISpar.image_file_Min=self.VISpar.image_file_Disp=''
659
+ if self.VISpar.img%2==0 and self.VISpar.FlagTR and not self.VISpar.LaserType:
660
+ f=[1,0][self.VISpar.frame-1]
661
+ else: f=self.VISpar.frame-1
662
+ self.VISpar.image_file_Disp=''
663
+ FlagDisparity=self.VISpar.Step==StepTypes.disp and (resultCheck(self,self.VISpar,ind=self.VISpar.ind) or self.VISpar.FlagView)
664
+ if FlagDisparity:
665
+ dispMap_filename=self.VISpar.resF(f'it{self.VISpar.it}',string='dispMap')
666
+ if os.path.exists(dispMap_filename):
667
+ self.VISpar.image_file_Disp=dispMap_filename
668
+ self.VISpar.image_file_Min=''
669
+ ITEs=self.gui.ui.Explorer.ITEsfromInd(self.VISpar.ind)
670
+ ind_min=list(ITEs[0].children).index(StepTypes.min)
671
+ FlagMinimum=(self.VISpar.FlagMIN or self.VISpar.Step==StepTypes.min) and (resultCheck(self,self.VISpar,ind=ITEs[ind_min+1].ind) or self.VISpar.FlagView)
672
+ if FlagMinimum:
673
+ if 0<=self.VISpar.cam-1<self.VISpar.ncam:
674
+ if 0<=f<len(self.VISpar.imListMin[self.VISpar.cam-1]):
675
+ self.VISpar.image_file_Min=self.VISpar.imListMin[self.VISpar.cam-1][f]
676
+ if self.VISpar.img>0:
677
+ self.VISpar.image_file=self.VISpar.path+self.VISpar.imList[self.VISpar.cam-1][self.VISpar.frame-1][self.VISpar.img-1] if len(self.VISpar.imList[self.VISpar.cam-1][self.VISpar.frame-1]) else ''
678
+ elif self.VISpar.img==0:
679
+ self.VISpar.image_file=self.VISpar.image_file_Current if self.VISpar.flagRun==-2 else self.VISpar.image_file_Disp if self.VISpar.variableKey==self.namesPIV.dispMap else self.VISpar.image_file_Min
680
+ else:
681
+ self.VISpar.image_file=self.image_file_Load
682
+
683
+ self.VISpar.result_file=self.VISpar.result_file_Mean=''
684
+ if self.VISpar.img==-1:
685
+ self.VISpar.result_file=self.result_file_Load
686
+ elif self.VISpar.img==0 and self.VISpar.flagRun==-2:
687
+ if (self.VISpar.Step==StepTypes.disp and self.VISpar.it==self.VISpar.Nit) or self.VISpar.Step!=StepTypes.disp:
688
+ self.VISpar.result_file=self.VISpar.result_file_Current
689
+ else:
690
+ self.VISpar.FlagResult=self.VISpar.Step!=StepTypes.min and (resultCheck(self,self.VISpar) or self.VISpar.FlagView)
691
+ if self.VISpar.FlagResult:
692
+ if self.VISpar.Step==StepTypes.disp:
693
+ self.VISpar.result_file_Mean=self.VISpar.resF(f'it{self.VISpar.it}')
694
+ else:
695
+ self.VISpar.result_file_Mean=self.VISpar.resF('*').replace('_*','')
696
+ if self.VISpar.img>0:
697
+ if self.VISpar.Step==StepTypes.disp:
698
+ self.VISpar.result_file=''
699
+ else:
700
+ self.VISpar.result_file=self.VISpar.resF(self.VISpar.img)
701
+ elif self.VISpar.img==0:
702
+ self.VISpar.result_file=self.VISpar.result_file_Mean
703
+
704
+ FlagNewImage, FlagNewResult, _=self.importFiles()
705
+ return FlagNewImage, FlagNewResult
706
+
707
+ def importFiles(self):
708
+ if self.VISpar.image_file_Min!=self.image_file_Min or self.VISpar.FlagMIN!=self.VISpar_old.FlagMIN or self.FlagReset:
709
+ self.image_file_Min,self.image_Min_raw=self.readImageFile(self.VISpar.image_file_Min)
710
+ if self.VISpar.image_file_Disp!=self.image_file_Disp or self.FlagReset:
711
+ self.image_file_Disp,self.image_Disp_raw=self.readImageFile(self.VISpar.image_file_Disp)
712
+ if self.VISpar.result_file_Mean!=self.result_file_Mean or self.VISpar.FlagResult!=self.VISpar_old.FlagResult or self.FlagReset:
713
+ self.result_file_Mean,self.result_Mean=self.readResultFile(self.VISpar.result_file_Mean)
714
+
715
+ FlagNewImage=self.VISpar.image_file!=self.image_file or self.VISpar.ind[:-1]!=self.VISpar_old.ind[:-1]
716
+ if FlagNewImage or self.FlagReset:
717
+ self.image_file=self.VISpar.image_file
718
+ if self.VISpar.img==0:
719
+ if self.VISpar.flagRun==-2:
720
+ self.image_raw=self.image_Current_raw[self.VISpar.frame] if self.image_Current_raw else None
721
+ else:
722
+ self.image_raw=self.image_Disp_raw if self.VISpar.variableKey==self.namesPIV.dispMap else self.image_Min_raw
723
+ else:
724
+ self.image_file,self.image_raw=self.readImageFile(self.VISpar.image_file)
725
+ mapVariableList=[]
726
+ #if self.image_raw is None and self.VISpar.img==0: mapVariableList=[]
727
+ #else:
728
+ if self.image_Disp_raw is not None and self.VISpar.img==0: mapVariableList+=[self.namesPIV.dispMap]
729
+ if (self.image_Min_raw is not None and self.VISpar.img==0) or self.VISpar.img!=0: mapVariableList+=[self.namesPIV.img]
730
+
731
+ FlagNewResult=self.VISpar.result_file!=self.result_file or self.VISpar.ind[:-1]!=self.VISpar_old.ind[:-1]
732
+ if FlagNewResult or self.FlagReset:
733
+ self.result_file=self.VISpar.result_file
734
+ if self.VISpar.img==0:
735
+ if self.VISpar.flagRun==-2:
736
+ self.result=self.result_Current
737
+ else:
738
+ self.result=self.result_Mean
739
+ else:
740
+ self.result_file,self.result=self.readResultFile(self.VISpar.result_file)
741
+
742
+ if self.image_raw is not None:
743
+ if self.VISpar.img>=0 and self.VISpar.variableKey!=self.namesPIV.dispMap:
744
+ self.image=transfIm(self.VISpar.Out,Images=[self.image_raw])[0]
745
+ else:
746
+ self.image=self.image_raw
747
+ self.getImageInfo()
748
+ else:
749
+ self.image=None
750
+ if self.image_Min_raw is not None:
751
+ self.image_Min=transfIm(self.VISpar.Out,Images=[self.image_Min_raw])[0]
752
+ else:
753
+ self.image_Min=None
754
+ if self.image_Disp_raw is not None:
755
+ self.image_Disp=self.image_Disp_raw #transfIm(self.VISpar.Out,Images=[self.image_Disp_raw])[0]
756
+ else:
757
+ self.image_Disp=None
758
+ if self.result is not None:
759
+ self.getResultInfo()
760
+
761
+ if self.result:
762
+ [mapVariableList.append(r) for r in list(self.result)]
763
+ self.FlagReset=False
764
+
765
+ comboItemsList=[]
766
+ if self.namesPIV.img in mapVariableList: comboItemsList+=[self.namesPIV.combo_dict[self.namesPIV.img]]
767
+ if self.namesPIV.dispMap in mapVariableList: comboItemsList+=[self.namesPIV.combo_dict[self.namesPIV.dispMap]]
768
+ for f in list(self.namesPIV.combo_dict)[2:]:
769
+ if f in mapVariableList: comboItemsList.append(self.namesPIV.combo_dict[f])
770
+ if len(comboItemsList)==0: comboItemsList=[self.namesPIV.combo_dict[self.namesPIV.img]]
771
+ if self.VISpar.variable not in comboItemsList:
772
+ self.VISpar.variable=comboItemsList[0]
773
+ self.VISpar.variableKey=self.namesPIV.combo_dict_keys[self.VISpar.variable]
774
+ if self.VISpar.variableKey==self.namesPIV.img and self.VISpar.img==0:
775
+ if self.VISpar.image_file!=self.VISpar.image_file_Min:
776
+ self.VISpar.image_file=self.VISpar.image_file_Min
777
+ self.image=self.image_Min
778
+ self.getImageInfo()
779
+ elif self.VISpar.variableKey==self.namesPIV.dispMap and self.VISpar.img==0:
780
+ if self.VISpar.image_file!=self.VISpar.image_file_Disp:
781
+ self.VISpar.image_file=self.VISpar.image_file_Disp
782
+ self.image=self.image_Disp
783
+ self.getImageInfo()
784
+ self.VISpar.type=int(self.VISpar.variableKey not in (self.namesPIV.img, self.namesPIV.dispMap) )
785
+
786
+ return FlagNewImage, FlagNewResult, comboItemsList
787
+
788
+ def checkVISTab(self,ind=None):
789
+ if ind is None: VIS:VISpar=self.VISpar
790
+ else: VIS:VISpar=self.TABpar_at(ind)
791
+ VIS.OptionDone=1 if (VIS.flagRun>0 and resultCheck(self,VIS)) or VIS.flagRun<=0 else 0
792
+
793
+ def adjustFieldRep(self):
794
+ if self.VISpar_old.field_rep!=self.VISpar.field_rep and self.result:
795
+ if not self.VISpar.unit[self.VISpar.type]:
796
+ xres,yres=self.getXYRes(type=1)
797
+ else: xres=yres=1.0
798
+ if self.namesPIV.x in self.result and self.namesPIV.y in self.result:
799
+ X=self.result[self.namesPIV.x]*xres
800
+ Y=self.result[self.namesPIV.y]*yres
801
+ elif self.namesPIV.X in self.result and self.namesPIV.Y in self.result:
802
+ X=self.result[self.namesPIV.X]*xres
803
+ Y=self.result[self.namesPIV.Y]*yres
804
+ else: return
805
+ dX=np.sqrt((X[0,1]-X[0,0])**2+(Y[1,0]-Y[0,0])**2)
806
+ dW=[X.max()-X.min(),Y.max()-Y.min()]
807
+ size_pixels=self.ui.plot.fig.get_size_inches()*self.ui.plot.fig.get_dpi()*self.ui.plot.axes.get_position().bounds[2:]
808
+ spaPixels=dX*size_pixels/dW
809
+ fac_spa=np.max(nPixelsPerVector/spaPixels).astype(int).item()
810
+ self.VISpar.vecspac=max([1,fac_spa])
811
+ self.VISpar.vecsize=5
812
+ self.VISpar.vecwid=1
813
+
814
+ #*************************************************** Layout
815
+ def setVISlayout(self):
816
+ _, _, comboItemsList=self.importFiles()
817
+ self.checkResVariables()
818
+
819
+ FlagLoad=self.image_file_Load!='' or self.result_file_Load!=''
820
+ FlagResults=self.image_file_Min!='' or self.result_file_Mean!='' or self.image_file_Disp!=''
821
+ FlagSpinsEnabled=self.VISpar.nimg or FlagLoad
822
+ FlagDispMap=self.VISpar.variableKey==self.namesPIV.dispMap
823
+ #self.ui.Plot_tools.setEnabled(FlagSpinsEnabled)
824
+
825
+ FlagIW=self.VISpar.type==0 and self.VISpar.Step in (StepTypes.piv,StepTypes.disp,StepTypes.spiv) and not FlagDispMap
826
+ self.ui.button_ShowIW.setVisible(FlagIW)
827
+ if FlagIW:
828
+ tip=f"{'Hide' if self.ui.button_ShowIW.isChecked() else 'Show'} Interrogation Window scheme"
829
+ self.ui.button_ShowIW.setToolTip(tip)
830
+ self.ui.button_ShowIW.setStatusTip(tip)
831
+
832
+ FlagCR=self.VISpar.type==0 and self.VISpar.Step in (StepTypes.disp,StepTypes.spiv) and not FlagDispMap
833
+ self.ui.button_ShowCR.setVisible(FlagCR)
834
+ if FlagCR:
835
+ tip=f"{'Hide' if self.ui.button_ShowCR.isChecked() else 'Show'} common region"
836
+ self.ui.button_ShowCR.setToolTip(tip)
837
+ self.ui.button_ShowCR.setStatusTip(tip)
838
+
839
+ FlagMIN=self.VISpar.type==0 and self.image_Min is not None and self.VISpar.img>0 #and self.VISpar.FlagMIN
840
+ self.ui.button_SubMIN.setVisible(FlagMIN)
841
+ if FlagMIN:
842
+ tip=f"{'Add' if self.ui.button_SubMIN.isChecked() else 'Subtract'} historical minimum background"
843
+ self.ui.button_SubMIN.setToolTip(tip)
844
+ self.ui.button_SubMIN.setStatusTip(tip)
845
+
846
+ self.ui.line_img.setVisible(FlagIW or FlagMIN)
847
+
848
+ FlagUnit=self.VISpar.Process==ProcessTypes.piv and (self.VISpar.Out.xres!=1.0 or self.VISpar.Out.pixAR!=1.0)
849
+ self.ui.button_unit.setVisible(FlagUnit)
850
+ if FlagUnit:
851
+ tip=f"Set {'pixel' if self.ui.button_unit.isChecked() else 'physical'} units"
852
+ self.ui.button_unit.setToolTip(tip)
853
+ self.ui.button_unit.setStatusTip(tip)
854
+
855
+ self.ui.line_unit.setVisible(FlagUnit)
856
+
857
+ self.ui.button_Contourf.setVisible(self.VISpar.type)
858
+ self.ui.line_Contourf.setVisible(self.VISpar.type==1)
859
+
860
+ self.ui.combo_map_var.clear()
861
+ self.ui.combo_map_var.addItems(comboItemsList)
862
+
863
+ FlagResult=self.result is not None and "U" in self.result and "V" in self.result and (self.VISpar.type>0 or self.VISpar.Step==StepTypes.piv)
864
+ self.ui.button_cvec.setVisible(FlagResult and self.VISpar.field_rep!=0)
865
+ self.ui.label_field_rep.setVisible(FlagResult)
866
+ self.ui.combo_field_rep.setVisible(FlagResult)
867
+
868
+ i=self.VISpar.setPage
869
+ c=self.ui.image_levels.count()-1-int(not FlagResult or (self.VISpar.type==0 and self.VISpar.field_rep==0)) #or (not self.VISpar.FlagContourf and not self.VISpar.field_rep))
870
+ if i>c: i=0
871
+ self.ui.image_levels.setCurrentIndex(i)
872
+ self.ui.label_title.setText(f"Settings ({i+1}/{c+1})")
873
+
874
+ Lim=self.VISpar.vLim[self.VISpar.variableKey]
875
+ step=Lim/nStepsSlider
876
+ FlagLim= self.VISpar.type or FlagDispMap
877
+ self.ui.spin_min.setMinimum(-Lim if FlagLim else 0)
878
+ self.ui.spin_min.setMaximum(Lim-2*step)
879
+ self.ui.spin_max.setMinimum(-Lim+2*step if FlagLim else 2*step)
880
+ self.ui.spin_max.setMaximum(Lim)
881
+ self.ui.spin_mean.setMinimum(-Lim+step if FlagLim else step)
882
+ self.ui.spin_mean.setMaximum(Lim-step)
883
+ self.ui.spin_range.setMinimum(2*step)
884
+ self.ui.spin_range.setMaximum(2*Lim if FlagLim else step)
885
+ self.ui.spin_vecspac.setMaximum(self.VISpar.size[1][4])
886
+
887
+ self.ui.label_vecspac.setVisible(self.VISpar.field_rep==1)
888
+ self.ui.slider_vecspac.setVisible(self.VISpar.field_rep==1)
889
+ self.ui.spin_vecspac.setVisible(self.VISpar.field_rep==1)
890
+ self.ui.label_vecsize.setVisible(self.VISpar.field_rep==1)
891
+ self.ui.slider_vecsize.setVisible(self.VISpar.field_rep==1)
892
+ self.ui.spin_vecsize.setVisible(self.VISpar.field_rep==1)
893
+ self.ui.label_vecwid.setVisible(self.VISpar.field_rep==1)
894
+ self.ui.slider_vecwid.setVisible(self.VISpar.field_rep==1)
895
+ self.ui.spin_vecwid.setVisible(self.VISpar.field_rep==1)
896
+ self.ui.spin_vecspac.setMaximum(self.VISpar.size_default[1][-1])
897
+ self.ui.label_streamdens.setVisible(self.VISpar.field_rep==2)
898
+ self.ui.slider_streamdens.setVisible(self.VISpar.field_rep==2)
899
+ self.ui.spin_streamdens.setVisible(self.VISpar.field_rep==2)
900
+
901
+ self.ui.spin_img.setMinimum(-1)
902
+ self.ui.spin_img.setMaximum(self.VISpar.nimg if self.VISpar.nimg else 0 if FlagResults else -1)
903
+ #self.ui.spin_img.setEnabled(FlagSpinsEnabled)
904
+ self.ui.spin_frame.setEnabled(FlagSpinsEnabled)
905
+ self.ui.spin_cam.setMaximum(self.VISpar.ncam)
906
+ self.ui.spin_cam.setEnabled(FlagSpinsEnabled and self.VISpar.ncam>1)
907
+
908
+ FlagCamFrame=self.VISpar.img>-1 and self.VISpar.type==0 and not FlagDispMap
909
+ self.ui.label_frame.setVisible(FlagCamFrame)
910
+ self.ui.spin_frame.setVisible(FlagCamFrame)
911
+ self.ui.label_cam.setVisible(FlagCamFrame)
912
+ self.ui.spin_cam.setVisible(FlagCamFrame)
913
+ FlagDispResult=self.VISpar.img==0 and self.VISpar.Step==StepTypes.disp #and self.VISpar.variableKey is not self.namesPIV.img #and self.VISpar.type==1
914
+ self.ui.label_it.setVisible(FlagDispResult)
915
+ self.ui.spin_it.setVisible(FlagDispResult)
916
+ self.ui.spin_it.setMinimum(1)
917
+ self.ui.spin_it.setMaximum(self.VISpar.Nit)
918
+ self.ui.spin_it.setEnabled(self.VISpar.flagRun!=-2)
919
+ if self.VISpar.type==0:
920
+ dataType='Input'
921
+ dataName=self.image_file if self.image is not None else None
922
+ else:
923
+ dataType='Output'
924
+ dataName=self.result_file if self.result is not None else None
925
+ if dataName:
926
+ self.ui.name_var.setText(f'{dataType} file: {os.path.basename(dataName)}')
927
+ else:
928
+ self.ui.name_var.setText(f'{dataType} file not available!')
929
+ self.ui.name_var.setToolTip(f'{dataType} file: {dataName}')
930
+ self.ui.name_var.setStatusTip(self.ui.name_var.toolTip())
931
+
932
+ self.VISpar.colorMap=self.VISpar.vcolorMap[self.VISpar.variableKey]
933
+ self.VISpar.vectorColor=self.VISpar.vvectorColor[self.VISpar.variableKey]
934
+
935
+ self.ui.button_cmap.setIcon(QIcon(icons_path+'colormaps/'+self.VISpar.colorMap+'.png'))
936
+ self.ui.button_cvec.setIcon(QIcon(icons_path+'colormaps/'+self.VISpar.vectorColor+'Vector.png'))
937
+
938
+ self.setLevels()
939
+ t=self.VISpar.type
940
+ if (t==0 and self.VISpar.unit[t]) or (t==1 and not self.VISpar.unit[t]):
941
+ self.xres,self.yres=self.getXYRes()
942
+ else: self.xres=self.yres=1.0
943
+ self.VISpar.xmin=self.VISpar.size[self.VISpar.type][0]*self.xres
944
+ self.VISpar.xmax=self.VISpar.size[self.VISpar.type][1]*self.xres
945
+ self.VISpar.ymin=self.VISpar.size[self.VISpar.type][2]*self.yres
946
+ self.VISpar.ymax=self.VISpar.size[self.VISpar.type][3]*self.yres
947
+
948
+ self.checkVISTab()
949
+ self.setVISwarn()
950
+ return
951
+
952
+ def setLevels(self):
953
+ self.VISpar.min=self.VISpar.vmin[self.VISpar.variableKey]
954
+ self.VISpar.max=self.VISpar.vmax[self.VISpar.variableKey]
955
+ self.VISpar.mean=self.VISpar.vmean[self.VISpar.variableKey]
956
+ self.VISpar.range=self.VISpar.vrange[self.VISpar.variableKey]
957
+
958
+ def resetLevels(self):
959
+ self.VISpar.vmin[self.VISpar.variableKey]=self.VISpar.vmin_default[self.VISpar.variableKey]
960
+ self.VISpar.vmax[self.VISpar.variableKey]=self.VISpar.vmax_default[self.VISpar.variableKey]
961
+ self.VISpar.vmean[self.VISpar.variableKey]=self.VISpar.vmean_default[self.VISpar.variableKey]
962
+ self.VISpar.vrange[self.VISpar.variableKey]=self.VISpar.vrange_default[self.VISpar.variableKey]
963
+ #self.setLevels()
964
+
965
+ def resetAllLevels(self, ind=None):
966
+ if ind is None: VIS:VISpar=self.VISpar
967
+ else: VIS:VISpar=self.TABpar_at(ind)
968
+ for field in ('min','max','mean','range'):
969
+ v=getattr(VIS,'v'+field)
970
+ w=getattr(VIS,'v'+field+'_default')
971
+ for f in list(w):
972
+ v[f]=w[f]
973
+ #self.setLevels()
974
+
975
+ def checkResVariables(self):
976
+ for field in ('min','max','mean','range'):
977
+ v=getattr(self.VISpar,'v'+field)
978
+ w=getattr(self.VISpar,'v'+field+'_default')
979
+ for f in list(w):
980
+ if f not in list(v):
981
+ v[f]=w[f]
982
+
983
+ def resetXYLims(self):
984
+ self.VISpar.size[self.VISpar.type][::]=self.VISpar.size_default[self.VISpar.type][::]
985
+
986
+ def resetAllXYLims(self, ind=None):
987
+ if ind is None: VIS:VISpar=self.VISpar
988
+ else: VIS:VISpar=self.TABpar_at(ind)
989
+ for t in (0,1):
990
+ VIS.size[t][::]=self.VISpar.size_default[t][::]
991
+
992
+ def readImageFile(self,filename):
993
+ I=None
994
+ if not filename: return filename, I
995
+ try:
996
+ if os.path.exists(filename):
997
+ pri.Info.cyan(f'Opening: {filename} [<--{self.image_file}]')
998
+ img=Image.open(filename)
999
+ I=np.ascontiguousarray(img)
1000
+ self.nbits=img.getextrema()[1].bit_length()
1001
+ #I=transfIm(self.VISpar.Out,Images=[I])[0]
1002
+ except Exception as inst:
1003
+ pri.Error.red(f'Error opening image file: {filename}\n{traceback.format_exc()}\n{inst}')
1004
+ I=None
1005
+ return filename, I
1006
+
1007
+ def getImageInfo(self,image=None,ind=None):
1008
+ if image is None: I=self.image
1009
+ else: I=image
1010
+ if ind is None: VIS:VISpar=self.VISpar
1011
+ else: VIS:VISpar=self.TABpar_at(ind)
1012
+ variableKey=self.VISpar.variableKey
1013
+ if variableKey is self.namesPIV.dispMap:
1014
+ variableKey=self.namesPIV.dispMap
1015
+ if image is None:
1016
+ CC_16bit=self.image.astype(np.float64) # Convert back to float
1017
+ I=(CC_16bit / 65535.0) * 2.0 - 1.0 # Reverse the normalization
1018
+ self.image=I
1019
+ mean=np.mean(I).item()
1020
+ std=np.std(I).item()
1021
+ VIS.vLim[variableKey]=1.0
1022
+ VIS.vmin_default[variableKey]=max([mean-2*std,-1.0])
1023
+ VIS.vmax_default[variableKey]=min([mean+2*std,1.0])
1024
+ else:
1025
+ mean=np.mean(I).item()
1026
+ std=np.std(I).item()
1027
+ VIS.vLim[variableKey]=min([2*I.max().item(),2**(self.nbits+1)])
1028
+ VIS.vmin_default[variableKey]=np.round(max([mean-2*std,0])).item()
1029
+ VIS.vmax_default[variableKey]=np.round(min([mean+2*std,VIS.vLim[variableKey]])).item()
1030
+
1031
+ VIS.vmean_default[variableKey]=0.5*(VIS.vmin_default[variableKey]+VIS.vmax_default[variableKey])
1032
+ VIS.vrange_default[variableKey]=VIS.vmax_default[variableKey]-VIS.vmin_default[variableKey]
1033
+ VIS.size_default[0]=[0,np.size(I,1),0,np.size(I,0),1]
1034
+ if variableKey not in VIS.vcolorMap:
1035
+ VIS.vcolorMap[variableKey]='gray' if variableKey in ('img','dispMap') else 'jet'
1036
+ if variableKey not in VIS.vvectorColor:
1037
+ VIS.vvectorColor[variableKey]='green' if variableKey in ('img','dispMap') else 'black'
1038
+
1039
+ def readResultFile(self,filename):
1040
+ res=None
1041
+ if not filename: return filename, res
1042
+ try:
1043
+ if os.path.exists(filename):
1044
+ pri.Info.cyan(f'Opening: {filename} [<--{self.result_file}]')
1045
+ ext=os.path.splitext(filename)[-1]
1046
+ if ext=='.mat':
1047
+ res = scipy.io.loadmat(filename)
1048
+ elif ext=='.plt':
1049
+ tres = readPlt(filename)
1050
+ res={}
1051
+ for j, n in enumerate(tres[1]):
1052
+ res[n]=tres[0][:,:,j]
1053
+ if self.namesPIV.u in res and self.namesPIV.v in res:
1054
+ res=self.calcMagnitude(res)
1055
+ res=self.calcZVorticity(res)
1056
+ for f in list(res):
1057
+ if not f in self.namesPIV.allFields: del res[f]
1058
+ except Exception as inst:
1059
+ pri.Error.red(f'Error opening image file: {filename}\n{traceback.format_exc()}\n{inst}')
1060
+ res=None
1061
+ return filename, res
1062
+
1063
+ def calcMagnitude(self,res):
1064
+ if self.namesPIV.u in res and self.namesPIV.v in res:
1065
+ if self.namesPIV.w in res:
1066
+ res[self.namesPIV.Mod]=np.sqrt(res[self.namesPIV.u]**2+res[self.namesPIV.v]**2+res[self.namesPIV.w]**2)
1067
+ else:
1068
+ res[self.namesPIV.Mod]=np.sqrt(res[self.namesPIV.u]**2+res[self.namesPIV.v]**2)
1069
+ return res
1070
+
1071
+ def calcZVorticity(self,res):
1072
+ if self.namesPIV.x in res and self.namesPIV.y in res and self.namesPIV.u in res and self.namesPIV.v in res:
1073
+ xres,yres=self.getXYRes(type=1)
1074
+ try:
1075
+ du_dy, _=np.gradient(res[self.namesPIV.u],res[self.namesPIV.y][:,0]*yres,res[self.namesPIV.x][0,:]*xres) # Derivate di u rispetto a y e x
1076
+ _, dv_dx=np.gradient(res[self.namesPIV.v],res[self.namesPIV.y][:,0]*yres,res[self.namesPIV.x][0,:]*xres) # Derivate di v rispetto a y e x
1077
+ res[self.namesPIV.ZVort]=dv_dx-du_dy
1078
+ except:
1079
+ pri.Error.red(f'Error while computing vorticity field:\n{traceback.format_exc()}\n\n')
1080
+ return res
1081
+
1082
+ def getResultInfo(self,result=None,ind=None):
1083
+ if result is None: res=self.result
1084
+ else: res=result
1085
+ if ind is None: VIS:VISpar=self.VISpar
1086
+ else: VIS:VISpar=self.TABpar_at(ind)
1087
+ for i in list(VIS.vmin_default):
1088
+ if i not in (self.namesPIV.img,self.namesPIV.dispMap):
1089
+ del VIS.vmin_default[i]
1090
+ del VIS.vmax_default[i]
1091
+ del VIS.vmean_default[i]
1092
+ del VIS.vrange_default[i]
1093
+ del VIS.vLim[i]
1094
+
1095
+ for f in list(res):
1096
+ V:np=res[f][~np.isnan(res[f])]
1097
+ #m=np.mean(V).item()
1098
+ #r=np.std(V).item()
1099
+ #VIS.vLim[f]=max([m+5*r,abs(m-5*r)])
1100
+ amax=np.max(np.abs(V))*5.0
1101
+ m=np.mean(V)
1102
+ r=(np.max(V)-np.min(V))*2.50
1103
+ rmax=np.abs(m+r)
1104
+ rmin=np.abs(m-r)
1105
+ VIS.vLim[f]=float(max([amax,rmax,rmin]))
1106
+ if VIS.vLim[f]<0.1: VIS.vLim[f]=1
1107
+ VIS.vmin_default[f]=float(np.percentile(V,1)) #np.round(m-2*r).item()
1108
+ VIS.vmax_default[f]=float(np.percentile(V,99)) #np.round(m+2*r).item()
1109
+ VIS.vmean_default[f]=0.5*(VIS.vmin_default[f]+VIS.vmax_default[f])
1110
+ VIS.vrange_default[f]=VIS.vmax_default[f]-VIS.vmin_default[f]
1111
+ if f not in VIS.vcolorMap:
1112
+ VIS.vcolorMap[f]='jet'
1113
+ if f not in VIS.vvectorColor:
1114
+ VIS.vvectorColor[f]='black'
1115
+ pass
1116
+
1117
+ FlagSize=False
1118
+ if "X" in list(res) and "Y" in list(res):
1119
+ X=res["X"]
1120
+ Y=res["Y"]
1121
+ FlagSize=True
1122
+ elif "x" in list(res) and "y" in list(res):
1123
+ X=res["x"]
1124
+ Y=res["y"]
1125
+ FlagSize=True
1126
+ if FlagSize:
1127
+ if np.size(X) and np.size(Y):
1128
+ VIS.size_default[1]=[X.min().item(),X.max().item(),Y.min().item(),Y.max().item(),int(max([np.size(X,0),np.size(X,1)])/4)]
1129
+ else:
1130
+ VIS.size_default[1]=[0,1,0,1,1]
1131
+
1132
+ def setVISwarn(self,ind=None):
1133
+ if ind is None: VIS:VISpar=self.VISpar
1134
+ else: VIS:VISpar=self.TABpar_at(ind)
1135
+ VIS.warningMessage='Result files correctly identified!' if VIS.OptionDone==1 else 'Result files corresponding to the current step appear to be missing from the specified output path.'
1136
+
1137
+ #*************************************************** Plot tools
1138
+ #******************** Actions
1139
+ def button_view_action(self):
1140
+ self.VISpar.FlagView=self.ui.button_view.isChecked()
1141
+
1142
+ def button_ShowIW_action(self):
1143
+ self.VISpar.FlagShowIW=self.ui.button_ShowIW.isChecked()
1144
+ self.resetXYLims()
1145
+
1146
+ def button_SubMIN_action(self):
1147
+ self.VISpar.FlagSubMIN=self.ui.button_SubMIN.isChecked()
1148
+
1149
+ def button_ShowCR_action(self):
1150
+ self.VISpar.FlagShowCR=self.ui.button_ShowCR.isChecked()
1151
+
1152
+ def button_unit_action(self):
1153
+ self.VISpar.unit[self.VISpar.type]=self.ui.button_unit.isChecked()
1154
+
1155
+ def button_Contourf_action(self):
1156
+ self.VISpar.FlagContourf=self.ui.button_Contourf.isChecked()
1157
+
1158
+ def button_cmap_action(self):
1159
+ # Show the popup menu
1160
+ self.colorMapMenu.exec(self.ui.button_cmap.mapToGlobal(self.ui.button_cmap.rect().bottomLeft()))
1161
+
1162
+ def button_cvec_action(self):
1163
+ # Show the popup menu
1164
+ self.vectorColorMenu.exec(self.ui.button_cvec.mapToGlobal(self.ui.button_cvec.rect().bottomLeft()))
1165
+
1166
+ def combo_map_var_action(self):
1167
+ self.VISpar.variable=self.ui.combo_map_var.currentText()
1168
+ self.VISpar.variableKey=self.namesPIV.combo_dict_keys[self.VISpar.variable]
1169
+ self.VISpar.type=int(self.VISpar.variable!=self.namesPIV.combo_dict[self.namesPIV.img])
1170
+ self.setLevels()
1171
+
1172
+ def button_automatic_levels_action(self):
1173
+ VISpar.FlagAutoLevels=self.ui.button_automatic_levels.isChecked()
1174
+ return True
1175
+
1176
+ def button_automatic_sizes_action(self):
1177
+ VISpar.FlagAutoSizes=self.ui.button_automatic_sizes.isChecked()
1178
+ return True
1179
+
1180
+ def button_restore_action(self):
1181
+ self.resetLevels()
1182
+
1183
+ def button_resize_action(self):
1184
+ self.resetXYLims()
1185
+
1186
+ def button_invert_y_action(self):
1187
+ self.VISpar.FlagYInvert[self.VISpar.type]=self.ui.button_invert_y.isChecked()
1188
+
1189
+ def spinLevels_action(self,spin:MyQDoubleSpin):
1190
+ n=spin.objectName().replace('spin_','')
1191
+ spin_value=getattr(self.VISpar,n)
1192
+
1193
+ v=getattr(self.VISpar,'v'+n)
1194
+ v[self.VISpar.variableKey]=spin_value
1195
+ self.adjustSpins(spin)
1196
+
1197
+ def adjustSpins(self,spin:MyQDoubleSpin):
1198
+ nspin=spin.objectName().replace('spin_','')
1199
+ if spin in (self.ui.spin_min,self.ui.spin_max):
1200
+ if spin==self.ui.spin_min and spin.value()>=self.ui.spin_max.value():
1201
+ self.VISpar.max=self.VISpar.min+self.ui.spin_range.minimum()
1202
+ elif spin==self.ui.spin_max and spin.value()<=self.ui.spin_min.value():
1203
+ self.VISpar.min=self.VISpar.max-self.ui.spin_range.minimum()
1204
+ self.VISpar.mean=0.5*(self.VISpar.min+self.VISpar.max)
1205
+ self.VISpar.range=self.VISpar.max-self.VISpar.min
1206
+ elif spin in (self.ui.spin_mean,self.ui.spin_range):
1207
+ m=self.ui.spin_mean.value()
1208
+ r=self.ui.spin_range.value()
1209
+ if m-r*0.5<self.ui.spin_min.minimum():
1210
+ self.VISpar.min=self.ui.spin_min.minimum()
1211
+ if spin==self.ui.spin_mean:
1212
+ self.VISpar.range=2*(m-self.VISpar.min)
1213
+ self.VISpar.max=m+0.5*self.VISpar.range
1214
+ else:
1215
+ self.VISpar.max=self.VISpar.min+r
1216
+ self.VISpar.mean=0.5*(self.VISpar.min+self.VISpar.max)
1217
+ elif m+r*0.5>self.ui.spin_max.maximum():
1218
+ self.VISpar.max=self.ui.spin_max.maximum()
1219
+ if spin==self.ui.spin_mean:
1220
+ self.VISpar.range=2*(self.VISpar.max-m)
1221
+ self.VISpar.min=m-0.5*self.VISpar.range
1222
+ else:
1223
+ self.VISpar.min=self.VISpar.max-r
1224
+ self.VISpar.mean=0.5*(self.VISpar.min+self.VISpar.max)
1225
+ else:
1226
+ self.VISpar.max=m+0.5*r
1227
+ self.VISpar.min=m-0.5*r
1228
+ if spin==self.ui.spin_mean: self.VISpar.range=(self.VISpar.max-self.VISpar.min)
1229
+ else: self.VISpar.mean=0.5*(self.VISpar.min+self.VISpar.max)
1230
+
1231
+ for n in ['min','max','mean','range']:
1232
+ if n!=nspin:
1233
+ spin=getattr(self.ui,'spin_'+n)
1234
+ slider=getattr(self.ui,'slider_'+n)
1235
+ val=getattr(self.VISpar,n)
1236
+ spin.setValue(val)
1237
+ self.slider_set(spin,slider)
1238
+
1239
+ def sliderLevels_changing(self,spin:MyQDoubleSpin,slider:QSlider,Flag=False):
1240
+ self.setSpinFromSlider(spin,slider)
1241
+ self.adjustSpins(spin)
1242
+ self.sliderLevels_action()
1243
+ return Flag
1244
+
1245
+ def setSpinFromSlider(self,spin:MyQDoubleSpin,slider:QSlider):
1246
+ slider_value=slider.value()
1247
+ spin_value=spin.minimum()+(spin.maximum()-spin.minimum())/slider.maximum()*slider_value
1248
+ spin.setValue(spin_value)
1249
+ n=spin.objectName().replace('spin_','')
1250
+ if n in ('nclev','vecspac'):
1251
+ spin_value=int(spin_value)
1252
+ setattr(self.VISpar,n,spin_value)
1253
+ return spin_value
1254
+
1255
+ def sliderLevels_action(self):
1256
+ for n in ('min','max','mean','range'):
1257
+ spin_value=getattr(self.VISpar,n)
1258
+ v=getattr(self.VISpar,'v'+n)
1259
+ v[self.VISpar.variableKey]=spin_value
1260
+
1261
+ def spinFieldRep_action(self,spin:MyQDoubleSpin):
1262
+ n=spin.objectName().replace('spin_','')
1263
+ spin_value=getattr(self.VISpar,n)
1264
+ if n in ('nclev','vecspac'): spin_value=int(spin_value)
1265
+ setattr(self.VISpar,n,spin_value)
1266
+
1267
+ def sliderFieldRep_changing(self,spin:MyQDoubleSpin,slider:QSlider,Flag=False):
1268
+ self.setSpinFromSlider(spin,slider)
1269
+ self.sliderFieldRep_action()
1270
+ return Flag
1271
+
1272
+ def sliderFieldRep_action(self):
1273
+ return
1274
+
1275
+ def spin_xy_action(self,spin,k):
1276
+ n=spin.objectName().replace('spin_','')
1277
+ spin_value=getattr(self.VISpar,n)
1278
+ res=self.xres if k<2 else self.yres
1279
+ self.VISpar.size[self.VISpar.type][k]=spin_value/res
1280
+
1281
+ def button_dx_left_action(self):
1282
+ dx=(self.VISpar.xmax-self.VISpar.xmin)/self.xres
1283
+ self.VISpar.size[self.VISpar.type][0]-=dx
1284
+ self.VISpar.size[self.VISpar.type][1]-=dx
1285
+
1286
+ def button_dx_right_action(self):
1287
+ dx=(self.VISpar.xmax-self.VISpar.xmin)/self.xres
1288
+ self.VISpar.size[self.VISpar.type][0]+=dx
1289
+ self.VISpar.size[self.VISpar.type][1]+=dx
1290
+
1291
+ def button_dy_down_action(self):
1292
+ dy=(self.VISpar.ymax-self.VISpar.ymin)/self.yres
1293
+ self.VISpar.size[self.VISpar.type][2]-=dy
1294
+ self.VISpar.size[self.VISpar.type][3]-=dy
1295
+
1296
+ def button_dy_up_action(self):
1297
+ dy=(self.VISpar.ymax-self.VISpar.ymin)/self.yres
1298
+ self.VISpar.size[self.VISpar.type][2]+=dy
1299
+ self.VISpar.size[self.VISpar.type][3]+=dy
1300
+
1301
+ def button_FocusIW_action(self):
1302
+ ve=self.VISpar.Pro.Vect if isinstance(self.VISpar.Pro.Vect[0],list) else [[v] for v in self.VISpar.Pro.Vect]
1303
+ Vect = [[val for val in v] for v in ve]
1304
+ if self.VISpar.unit[self.VISpar.type] and self.VISpar.type!=0:
1305
+ yres=self.VISpar.Out.xres*self.VISpar.Out.pixAR
1306
+ for k in range(2): Vect[k]=[val/self.VISpar.Out.xres for val in Vect[k]]
1307
+ for k in range(2,4): Vect[k]=[val/yres for val in Vect[k]]
1308
+ else: yres=1.0
1309
+ W=Vect[2][-1]
1310
+ FlagDisp=self.VISpar.variableKey is self.namesPIV.dispMap
1311
+ if FlagDisp:
1312
+ H=self.gui.w_Process_Disp.PROpar.SemiWidth_Epipolar*2+1
1313
+ H/=yres
1314
+ FlagBordo=False
1315
+ else:
1316
+ H=Vect[0][-1]
1317
+ FlagBordo=self.VISpar.Pro.FlagBordo
1318
+ if abs(self.VISpar.size[self.VISpar.type][1]-self.VISpar.size[self.VISpar.type][0]-W)<1 and abs(self.VISpar.size[self.VISpar.type][3]-self.VISpar.size[self.VISpar.type][2]-H)<1:
1319
+ dW=W if FlagDisp else Vect[3][-1]
1320
+ boundDist=W/2 if not FlagBordo else dW
1321
+ x0=int((self.VISpar.size[self.VISpar.type][0]-boundDist+W/2)/dW)*dW+boundDist-W/2 if self.VISpar.size[self.VISpar.type][0]>boundDist else boundDist-W/2
1322
+ dH=H if FlagDisp else Vect[1][-1]
1323
+ boundDist=H/2 if not FlagBordo else dH
1324
+ y0=int((self.VISpar.size[self.VISpar.type][2]-boundDist+H/2)/dH)*dH+boundDist-H/2 if self.VISpar.size[self.VISpar.type][2]>boundDist else boundDist-H/2
1325
+ self.VISpar.size[self.VISpar.type][0]=x0
1326
+ self.VISpar.size[self.VISpar.type][2]=y0
1327
+ self.VISpar.size[self.VISpar.type][1]=x0+W
1328
+ self.VISpar.size[self.VISpar.type][3]=y0+H
1329
+ else:
1330
+ self.VISpar.size[self.VISpar.type][1]=self.VISpar.size[self.VISpar.type][0]+W
1331
+ self.VISpar.size[self.VISpar.type][3]=self.VISpar.size[self.VISpar.type][2]+H
1332
+
1333
+ #******************** Settings
1334
+ def button_view_set(self):
1335
+ self.ui.button_view.setChecked(self.VISpar.FlagView)
1336
+
1337
+ def button_ShowIW_set(self):
1338
+ self.ui.button_ShowIW.setChecked(self.VISpar.FlagShowIW)
1339
+
1340
+ def button_ShowCR_set(self):
1341
+ self.ui.button_ShowCR.setChecked(self.VISpar.FlagShowCR)
1342
+
1343
+ def button_SubMIN_set(self):
1344
+ self.ui.button_SubMIN.setChecked(self.VISpar.FlagSubMIN)
1345
+
1346
+ def button_unit_set(self):
1347
+ self.ui.button_unit.setChecked(self.VISpar.unit[self.VISpar.type])
1348
+
1349
+ def button_Contourf_set(self):
1350
+ self.ui.button_Contourf.setChecked(self.VISpar.FlagContourf)
1351
+
1352
+ def button_automatic_levels_set(self):
1353
+ self.ui.button_automatic_levels.setChecked(VISpar.FlagAutoLevels)
1354
+
1355
+ def button_automatic_sizes_set(self):
1356
+ self.ui.button_automatic_sizes.setChecked(VISpar.FlagAutoSizes)
1357
+
1358
+ def button_invert_y_set(self):
1359
+ self.ui.button_invert_y.setChecked(self.VISpar.FlagYInvert[self.VISpar.type])
1360
+
1361
+ def combo_map_var_set(self):
1362
+ self.ui.combo_map_var.setCurrentText(self.VISpar.variable)
1363
+
1364
+ def slider_set(self,spin:MyQDoubleSpin,slider:QSlider):
1365
+ spin_value=getattr(self.VISpar,spin.objectName().replace('spin_',''))
1366
+ if spin.maximum()>spin.minimum():
1367
+ slider_value=int((spin_value-spin.minimum())/(spin.maximum()-spin.minimum())*slider.maximum())
1368
+ else: slider_value=0
1369
+ slider.setValue(slider_value)
1370
+
1371
+ #******************** Layout
1372
+ def leftrightCallback(self,di):
1373
+ i=self.ui.image_levels.currentIndex()
1374
+ i=i+di
1375
+ c=self.ui.image_levels.count()-1-int(self.result is None)
1376
+ if i<0: i=c
1377
+ elif i>c: i=0
1378
+ self.VISpar.setPage=i
1379
+
1380
+ #*************************************************** Plot
1381
+ def updatingPlot(self):
1382
+ xmin,xmax=list(self.ui.plot.axes.get_xlim())
1383
+ ymin,ymax=list(self.ui.plot.axes.get_ylim())
1384
+ self.VISpar.size[self.VISpar.type][:2]=[xmin/self.xres,xmax/self.xres]
1385
+ self.VISpar.size[self.VISpar.type][2:4]=[ymin/self.yres,ymax/self.yres]
1386
+
1387
+ def brushCursor(self):
1388
+ if self.FlagNormalCursor:
1389
+ self.FlagNormalCursor=False
1390
+ QApplication.setOverrideCursor(self.brush_cursor)
1391
+ def restoreCursor():
1392
+ QApplication.restoreOverrideCursor()
1393
+ self.FlagNormalCursor=True
1394
+ QTimer.singleShot(250,lambda: restoreCursor())
1395
+
1396
+ def setMapVar(self):
1397
+ pri.PlotTime.magenta(f'{"/"*25} Plotting image - start')
1398
+ self.brushCursor()
1399
+ try:
1400
+ if self.VISpar.type==0:
1401
+ fields=['image_file','variable','unit','FlagSubMIN','Out','colorMap']
1402
+ img=self.image
1403
+ if img is not None and self.VISpar.img>0 and self.VISpar.FlagSubMIN and self.image_Min is not None:
1404
+ img=img-self.image_Min
1405
+ self.img=img
1406
+ FlagDraw=self.showImg(fields)
1407
+
1408
+ FlagIW=self.VISpar.isDifferentFrom(self.VISpar_old,fields=['FlagShowIW','Pro'])
1409
+ if FlagIW or FlagDraw: self.showRect()
1410
+ FlagDraw=FlagDraw or FlagIW
1411
+ if self.image is not None and self.VISpar.FlagShowCR and self.VISpar.variableKey!=self.namesPIV.dispMap:
1412
+ self.showCommonRegion()
1413
+ FlagDraw=FlagDraw or self.CR is not None
1414
+ else:
1415
+ self.cleanCommonRegion()
1416
+ else:
1417
+ if self.orect: self.cleanRect()
1418
+ self.cleanCommonRegion()
1419
+ fields=['result_file','variable','unit','min','max','nclev','FlagContourf','colorMap']
1420
+ V=self.result[self.VISpar.variableKey]
1421
+ if not self.VISpar.FlagContourf:
1422
+ self.img,Ximg,Yimg,FlagInterp,size=self.calcMap(V,size_pixels=[np.size(V,0), np.size(V,1)])
1423
+ FlagDraw=self.showImg(fields,size)
1424
+ else:
1425
+ self.img,Ximg,Yimg,FlagInterp,size=self.calcMap(self.result[self.VISpar.variableKey])
1426
+ if FlagInterp:
1427
+ FlagDraw=self.showImg(fields,size)
1428
+ else:
1429
+ FlagDraw=self.showMap(fields)
1430
+ if self.contour is None:
1431
+ FlagDraw=self.showImg(fields,size)
1432
+ fields=['result_file','variable','FlagContourf','field_rep','unit','vectorColor']
1433
+ if self.VISpar.field_rep==1: fields+=['vecsize','vecwid','vecspac']
1434
+ elif self.VISpar.field_rep==2: fields+=['streamdens']
1435
+ if self.VISpar.Step!=StepTypes.piv: fields+=['type']
1436
+ FlagVecField=self.VISpar.isDifferentFrom(self.VISpar_old,fields=fields)
1437
+ if FlagVecField and self.result:
1438
+ self.showVecField()
1439
+ FlagDraw=FlagDraw or FlagVecField
1440
+
1441
+ if FlagDraw:
1442
+ #self.ui.plot.draw()
1443
+ self.ui.plot.draw_idle()
1444
+ except:
1445
+ pri.Error.red(f'Error while generating plot:\n{traceback.format_exc()}\n\n')
1446
+ printException()
1447
+ #self.exitVISerr(False)
1448
+ pri.PlotTime.magenta(f'{"%"*25} Plotting image - end')
1449
+
1450
+ def showImg(self,fields,size:list=None):
1451
+ img=self.img
1452
+ if img is None:
1453
+ self.cleanAxes(FlagAxis=False)
1454
+ return True #raise Exception('Invalid input image!')
1455
+
1456
+ FlagNewPlot=self.VISpar.isDifferentFrom(self.VISpar_old,fields=fields)
1457
+ FlagOut=self.VISpar.isDifferentFrom(self.VISpar_old,fields=['Out'])
1458
+ FlagXLim=self.VISpar.isDifferentFrom(self.VISpar_old,fields=['xmin','xmax','ymin','ymax','unit','FlagYInvert','Out'])
1459
+ FlagCMap=self.VISpar.isDifferentFrom(self.VISpar_old,fields=['colorMap','nclev'])
1460
+ FlagCLim=self.VISpar.isDifferentFrom(self.VISpar_old,fields=['min','max','nclev','colorMap'] if self.VISpar.type else ['min','max'])
1461
+ FlagExtent=False
1462
+
1463
+ if FlagNewPlot:
1464
+ FlagVariable=self.VISpar_old.variable!=self.VISpar.variable
1465
+
1466
+ if self.imgshow is None or self.VISpar_old.FlagContourf!=self.VISpar.FlagContourf or FlagOut:
1467
+ self.cleanAxes()
1468
+ self.imgshow=self.ui.plot.axes.imshow(img,extent=self.imgExtent(size), origin='lower', vmin=self.VISpar.min,vmax=self.VISpar.max,zorder=0)
1469
+ self.imgshow.format_cursor_data=lambda v: self.custom_format_cursor_data(v)
1470
+ cmap,_=self.colorMap()
1471
+ self.imgshow.set_cmap(cmap)
1472
+ divider = make_axes_locatable(self.ui.plot.axes)
1473
+ cax = divider.append_axes("right", size="5%", pad=0.05)
1474
+ self.cb=self.ui.plot.fig.colorbar(self.imgshow,cax=cax)
1475
+ self.setTitleLabels()
1476
+ FlagXLim=True
1477
+ else:
1478
+ self.imgshow.set_data(img)
1479
+ extent=self.imgExtent()
1480
+ if extent!=self.imgshow.get_extent():
1481
+ self.imgshow.set_extent(extent)
1482
+ FlagExtent=True
1483
+ if FlagCMap:
1484
+ cmap,_=self.colorMap()
1485
+ self.imgshow.set_cmap(cmap)
1486
+ if FlagCLim:
1487
+ self.imgshow.set_clim(self.VISpar.min,self.VISpar.max)
1488
+ if FlagVariable:
1489
+ self.setTitleLabels()
1490
+ else:
1491
+ if FlagCMap:
1492
+ cmap,_=self.colorMap()
1493
+ self.imgshow.set_cmap(cmap)
1494
+ if FlagCLim:
1495
+ self.imgshow.set_clim(self.VISpar.min,self.VISpar.max)
1496
+ if FlagXLim:
1497
+ self.setAxisLim()
1498
+ self.Ptoolbar.update()
1499
+
1500
+ FlagDraw=FlagNewPlot or FlagOut or FlagXLim or FlagCMap or FlagCLim or FlagExtent
1501
+ return FlagDraw
1502
+
1503
+ def colorMap(self):
1504
+ if self.VISpar.type==0:
1505
+ cmap=mpl.colormaps[self.VISpar.colorMap]
1506
+ levs=np.linspace(self.VISpar.min,self.VISpar.max,int(self.VISpar.max-self.VISpar.min))
1507
+ else:
1508
+ if self.VISpar.min<self.VISpar.max:
1509
+ levs=np.linspace(self.VISpar.min,self.VISpar.max,self.VISpar.nclev)
1510
+ else:
1511
+ levs=np.linspace(self.VISpar.max-self.ui.spin_min.singleStep(),\
1512
+ self.VISpar.max,self.VISpar.nclev)
1513
+ colormap = pyplt.get_cmap(self.VISpar.colorMap)
1514
+ colors=colormap(np.linspace(0, 1, len(levs)))
1515
+ cmap = mpl.colors.ListedColormap(colors)
1516
+ return cmap, levs
1517
+
1518
+ def getXYRes(self,type=None):
1519
+ if not type: type=self.VISpar.type
1520
+ xres=yres=1.0
1521
+ if self.VISpar.Process==ProcessTypes.piv and not self.VISpar.Out.FlagNone:
1522
+ if type==0: #mm/pixels
1523
+ xres =1.0/self.VISpar.Out.xres
1524
+ yres=1.0/(self.VISpar.Out.xres*self.VISpar.Out.pixAR)
1525
+ elif type==1: #pixels/mm
1526
+ xres=self.VISpar.Out.xres
1527
+ yres=self.VISpar.Out.xres*self.VISpar.Out.pixAR
1528
+ return xres, yres
1529
+
1530
+ def imgExtent(self,size=None):
1531
+ if size is None: size=self.VISpar.size_default[self.VISpar.type]
1532
+ return [k*self.xres for k in size[:2]]+[k*self.yres for k in size[2:4]]
1533
+
1534
+ def setAxisLim(self):
1535
+ self.ui.plot.axes.set_xlim(self.VISpar.xmin,self.VISpar.xmax)
1536
+ ylim=[self.VISpar.ymin,self.VISpar.ymax]
1537
+ if self.VISpar.FlagYInvert[self.VISpar.type]:
1538
+ self.ui.plot.axes.set_ylim(max(ylim),min(ylim))
1539
+ else:
1540
+ self.ui.plot.axes.set_ylim(min(ylim),max(ylim))
1541
+ self.ui.plot.axes.set_aspect('equal', adjustable='box')
1542
+
1543
+ def setTitleLabels(self):
1544
+ self.ui.plot.axes.set_title(self.namesPIV.titles_dict[self.VISpar.variableKey])
1545
+ self.cb.ax.set_title(self.namesPIV.titles_cb_dict[self.VISpar.variableKey])
1546
+ self.ui.plot.axes.set_xlabel("x" if self.VISpar.type else "")
1547
+ self.ui.plot.axes.set_ylabel("y" if self.VISpar.type else "")
1548
+
1549
+ def showMap(self,fields):
1550
+ result=self.result
1551
+ if result is None:
1552
+ self.cleanAxes(FlagAxis=False)
1553
+ return True #raise Exception('Invalid output image!')
1554
+
1555
+ FlagNewPlot=self.VISpar.isDifferentFrom(self.VISpar_old,fields=fields)
1556
+ FlagXLim=self.VISpar.isDifferentFrom(self.VISpar_old,fields=['xmin','xmax','ymin','ymax','unit','FlagYInvert','Out'])
1557
+ FlagCMap=self.VISpar_old.colorMap!=self.VISpar.colorMap
1558
+ FlagCLim=self.VISpar.isDifferentFrom(self.VISpar_old,fields=['min','max'])
1559
+
1560
+ if FlagNewPlot or self.VISpar_old.FlagContourf!=self.VISpar.FlagContourf or self.VISpar_old.nclev!=self.VISpar.nclev:
1561
+ self.cleanAxes()
1562
+ if not self.VISpar.unit[self.VISpar.type]:
1563
+ xres,yres=self.getXYRes(type=1)
1564
+ else: xres=yres=1.0
1565
+ X=result[self.namesPIV.x]*xres
1566
+ Y=result[self.namesPIV.y]*yres
1567
+ V=result[self.VISpar.variableKey]
1568
+ self.map=[X,Y,V]
1569
+
1570
+ cmap,levs=self.colorMap()
1571
+ try:
1572
+ self.contour=self.ui.plot.axes.contourf(X, Y, V, levs, \
1573
+ cmap=cmap, origin='lower', extend='both', zorder=0)
1574
+ self.contour.format_cursor_data=lambda v: self.custom_format_cursor_data(v)
1575
+ except:
1576
+ pri.Error.red(f'Error while generating contour lines:\n{traceback.format_exc()}\n\n')
1577
+ self.contour=None
1578
+ return
1579
+ self.contour.set_clim(levs[0],levs[-1])
1580
+ divider = make_axes_locatable(self.ui.plot.axes)
1581
+ cax = divider.append_axes("right", size="5%", pad=0.05)
1582
+ self.cb=self.ui.plot.fig.colorbar(self.contour,cax=cax)
1583
+ self.setTitleLabels()
1584
+ FlagXLim=True
1585
+ else:
1586
+ if FlagCMap:
1587
+ cmap,_=self.colorMap()
1588
+ self.contour.set_cmap(cmap)
1589
+ if FlagCLim:
1590
+ self.contour.set_clim(self.VISpar.min,self.VISpar.max)
1591
+ if FlagXLim:
1592
+ self.setAxisLim()
1593
+ self.Ptoolbar.update()
1594
+
1595
+ FlagDraw=FlagNewPlot or FlagXLim or FlagCMap or FlagCLim
1596
+ return FlagDraw
1597
+
1598
+ def calcMap(self,V,size_pixels=[1000]*2):
1599
+ #size_pixels=self.ui.plot.fig.get_size_inches()*self.ui.plot.fig.get_dpi()
1600
+ #size_pixels=np.minimum(np.round(0.5*size_pixels).astype(int),1000)
1601
+ FlagSize=False
1602
+ if "X" in list(self.result) and "Y" in list(self.result):
1603
+ X=self.result["X"]
1604
+ Y=self.result["Y"]
1605
+ FlagSize=True
1606
+ elif "x" in list(self.result) and "y" in list(self.result):
1607
+ X=self.result["x"]
1608
+ Y=self.result["y"]
1609
+ FlagSize=True
1610
+ if FlagSize:
1611
+ xmin,xmax,ymin,ymax=[X.min(),X.max(),Y.min(),Y.max()]
1612
+ else:
1613
+ xmin,xmax,ymin,ymax=[0,np.size(V,1),0,np.size(V,0)]
1614
+ xstep_half=(xmax-xmin)/(np.size(V,1)-1)*0.5
1615
+ x = self.mylinspace(xmin,xmax, np.size(V,1))
1616
+ ystep_half=(ymax-ymin)/(np.size(V,0)-1)*0.5
1617
+ y = self.mylinspace(ymin,ymax, np.size(V,0))
1618
+ FlagInterp=False
1619
+ if (np.size(V,1)<size_pixels[1] or np.size(V,0)<size_pixels[0]) and not bool(np.any(np.isnan(V))):
1620
+ x_new = self.mylinspace(xmin, xmax, size_pixels[0])
1621
+ y_new = self.mylinspace(ymin, ymax, size_pixels[1])
1622
+ try:
1623
+ f = scipy.interpolate.RectBivariateSpline(y, x, V)
1624
+ V_new = f(y_new, x_new)
1625
+ FlagInterp=True
1626
+ except:
1627
+ try:
1628
+ x_flat, y_flat = np.meshgrid(x, y) # Griglia 2D
1629
+ points = np.column_stack((x_flat.ravel(), y_flat.ravel())) # Punti 2D
1630
+ X_new, Y_new = np.meshgrid(x_new, y_new)
1631
+ V_new = scipy.interpolate.griddata(points, V.ravel(), (X_new, Y_new), method='cubic') #'nearest', 'linear', 'cubic'
1632
+ FlagInterp=True
1633
+ pass
1634
+ except:
1635
+ pri.Error.red(f'Error while interpolating map variable field for contour representation:\n{traceback.format_exc()}\n\n')
1636
+ x_new=x
1637
+ y_new=y
1638
+ V_new=V
1639
+ FlagInterp=False
1640
+ pass
1641
+ else:
1642
+ x_new=x
1643
+ y_new=y
1644
+ V_new=V
1645
+ FlagInterp=not bool(np.any(np.isnan(V)))
1646
+ X_new, Y_new = np.meshgrid(x_new, y_new)
1647
+ return V_new, X_new, Y_new, FlagInterp, (xmin-xstep_half,xmax+ystep_half,ymin-ystep_half,ymax+ystep_half)
1648
+
1649
+ def mylinspace(self,xmin,xmax,N):
1650
+ step=(xmax-xmin)/(N-1)
1651
+ return xmin+np.arange(0,N,1)*step
1652
+
1653
+ def cleanVecField(self):
1654
+ if self.qui!=None:
1655
+ self.qui.remove()
1656
+ self.qui=None
1657
+ if self.stream is not None:
1658
+ self.stream.lines.remove()
1659
+ for ax in self.ui.plot.axes.get_children():
1660
+ if isinstance(ax, mpl.patches.FancyArrowPatch):
1661
+ ax.remove()
1662
+ self.stream=None
1663
+
1664
+ def showVecField(self):
1665
+ ind=self.VISpar.field_rep
1666
+ self.cleanVecField()
1667
+ if self.qui!=None:
1668
+ self.qui.remove()
1669
+ self.qui=None
1670
+ if self.stream is not None:
1671
+ self.stream.lines.remove()
1672
+ for ax in self.ui.plot.axes.get_children():
1673
+ if isinstance(ax, mpl.patches.FancyArrowPatch):
1674
+ ax.remove()
1675
+ self.stream=None
1676
+ if ind in (1,2) and (self.VISpar.type>0 or self.VISpar.Step==StepTypes.piv):
1677
+ if not self.VISpar.unit[self.VISpar.type]:
1678
+ xres,yres=self.getXYRes(type=1)
1679
+ else: xres=yres=1.0
1680
+ if self.namesPIV.x in self.result and self.namesPIV.y in self.result:
1681
+ X=self.result[self.namesPIV.x]*xres
1682
+ Y=self.result[self.namesPIV.y]*yres
1683
+ elif self.namesPIV.X in self.result and self.namesPIV.Y in self.result:
1684
+ X=self.result[self.namesPIV.X]*xres
1685
+ Y=self.result[self.namesPIV.Y]*yres
1686
+ U=self.result[self.namesPIV.u]
1687
+ V=self.result[self.namesPIV.v]
1688
+ Mod=np.sqrt(U**2+V**2)
1689
+ if ind==1:
1690
+ dX=np.sqrt((X[0,1]-X[0,0])**2+(Y[1,0]-Y[0,0])**2)
1691
+ spa=self.VISpar.vecspac
1692
+ vecsize=self.VISpar.vecsize
1693
+ fac=dX*vecsize*spa
1694
+ Modq= Mod[::spa,::spa]
1695
+ Uq=np.divide(U[::spa,::spa], Modq, where=Modq!=0)*fac
1696
+ Vq=np.divide(V[::spa,::spa], Modq, where=Modq!=0)*fac
1697
+ w=0.15*fac
1698
+ n=3
1699
+ wmax=min([X.max()-X.min(),Y.max()-Y.min()])*0.001
1700
+ qwidth=min([w,wmax])*self.VISpar.vecwid**2
1701
+ hwidth=4 if vecsize<4 else vecsize
1702
+ self.qui=self.ui.plot.axes.quiver(
1703
+ X[::spa,::spa],Y[::spa,::spa],Uq,Vq, color=VIS_VectorColors[self.VISpar.vectorColor], clip_on=True,
1704
+ angles='xy',scale_units='xy',scale=1.0,
1705
+ units='xy',width=qwidth,headwidth=hwidth,headlength=1.25*hwidth,headaxislength=0.75*hwidth,zorder=10)
1706
+ elif ind==2:
1707
+ size_pixels=np.shape(U)
1708
+ Up,_,_,_,_=self.calcMap(U,size_pixels=size_pixels)
1709
+ Vp,Xp,Yp,_,_=self.calcMap(V,size_pixels=size_pixels)
1710
+ self.stream=self.ui.plot.axes.streamplot(Xp,Yp,Up,Vp,color=VIS_VectorColors[self.VISpar.vectorColor],density=self.VISpar.streamdens,zorder=10)
1711
+
1712
+ def cleanAxes(self,FlagAxis=True):
1713
+ self.imgshow=self.contour=self.CR=self.RF=None
1714
+ self.orect=[]
1715
+ self.qui=self.stream=None
1716
+ """
1717
+ self.cleanCommonRegion()
1718
+ self.cleanReferenceFrame()
1719
+ self.cleanRect()
1720
+ self.cleanVecField()
1721
+ if self.contour:
1722
+ for coll in self.contour.collections:
1723
+ coll.remove()
1724
+ """
1725
+ if self.cb:
1726
+ self.cb.remove()
1727
+ self.cb=None
1728
+ self.ui.plot.axes.cla()
1729
+ self.ui.plot.axes.axis('on' if FlagAxis else 'off')
1730
+ #self.ui.Plot_tools.setEnabled(FlagAxis)
1731
+
1732
+ def custom_format_coord(self,x,y):
1733
+ if self.contour is not None:
1734
+ X=self.map[0]
1735
+ Y=self.map[1]
1736
+
1737
+ if X.min() <= x <= X.max() and Y.min() <= y <= Y.max():
1738
+ # Trova l'indice più vicino nella matrice
1739
+ col = np.searchsorted(X[0,:],x) - 1
1740
+ row = np.searchsorted(Y[:,0],y) - 1
1741
+ Z=self.map[2]
1742
+
1743
+ # Estrai il valore dal dato Z
1744
+ if 0 <= row < Z.shape[0] and 0 <= col < Z.shape[1]:
1745
+ value = Z[row, col]
1746
+ formatted_value = f"{value:.4f}".rstrip('0').rstrip('.')
1747
+ return f"(x, y)=({x:.2f}, {y:.2f})\n[{formatted_value}]"
1748
+ return f"(x, y)=({x:.2f}, {y:.2f})"
1749
+ else:
1750
+ return f"(x, y)=({x:.2f}, {y:.2f})"
1751
+
1752
+ def custom_format_cursor_data(self,value):
1753
+ formatted_value = f"{value:.4f}".rstrip('0').rstrip('.')
1754
+ return f"[{formatted_value}]"
1755
+
1756
+ def cleanRect(self):
1757
+ if len(self.orect):
1758
+ for r in self.orect:
1759
+ if type(r)==list:
1760
+ for s in r:
1761
+ try: s.remove()
1762
+ except: pass
1763
+ else:
1764
+ try: r.remove()
1765
+ except: pass
1766
+
1767
+ def showRect(self):
1768
+ if not len(self.VISpar.Pro.Vect): return
1769
+ self.cleanRect()
1770
+ if not self.VISpar.FlagShowIW: return
1771
+ colors='rgbymc'
1772
+ lwidth=1
1773
+ nov_hor=3
1774
+ nov_vert=3
1775
+
1776
+ H=self.VISpar.size[self.VISpar.type][1]
1777
+ ve=self.VISpar.Pro.Vect if isinstance(self.VISpar.Pro.Vect[0],list) else [[v] for v in self.VISpar.Pro.Vect]
1778
+ Vect = [[val for val in v] for v in ve]
1779
+ dxin=dyin=5
1780
+ if self.VISpar.unit[self.VISpar.type]:
1781
+ xres,yres=self.getXYRes(type=0)
1782
+ for k in range(2): Vect[k]=[val*xres for val in Vect[k]]
1783
+ for k in range(2,4): Vect[k]=[val*yres for val in Vect[k]]
1784
+ dxin=dxin*xres
1785
+ dyin=dyin*yres
1786
+ nw=len(Vect[0])
1787
+ xin0=yin0=0
1788
+ xmax=ymax=0
1789
+ xlim_min=ylim_min=float('inf')
1790
+ xlim_max=ylim_max=-float('inf')
1791
+ self.orect=[]
1792
+ for k in range(nw):
1793
+ if self.VISpar.Pro.FlagBordo:
1794
+ if not xin0: dx=-Vect[0][k]/2+Vect[1][k]
1795
+ else: dx=0
1796
+ if not yin0: dy=-Vect[2][k]/2+Vect[3][k]
1797
+ else: dy=0
1798
+ else:
1799
+ dx=dy=0
1800
+ for i in range(nov_vert):
1801
+ yin=yin0+i*Vect[3][k]+dy
1802
+ ylim_min=min([ylim_min,yin])
1803
+ for j in range(nov_hor):
1804
+ xin=xin0+j*Vect[1][k]+dx
1805
+ xlim_min=min([xlim_min,xin])
1806
+ kk=i+j*nov_vert
1807
+ if kk%2: lst=':'
1808
+ else: lst='-'
1809
+ kc=k%len(colors)
1810
+ rect = mpl.patches.Rectangle((xin, yin), Vect[0][k], Vect[2][k],\
1811
+ linewidth=lwidth, edgecolor=colors[kc], facecolor=colors[kc],\
1812
+ alpha=0.25,linestyle=lst)
1813
+ self.ui.plot.axes.add_patch(rect)
1814
+ rect2 = mpl.patches.Rectangle((xin, yin), Vect[0][k], Vect[2][k],\
1815
+ linewidth=lwidth, edgecolor=colors[kc], facecolor='none',\
1816
+ alpha=1,linestyle=lst)
1817
+ self.ui.plot.axes.add_patch(rect2)
1818
+ points=self.ui.plot.axes.plot(xin+ Vect[0][k]/2,yin+ Vect[2][k]/2,\
1819
+ 'o',color=colors[kc])
1820
+ if not kk:
1821
+ if self.VISpar.FlagYInvert[self.VISpar.type]: va='top'
1822
+ else: va='bottom'
1823
+ text=self.ui.plot.axes.text(xin+dxin,yin+dyin,str(k),\
1824
+ horizontalalignment='left',verticalalignment=va,\
1825
+ fontsize='large',color='w',fontweight='bold')
1826
+ self.orect=self.orect+[rect,rect2,points,text]
1827
+ xmaxk=xin+Vect[0][k]
1828
+ ymaxk=yin+Vect[2][k]
1829
+ xlim_max=max([xlim_max,xmaxk])
1830
+ ylim_max=max([ylim_max,ymaxk])
1831
+ if xmaxk>xmax: xmax=xmaxk
1832
+ if ymaxk>ymax: ymax=ymaxk
1833
+ if k==nw-1: continue
1834
+ if ymaxk+Vect[2][k+1]+(nov_vert-1)*Vect[3][k+1]<H:
1835
+ yin0=ymaxk
1836
+ else:
1837
+ yin0=0
1838
+ xin0=xmax
1839
+ xlim=self.ui.plot.axes.get_xlim()
1840
+ xlim_min=min([xlim[0],xlim_min])
1841
+ xlim_max=max([xlim[1],xlim_max])
1842
+ self.ui.plot.axes.set_xlim(xlim_min,xlim_max)
1843
+ if self.VISpar.FlagYInvert[self.VISpar.type]:
1844
+ ylim=self.ui.plot.axes.get_ylim()
1845
+ ylim_max=min([ylim[1],ylim_min])
1846
+ ylim_min=max([ylim[0],ylim_max])
1847
+ else:
1848
+ ylim=self.ui.plot.axes.get_ylim()
1849
+ ylim_min=min([ylim[0],ylim_min])
1850
+ ylim_max=max([ylim[1],ylim_max])
1851
+ self.ui.plot.axes.set_ylim(ylim_min,ylim_max)
1852
+ self.VISpar.xmin,self.VISpar.xmax=list(self.ui.plot.axes.get_xlim())
1853
+ self.VISpar.ymin,self.VISpar.ymax=list(self.ui.plot.axes.get_ylim())
1854
+
1855
+ def cleanCommonRegion(self):
1856
+ if self.CR:
1857
+ self.CR.remove()
1858
+ self.CR=None
1859
+ self.ui.plot.draw_idle()
1860
+ self.cleanReferenceFrame()
1861
+
1862
+ def showCommonRegion(self):
1863
+ self.cleanCommonRegion()
1864
+ try:
1865
+ mapFun=PaIRS_lib.MappingFunction()
1866
+ mapFun.readCal(self.VISpar.calList)
1867
+
1868
+ #if self.VISpar.Step==StepTypes.spiv:
1869
+ # planeConst=self.readLaserPlaneConst(self.VISpar.dispFile)
1870
+ #else:
1871
+ # planeConst=[0.0,0.0,0.0]
1872
+ planeConst=[self.VISpar.Out.zconst,self.VISpar.Out.xterm,self.VISpar.Out.yterm]
1873
+
1874
+ o=self.VISpar.Out
1875
+ points=[ [o.x_min, o.y_min], [o.x_max, o.y_min], [o.x_max, o.y_max], [o.x_min, o.y_max]]
1876
+ zLaser=lambda xy: self.zLaser(xy[0],xy[1],planeConst)
1877
+ for p in points: p.append(zLaser(p))
1878
+ points_array=np.array(points,dtype=np.float64,order='C')
1879
+ cam=self.VISpar.cam-1
1880
+ X=mapFun.worldToImg(points_array,cam,None)# In output X1 is equal to X if correctly allocated
1881
+
1882
+ x_values = [Xp[0] for Xp in X]+[X[0][0]]
1883
+ y_values = [Xp[1] for Xp in X]+[X[0][1]]
1884
+ self.CR,=self.ui.plot.axes.plot(x_values, y_values, 'b-',clip_on=False)
1885
+ self.showReferenceFrame(mapFun=mapFun)
1886
+ except Exception as exc:
1887
+ pri.Error.red(f"[VIS] Error while plotting common zone!\n{traceback.format_exc()}\n")
1888
+ return
1889
+
1890
+ def zLaser(self,x,y,planeConst):
1891
+ return planeConst[0]+planeConst[1]*x+planeConst[2]*y
1892
+
1893
+ def cleanReferenceFrame(self):
1894
+ if self.RF:
1895
+ for p in self.RF:
1896
+ p.remove()
1897
+ self.RF=None
1898
+ self.ui.plot.draw_idle()
1899
+
1900
+ def showReferenceFrame(self,mapFun=None):
1901
+ self.cleanReferenceFrame()
1902
+ try:
1903
+ if mapFun is None:
1904
+ mapFun=PaIRS_lib.MappingFunction()
1905
+ mapFun.readCal(self.VISpar.calList)
1906
+
1907
+ labels=['O','x','y','z']
1908
+ unit=1
1909
+
1910
+ points=[ [0, 0, 0], [unit, 0, 0], [0, unit, 0], [0, 0, unit]]
1911
+ points_array=np.array(points,dtype=np.float64,order='C')
1912
+ cam=self.VISpar.cam-1
1913
+ X=mapFun.worldToImg(points_array,cam,None)# In output X1 is equal to X if correctly allocated
1914
+
1915
+ self.RF=[]
1916
+ origin=X[0]
1917
+ hp,=self.ui.plot.axes.plot(origin[0], origin[1], 'o', color='darkblue') # 'ko' indica un pallino nero
1918
+ self.RF.append(hp)
1919
+ length=0.25*min([q for q in self.image.shape])
1920
+ qwidth=length/25
1921
+ hwidth=4
1922
+ vnorm = np.linalg.norm(X[2]-origin)
1923
+ #colors=['darkred','darkgreen','darkmagenta']
1924
+ for k in range(1,len(X)-1): #-1 exclude z
1925
+ P=X[k]
1926
+ v=P-origin
1927
+ if vnorm!=0: v=v/vnorm*length
1928
+ hp=self.ui.plot.axes.quiver(origin[0], origin[1], v[0], v[1],
1929
+ color='darkblue',#color=colors[k-1],
1930
+ angles='xy',scale_units='xy',scale=1.0,
1931
+ units='xy',width=qwidth,headwidth=hwidth,headlength=1.25*hwidth,headaxislength=0.75*hwidth,zorder=10)
1932
+ self.RF.append(hp)
1933
+ T=origin+v*1.2
1934
+ ha=self.ui.plot.axes.text(T[0], T[1], f'{labels[k]}', color='darkblue', fontsize=fontPixelSize)
1935
+ self.RF.append(ha)
1936
+ """
1937
+ X[k]=T
1938
+ T=0.5*(X[1]+X[2])
1939
+ T=origin-0.1*(T-origin)
1940
+ ha=self.ui.plot.axes.text(T[0], T[1], f'{labels[0]}', color='darkblue', fontsize=fontPixelSize)
1941
+ self.RF.append(ha)
1942
+ """
1943
+ except Exception as exc:
1944
+ pri.Error.red(f"[VIS] Error while plotting reference frame!\n{traceback.format_exc()}\n")
1945
+ return
1946
+
1947
+ """
1948
+ def getZonaCom(self,c:int):
1949
+ return (min (self.disp.vect.Xinf[c],self.disp.vect.Xsup[c]),
1950
+ min (self.disp.vect.Yinf[c],self.disp.vect.Ysup[c]),
1951
+ max (self.disp.vect.Xinf[c],self.disp.vect.Xsup[c]),
1952
+ max (self.disp.vect.Yinf[c],self.disp.vect.Ysup[c]))
1953
+ """
1954
+
1955
+ #*************************************************** Menus
1956
+ def contextMenuEvent(self, event):
1957
+ contextMenu = QMenu(self)
1958
+ copy2clipboard = contextMenu.addAction("Copy to clipboard ("+self.QS_copy2clipboard.key().toString(QKeySequence.NativeText)+")")
1959
+ copy2clipboard.setIcon(self.ui.plot.copyIcon)
1960
+ copy2newfig = contextMenu.addAction("Open in new figure ("+self.QS_copy2newfig.key().toString(QKeySequence.NativeText)+")")
1961
+ copy2newfig.setIcon(self.ui.plot.openNewWindowIcon)
1962
+ contextMenu.addSeparator()
1963
+ if len(self.ui.plot.fig2)>0:
1964
+ showAll = contextMenu.addAction("Show all")
1965
+ showAll.setIcon(self.ui.plot.showAllIcon)
1966
+ alignAll = contextMenu.addAction("Align all")
1967
+ alignAll.setIcon(self.ui.plot.alignAllIcon)
1968
+ closeAll = contextMenu.addAction("Close all")
1969
+ closeAll.setIcon(self.ui.plot.closeAllIcon)
1970
+ contextMenu.addSeparator()
1971
+ else:
1972
+ showAll = None
1973
+ closeAll= None
1974
+ alignAll= None
1975
+ loadImg = contextMenu.addAction("Load image")
1976
+ loadImg.setIcon(self.ui.plot.loadImageIcon)
1977
+ loadRes = contextMenu.addAction("Load result")
1978
+ loadRes.setIcon(self.ui.plot.loadResultIcon)
1979
+
1980
+ action = contextMenu.exec(self.mapToGlobal(event.pos()))
1981
+ if action == copy2clipboard:
1982
+ self.ui.plot.copy2clipboard()
1983
+ elif action == copy2newfig:
1984
+ self.ui.plot.copy2newfig(self.ui.name_var.toolTip())
1985
+ elif action == showAll:
1986
+ self.ui.plot.showAll()
1987
+ elif action == closeAll:
1988
+ self.ui.plot.closeAll()
1989
+ elif action == alignAll:
1990
+ self.ui.plot.alignAll()
1991
+ elif action == loadImg:
1992
+ self.load_Img_callback()
1993
+ elif action == loadRes:
1994
+ self.load_Res_callback()
1995
+
1996
+ def loadImg(self,filename=None):
1997
+ if filename is None:
1998
+ filename, _ = QFileDialog.getOpenFileName(self,\
1999
+ "Select an image file of the sequence", filter=text_filter,\
2000
+ options=optionNativeDialog)
2001
+ else:
2002
+ if os.path.exists(filename): filename=None
2003
+ if filename:
2004
+ self.image_file_Load=filename
2005
+ self.image_raw=None
2006
+ self.image=None
2007
+
2008
+ self.ui.spin_img.setMinimum(-1)
2009
+ self.VISpar.image_file=''
2010
+ self.VISpar.img=-1
2011
+ self.VISpar.type=0
2012
+ self.VISpar.variable=self.namesPIV.combo_dict[self.namesPIV.img]
2013
+ self.VISpar.variableKey=self.namesPIV.combo_dict_keys[self.VISpar.variable]
2014
+
2015
+ self.FlagResetLevels=self.FlagResetSizes=True
2016
+ self.cleanAxes()
2017
+
2018
+ def loadRes(self):
2019
+ filename, _ = QFileDialog.getOpenFileName(self,\
2020
+ "Select an image file of the sequence", filter="All files (*.mat *.plt);; .mat (*.mat);; .plt (*.plt)",\
2021
+ options=optionNativeDialog)
2022
+ if filename:
2023
+ self.result_file_Load=filename
2024
+ self.result=None
2025
+ self.ui.spin_img.setMinimum(-1)
2026
+ self.VISpar.result_file=''
2027
+ self.VISpar.img=-1
2028
+ self.VISpar.variable=self.namesPIV.combo_dict[self.namesPIV.Mod]
2029
+ self.VISpar.variableKey=self.namesPIV.combo_dict_keys[self.VISpar.variable]
2030
+ self.FlagResetLevels=self.FlagResetSizes=True
2031
+ self.VISpar.type=1
2032
+ self.cleanAxes()
2033
+
2034
+ def create_colormap_image(colormap, width, height, FlagVerticalColormap, imgMapPath):
2035
+ # Create an empty image
2036
+ img = np.zeros((height, width, 3), dtype=np.uint8)
2037
+ # Get the Matplotlib colormap
2038
+ cmap = plt.get_cmap(colormap)
2039
+ # Calculate the colors of the colormap and assign them to the image
2040
+ for y in range(height):
2041
+ for x in range(width):
2042
+ if FlagVerticalColormap:
2043
+ normalized_y = (height-y)/ height
2044
+ color = cmap(normalized_y)
2045
+ else:
2046
+ normalized_x = x / width
2047
+ color = cmap(normalized_x)
2048
+ img[y, x] = [int(c * 255) for c in color[:3]] # Convert colors to range 0-255
2049
+ plt.imsave(imgMapPath, img)
2050
+ pixmap=numpy_to_qpixmap(img)
2051
+ return pixmap
2052
+
2053
+ def numpy_to_qpixmap(img):
2054
+ height, width, channel = img.shape
2055
+ bytes_per_line = 3 * width
2056
+ qimage = QImage(img.data, width, height, bytes_per_line, QImage.Format_RGB888)
2057
+ qpixmap = QPixmap.fromImage(qimage)
2058
+ return qpixmap
2059
+
2060
+ def create_arrow_pixmap(rgb_color, width, height, path):
2061
+ fig, ax = plt.subplots(figsize=(width / 100, height / 100), dpi=100)
2062
+ ax.axis('off')
2063
+
2064
+ # Calcola la posizione e la direzione della freccia
2065
+ x = width / 8
2066
+ y = height / 2
2067
+ u = width *3/4
2068
+ v = 0
2069
+
2070
+ # Disegna la freccia con quiver
2071
+ ax.quiver(x, y, u, v, color=rgb_color, angles='xy', scale_units='xy', scale=1, width=0.002*width, headwidth=5, headlength=5,headaxislength=3)
2072
+
2073
+ ax.set_xlim(0, width)
2074
+ ax.set_ylim(0, height)
2075
+
2076
+ # Salva l'immagine in un buffer
2077
+ buf = io.BytesIO()
2078
+ plt.savefig(buf, format='png', bbox_inches='tight', pad_inches=0, transparent=True)
2079
+ plt.close(fig)
2080
+ buf.seek(0)
2081
+
2082
+ image = Image.open(buf)
2083
+ image.save(path)
2084
+ pixmap=QPixmap(path)
2085
+ return pixmap
2086
+
2087
+
2088
+ if __name__ == "__main__":
2089
+ import sys
2090
+ app=QApplication.instance()
2091
+ if not app:app = QApplication(sys.argv)
2092
+ app.setStyle('Fusion')
2093
+ object = Vis_Tab(None)
2094
+ object.show()
2095
+ app.exec()
2096
+ app.quit()
2097
+ app=None
2098
+
2099
+
2100
+