PaIRS-UniNa 0.2.10__cp313-cp313-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 +347 -0
  2. PaIRS_UniNa/Changes.txt +174 -0
  3. PaIRS_UniNa/Custom_Top.py +303 -0
  4. PaIRS_UniNa/Explorer.py +3322 -0
  5. PaIRS_UniNa/FolderLoop.py +562 -0
  6. PaIRS_UniNa/Input_Tab.py +829 -0
  7. PaIRS_UniNa/Input_Tab_CalVi.py +787 -0
  8. PaIRS_UniNa/Input_Tab_tools.py +3026 -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 +1374 -0
  14. PaIRS_UniNa/Process_Tab.py +1761 -0
  15. PaIRS_UniNa/Process_Tab_CalVi.py +313 -0
  16. PaIRS_UniNa/Process_Tab_Disp.py +170 -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 +298 -0
  21. PaIRS_UniNa/TabTools.py +1413 -0
  22. PaIRS_UniNa/Vis_Tab.py +2176 -0
  23. PaIRS_UniNa/Vis_Tab_CalVi.py +982 -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 +1633 -0
  29. PaIRS_UniNa/calib.py +1488 -0
  30. PaIRS_UniNa/calibView.py +833 -0
  31. PaIRS_UniNa/gPaIRS.py +3957 -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 +4 -0
  330. pairs_unina-0.2.10.dist-info/METADATA +159 -0
  331. pairs_unina-0.2.10.dist-info/RECORD +333 -0
  332. pairs_unina-0.2.10.dist-info/WHEEL +5 -0
  333. pairs_unina-0.2.10.dist-info/top_level.txt +2 -0
