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