PaIRS-UniNa 0.2.7__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.

Potentially problematic release.


This version of PaIRS-UniNa might be problematic. Click here for more details.

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