PaIRS_UniNa/Vis_Tab.py ADDED
@@ -0,0 +1,2176 @@
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
+ self.colorMapMenu.setStyleSheet(self.gui.ui.menu.styleSheet())
447
+ # Add the colormap thumbnails to the menu
448
+ def on_colormap_selected(name):
449
+ self.VISpar.vcolorMap[self.VISpar.variableKey]=self.VISpar.colorMap=name
450
+ for k, colorMapClass in enumerate(VIS_ColorMaps):
451
+ if not k: menu=self.colorMapMenu
452
+ else: menu=self.colorMapMenu.addMenu(colorMapClass)
453
+ #for colormap in VIS_ColorMaps[colorMapClass]:
454
+ for colormap in VIS_ColorMaps[colorMapClass]:
455
+ imgMapPath=icons_path+'colormaps/'+colormap+'.png'
456
+ if os.path.exists(imgMapPath) and not FlagGenerateColormaps:
457
+ pixmap = QPixmap(imgMapPath)
458
+ else:
459
+ pixmap=create_colormap_image(colormap, 25, 50, FlagVerticalColormap, imgMapPath)
460
+ action = menu.addAction(QIcon(pixmap), ' '+colormap)
461
+ action.triggered.connect(lambda _, name=colormap: on_colormap_selected(name))
462
+ pri.Time.magenta('Colormap generation: end')
463
+
464
+ pri.Time.magenta('Vector color generation: start')
465
+ # Create the popup menu
466
+ self.vectorColorMenu = QMenu(self)
467
+ self.vectorColorMenu.setStyleSheet(self.gui.ui.menu.styleSheet())
468
+ # Add the colormap thumbnails to the menu
469
+ def on_vectorcolor_selected(name):
470
+ self.VISpar.vvectorColor[self.VISpar.variableKey]=self.VISpar.vectorColor=name
471
+ for colorName, color in VIS_VectorColors.items():
472
+ menu=self.vectorColorMenu
473
+ #for colormap in VIS_ColorMaps[colorMapClass]:
474
+ imgMapPath=icons_path+'colormaps/'+colorName+'Vector.png'
475
+ if os.path.exists(imgMapPath) and not FlagGenerateColorvectors:
476
+ pixmap = QPixmap(imgMapPath)
477
+ else:
478
+ pixmap=create_arrow_pixmap(color, 50, 50, imgMapPath)
479
+ action = menu.addAction(QIcon(pixmap), ' '+colorName.lower())
480
+ action.triggered.connect(lambda _, name=colorName: on_vectorcolor_selected(name))
481
+ pri.Time.magenta('Vector color generation: end')
482
+
483
+ apply_hover_glow_label(self.ui.icon)
484
+
485
+ #------------------------------------- Declaration of parameters
486
+ self.VISpar_base=VISpar()
487
+ self.VISpar:VISpar=self.TABpar
488
+ self.VISpar_old:VISpar=self.TABpar_old
489
+
490
+ #------------------------------------- Callbacks
491
+ self.defineWidgets()
492
+ self.setupWid() #---------------- IMPORTANT
493
+
494
+ FlagPreventAddPrev_Slider=False
495
+ for n in ('min','max','mean','range','nclev','vecsize','vecwid','vecspac','streamdens'):
496
+ def defineSliderCallbackSet(n):
497
+ spin:QSpinBox=getattr(self.ui,'spin_'+n)
498
+ slider:QSlider=getattr(self.ui,'slider_'+n)
499
+
500
+ if n in ('min','max','mean','range'):
501
+ changingAction=lambda: self.sliderLevels_changing(spin,slider,FlagPreventAddPrev_Slider)
502
+ callback=self.wrappedCallback(spin_tips[n],changingAction)
503
+ action=lambda: self.spinLevels_action(spin)
504
+ elif n in ('nclev','vecsize','vecwid','vecspac','streamdens'):
505
+ changingAction=lambda: self.sliderFieldRep_changing(spin,slider,FlagPreventAddPrev_Slider)
506
+ callback=self.wrappedCallback(spin_tips[n],changingAction)
507
+ action=lambda: self.spinFieldRep_action(spin)
508
+ setting=lambda: self.slider_set(spin,slider)
509
+
510
+ slider.valueChanged.connect(callback)
511
+
512
+ """
513
+ if n in ('nclev','streamdens'):
514
+ def sliderMessage(s:QSlider):
515
+ if self.VISpar.field_rep==2:
516
+ tip = f"Release to repaint"
517
+ show_mouse_tooltip(s,tip)
518
+ slider.sliderPressed.connect(lambda: sliderMessage(slider))
519
+ """
520
+
521
+ setattr(self,'slider_'+n+'_callbcak',callback)
522
+ setattr(self,'spin_'+n+'_action',action)
523
+ setattr(self,'spin_'+n+'_set',setting)
524
+
525
+ defineSliderCallbackSet(n)
526
+
527
+
528
+ for k,n in enumerate(['xmin','xmax','ymin','ymax']):
529
+ def defineXYAction(k,n):
530
+ spin=getattr(self.ui,'spin_'+n)
531
+ action=lambda: self.spin_xy_action(spin,k)
532
+ setattr(self,'spin_'+n+'_action',action)
533
+ defineXYAction(k,n)
534
+
535
+ self.plot_callback=self.wrappedCallback('Plot interaction',self.updatingPlot)
536
+ self.ui.plot.addfuncrelease['fPlotCallback']=self.plot_callback
537
+
538
+ self.button_left_action=lambda: self.leftrightCallback(-1)
539
+ self.button_right_action=lambda: self.leftrightCallback(+1)
540
+
541
+ self.QS_copy2clipboard=QShortcut(QKeySequence('Ctrl+C'), self.ui.plot)
542
+ self.QS_copy2clipboard.activated.connect(self.ui.plot.copy2clipboard)
543
+ self.QS_copy2newfig=QShortcut(QKeySequence('Ctrl+D'), self.ui.plot)
544
+ self.QS_copy2newfig.activated.connect(lambda: self.ui.plot.copy2newfig(self.ui.name_var.toolTip()))
545
+ self.load_Img_callback=self.wrappedCallback('Loading image',self.loadImg)
546
+ self.load_Res_callback=self.wrappedCallback('Loading result',self.loadRes)
547
+
548
+ self.defineCallbacks()
549
+ self.spins_valueChanged=[self.ui.spin_img,self.ui.spin_frame,self.ui.spin_cam,self.ui.spin_it]
550
+ self.connectCallbacks()
551
+
552
+ self.defineSettings()
553
+ self.TABsettings.append(self.setMapVar)
554
+
555
+ self.adjustTABpar=self.adjustVISpar
556
+ self.setTABlayout=self.setVISlayout
557
+
558
+ self.FlagReset=True
559
+ self.FlagResetLevels=False
560
+ self.FlagResetSizes =False
561
+
562
+ self.image_file=''
563
+ self.image_raw=None
564
+ self.image=None
565
+ self.image_file_Min=''
566
+ self.image_Min_raw=None
567
+ self.image_Min=None
568
+ self.image_file_Disp=''
569
+ self.image_Disp_raw=None
570
+ self.image_Disp=None
571
+ self.nbits=0
572
+ self.result_file=''
573
+ self.result=None
574
+ self.result_file_Mean=''
575
+ self.result_Mean=None
576
+ self.image_file_Load=''
577
+ self.result_file_Load=''
578
+
579
+ self.image_Current_raw=None
580
+ self.image_Current=None
581
+ self.result_Current=None
582
+
583
+ self.FlagAddPrev=False
584
+
585
+ #------------------------------------- Initializing
586
+ if flagInit:
587
+ self.initialize()
588
+ #else:
589
+ # self.adjustTABpar()
590
+ # self.setTABpar(FlagBridge=False)
591
+
592
+ def addPlotToolBar(self):
593
+ if self.Ptoolbar:
594
+ self.Ptoolbar.setParent(None)
595
+ self.Ptoolbar = NavigationToolbar(self.ui.plot, self)
596
+ unwanted_buttons = ['Home','Back','Forward','Customize'] #'Subplots','Save'
597
+ for x in self.Ptoolbar.actions():
598
+ if x.text() in unwanted_buttons:
599
+ self.Ptoolbar.removeAction(x)
600
+ self.ui.lay_w_Plot.addWidget(self.Ptoolbar)
601
+
602
+ def initialize(self):
603
+ pri.Info.yellow(f'{"*"*20} VIS initialization {"*"*20}')
604
+ self.setExample()
605
+ self.adjustVISpar()
606
+ self.setVISlayout()
607
+ self.setTABpar(FlagBridge=False) #with bridge
608
+ self.add_TABpar('initialization')
609
+
610
+ def setExample(self):
611
+ if not basefold_DEBUG_VIS: return
612
+ imSet=ImageSet(path=basefold_DEBUG_VIS)
613
+
614
+ k1=0
615
+ k2=imSet.link[k1][0]
616
+ self.VISpar.path=imSet.path
617
+ self.VISpar.imList,_=imSet.genListsFromFrame([k1],[k2+1],imSet.ind_in[k1],imSet.nimg[k1],1,False)
618
+
619
+ outPath=myStandardPath(os.path.dirname(imSet.outFiles[outExt.piv][0]))
620
+ outSet=ImageSet(path=outPath,exts=list(outType_dict))
621
+
622
+ im_min_a=findFiles_sorted(outPath+'*a_min.*')
623
+ if im_min_a: self.VISpar.imListMin[0].append(im_min_a[0])
624
+ im_min_b=findFiles_sorted(outPath+'*b_min.*')
625
+ if im_min_b: self.VISpar.imListMin[0].append(im_min_b[0])
626
+ 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)
627
+ self.VISpar.result_file_Mean=self.VISpar.resF('*').replace('_*','')
628
+ self.VISpar.img=1
629
+ self.VISpar.Out.FlagNone=True
630
+ return
631
+
632
+ #*************************************************** Adjusting parameters
633
+ def adjustVISpar(self):
634
+ self.VISpar.ncam=len(self.VISpar.imList)
635
+ if self.VISpar.ncam and not self.VISpar.cam: self.VISpar.cam=1
636
+ self.VISpar.nimg=len(self.VISpar.imList[0][0]) if len(self.VISpar.imList[0]) else 0 if self.VISpar.ncam else 0
637
+ if not self.VISpar.nimg and self.VISpar.img:
638
+ FlagResults=self.image_file_Min!='' or self.result_file_Mean!='' or self.image_file_Disp!=''
639
+ self.VISpar.img=0 if FlagResults else -1
640
+
641
+ FlagNewImage, FlagNewResult = self.adjustImport()
642
+
643
+ FlagNew=(not self.VISpar.type and FlagNewImage) or (self.VISpar.type==1 and FlagNewResult)
644
+ FlagDiff=self.VISpar.isDifferentFrom(self.VISpar_old,fields=['img','cam','frame']) or FlagNew
645
+
646
+ if (self.VISpar.FlagAutoLevels and (FlagNewImage or FlagNewResult)):
647
+ self.resetAllLevels()
648
+ if FlagDiff or self.FlagResetLevels:
649
+ self.FlagResetLevels=False
650
+ self.resetLevels()
651
+ elif self.FlagResetLevels:
652
+ self.FlagResetLevels=False
653
+ self.resetLevels()
654
+
655
+ if (self.VISpar.FlagAutoSizes and (FlagNewImage or FlagNewResult)):
656
+ self.resetAllXYLims()
657
+ if FlagDiff or self.FlagResetSizes:
658
+ self.FlagResetSizes=False
659
+ self.resetXYLims()
660
+ elif self.FlagResetSizes:
661
+ self.FlagResetSizes=False
662
+ self.resetXYLims()
663
+
664
+ self.adjustFieldRep()
665
+
666
+
667
+ def adjustImport(self):
668
+ self.VISpar.image_file=self.VISpar.image_file_Min=self.VISpar.image_file_Disp=''
669
+ if self.VISpar.img%2==0 and self.VISpar.FlagTR and not self.VISpar.LaserType:
670
+ f=[1,0][self.VISpar.frame-1]
671
+ else: f=self.VISpar.frame-1
672
+ self.VISpar.image_file_Disp=''
673
+ FlagDisparity=self.VISpar.Step==StepTypes.disp and (resultCheck(self,self.VISpar,ind=self.VISpar.ind) or self.VISpar.FlagView)
674
+ if FlagDisparity:
675
+ dispMap_filename=self.VISpar.resF(f'it{self.VISpar.it}',string='dispMap')
676
+ if os.path.exists(dispMap_filename):
677
+ self.VISpar.image_file_Disp=dispMap_filename
678
+ self.VISpar.image_file_Min=''
679
+ ITEs=self.gui.ui.Explorer.ITEsfromInd(self.VISpar.ind)
680
+ ind_min=list(ITEs[0].children).index(StepTypes.min)
681
+ 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)
682
+ if FlagMinimum:
683
+ if 0<=self.VISpar.cam-1<self.VISpar.ncam:
684
+ if 0<=f<len(self.VISpar.imListMin[self.VISpar.cam-1]):
685
+ self.VISpar.image_file_Min=self.VISpar.imListMin[self.VISpar.cam-1][f]
686
+ if self.VISpar.img>0:
687
+ 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 ''
688
+ elif self.VISpar.img==0:
689
+ 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
690
+ else:
691
+ self.VISpar.image_file=self.image_file_Load
692
+
693
+ self.VISpar.result_file=self.VISpar.result_file_Mean=''
694
+ if self.VISpar.img==-1:
695
+ self.VISpar.result_file=self.result_file_Load
696
+ elif self.VISpar.img==0 and self.VISpar.flagRun==-2:
697
+ if (self.VISpar.Step==StepTypes.disp and self.VISpar.it==self.VISpar.Nit) or self.VISpar.Step!=StepTypes.disp:
698
+ self.VISpar.result_file=self.VISpar.result_file_Current
699
+ else:
700
+ self.VISpar.FlagResult=self.VISpar.Step!=StepTypes.min and (resultCheck(self,self.VISpar) or self.VISpar.FlagView)
701
+ if self.VISpar.FlagResult:
702
+ if self.VISpar.Step==StepTypes.disp:
703
+ self.VISpar.result_file_Mean=self.VISpar.resF(f'it{self.VISpar.it}')
704
+ else:
705
+ self.VISpar.result_file_Mean=self.VISpar.resF('*').replace('_*','')
706
+ if self.VISpar.img>0:
707
+ if self.VISpar.Step==StepTypes.disp:
708
+ self.VISpar.result_file=''
709
+ else:
710
+ self.VISpar.result_file=self.VISpar.resF(self.VISpar.img)
711
+ elif self.VISpar.img==0:
712
+ self.VISpar.result_file=self.VISpar.result_file_Mean
713
+ if not self.VISpar.FlagView:
714
+ ITE=self.gui.ui.Explorer.ITEfromInd(self.VISpar.ind)
715
+ id=ITE.procdata.name_proc
716
+ self.VISpar.FlagResult=fileIdenitifierCheck(id,self.VISpar.result_file)
717
+ if not self.VISpar.FlagResult: self.VISpar.result_file=''
718
+
719
+
720
+ FlagNewImage, FlagNewResult, _=self.importFiles()
721
+ return FlagNewImage, FlagNewResult
722
+
723
+ def importFiles(self):
724
+ if self.VISpar.image_file_Min!=self.image_file_Min or self.VISpar.FlagMIN!=self.VISpar_old.FlagMIN or self.FlagReset:
725
+ self.image_file_Min,self.image_Min_raw=self.readImageFile(self.VISpar.image_file_Min)
726
+ if self.VISpar.image_file_Disp!=self.image_file_Disp or self.FlagReset:
727
+ self.image_file_Disp,self.image_Disp_raw=self.readImageFile(self.VISpar.image_file_Disp)
728
+ if self.VISpar.result_file_Mean!=self.result_file_Mean or self.VISpar.FlagResult!=self.VISpar_old.FlagResult or self.FlagReset:
729
+ self.result_file_Mean,self.result_Mean=self.readResultFile(self.VISpar.result_file_Mean)
730
+
731
+ FlagNewImage=self.VISpar.image_file!=self.image_file or self.VISpar.ind[:-1]!=self.VISpar_old.ind[:-1]
732
+ if FlagNewImage or self.FlagReset:
733
+ self.image_file=self.VISpar.image_file
734
+ if self.VISpar.img==0:
735
+ if self.VISpar.flagRun==-2:
736
+ 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
737
+ else:
738
+ self.image_raw=self.image_Disp_raw if self.VISpar.variableKey==self.namesPIV.dispMap else self.image_Min_raw
739
+ else:
740
+ self.image_file,self.image_raw=self.readImageFile(self.VISpar.image_file)
741
+ mapVariableList=[]
742
+ #if self.image_raw is None and self.VISpar.img==0: mapVariableList=[]
743
+ #else:
744
+ if self.image_Disp_raw is not None and self.VISpar.img==0: mapVariableList+=[self.namesPIV.dispMap]
745
+ if (self.image_Min_raw is not None and self.VISpar.img==0) or self.VISpar.img!=0: mapVariableList+=[self.namesPIV.img]
746
+
747
+ FlagNewResult=self.VISpar.result_file!=self.result_file or self.VISpar.ind[:-1]!=self.VISpar_old.ind[:-1]
748
+ if FlagNewResult or self.FlagReset:
749
+ self.result_file=self.VISpar.result_file
750
+ if self.VISpar.img==0:
751
+ if self.VISpar.flagRun==-2:
752
+ self.result=self.result_Current
753
+ else:
754
+ self.result=self.result_Mean
755
+ else:
756
+ self.result_file,self.result=self.readResultFile(self.VISpar.result_file)
757
+
758
+ if self.image_raw is not None:
759
+ if self.VISpar.img>=0 and self.VISpar.variableKey!=self.namesPIV.dispMap:
760
+ self.image=transfIm(self.VISpar.Out,Images=[self.image_raw])[0]
761
+ else:
762
+ self.image=self.image_raw
763
+ self.getImageInfo()
764
+ else:
765
+ self.image=None
766
+ if self.image_Min_raw is not None:
767
+ self.image_Min=transfIm(self.VISpar.Out,Images=[self.image_Min_raw])[0]
768
+ else:
769
+ self.image_Min=None
770
+ if self.image_Disp_raw is not None:
771
+ self.image_Disp=self.image_Disp_raw #transfIm(self.VISpar.Out,Images=[self.image_Disp_raw])[0]
772
+ else:
773
+ self.image_Disp=None
774
+ if self.result is not None:
775
+ self.getResultInfo()
776
+
777
+ if self.result:
778
+ [mapVariableList.append(r) for r in list(self.result)]
779
+ self.FlagReset=False
780
+
781
+ comboItemsList=[]
782
+ if self.namesPIV.img in mapVariableList: comboItemsList+=[self.namesPIV.combo_dict[self.namesPIV.img]]
783
+ if self.namesPIV.dispMap in mapVariableList: comboItemsList+=[self.namesPIV.combo_dict[self.namesPIV.dispMap]]
784
+ for f in list(self.namesPIV.combo_dict)[2:]:
785
+ if f in mapVariableList: comboItemsList.append(self.namesPIV.combo_dict[f])
786
+ if len(comboItemsList)==0: comboItemsList=[self.namesPIV.combo_dict[self.namesPIV.img]]
787
+ if self.VISpar.variable not in comboItemsList:
788
+ self.VISpar.variable=comboItemsList[0]
789
+ self.VISpar.variableKey=self.namesPIV.combo_dict_keys[self.VISpar.variable]
790
+ if self.VISpar.variableKey==self.namesPIV.img and self.VISpar.img==0:
791
+ if self.VISpar.image_file!=self.VISpar.image_file_Min:
792
+ self.VISpar.image_file=self.VISpar.image_file_Min
793
+ self.image=self.image_Min
794
+ self.getImageInfo()
795
+ elif self.VISpar.variableKey==self.namesPIV.dispMap and self.VISpar.img==0:
796
+ if self.VISpar.image_file!=self.VISpar.image_file_Disp:
797
+ self.VISpar.image_file=self.VISpar.image_file_Disp
798
+ self.image=self.image_Disp
799
+ self.getImageInfo()
800
+ self.VISpar.type=int(self.VISpar.variableKey not in (self.namesPIV.img, self.namesPIV.dispMap) )
801
+
802
+ return FlagNewImage, FlagNewResult, comboItemsList
803
+
804
+ def checkVISTab(self,ind=None):
805
+ if ind is None: VIS:VISpar=self.VISpar
806
+ else: VIS:VISpar=self.TABpar_at(ind)
807
+ VIS.OptionDone=1 if (VIS.flagRun>0 and resultCheck(self,VIS)) or VIS.flagRun<=0 else 0
808
+
809
+ def adjustFieldRep(self):
810
+ if self.VISpar_old.field_rep!=self.VISpar.field_rep and self.result:
811
+ if not self.VISpar.unit[self.VISpar.type]:
812
+ xres,yres=self.getXYRes(type=1)
813
+ else: xres=yres=1.0
814
+ if self.namesPIV.x in self.result and self.namesPIV.y in self.result:
815
+ X=self.result[self.namesPIV.x]*xres
816
+ Y=self.result[self.namesPIV.y]*yres
817
+ elif self.namesPIV.X in self.result and self.namesPIV.Y in self.result:
818
+ X=self.result[self.namesPIV.X]*xres
819
+ Y=self.result[self.namesPIV.Y]*yres
820
+ else: return
821
+ dX=np.sqrt((X[0,1]-X[0,0])**2+(Y[1,0]-Y[0,0])**2)
822
+ dW=[X.max()-X.min(),Y.max()-Y.min()]
823
+ size_pixels=self.ui.plot.fig.get_size_inches()*self.ui.plot.fig.get_dpi()*self.ui.plot.axes.get_position().bounds[2:]
824
+ spaPixels=dX*size_pixels/dW
825
+ fac_spa=np.max(nPixelsPerVector/spaPixels).astype(int).item()
826
+ self.VISpar.vecspac=max([1,fac_spa])
827
+ self.VISpar.vecsize=5
828
+ self.VISpar.vecwid=1
829
+
830
+ #*************************************************** Layout
831
+ def setVISlayout(self):
832
+ _, _, comboItemsList=self.importFiles()
833
+ self.checkResVariables()
834
+
835
+ FlagLoad=self.image_file_Load!='' or self.result_file_Load!=''
836
+ FlagResults=self.image_file_Min!='' or self.result_file_Mean!='' or self.image_file_Disp!=''
837
+ FlagSpinsEnabled=self.VISpar.nimg or FlagLoad
838
+ FlagDispMap=self.VISpar.variableKey==self.namesPIV.dispMap
839
+ #self.ui.Plot_tools.setEnabled(FlagSpinsEnabled)
840
+
841
+ FlagIW=self.VISpar.type==0 and self.VISpar.Step in (StepTypes.piv,StepTypes.disp,StepTypes.spiv) and not FlagDispMap
842
+ self.ui.button_ShowIW.setVisible(FlagIW)
843
+ if FlagIW:
844
+ tip=f"{'Hide' if self.ui.button_ShowIW.isChecked() else 'Show'} Interrogation Window scheme"
845
+ self.ui.button_ShowIW.setToolTip(tip)
846
+ self.ui.button_ShowIW.setStatusTip(tip)
847
+
848
+ FlagCR=self.VISpar.type==0 and self.VISpar.Step in (StepTypes.disp,StepTypes.spiv) and not FlagDispMap
849
+ self.ui.button_ShowCR.setVisible(FlagCR)
850
+ if FlagCR:
851
+ tip=f"{'Hide' if self.ui.button_ShowCR.isChecked() else 'Show'} common region"
852
+ self.ui.button_ShowCR.setToolTip(tip)
853
+ self.ui.button_ShowCR.setStatusTip(tip)
854
+
855
+ FlagMIN=self.VISpar.type==0 and self.image_Min is not None and self.VISpar.img>0 #and self.VISpar.FlagMIN
856
+ self.ui.button_SubMIN.setVisible(FlagMIN)
857
+ if FlagMIN:
858
+ tip=f"{'Add' if self.ui.button_SubMIN.isChecked() else 'Subtract'} historical minimum background"
859
+ self.ui.button_SubMIN.setToolTip(tip)
860
+ self.ui.button_SubMIN.setStatusTip(tip)
861
+
862
+ self.ui.line_img.setVisible(FlagIW or FlagMIN)
863
+
864
+ FlagUnit=self.VISpar.Process==ProcessTypes.piv and (self.VISpar.Out.xres!=1.0 or self.VISpar.Out.pixAR!=1.0)
865
+ self.ui.button_unit.setVisible(FlagUnit)
866
+ if FlagUnit:
867
+ tip=f"Set {'pixel' if self.ui.button_unit.isChecked() else 'physical'} units"
868
+ self.ui.button_unit.setToolTip(tip)
869
+ self.ui.button_unit.setStatusTip(tip)
870
+
871
+ self.ui.line_unit.setVisible(FlagUnit)
872
+
873
+ self.ui.button_Contourf.setVisible(self.VISpar.type)
874
+ self.ui.line_Contourf.setVisible(self.VISpar.type==1)
875
+
876
+ self.ui.combo_map_var.clear()
877
+ self.ui.combo_map_var.addItems(comboItemsList)
878
+
879
+ 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)
880
+ self.ui.button_cvec.setVisible(FlagResult and self.VISpar.field_rep!=0)
881
+ self.ui.label_field_rep.setVisible(FlagResult)
882
+ self.ui.combo_field_rep.setVisible(FlagResult)
883
+
884
+ i=self.VISpar.setPage
885
+ 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))
886
+ if i>c: i=0
887
+ self.ui.image_levels.setCurrentIndex(i)
888
+ self.ui.label_title.setText(f"Settings ({i+1}/{c+1})")
889
+
890
+ if self.VISpar.variableKey in self.VISpar.vLim:
891
+ Lim=self.VISpar.vLim[self.VISpar.variableKey]
892
+ else:
893
+ Lim=1.0
894
+ step=Lim/nStepsSlider
895
+ FlagLim= self.VISpar.type or FlagDispMap
896
+ self.ui.spin_min.setMinimum(-Lim if FlagLim else 0)
897
+ self.ui.spin_min.setMaximum(Lim-2*step)
898
+ self.ui.spin_max.setMinimum(-Lim+2*step if FlagLim else 2*step)
899
+ self.ui.spin_max.setMaximum(Lim)
900
+ self.ui.spin_mean.setMinimum(-Lim+step if FlagLim else step)
901
+ self.ui.spin_mean.setMaximum(Lim-step)
902
+ self.ui.spin_range.setMinimum(2*step)
903
+ self.ui.spin_range.setMaximum(2*Lim if FlagLim else step)
904
+ self.ui.spin_vecspac.setMaximum(self.VISpar.size[1][4])
905
+
906
+ self.ui.label_vecspac.setVisible(self.VISpar.field_rep==1)
907
+ self.ui.slider_vecspac.setVisible(self.VISpar.field_rep==1)
908
+ self.ui.spin_vecspac.setVisible(self.VISpar.field_rep==1)
909
+ self.ui.label_vecsize.setVisible(self.VISpar.field_rep==1)
910
+ self.ui.slider_vecsize.setVisible(self.VISpar.field_rep==1)
911
+ self.ui.spin_vecsize.setVisible(self.VISpar.field_rep==1)
912
+ self.ui.label_vecwid.setVisible(self.VISpar.field_rep==1)
913
+ self.ui.slider_vecwid.setVisible(self.VISpar.field_rep==1)
914
+ self.ui.spin_vecwid.setVisible(self.VISpar.field_rep==1)
915
+ self.ui.spin_vecspac.setMaximum(self.VISpar.size_default[1][-1])
916
+ self.ui.label_streamdens.setVisible(self.VISpar.field_rep==2)
917
+ self.ui.slider_streamdens.setVisible(self.VISpar.field_rep==2)
918
+ self.ui.spin_streamdens.setVisible(self.VISpar.field_rep==2)
919
+
920
+ self.ui.spin_img.setMinimum(-1)
921
+ self.ui.spin_img.setMaximum(self.VISpar.nimg if self.VISpar.nimg else 0 if FlagResults else -1)
922
+ #self.ui.spin_img.setEnabled(FlagSpinsEnabled)
923
+ self.ui.spin_frame.setEnabled(FlagSpinsEnabled)
924
+ self.ui.spin_cam.setMaximum(self.VISpar.ncam)
925
+ self.ui.spin_cam.setEnabled(FlagSpinsEnabled and self.VISpar.ncam>1)
926
+
927
+ FlagCamFrame=self.VISpar.img>-1 and self.VISpar.type==0 and not FlagDispMap
928
+ self.ui.label_frame.setVisible(FlagCamFrame)
929
+ self.ui.spin_frame.setVisible(FlagCamFrame)
930
+ self.ui.label_cam.setVisible(FlagCamFrame)
931
+ self.ui.spin_cam.setVisible(FlagCamFrame)
932
+ 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
933
+ self.ui.label_it.setVisible(FlagDispResult)
934
+ self.ui.spin_it.setVisible(FlagDispResult)
935
+ self.ui.spin_it.setMinimum(1)
936
+ self.ui.spin_it.setMaximum(self.VISpar.Nit)
937
+ self.ui.spin_it.setEnabled(self.VISpar.flagRun!=-2)
938
+ if self.VISpar.type==0:
939
+ dataType='Input'
940
+ dataName=self.image_file if self.image is not None else None
941
+ else:
942
+ dataType='Output'
943
+ dataName=self.result_file if self.result is not None else None
944
+ if dataName:
945
+ self.ui.name_var.setText(f'{dataType} file: {os.path.basename(dataName)}')
946
+ else:
947
+ self.ui.name_var.setText(f'{dataType} file not available!')
948
+ self.ui.name_var.setToolTip(f'{dataType} file: {dataName}')
949
+ self.ui.name_var.setStatusTip(self.ui.name_var.toolTip())
950
+
951
+ if self.VISpar.variableKey in self.VISpar.vcolorMap:
952
+ self.VISpar.colorMap=self.VISpar.vcolorMap[self.VISpar.variableKey]
953
+ if self.VISpar.variableKey in self.VISpar.vvectorColor:
954
+ self.VISpar.vectorColor=self.VISpar.vvectorColor[self.VISpar.variableKey]
955
+
956
+ self.ui.button_cmap.setIcon(QIcon(icons_path+'colormaps/'+self.VISpar.colorMap+'.png'))
957
+ self.ui.button_cvec.setIcon(QIcon(icons_path+'colormaps/'+self.VISpar.vectorColor+'Vector.png'))
958
+
959
+ self.setLevels()
960
+ t=self.VISpar.type
961
+ if (t==0 and self.VISpar.unit[t]) or (t==1 and not self.VISpar.unit[t]):
962
+ self.xres,self.yres=self.getXYRes()
963
+ else: self.xres=self.yres=1.0
964
+ self.VISpar.xmin=self.VISpar.size[self.VISpar.type][0]*self.xres
965
+ self.VISpar.xmax=self.VISpar.size[self.VISpar.type][1]*self.xres
966
+ self.VISpar.ymin=self.VISpar.size[self.VISpar.type][2]*self.yres
967
+ self.VISpar.ymax=self.VISpar.size[self.VISpar.type][3]*self.yres
968
+
969
+ self.checkVISTab()
970
+ self.setVISwarn()
971
+ return
972
+
973
+ def setLevels(self):
974
+ if self.VISpar.variableKey in self.VISpar.vmin:
975
+ self.VISpar.min=self.VISpar.vmin[self.VISpar.variableKey]
976
+ self.VISpar.max=self.VISpar.vmax[self.VISpar.variableKey]
977
+ self.VISpar.mean=self.VISpar.vmean[self.VISpar.variableKey]
978
+ self.VISpar.range=self.VISpar.vrange[self.VISpar.variableKey]
979
+
980
+ def resetLevels(self):
981
+ if self.VISpar.variableKey in self.VISpar.vmin_default:
982
+ self.VISpar.vmin[self.VISpar.variableKey]=self.VISpar.vmin_default[self.VISpar.variableKey]
983
+ self.VISpar.vmax[self.VISpar.variableKey]=self.VISpar.vmax_default[self.VISpar.variableKey]
984
+ self.VISpar.vmean[self.VISpar.variableKey]=self.VISpar.vmean_default[self.VISpar.variableKey]
985
+ self.VISpar.vrange[self.VISpar.variableKey]=self.VISpar.vrange_default[self.VISpar.variableKey]
986
+ #self.setLevels()
987
+
988
+ def resetAllLevels(self, ind=None):
989
+ if ind is None: VIS:VISpar=self.VISpar
990
+ else: VIS:VISpar=self.TABpar_at(ind)
991
+ for field in ('min','max','mean','range'):
992
+ v=getattr(VIS,'v'+field)
993
+ w=getattr(VIS,'v'+field+'_default')
994
+ for f in list(w):
995
+ v[f]=w[f]
996
+ #self.setLevels()
997
+
998
+ def checkResVariables(self):
999
+ for field in ('min','max','mean','range'):
1000
+ v=getattr(self.VISpar,'v'+field)
1001
+ w=getattr(self.VISpar,'v'+field+'_default')
1002
+ for f in list(w):
1003
+ if f not in list(v):
1004
+ v[f]=w[f]
1005
+
1006
+ def resetXYLims(self):
1007
+ self.VISpar.size[self.VISpar.type][::]=self.VISpar.size_default[self.VISpar.type][::]
1008
+
1009
+ def resetAllXYLims(self, ind=None):
1010
+ if ind is None: VIS:VISpar=self.VISpar
1011
+ else: VIS:VISpar=self.TABpar_at(ind)
1012
+ for t in (0,1):
1013
+ VIS.size[t][::]=self.VISpar.size_default[t][::]
1014
+
1015
+ def readImageFile(self,filename):
1016
+ I=None
1017
+ if not filename: return filename, I
1018
+ try:
1019
+ if os.path.exists(filename):
1020
+ pri.Info.cyan(f'Opening: {filename} [<--{self.image_file}]')
1021
+ img=Image.open(filename)
1022
+ I=np.ascontiguousarray(img)
1023
+ self.nbits=img.getextrema()[1].bit_length()
1024
+ #I=transfIm(self.VISpar.Out,Images=[I])[0]
1025
+ except Exception as inst:
1026
+ pri.Error.red(f'Error opening image file: {filename}\n{traceback.format_exc()}\n{inst}')
1027
+ I=None
1028
+ return filename, I
1029
+
1030
+ def getImageInfo(self,image=None,ind=None):
1031
+ if image is None: I=self.image
1032
+ else: I=image
1033
+ if I is None: return
1034
+ if ind is None: VIS:VISpar=self.VISpar
1035
+ else: VIS:VISpar=self.TABpar_at(ind)
1036
+ variableKey=self.VISpar.variableKey
1037
+ if variableKey is self.namesPIV.dispMap:
1038
+ variableKey=self.namesPIV.dispMap
1039
+ if image is None:
1040
+ CC_16bit=self.image.astype(np.float64) # Convert back to float
1041
+ I=(CC_16bit / 65535.0) * 2.0 - 1.0 # Reverse the normalization
1042
+ self.image=I
1043
+ mean=np.mean(I).item()
1044
+ std=np.std(I).item()
1045
+ VIS.vLim[variableKey]=1.0
1046
+ VIS.vmin_default[variableKey]=max([mean-2*std,-1.0])
1047
+ VIS.vmax_default[variableKey]=min([mean+2*std,1.0])
1048
+ else:
1049
+ mean=np.mean(I).item()
1050
+ std=np.std(I).item()
1051
+ VIS.vLim[variableKey]=min([2*I.max().item(),2**(self.nbits+1)])
1052
+ VIS.vmin_default[variableKey]=np.round(max([mean-2*std,0])).item()
1053
+ VIS.vmax_default[variableKey]=np.round(min([mean+2*std,VIS.vLim[variableKey]])).item()
1054
+
1055
+ VIS.vmean_default[variableKey]=0.5*(VIS.vmin_default[variableKey]+VIS.vmax_default[variableKey])
1056
+ VIS.vrange_default[variableKey]=VIS.vmax_default[variableKey]-VIS.vmin_default[variableKey]
1057
+ VIS.size_default[0]=[0,np.size(I,1),0,np.size(I,0),1]
1058
+ if variableKey not in VIS.vcolorMap:
1059
+ VIS.vcolorMap[variableKey]='gray' if variableKey in ('img','dispMap') else 'jet'
1060
+ if variableKey not in VIS.vvectorColor:
1061
+ VIS.vvectorColor[variableKey]='green' if variableKey in ('img','dispMap') else 'black'
1062
+
1063
+ def readResultFile(self,filename):
1064
+ res=None
1065
+ if not filename: return filename, res
1066
+ try:
1067
+ if os.path.exists(filename):
1068
+ pri.Info.cyan(f'Opening: {filename} [<--{self.result_file}]')
1069
+ ext=os.path.splitext(filename)[-1]
1070
+ if ext=='.mat':
1071
+ res = scipy.io.loadmat(filename)
1072
+ elif ext=='.plt':
1073
+ tres = readPlt(filename)
1074
+ res={}
1075
+ for j, n in enumerate(tres[1]):
1076
+ res[n]=tres[0][:,:,j]
1077
+ if self.namesPIV.u in res and self.namesPIV.v in res:
1078
+ res=self.calcMagnitude(res)
1079
+ FlagUnit=self.VISpar.Out.xres!=1.0 or self.VISpar.Out.pixAR!=1.0
1080
+ res=self.calcZVorticity(res,FlagUnit)
1081
+ for f in list(res):
1082
+ if not f in self.namesPIV.allFields: del res[f]
1083
+ except Exception as inst:
1084
+ pri.Error.red(f'Error opening image file: {filename}\n{traceback.format_exc()}\n{inst}')
1085
+ res=None
1086
+ return filename, res
1087
+
1088
+ def calcMagnitude(self,res):
1089
+ if self.namesPIV.u in res and self.namesPIV.v in res:
1090
+ if self.namesPIV.w in res:
1091
+ res[self.namesPIV.Mod]=np.sqrt(res[self.namesPIV.u]**2+res[self.namesPIV.v]**2+res[self.namesPIV.w]**2)
1092
+ else:
1093
+ res[self.namesPIV.Mod]=np.sqrt(res[self.namesPIV.u]**2+res[self.namesPIV.v]**2)
1094
+ return res
1095
+
1096
+ def calcZVorticity(self,res,FlagUnit=False):
1097
+ if self.namesPIV.x in res and self.namesPIV.y in res and self.namesPIV.u in res and self.namesPIV.v in res:
1098
+ if FlagUnit: xres=yres=1/1000
1099
+ else: xres=yres=1.0
1100
+ try:
1101
+ 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
1102
+ _, 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
1103
+ res[self.namesPIV.ZVort]=dv_dx-du_dy
1104
+ except:
1105
+ pri.Error.red(f'Error while computing vorticity field:\n{traceback.format_exc()}\n\n')
1106
+ return res
1107
+
1108
+ def getResultInfo(self,result=None,ind=None):
1109
+ if result is None: res=self.result
1110
+ else: res=result
1111
+ if res is None: return
1112
+ if ind is None: VIS:VISpar=self.VISpar
1113
+ else: VIS:VISpar=self.TABpar_at(ind)
1114
+ for i in list(VIS.vmin_default):
1115
+ if i not in (self.namesPIV.img,self.namesPIV.dispMap):
1116
+ del VIS.vmin_default[i]
1117
+ del VIS.vmax_default[i]
1118
+ del VIS.vmean_default[i]
1119
+ del VIS.vrange_default[i]
1120
+ del VIS.vLim[i]
1121
+
1122
+ for f in list(res):
1123
+ V:np=res[f][~np.isnan(res[f])]
1124
+ #m=np.mean(V).item()
1125
+ #r=np.std(V).item()
1126
+ #VIS.vLim[f]=max([m+5*r,abs(m-5*r)])
1127
+ amax=np.max(np.abs(V))*5.0
1128
+ m=np.mean(V)
1129
+ r=(np.max(V)-np.min(V))*2.50
1130
+ rmax=np.abs(m+r)
1131
+ rmin=np.abs(m-r)
1132
+ VIS.vLim[f]=float(max([amax,rmax,rmin]))
1133
+ if VIS.vLim[f]<0.1: VIS.vLim[f]=1
1134
+ VIS.vmin_default[f]=float(np.percentile(V,1)) #np.round(m-2*r).item()
1135
+ VIS.vmax_default[f]=float(np.percentile(V,99)) #np.round(m+2*r).item()
1136
+ VIS.vmean_default[f]=0.5*(VIS.vmin_default[f]+VIS.vmax_default[f])
1137
+ VIS.vrange_default[f]=VIS.vmax_default[f]-VIS.vmin_default[f]
1138
+ if f not in VIS.vcolorMap:
1139
+ VIS.vcolorMap[f]='jet'
1140
+ if f not in VIS.vvectorColor:
1141
+ VIS.vvectorColor[f]='black'
1142
+ pass
1143
+
1144
+ FlagSize=False
1145
+ if "X" in list(res) and "Y" in list(res):
1146
+ X=res["X"]
1147
+ Y=res["Y"]
1148
+ FlagSize=True
1149
+ elif "x" in list(res) and "y" in list(res):
1150
+ X=res["x"]
1151
+ Y=res["y"]
1152
+ FlagSize=True
1153
+ if FlagSize:
1154
+ if np.size(X) and np.size(Y):
1155
+ 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)]
1156
+ else:
1157
+ VIS.size_default[1]=[0,1,0,1,1]
1158
+
1159
+ def setVISwarn(self,ind=None):
1160
+ if ind is None: VIS:VISpar=self.VISpar
1161
+ else: VIS:VISpar=self.TABpar_at(ind)
1162
+ 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.'
1163
+
1164
+ #*************************************************** Plot tools
1165
+ #******************** Actions
1166
+ def button_view_action(self):
1167
+ self.VISpar.FlagView=self.ui.button_view.isChecked()
1168
+
1169
+ def button_ShowIW_action(self):
1170
+ self.VISpar.FlagShowIW=self.ui.button_ShowIW.isChecked()
1171
+ #if self.VISpar.FlagShowIW: self.resetXYLims()
1172
+
1173
+ def button_SubMIN_action(self):
1174
+ self.VISpar.FlagSubMIN=self.ui.button_SubMIN.isChecked()
1175
+
1176
+ def button_ShowCR_action(self):
1177
+ self.VISpar.FlagShowCR=self.ui.button_ShowCR.isChecked()
1178
+
1179
+ def button_unit_action(self):
1180
+ self.VISpar.unit[self.VISpar.type]=self.ui.button_unit.isChecked()
1181
+
1182
+ def button_Contourf_action(self):
1183
+ self.VISpar.FlagContourf=self.ui.button_Contourf.isChecked()
1184
+
1185
+ def button_cmap_action(self):
1186
+ # Show the popup menu
1187
+ self.colorMapMenu.exec(self.ui.button_cmap.mapToGlobal(self.ui.button_cmap.rect().bottomLeft()))
1188
+
1189
+ def button_cvec_action(self):
1190
+ # Show the popup menu
1191
+ self.vectorColorMenu.exec(self.ui.button_cvec.mapToGlobal(self.ui.button_cvec.rect().bottomLeft()))
1192
+
1193
+ def combo_map_var_action(self):
1194
+ self.VISpar.variable=self.ui.combo_map_var.currentText()
1195
+ self.VISpar.variableKey=self.namesPIV.combo_dict_keys[self.VISpar.variable]
1196
+ self.VISpar.type=int(self.VISpar.variable!=self.namesPIV.combo_dict[self.namesPIV.img])
1197
+ self.setLevels()
1198
+
1199
+ def button_automatic_levels_action(self):
1200
+ self.VISpar.FlagAutoLevels=self.ui.button_automatic_levels.isChecked()
1201
+ return True
1202
+
1203
+ def button_automatic_sizes_action(self):
1204
+ self.VISpar.FlagAutoSizes=self.ui.button_automatic_sizes.isChecked()
1205
+ if self.VISpar.FlagAutoSizes is False and self.VISpar.Process==ProcessTypes.piv:
1206
+ type2=0 if self.VISpar.type==1 else 1
1207
+ if self.VISpar.unit[self.VISpar.type]!=self.VISpar.unit[type2]:
1208
+ xres,yres=self.getXYRes(type=self.VISpar.unit[self.VISpar.type])
1209
+ else: xres=yres=1.0
1210
+ if (type2==0 and self.VISpar.unit[type2]) or (type2==1 and not self.VISpar.unit[type2]):
1211
+ xres2,yres2=self.getXYRes(type=type2)
1212
+ else: xres2=yres2=1.0
1213
+ self.VISpar.size[type2][0:2]=[s*xres/xres2 for s in [self.VISpar.xmin, self.VISpar.xmax]]
1214
+ self.VISpar.size[type2][2:4]=[s*yres/yres2 for s in [self.VISpar.ymin, self.VISpar.ymax]]
1215
+ return True
1216
+
1217
+ def button_restore_action(self):
1218
+ self.resetLevels()
1219
+
1220
+ def button_resize_action(self):
1221
+ self.resetXYLims()
1222
+
1223
+ def button_invert_y_action(self):
1224
+ self.VISpar.FlagYInvert[self.VISpar.type]=self.ui.button_invert_y.isChecked()
1225
+
1226
+ def spinLevels_action(self,spin:MyQDoubleSpin):
1227
+ n=spin.objectName().replace('spin_','')
1228
+ spin_value=getattr(self.VISpar,n)
1229
+
1230
+ v=getattr(self.VISpar,'v'+n)
1231
+ v[self.VISpar.variableKey]=spin_value
1232
+ self.adjustSpins(spin)
1233
+
1234
+ def adjustSpins(self,spin:MyQDoubleSpin):
1235
+ nspin=spin.objectName().replace('spin_','')
1236
+ if spin in (self.ui.spin_min,self.ui.spin_max):
1237
+ if spin==self.ui.spin_min and spin.value()>=self.ui.spin_max.value():
1238
+ self.VISpar.max=self.VISpar.min+self.ui.spin_range.minimum()
1239
+ elif spin==self.ui.spin_max and spin.value()<=self.ui.spin_min.value():
1240
+ self.VISpar.min=self.VISpar.max-self.ui.spin_range.minimum()
1241
+ self.VISpar.mean=0.5*(self.VISpar.min+self.VISpar.max)
1242
+ self.VISpar.range=self.VISpar.max-self.VISpar.min
1243
+ elif spin in (self.ui.spin_mean,self.ui.spin_range):
1244
+ m=self.ui.spin_mean.value()
1245
+ r=self.ui.spin_range.value()
1246
+ if m-r*0.5<self.ui.spin_min.minimum():
1247
+ self.VISpar.min=self.ui.spin_min.minimum()
1248
+ if spin==self.ui.spin_mean:
1249
+ self.VISpar.range=2*(m-self.VISpar.min)
1250
+ self.VISpar.max=m+0.5*self.VISpar.range
1251
+ else:
1252
+ self.VISpar.max=self.VISpar.min+r
1253
+ self.VISpar.mean=0.5*(self.VISpar.min+self.VISpar.max)
1254
+ elif m+r*0.5>self.ui.spin_max.maximum():
1255
+ self.VISpar.max=self.ui.spin_max.maximum()
1256
+ if spin==self.ui.spin_mean:
1257
+ self.VISpar.range=2*(self.VISpar.max-m)
1258
+ self.VISpar.min=m-0.5*self.VISpar.range
1259
+ else:
1260
+ self.VISpar.min=self.VISpar.max-r
1261
+ self.VISpar.mean=0.5*(self.VISpar.min+self.VISpar.max)
1262
+ else:
1263
+ self.VISpar.max=m+0.5*r
1264
+ self.VISpar.min=m-0.5*r
1265
+ if spin==self.ui.spin_mean: self.VISpar.range=(self.VISpar.max-self.VISpar.min)
1266
+ else: self.VISpar.mean=0.5*(self.VISpar.min+self.VISpar.max)
1267
+
1268
+ for n in ['min','max','mean','range']:
1269
+ if n!=nspin:
1270
+ spin=getattr(self.ui,'spin_'+n)
1271
+ slider=getattr(self.ui,'slider_'+n)
1272
+ val=getattr(self.VISpar,n)
1273
+ spin.setValue(val)
1274
+ self.slider_set(spin,slider)
1275
+
1276
+ def sliderLevels_changing(self,spin:MyQDoubleSpin,slider:QSlider,Flag=False):
1277
+ self.setSpinFromSlider(spin,slider)
1278
+ self.adjustSpins(spin)
1279
+ self.sliderLevels_action()
1280
+ return Flag
1281
+
1282
+ def setSpinFromSlider(self,spin:MyQDoubleSpin,slider:QSlider):
1283
+ slider_value=slider.value()
1284
+ spin_value=spin.minimum()+(spin.maximum()-spin.minimum())/slider.maximum()*slider_value
1285
+ spin.setValue(spin_value)
1286
+ n=spin.objectName().replace('spin_','')
1287
+ if n in ('nclev','vecspac'):
1288
+ spin_value=int(spin_value)
1289
+ setattr(self.VISpar,n,spin_value)
1290
+ return spin_value
1291
+
1292
+ def sliderLevels_action(self):
1293
+ for n in ('min','max','mean','range'):
1294
+ spin_value=getattr(self.VISpar,n)
1295
+ v=getattr(self.VISpar,'v'+n)
1296
+ v[self.VISpar.variableKey]=spin_value
1297
+
1298
+ def spinFieldRep_action(self,spin:MyQDoubleSpin):
1299
+ n=spin.objectName().replace('spin_','')
1300
+ spin_value=getattr(self.VISpar,n)
1301
+ if n in ('nclev','vecspac'): spin_value=int(spin_value)
1302
+ setattr(self.VISpar,n,spin_value)
1303
+
1304
+ def sliderFieldRep_changing(self,spin:MyQDoubleSpin,slider:QSlider,Flag=False):
1305
+ self.setSpinFromSlider(spin,slider)
1306
+ self.sliderFieldRep_action()
1307
+ return Flag
1308
+
1309
+ def sliderFieldRep_action(self):
1310
+ return
1311
+
1312
+ def spin_xy_action(self,spin,k):
1313
+ n=spin.objectName().replace('spin_','')
1314
+ spin_value=getattr(self.VISpar,n)
1315
+ res=self.xres if k<2 else self.yres
1316
+ self.VISpar.size[self.VISpar.type][k]=spin_value/res
1317
+
1318
+ def button_dx_left_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_dx_right_action(self):
1324
+ dx=(self.VISpar.xmax-self.VISpar.xmin)/self.xres
1325
+ self.VISpar.size[self.VISpar.type][0]+=dx
1326
+ self.VISpar.size[self.VISpar.type][1]+=dx
1327
+
1328
+ def button_dy_down_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_dy_up_action(self):
1334
+ dy=(self.VISpar.ymax-self.VISpar.ymin)/self.yres
1335
+ self.VISpar.size[self.VISpar.type][2]+=dy
1336
+ self.VISpar.size[self.VISpar.type][3]+=dy
1337
+
1338
+ def button_FocusIW_action(self):
1339
+ """
1340
+ Show a popup menu with options 'H x W' and return the selected index (int) or None.
1341
+ Labels are formatted as f"{Vect[2][i]} x {Vect[0][i]}".
1342
+ """
1343
+ FlagDisp=self.VISpar.variableKey is self.namesPIV.dispMap
1344
+ if FlagDisp: it=-1
1345
+ else:
1346
+ # Ensure consistent length between lists 0 (width values) and 2 (height values)
1347
+ ve=self.VISpar.Pro.Vect if isinstance(self.VISpar.Pro.Vect[0],list) else [[v] for v in self.VISpar.Pro.Vect]
1348
+ Vect = [[val for val in v] for v in ve]
1349
+ n = min(len(Vect[0]), len(Vect[2]))
1350
+ if n == 0:
1351
+ return None
1352
+
1353
+ # Create a context menu and populate it with the available sizes
1354
+ menu = QMenu(self)
1355
+ menu.setStyleSheet(self.gui.ui.menu.styleSheet())
1356
+ for i in range(n):
1357
+ label = f"{Vect[2][i]} x {Vect[0][i]}"
1358
+ act = menu.addAction(label)
1359
+ act.setData(i)
1360
+
1361
+ # Display the menu at the current cursor position and wait for user selection
1362
+ chosen = menu.exec(QCursor.pos())
1363
+ it = None if chosen is None else chosen.data()
1364
+ if it is not None: self.FocusIW_it(it)
1365
+
1366
+ def FocusIW_it(self,it=-1):
1367
+ ve=self.VISpar.Pro.Vect if isinstance(self.VISpar.Pro.Vect[0],list) else [[v] for v in self.VISpar.Pro.Vect]
1368
+ Vect = [[val for val in v] for v in ve]
1369
+ if self.VISpar.unit[self.VISpar.type] and self.VISpar.type!=0:
1370
+ yres=self.VISpar.Out.xres*self.VISpar.Out.pixAR
1371
+ for k in range(2): Vect[k]=[val/self.VISpar.Out.xres for val in Vect[k]]
1372
+ for k in range(2,4): Vect[k]=[val/yres for val in Vect[k]]
1373
+ else: yres=1.0
1374
+ W=Vect[2][it]
1375
+ FlagDisp=self.VISpar.variableKey is self.namesPIV.dispMap
1376
+ if FlagDisp:
1377
+ H=self.gui.w_Process_Disp.PROpar.SemiWidth_Epipolar*2+1
1378
+ H/=yres
1379
+ FlagBordo=False
1380
+ else:
1381
+ H=Vect[0][it]
1382
+ FlagBordo=self.VISpar.Pro.FlagBordo
1383
+ 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:
1384
+ dW=W if FlagDisp else Vect[3][it]
1385
+ boundDist=W/2 if not FlagBordo else dW
1386
+ 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
1387
+ dH=H if FlagDisp else Vect[1][it]
1388
+ boundDist=H/2 if not FlagBordo else dH
1389
+ 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
1390
+ self.VISpar.size[self.VISpar.type][0]=x0
1391
+ self.VISpar.size[self.VISpar.type][2]=y0
1392
+ self.VISpar.size[self.VISpar.type][1]=x0+W
1393
+ self.VISpar.size[self.VISpar.type][3]=y0+H
1394
+ else:
1395
+ self.VISpar.size[self.VISpar.type][1]=self.VISpar.size[self.VISpar.type][0]+W
1396
+ self.VISpar.size[self.VISpar.type][3]=self.VISpar.size[self.VISpar.type][2]+H
1397
+
1398
+ #******************** Settings
1399
+ def button_view_set(self):
1400
+ self.ui.button_view.setChecked(self.VISpar.FlagView)
1401
+
1402
+ def button_ShowIW_set(self):
1403
+ self.ui.button_ShowIW.setChecked(self.VISpar.FlagShowIW)
1404
+
1405
+ def button_ShowCR_set(self):
1406
+ self.ui.button_ShowCR.setChecked(self.VISpar.FlagShowCR)
1407
+
1408
+ def button_SubMIN_set(self):
1409
+ self.ui.button_SubMIN.setChecked(self.VISpar.FlagSubMIN)
1410
+
1411
+ def button_unit_set(self):
1412
+ self.ui.button_unit.setChecked(self.VISpar.unit[self.VISpar.type])
1413
+
1414
+ def button_Contourf_set(self):
1415
+ self.ui.button_Contourf.setChecked(self.VISpar.FlagContourf)
1416
+
1417
+ def button_automatic_levels_set(self):
1418
+ self.ui.button_automatic_levels.setChecked(self.VISpar.FlagAutoLevels)
1419
+
1420
+ def button_automatic_sizes_set(self):
1421
+ self.ui.button_automatic_sizes.setChecked(self.VISpar.FlagAutoSizes)
1422
+
1423
+ def button_invert_y_set(self):
1424
+ self.ui.button_invert_y.setChecked(self.VISpar.FlagYInvert[self.VISpar.type])
1425
+
1426
+ def combo_map_var_set(self):
1427
+ self.ui.combo_map_var.setCurrentText(self.VISpar.variable)
1428
+
1429
+ def slider_set(self,spin:MyQDoubleSpin,slider:QSlider):
1430
+ spin_value=getattr(self.VISpar,spin.objectName().replace('spin_',''))
1431
+ if spin.maximum()>spin.minimum():
1432
+ slider_value=int((spin_value-spin.minimum())/(spin.maximum()-spin.minimum())*slider.maximum())
1433
+ else: slider_value=0
1434
+ slider.setValue(slider_value)
1435
+
1436
+ #******************** Layout
1437
+ def leftrightCallback(self,di):
1438
+ i=self.ui.image_levels.currentIndex()
1439
+ i=i+di
1440
+ c=self.ui.image_levels.count()-1-int(self.result is None)
1441
+ if i<0: i=c
1442
+ elif i>c: i=0
1443
+ self.VISpar.setPage=i
1444
+
1445
+ #*************************************************** Plot
1446
+ def updatingPlot(self):
1447
+ xmin,xmax=list(self.ui.plot.axes.get_xlim())
1448
+ ymin,ymax=list(self.ui.plot.axes.get_ylim())
1449
+ self.VISpar.size[self.VISpar.type][:2]=[xmin/self.xres,xmax/self.xres]
1450
+ self.VISpar.size[self.VISpar.type][2:4]=[ymin/self.yres,ymax/self.yres]
1451
+
1452
+ def forceRestoreArrowCursor(self):
1453
+ if self.CursorTimer.isActive():
1454
+ self.CursorTimer.stop()
1455
+ while QApplication.overrideCursor() is not None:
1456
+ QApplication.restoreOverrideCursor()
1457
+ self.FlagNormalCursor = True
1458
+
1459
+ def brushCursor(self):
1460
+ self.forceRestoreArrowCursor()
1461
+ self.FlagNormalCursor=False
1462
+ QApplication.setOverrideCursor(self.brush_cursor)
1463
+ self.CursorTimer.start(250)
1464
+
1465
+ def setMapVar(self):
1466
+ pri.PlotTime.magenta(f'{"/"*25} Plotting image - start')
1467
+ self.brushCursor()
1468
+ try:
1469
+ if self.VISpar.type==0:
1470
+ fields=['image_file','variable','unit','FlagSubMIN','Out','colorMap']
1471
+ img=self.image
1472
+ if img is not None and self.VISpar.img>0 and self.VISpar.FlagSubMIN and self.image_Min is not None:
1473
+ img=img-self.image_Min
1474
+ self.img=img
1475
+ FlagDraw=self.showImg(fields)
1476
+
1477
+ FlagIW=self.VISpar.isDifferentFrom(self.VISpar_old,fields=['FlagShowIW','Pro'])
1478
+ if FlagIW or FlagDraw: self.showRect()
1479
+ FlagDraw=FlagDraw or FlagIW
1480
+ if self.image is not None and self.VISpar.FlagShowCR and self.VISpar.variableKey!=self.namesPIV.dispMap:
1481
+ self.showCommonRegion()
1482
+ FlagDraw=FlagDraw or self.CR is not None
1483
+ else:
1484
+ self.cleanCommonRegion()
1485
+ else:
1486
+ if self.orect: self.cleanRect()
1487
+ self.cleanCommonRegion()
1488
+ fields=['result_file','variable','unit','min','max','nclev','FlagContourf','colorMap']
1489
+ if self.VISpar.variableKey not in self.result: raise('Variable not found in result structure!')
1490
+ V=self.result[self.VISpar.variableKey]
1491
+ if not self.VISpar.FlagContourf:
1492
+ self.img,Ximg,Yimg,FlagInterp,size=self.calcMap(V,size_pixels=[np.size(V,0), np.size(V,1)])
1493
+ FlagDraw=self.showImg(fields,size)
1494
+ else:
1495
+ self.img,Ximg,Yimg,FlagInterp,size=self.calcMap(V)
1496
+ if FlagInterp:
1497
+ FlagDraw=self.showImg(fields,size)
1498
+ else:
1499
+ FlagDraw=self.showMap(fields)
1500
+ if self.contour is None:
1501
+ FlagDraw=self.showImg(fields,size)
1502
+ fields=['result_file','variable','FlagContourf','field_rep','unit','vectorColor']
1503
+ if self.VISpar.field_rep==1: fields+=['vecsize','vecwid','vecspac']
1504
+ elif self.VISpar.field_rep==2: fields+=['streamdens']
1505
+ if self.VISpar.Step!=StepTypes.piv: fields+=['type']
1506
+ FlagVecField=self.VISpar.isDifferentFrom(self.VISpar_old,fields=fields)
1507
+ if FlagVecField and self.result:
1508
+ self.showVecField()
1509
+ elif self.result is None: self.cleanVecField()
1510
+ FlagDraw=FlagDraw or FlagVecField
1511
+
1512
+ if FlagDraw:
1513
+ #self.ui.plot.draw()
1514
+ self.ui.plot.draw_idle()
1515
+ except:
1516
+ pri.Error.red(f'Error while generating plot:\n{traceback.format_exc()}\n\n')
1517
+ printException()
1518
+ #self.exitVISerr(False)
1519
+ pri.PlotTime.magenta(f'{"%"*25} Plotting image - end')
1520
+
1521
+ def showImg(self,fields,size:list=None):
1522
+ img=self.img
1523
+ if img is None:
1524
+ self.cleanAxes(FlagAxis=False)
1525
+ return True #raise Exception('Invalid input image!')
1526
+
1527
+ FlagNewPlot=self.VISpar.isDifferentFrom(self.VISpar_old,fields=fields)
1528
+ FlagOut=self.VISpar.isDifferentFrom(self.VISpar_old,fields=['Out'])
1529
+ FlagXLim=self.VISpar.isDifferentFrom(self.VISpar_old,fields=['xmin','xmax','ymin','ymax','unit','FlagYInvert','Out'])
1530
+ FlagCMap=self.VISpar.isDifferentFrom(self.VISpar_old,fields=['colorMap','nclev'])
1531
+ FlagCLim=self.VISpar.isDifferentFrom(self.VISpar_old,fields=['min','max','nclev','colorMap'] if self.VISpar.type else ['min','max'])
1532
+ FlagExtent=False
1533
+
1534
+ if FlagNewPlot:
1535
+ FlagVariable=self.VISpar_old.variable!=self.VISpar.variable
1536
+
1537
+ if self.imgshow is None or self.VISpar_old.FlagContourf!=self.VISpar.FlagContourf or FlagOut:
1538
+ self.cleanAxes()
1539
+ self.imgshow=self.ui.plot.axes.imshow(img,extent=self.imgExtent(size), origin='lower', vmin=self.VISpar.min,vmax=self.VISpar.max,zorder=0)
1540
+ self.imgshow.format_cursor_data=lambda v: self.custom_format_cursor_data(v)
1541
+ cmap,_=self.colorMap()
1542
+ self.imgshow.set_cmap(cmap)
1543
+ divider = make_axes_locatable(self.ui.plot.axes)
1544
+ cax = divider.append_axes("right", size="5%", pad=0.05)
1545
+ self.cb=self.ui.plot.fig.colorbar(self.imgshow,cax=cax)
1546
+ self.setTitleLabels()
1547
+ FlagXLim=True
1548
+ else:
1549
+ self.imgshow.set_data(img)
1550
+ extent=self.imgExtent(size)
1551
+ if extent!=self.imgshow.get_extent():
1552
+ self.imgshow.set_extent(extent)
1553
+ FlagExtent=True
1554
+ if FlagCMap:
1555
+ cmap,_=self.colorMap()
1556
+ self.imgshow.set_cmap(cmap)
1557
+ if FlagCLim:
1558
+ self.imgshow.set_clim(self.VISpar.min,self.VISpar.max)
1559
+ if FlagVariable:
1560
+ self.setTitleLabels()
1561
+ else:
1562
+ if FlagCMap:
1563
+ cmap,_=self.colorMap()
1564
+ self.imgshow.set_cmap(cmap)
1565
+ if FlagCLim:
1566
+ self.imgshow.set_clim(self.VISpar.min,self.VISpar.max)
1567
+ if FlagXLim:
1568
+ self.setAxisLim()
1569
+ self.Ptoolbar.update()
1570
+
1571
+ FlagDraw=FlagNewPlot or FlagOut or FlagXLim or FlagCMap or FlagCLim or FlagExtent
1572
+ return FlagDraw
1573
+
1574
+ def colorMap(self):
1575
+ if self.VISpar.type==0:
1576
+ cmap=mpl.colormaps[self.VISpar.colorMap]
1577
+ levs=np.linspace(self.VISpar.min,self.VISpar.max,int(self.VISpar.max-self.VISpar.min))
1578
+ else:
1579
+ if self.VISpar.min<self.VISpar.max:
1580
+ levs=np.linspace(self.VISpar.min,self.VISpar.max,self.VISpar.nclev)
1581
+ else:
1582
+ levs=np.linspace(self.VISpar.max-self.ui.spin_min.singleStep(),\
1583
+ self.VISpar.max,self.VISpar.nclev)
1584
+ colormap = pyplt.get_cmap(self.VISpar.colorMap)
1585
+ colors=colormap(np.linspace(0, 1, len(levs)))
1586
+ cmap = mpl.colors.ListedColormap(colors)
1587
+ return cmap, levs
1588
+
1589
+ def getXYRes(self,type=None):
1590
+ if type is None: type=self.VISpar.type
1591
+ xres=yres=1.0
1592
+ if self.VISpar.Process==ProcessTypes.piv and not self.VISpar.Out.FlagNone:
1593
+ if type==0: #mm/pixels
1594
+ xres =1.0/self.VISpar.Out.xres
1595
+ yres=1.0/(self.VISpar.Out.xres*self.VISpar.Out.pixAR)
1596
+ elif type==1: #pixels/mm
1597
+ xres=self.VISpar.Out.xres
1598
+ yres=self.VISpar.Out.xres*self.VISpar.Out.pixAR
1599
+ return xres, yres
1600
+
1601
+ def imgExtent(self,size=None):
1602
+ if size is None: size=self.VISpar.size_default[self.VISpar.type]
1603
+ return [k*self.xres for k in size[:2]]+[k*self.yres for k in size[2:4]]
1604
+
1605
+ def setAxisLim(self):
1606
+ self.ui.plot.axes.set_xlim(self.VISpar.xmin,self.VISpar.xmax)
1607
+ ylim=[self.VISpar.ymin,self.VISpar.ymax]
1608
+ if self.VISpar.FlagYInvert[self.VISpar.type]:
1609
+ self.ui.plot.axes.set_ylim(max(ylim),min(ylim))
1610
+ else:
1611
+ self.ui.plot.axes.set_ylim(min(ylim),max(ylim))
1612
+ self.ui.plot.axes.set_aspect('equal', adjustable='box')
1613
+
1614
+ def setTitleLabels(self):
1615
+ self.ui.plot.axes.set_title(self.namesPIV.titles_dict[self.VISpar.variableKey])
1616
+ self.cb.ax.set_title(self.namesPIV.titles_cb_dict[self.VISpar.variableKey])
1617
+ self.ui.plot.axes.set_xlabel("x" if self.VISpar.type else "")
1618
+ self.ui.plot.axes.set_ylabel("y" if self.VISpar.type else "")
1619
+
1620
+ def showMap(self,fields):
1621
+ result=self.result
1622
+ if result is None:
1623
+ self.cleanAxes(FlagAxis=False)
1624
+ return True #raise Exception('Invalid output image!')
1625
+
1626
+ FlagNewPlot=self.VISpar.isDifferentFrom(self.VISpar_old,fields=fields)
1627
+ FlagXLim=self.VISpar.isDifferentFrom(self.VISpar_old,fields=['xmin','xmax','ymin','ymax','unit','FlagYInvert','Out'])
1628
+ FlagCMap=self.VISpar_old.colorMap!=self.VISpar.colorMap
1629
+ FlagCLim=self.VISpar.isDifferentFrom(self.VISpar_old,fields=['min','max'])
1630
+
1631
+ if FlagNewPlot or self.VISpar_old.FlagContourf!=self.VISpar.FlagContourf or self.VISpar_old.nclev!=self.VISpar.nclev:
1632
+ self.cleanAxes()
1633
+ if not self.VISpar.unit[self.VISpar.type]:
1634
+ xres,yres=self.getXYRes(type=1)
1635
+ else: xres=yres=1.0
1636
+ X=result[self.namesPIV.x]*xres
1637
+ Y=result[self.namesPIV.y]*yres
1638
+ if self.VISpar.variableKey not in self.result: raise('Variable not found in result structure!')
1639
+ V=result[self.VISpar.variableKey]
1640
+ self.map=[X,Y,V]
1641
+
1642
+ cmap,levs=self.colorMap()
1643
+ try:
1644
+ self.contour=self.ui.plot.axes.contourf(X, Y, V, levs, \
1645
+ cmap=cmap, origin='lower', extend='both', zorder=0)
1646
+ self.contour.format_cursor_data=lambda v: self.custom_format_cursor_data(v)
1647
+ except:
1648
+ pri.Error.red(f'Error while generating contour lines:\n{traceback.format_exc()}\n\n')
1649
+ self.contour=None
1650
+ return
1651
+ self.contour.set_clim(levs[0],levs[-1])
1652
+ divider = make_axes_locatable(self.ui.plot.axes)
1653
+ cax = divider.append_axes("right", size="5%", pad=0.05)
1654
+ self.cb=self.ui.plot.fig.colorbar(self.contour,cax=cax)
1655
+ self.setTitleLabels()
1656
+ FlagXLim=True
1657
+ else:
1658
+ if FlagCMap:
1659
+ cmap,_=self.colorMap()
1660
+ self.contour.set_cmap(cmap)
1661
+ if FlagCLim:
1662
+ self.contour.set_clim(self.VISpar.min,self.VISpar.max)
1663
+ if FlagXLim:
1664
+ self.setAxisLim()
1665
+ self.Ptoolbar.update()
1666
+
1667
+ FlagDraw=FlagNewPlot or FlagXLim or FlagCMap or FlagCLim
1668
+ return FlagDraw
1669
+
1670
+ def calcMap(self,V,size_pixels=[1000]*2):
1671
+ #size_pixels=self.ui.plot.fig.get_size_inches()*self.ui.plot.fig.get_dpi()
1672
+ #size_pixels=np.minimum(np.round(0.5*size_pixels).astype(int),1000)
1673
+ FlagSize=False
1674
+ if "X" in list(self.result) and "Y" in list(self.result):
1675
+ X=self.result["X"]
1676
+ Y=self.result["Y"]
1677
+ FlagSize=True
1678
+ elif "x" in list(self.result) and "y" in list(self.result):
1679
+ X=self.result["x"]
1680
+ Y=self.result["y"]
1681
+ FlagSize=True
1682
+ if FlagSize:
1683
+ xmin,xmax,ymin,ymax=[X.min(),X.max(),Y.min(),Y.max()]
1684
+ else:
1685
+ xmin,xmax,ymin,ymax=[0,np.size(V,1),0,np.size(V,0)]
1686
+ xstep_half=(xmax-xmin)/(np.size(V,1)-1)*0.5
1687
+ x = self.mylinspace(xmin,xmax, np.size(V,1))
1688
+ ystep_half=(ymax-ymin)/(np.size(V,0)-1)*0.5
1689
+ y = self.mylinspace(ymin,ymax, np.size(V,0))
1690
+ FlagInterp=False
1691
+ if (np.size(V,1)<size_pixels[1] or np.size(V,0)<size_pixels[0]) and not bool(np.any(np.isnan(V))):
1692
+ x_new = self.mylinspace(xmin, xmax, size_pixels[0])
1693
+ y_new = self.mylinspace(ymin, ymax, size_pixels[1])
1694
+ try:
1695
+ f = scipy.interpolate.RectBivariateSpline(y, x, V)
1696
+ V_new = f(y_new, x_new)
1697
+ FlagInterp=True
1698
+ except:
1699
+ try:
1700
+ x_flat, y_flat = np.meshgrid(x, y) # Griglia 2D
1701
+ points = np.column_stack((x_flat.ravel(), y_flat.ravel())) # Punti 2D
1702
+ X_new, Y_new = np.meshgrid(x_new, y_new)
1703
+ V_new = scipy.interpolate.griddata(points, V.ravel(), (X_new, Y_new), method='cubic') #'nearest', 'linear', 'cubic'
1704
+ FlagInterp=True
1705
+ pass
1706
+ except:
1707
+ pri.Error.red(f'Error while interpolating map variable field for contour representation:\n{traceback.format_exc()}\n\n')
1708
+ x_new=x
1709
+ y_new=y
1710
+ V_new=V
1711
+ FlagInterp=False
1712
+ pass
1713
+ else:
1714
+ x_new=x
1715
+ y_new=y
1716
+ V_new=V
1717
+ FlagInterp=not bool(np.any(np.isnan(V)))
1718
+ X_new, Y_new = np.meshgrid(x_new, y_new)
1719
+ return V_new, X_new, Y_new, FlagInterp, (xmin-xstep_half,xmax+ystep_half,ymin-ystep_half,ymax+ystep_half)
1720
+
1721
+ def mylinspace(self,xmin,xmax,N):
1722
+ step=(xmax-xmin)/(N-1)
1723
+ return xmin+np.arange(0,N,1)*step
1724
+
1725
+ def cleanVecField(self):
1726
+ if self.qui!=None:
1727
+ self.qui.remove()
1728
+ self.qui=None
1729
+ if self.stream is not None:
1730
+ self.stream.lines.remove()
1731
+ for ax in self.ui.plot.axes.get_children():
1732
+ if isinstance(ax, mpl.patches.FancyArrowPatch):
1733
+ ax.remove()
1734
+ self.stream=None
1735
+
1736
+ def showVecField(self):
1737
+ ind=self.VISpar.field_rep
1738
+ self.cleanVecField()
1739
+ if self.qui!=None:
1740
+ self.qui.remove()
1741
+ self.qui=None
1742
+ if self.stream is not None:
1743
+ self.stream.lines.remove()
1744
+ for ax in self.ui.plot.axes.get_children():
1745
+ if isinstance(ax, mpl.patches.FancyArrowPatch):
1746
+ ax.remove()
1747
+ self.stream=None
1748
+ if ind in (1,2) and (self.VISpar.type>0 or self.VISpar.Step==StepTypes.piv):
1749
+ if not self.VISpar.unit[self.VISpar.type]:
1750
+ xres,yres=self.getXYRes(type=1)
1751
+ else: xres=yres=1.0
1752
+ if self.namesPIV.x in self.result and self.namesPIV.y in self.result:
1753
+ X=self.result[self.namesPIV.x]*xres
1754
+ Y=self.result[self.namesPIV.y]*yres
1755
+ elif self.namesPIV.X in self.result and self.namesPIV.Y in self.result:
1756
+ X=self.result[self.namesPIV.X]*xres
1757
+ Y=self.result[self.namesPIV.Y]*yres
1758
+ U=self.result[self.namesPIV.u]
1759
+ V=self.result[self.namesPIV.v]
1760
+ Mod=np.sqrt(U**2+V**2)
1761
+ if ind==1:
1762
+ dX=np.sqrt((X[0,1]-X[0,0])**2+(Y[1,0]-Y[0,0])**2)
1763
+ spa=self.VISpar.vecspac
1764
+ vecsize=self.VISpar.vecsize
1765
+ fac=dX*vecsize*spa
1766
+ Modq= Mod[::spa,::spa]
1767
+ Uq=np.divide(U[::spa,::spa], Modq, where=Modq!=0)*fac
1768
+ Vq=np.divide(V[::spa,::spa], Modq, where=Modq!=0)*fac
1769
+ w=0.15*fac
1770
+ n=3
1771
+ wmax=min([X.max()-X.min(),Y.max()-Y.min()])*0.001
1772
+ qwidth=min([w,wmax])*self.VISpar.vecwid**2
1773
+ hwidth=4 if vecsize<4 else vecsize
1774
+ self.qui=self.ui.plot.axes.quiver(
1775
+ X[::spa,::spa],Y[::spa,::spa],Uq,Vq, color=VIS_VectorColors[self.VISpar.vectorColor], clip_on=True,
1776
+ angles='xy',scale_units='xy',scale=1.0,
1777
+ units='xy',width=qwidth,headwidth=hwidth,headlength=1.25*hwidth,headaxislength=0.75*hwidth,zorder=10)
1778
+ elif ind==2:
1779
+ size_pixels=np.shape(U)
1780
+ Up,_,_,_,_=self.calcMap(U,size_pixels=size_pixels)
1781
+ Vp,Xp,Yp,_,_=self.calcMap(V,size_pixels=size_pixels)
1782
+ Xp=Xp*xres
1783
+ Yp=Yp*yres
1784
+ self.stream=self.ui.plot.axes.streamplot(Xp,Yp,Up,Vp,color=VIS_VectorColors[self.VISpar.vectorColor],density=self.VISpar.streamdens,zorder=10)
1785
+
1786
+ def cleanAxes(self,FlagAxis=True):
1787
+ self.imgshow=self.contour=self.CR=self.RF=None
1788
+ self.orect=[]
1789
+ self.qui=self.stream=None
1790
+ """
1791
+ self.cleanCommonRegion()
1792
+ self.cleanReferenceFrame()
1793
+ self.cleanRect()
1794
+ self.cleanVecField()
1795
+ if self.contour:
1796
+ for coll in self.contour.collections:
1797
+ coll.remove()
1798
+ """
1799
+ if self.cb:
1800
+ self.cb.remove()
1801
+ self.cb=None
1802
+ self.ui.plot.axes.cla()
1803
+ self.ui.plot.axes.axis('on' if FlagAxis else 'off')
1804
+ #self.ui.Plot_tools.setEnabled(FlagAxis)
1805
+
1806
+ def custom_format_coord(self,x,y):
1807
+ if self.contour is not None:
1808
+ X=self.map[0]
1809
+ Y=self.map[1]
1810
+
1811
+ if X.min() <= x <= X.max() and Y.min() <= y <= Y.max():
1812
+ # Trova l'indice più vicino nella matrice
1813
+ col = np.searchsorted(X[0,:],x) - 1
1814
+ row = np.searchsorted(Y[:,0],y) - 1
1815
+ Z=self.map[2]
1816
+
1817
+ # Estrai il valore dal dato Z
1818
+ if 0 <= row < Z.shape[0] and 0 <= col < Z.shape[1]:
1819
+ value = Z[row, col]
1820
+ formatted_value = f"{value:.4f}".rstrip('0').rstrip('.')
1821
+ return f"(x, y)=({x:.2f}, {y:.2f})\n[{formatted_value}]"
1822
+ return f"(x, y)=({x:.2f}, {y:.2f})"
1823
+ else:
1824
+ return f"(x, y)=({x:.2f}, {y:.2f})"
1825
+
1826
+ def custom_format_cursor_data(self,value):
1827
+ formatted_value = f"{value:.4f}".rstrip('0').rstrip('.')
1828
+ return f"[{formatted_value}]"
1829
+
1830
+ def cleanRect(self):
1831
+ if len(self.orect):
1832
+ for r in self.orect:
1833
+ if type(r)==list:
1834
+ for s in r:
1835
+ try: s.remove()
1836
+ except: pass
1837
+ else:
1838
+ try: r.remove()
1839
+ except: pass
1840
+
1841
+ def showRect(self):
1842
+ if not len(self.VISpar.Pro.Vect): return
1843
+ self.cleanRect()
1844
+ if not self.VISpar.FlagShowIW: return
1845
+ colors='rgbymc'
1846
+ lwidth=1
1847
+ nov_hor=3
1848
+ nov_vert=3
1849
+
1850
+ H=self.VISpar.size[self.VISpar.type][1]
1851
+ ve=self.VISpar.Pro.Vect if isinstance(self.VISpar.Pro.Vect[0],list) else [[v] for v in self.VISpar.Pro.Vect]
1852
+ Vect = [[val for val in v] for v in ve]
1853
+ dxin=dyin=5
1854
+ if self.VISpar.unit[self.VISpar.type]:
1855
+ xres,yres=self.getXYRes(type=0)
1856
+ for k in range(2): Vect[k]=[val*xres for val in Vect[k]]
1857
+ for k in range(2,4): Vect[k]=[val*yres for val in Vect[k]]
1858
+ dxin=dxin*xres
1859
+ dyin=dyin*yres
1860
+ nw=len(Vect[0])
1861
+ xin0=yin0=0
1862
+ xmax=ymax=0
1863
+ xlim_min=ylim_min=float('inf')
1864
+ xlim_max=ylim_max=-float('inf')
1865
+ self.orect=[]
1866
+ for k in range(nw):
1867
+ if self.VISpar.Pro.FlagBordo:
1868
+ if not xin0: dx=-Vect[0][k]/2+Vect[1][k]
1869
+ else: dx=0
1870
+ if not yin0: dy=-Vect[2][k]/2+Vect[3][k]
1871
+ else: dy=0
1872
+ else:
1873
+ dx=dy=0
1874
+ for i in range(nov_vert):
1875
+ yin=yin0+i*Vect[3][k]+dy
1876
+ ylim_min=min([ylim_min,yin])
1877
+ for j in range(nov_hor):
1878
+ xin=xin0+j*Vect[1][k]+dx
1879
+ xlim_min=min([xlim_min,xin])
1880
+ kk=i+j*nov_vert
1881
+ if kk%2: lst=':'
1882
+ else: lst='-'
1883
+ kc=k%len(colors)
1884
+ rect = mpl.patches.Rectangle((xin, yin), Vect[0][k], Vect[2][k],\
1885
+ linewidth=lwidth, edgecolor=colors[kc], facecolor=colors[kc],\
1886
+ alpha=0.25,linestyle=lst)
1887
+ self.ui.plot.axes.add_patch(rect)
1888
+ rect2 = mpl.patches.Rectangle((xin, yin), Vect[0][k], Vect[2][k],\
1889
+ linewidth=lwidth, edgecolor=colors[kc], facecolor='none',\
1890
+ alpha=1,linestyle=lst)
1891
+ self.ui.plot.axes.add_patch(rect2)
1892
+ points=self.ui.plot.axes.plot(xin+ Vect[0][k]/2,yin+ Vect[2][k]/2,\
1893
+ 'o',color=colors[kc])
1894
+ if not kk:
1895
+ if self.VISpar.FlagYInvert[self.VISpar.type]: va='top'
1896
+ else: va='bottom'
1897
+ text=self.ui.plot.axes.text(xin+dxin,yin+dyin,str(k),\
1898
+ horizontalalignment='left',verticalalignment=va,\
1899
+ fontsize='large',color='w',fontweight='bold')
1900
+ self.orect=self.orect+[rect,rect2,points,text]
1901
+ xmaxk=xin+Vect[0][k]
1902
+ ymaxk=yin+Vect[2][k]
1903
+ xlim_max=max([xlim_max,xmaxk])
1904
+ ylim_max=max([ylim_max,ymaxk])
1905
+ if xmaxk>xmax: xmax=xmaxk
1906
+ if ymaxk>ymax: ymax=ymaxk
1907
+ if k==nw-1: continue
1908
+ if ymaxk+Vect[2][k+1]+(nov_vert-1)*Vect[3][k+1]<H:
1909
+ yin0=ymaxk
1910
+ else:
1911
+ yin0=0
1912
+ xin0=xmax
1913
+ if self.VISpar.FlagShowIW and self.VISpar.isDifferentFrom(self.VISpar_old,fields=['FlagShowIW']):
1914
+ xlim=self.ui.plot.axes.get_xlim()
1915
+ xlim_min=min([xlim[0],xlim_min])
1916
+ xlim_max=max([xlim[1],xlim_max])
1917
+ self.ui.plot.axes.set_xlim(xlim_min,xlim_max)
1918
+ if self.VISpar.FlagYInvert[self.VISpar.type]:
1919
+ ylim=self.ui.plot.axes.get_ylim()
1920
+ ylim_max=min([ylim[1],ylim_min])
1921
+ ylim_min=max([ylim[0],ylim_max])
1922
+ else:
1923
+ ylim=self.ui.plot.axes.get_ylim()
1924
+ ylim_min=min([ylim[0],ylim_min])
1925
+ ylim_max=max([ylim[1],ylim_max])
1926
+ self.ui.plot.axes.set_ylim(ylim_min,ylim_max)
1927
+ self.VISpar.xmin,self.VISpar.xmax=list(self.ui.plot.axes.get_xlim())
1928
+ self.VISpar.ymin,self.VISpar.ymax=list(self.ui.plot.axes.get_ylim())
1929
+
1930
+ def cleanCommonRegion(self):
1931
+ if self.CR:
1932
+ self.CR.remove()
1933
+ self.CR=None
1934
+ self.ui.plot.draw_idle()
1935
+ self.cleanReferenceFrame()
1936
+
1937
+ def showCommonRegion(self):
1938
+ self.cleanCommonRegion()
1939
+ try:
1940
+ mapFun=PaIRS_lib.MappingFunction()
1941
+ mapFun.readCal(self.VISpar.calList)
1942
+
1943
+ #if self.VISpar.Step==StepTypes.spiv:
1944
+ # planeConst=self.readLaserPlaneConst(self.VISpar.dispFile)
1945
+ #else:
1946
+ # planeConst=[0.0,0.0,0.0]
1947
+ planeConst=[self.VISpar.Out.zconst,self.VISpar.Out.xterm,self.VISpar.Out.yterm]
1948
+
1949
+ o=self.VISpar.Out
1950
+ 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]]
1951
+ zLaser=lambda xy: self.zLaser(xy[0],xy[1],planeConst)
1952
+ for p in points: p.append(zLaser(p))
1953
+ points_array=np.array(points,dtype=np.float64,order='C')
1954
+ cam=self.VISpar.cam-1
1955
+ X=mapFun.worldToImg(points_array,cam,None)# In output X1 is equal to X if correctly allocated
1956
+
1957
+ x_values = [Xp[0] for Xp in X]+[X[0][0]]
1958
+ y_values = [Xp[1] for Xp in X]+[X[0][1]]
1959
+ self.CR,=self.ui.plot.axes.plot(x_values, y_values, 'b-',clip_on=False)
1960
+ self.showReferenceFrame(mapFun=mapFun)
1961
+ except Exception as exc:
1962
+ pri.Error.red(f"[VIS] Error while plotting common zone!\n{traceback.format_exc()}\n")
1963
+ return
1964
+
1965
+ def zLaser(self,x,y,planeConst):
1966
+ return planeConst[0]+planeConst[1]*x+planeConst[2]*y
1967
+
1968
+ def cleanReferenceFrame(self):
1969
+ if self.RF:
1970
+ for p in self.RF:
1971
+ p.remove()
1972
+ self.RF=None
1973
+ self.ui.plot.draw_idle()
1974
+
1975
+ def showReferenceFrame(self,mapFun=None):
1976
+ self.cleanReferenceFrame()
1977
+ try:
1978
+ if mapFun is None:
1979
+ mapFun=PaIRS_lib.MappingFunction()
1980
+ mapFun.readCal(self.VISpar.calList)
1981
+
1982
+ labels=['O','x','y','z']
1983
+ unit=1
1984
+
1985
+ points=[ [0, 0, 0], [unit, 0, 0], [0, unit, 0], [0, 0, unit]]
1986
+ points_array=np.array(points,dtype=np.float64,order='C')
1987
+ cam=self.VISpar.cam-1
1988
+ X=mapFun.worldToImg(points_array,cam,None)# In output X1 is equal to X if correctly allocated
1989
+
1990
+ self.RF=[]
1991
+ origin=X[0]
1992
+ hp,=self.ui.plot.axes.plot(origin[0], origin[1], 'o', color='darkblue') # 'ko' indica un pallino nero
1993
+ self.RF.append(hp)
1994
+ length=0.25*min([q for q in self.image.shape])
1995
+ qwidth=length/25
1996
+ hwidth=4
1997
+ vnorm = np.linalg.norm(X[2]-origin)
1998
+ #colors=['darkred','darkgreen','darkmagenta']
1999
+ for k in range(1,len(X)-1): #-1 exclude z
2000
+ P=X[k]
2001
+ v=P-origin
2002
+ if vnorm!=0: v=v/vnorm*length
2003
+ hp=self.ui.plot.axes.quiver(origin[0], origin[1], v[0], v[1],
2004
+ color='darkblue',#color=colors[k-1],
2005
+ angles='xy',scale_units='xy',scale=1.0,
2006
+ units='xy',width=qwidth,headwidth=hwidth,headlength=1.25*hwidth,headaxislength=0.75*hwidth,zorder=10)
2007
+ self.RF.append(hp)
2008
+ T=origin+v*1.2
2009
+ ha=self.ui.plot.axes.text(T[0], T[1], f'{labels[k]}', color='darkblue', fontsize=fontPixelSize)
2010
+ self.RF.append(ha)
2011
+ """
2012
+ X[k]=T
2013
+ T=0.5*(X[1]+X[2])
2014
+ T=origin-0.1*(T-origin)
2015
+ ha=self.ui.plot.axes.text(T[0], T[1], f'{labels[0]}', color='darkblue', fontsize=fontPixelSize)
2016
+ self.RF.append(ha)
2017
+ """
2018
+ except Exception as exc:
2019
+ pri.Error.red(f"[VIS] Error while plotting reference frame!\n{traceback.format_exc()}\n")
2020
+ return
2021
+
2022
+ """
2023
+ def getZonaCom(self,c:int):
2024
+ return (min (self.disp.vect.Xinf[c],self.disp.vect.Xsup[c]),
2025
+ min (self.disp.vect.Yinf[c],self.disp.vect.Ysup[c]),
2026
+ max (self.disp.vect.Xinf[c],self.disp.vect.Xsup[c]),
2027
+ max (self.disp.vect.Yinf[c],self.disp.vect.Ysup[c]))
2028
+ """
2029
+
2030
+ #*************************************************** Menus
2031
+ def contextMenuEvent(self, event):
2032
+ contextMenu = QMenu(self)
2033
+ contextMenu.setStyleSheet(self.gui.ui.menu.styleSheet())
2034
+ copy2clipboard = contextMenu.addAction("Copy to clipboard ("+self.QS_copy2clipboard.key().toString(QKeySequence.NativeText)+")")
2035
+ copy2clipboard.setIcon(self.ui.plot.copyIcon)
2036
+ copy2newfig = contextMenu.addAction("Open in new figure ("+self.QS_copy2newfig.key().toString(QKeySequence.NativeText)+")")
2037
+ copy2newfig.setIcon(self.ui.plot.openNewWindowIcon)
2038
+ contextMenu.addSeparator()
2039
+ if len(self.ui.plot.fig2)>0:
2040
+ showAll = contextMenu.addAction("Show all")
2041
+ showAll.setIcon(self.ui.plot.showAllIcon)
2042
+ alignAll = contextMenu.addAction("Align all")
2043
+ alignAll.setIcon(self.ui.plot.alignAllIcon)
2044
+ closeAll = contextMenu.addAction("Close all")
2045
+ closeAll.setIcon(self.ui.plot.closeAllIcon)
2046
+ contextMenu.addSeparator()
2047
+ else:
2048
+ showAll = None
2049
+ closeAll= None
2050
+ alignAll= None
2051
+ loadImg = contextMenu.addAction("Load image")
2052
+ loadImg.setIcon(self.ui.plot.loadImageIcon)
2053
+ loadRes = contextMenu.addAction("Load result")
2054
+ loadRes.setIcon(self.ui.plot.loadResultIcon)
2055
+
2056
+ action = contextMenu.exec(self.mapToGlobal(event.pos()))
2057
+ if action == copy2clipboard:
2058
+ self.ui.plot.copy2clipboard()
2059
+ elif action == copy2newfig:
2060
+ self.ui.plot.copy2newfig(self.ui.name_var.toolTip())
2061
+ elif action == showAll:
2062
+ self.ui.plot.showAll()
2063
+ elif action == closeAll:
2064
+ self.ui.plot.closeAll()
2065
+ elif action == alignAll:
2066
+ self.ui.plot.alignAll()
2067
+ elif action == loadImg:
2068
+ self.load_Img_callback()
2069
+ elif action == loadRes:
2070
+ self.load_Res_callback()
2071
+
2072
+ def loadImg(self,filename=None):
2073
+ if filename is None:
2074
+ filename, _ = QFileDialog.getOpenFileName(self,\
2075
+ "Select an image file of the sequence", filter=text_filter,\
2076
+ options=optionNativeDialog)
2077
+ else:
2078
+ if os.path.exists(filename): filename=None
2079
+ if filename:
2080
+ self.image_file_Load=filename
2081
+ self.image_raw=None
2082
+ self.image=None
2083
+
2084
+ self.ui.spin_img.setMinimum(-1)
2085
+ self.VISpar.image_file=''
2086
+ self.VISpar.img=-1
2087
+ self.VISpar.type=0
2088
+ self.VISpar.variable=self.namesPIV.combo_dict[self.namesPIV.img]
2089
+ self.VISpar.variableKey=self.namesPIV.combo_dict_keys[self.VISpar.variable]
2090
+
2091
+ self.FlagResetLevels=self.FlagResetSizes=True
2092
+ self.cleanAxes()
2093
+
2094
+ def loadRes(self):
2095
+ filename, _ = QFileDialog.getOpenFileName(self,\
2096
+ "Select an image file of the sequence", filter="All files (*.mat *.plt);; .mat (*.mat);; .plt (*.plt)",\
2097
+ options=optionNativeDialog)
2098
+ if filename:
2099
+ self.result_file_Load=filename
2100
+ self.result=None
2101
+ self.ui.spin_img.setMinimum(-1)
2102
+ self.VISpar.result_file=''
2103
+ self.VISpar.img=-1
2104
+ self.VISpar.variable=self.namesPIV.combo_dict[self.namesPIV.Mod]
2105
+ self.VISpar.variableKey=self.namesPIV.combo_dict_keys[self.VISpar.variable]
2106
+ self.FlagResetLevels=self.FlagResetSizes=True
2107
+ self.VISpar.type=1
2108
+ self.cleanAxes()
2109
+
2110
+ def create_colormap_image(colormap, width, height, FlagVerticalColormap, imgMapPath):
2111
+ # Create an empty image
2112
+ img = np.zeros((height, width, 3), dtype=np.uint8)
2113
+ # Get the Matplotlib colormap
2114
+ cmap = plt.get_cmap(colormap)
2115
+ # Calculate the colors of the colormap and assign them to the image
2116
+ for y in range(height):
2117
+ for x in range(width):
2118
+ if FlagVerticalColormap:
2119
+ normalized_y = (height-y)/ height
2120
+ color = cmap(normalized_y)
2121
+ else:
2122
+ normalized_x = x / width
2123
+ color = cmap(normalized_x)
2124
+ img[y, x] = [int(c * 255) for c in color[:3]] # Convert colors to range 0-255
2125
+ plt.imsave(imgMapPath, img)
2126
+ pixmap=numpy_to_qpixmap(img)
2127
+ return pixmap
2128
+
2129
+ def numpy_to_qpixmap(img):
2130
+ height, width, channel = img.shape
2131
+ bytes_per_line = 3 * width
2132
+ qimage = QImage(img.data, width, height, bytes_per_line, QImage.Format_RGB888)
2133
+ qpixmap = QPixmap.fromImage(qimage)
2134
+ return qpixmap
2135
+
2136
+ def create_arrow_pixmap(rgb_color, width, height, path):
2137
+ fig, ax = plt.subplots(figsize=(width / 100, height / 100), dpi=100)
2138
+ ax.axis('off')
2139
+
2140
+ # Calcola la posizione e la direzione della freccia
2141
+ x = width / 8
2142
+ y = height / 2
2143
+ u = width *3/4
2144
+ v = 0
2145
+
2146
+ # Disegna la freccia con quiver
2147
+ 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)
2148
+
2149
+ ax.set_xlim(0, width)
2150
+ ax.set_ylim(0, height)
2151
+
2152
+ # Salva l'immagine in un buffer
2153
+ buf = io.BytesIO()
2154
+ plt.savefig(buf, format='png', bbox_inches='tight', pad_inches=0, transparent=True)
2155
+ plt.close(fig)
2156
+ buf.seek(0)
2157
+
2158
+ image = Image.open(buf)
2159
+ image.save(path)
2160
+ pixmap=QPixmap(path)
2161
+ return pixmap
2162
+
2163
+
2164
+ if __name__ == "__main__":
2165
+ import sys
2166
+ app=QApplication.instance()
2167
+ if not app:app = QApplication(sys.argv)
2168
+ app.setStyle('Fusion')
2169
+ object = Vis_Tab(None)
2170
+ object.show()
2171
+ app.exec()
2172
+ app.quit()
2173
+ app=None
2174
+
2175
+
2176
+