PaIRS-UniNa 0.2.10__cp313-cp313-macosx_11_0_universal2.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (333) hide show
  1. PaIRS_UniNa/Calibration_Tab.py +347 -0
  2. PaIRS_UniNa/Changes.txt +174 -0
  3. PaIRS_UniNa/Custom_Top.py +303 -0
  4. PaIRS_UniNa/Explorer.py +3322 -0
  5. PaIRS_UniNa/FolderLoop.py +562 -0
  6. PaIRS_UniNa/Input_Tab.py +829 -0
  7. PaIRS_UniNa/Input_Tab_CalVi.py +787 -0
  8. PaIRS_UniNa/Input_Tab_tools.py +3026 -0
  9. PaIRS_UniNa/Log_Tab.py +110 -0
  10. PaIRS_UniNa/Output_Tab.py +922 -0
  11. PaIRS_UniNa/PaIRS.py +18 -0
  12. PaIRS_UniNa/PaIRS_PIV.py +873 -0
  13. PaIRS_UniNa/PaIRS_pypacks.py +1374 -0
  14. PaIRS_UniNa/Process_Tab.py +1761 -0
  15. PaIRS_UniNa/Process_Tab_CalVi.py +313 -0
  16. PaIRS_UniNa/Process_Tab_Disp.py +170 -0
  17. PaIRS_UniNa/Process_Tab_Min.py +120 -0
  18. PaIRS_UniNa/ResizePopup.py +55 -0
  19. PaIRS_UniNa/SPIVCalHelp.py +155 -0
  20. PaIRS_UniNa/Saving_tools.py +298 -0
  21. PaIRS_UniNa/TabTools.py +1413 -0
  22. PaIRS_UniNa/Vis_Tab.py +2176 -0
  23. PaIRS_UniNa/Vis_Tab_CalVi.py +982 -0
  24. PaIRS_UniNa/Whatsnew.py +130 -0
  25. PaIRS_UniNa/_PaIRS_PIV.so +0 -0
  26. PaIRS_UniNa/__init__.py +6 -0
  27. PaIRS_UniNa/__main__.py +45 -0
  28. PaIRS_UniNa/addwidgets_ps.py +1633 -0
  29. PaIRS_UniNa/calib.py +1488 -0
  30. PaIRS_UniNa/calibView.py +833 -0
  31. PaIRS_UniNa/gPaIRS.py +3957 -0
  32. PaIRS_UniNa/gPalette.py +189 -0
  33. PaIRS_UniNa/icons/abort.png +0 -0
  34. PaIRS_UniNa/icons/about.png +0 -0
  35. PaIRS_UniNa/icons/align_all.png +0 -0
  36. PaIRS_UniNa/icons/announcement.png +0 -0
  37. PaIRS_UniNa/icons/automatic_levels_off.png +0 -0
  38. PaIRS_UniNa/icons/automatic_levels_on.png +0 -0
  39. PaIRS_UniNa/icons/automatic_off.png +0 -0
  40. PaIRS_UniNa/icons/automatic_on.png +0 -0
  41. PaIRS_UniNa/icons/automatic_size_off.png +0 -0
  42. PaIRS_UniNa/icons/automatic_size_on.png +0 -0
  43. PaIRS_UniNa/icons/axes.png +0 -0
  44. PaIRS_UniNa/icons/background.png +0 -0
  45. PaIRS_UniNa/icons/background_vectors.png +0 -0
  46. PaIRS_UniNa/icons/bin_off.png +0 -0
  47. PaIRS_UniNa/icons/bin_on.png +0 -0
  48. PaIRS_UniNa/icons/browse_file_c.png +0 -0
  49. PaIRS_UniNa/icons/browse_folder_c.png +0 -0
  50. PaIRS_UniNa/icons/brush_cursor.png +0 -0
  51. PaIRS_UniNa/icons/bugfix.png +0 -0
  52. PaIRS_UniNa/icons/cal_proc.png +0 -0
  53. PaIRS_UniNa/icons/cal_proc_off.png +0 -0
  54. PaIRS_UniNa/icons/cal_step.png +0 -0
  55. PaIRS_UniNa/icons/cal_step_off.png +0 -0
  56. PaIRS_UniNa/icons/calibrate.png +0 -0
  57. PaIRS_UniNa/icons/calibration_logo.png +0 -0
  58. PaIRS_UniNa/icons/change_folder.png +0 -0
  59. PaIRS_UniNa/icons/change_folder_off.png +0 -0
  60. PaIRS_UniNa/icons/checklist.png +0 -0
  61. PaIRS_UniNa/icons/clean.png +0 -0
  62. PaIRS_UniNa/icons/clean_run.png +0 -0
  63. PaIRS_UniNa/icons/close.png +0 -0
  64. PaIRS_UniNa/icons/close_all.png +0 -0
  65. PaIRS_UniNa/icons/close_project.png +0 -0
  66. PaIRS_UniNa/icons/close_workspace.png +0 -0
  67. PaIRS_UniNa/icons/colormap.png +0 -0
  68. PaIRS_UniNa/icons/colormaps/Accent.png +0 -0
  69. PaIRS_UniNa/icons/colormaps/BrBG.png +0 -0
  70. PaIRS_UniNa/icons/colormaps/Dark2.png +0 -0
  71. PaIRS_UniNa/icons/colormaps/PRGn.png +0 -0
  72. PaIRS_UniNa/icons/colormaps/Paired.png +0 -0
  73. PaIRS_UniNa/icons/colormaps/Pastel1.png +0 -0
  74. PaIRS_UniNa/icons/colormaps/Pastel2.png +0 -0
  75. PaIRS_UniNa/icons/colormaps/PiYG.png +0 -0
  76. PaIRS_UniNa/icons/colormaps/PuOr.png +0 -0
  77. PaIRS_UniNa/icons/colormaps/RdBu.png +0 -0
  78. PaIRS_UniNa/icons/colormaps/RdGy.png +0 -0
  79. PaIRS_UniNa/icons/colormaps/RdYlBu.png +0 -0
  80. PaIRS_UniNa/icons/colormaps/RdYlGn.png +0 -0
  81. PaIRS_UniNa/icons/colormaps/Set1.png +0 -0
  82. PaIRS_UniNa/icons/colormaps/Set2.png +0 -0
  83. PaIRS_UniNa/icons/colormaps/Set3.png +0 -0
  84. PaIRS_UniNa/icons/colormaps/Spectral.png +0 -0
  85. PaIRS_UniNa/icons/colormaps/Wistia.png +0 -0
  86. PaIRS_UniNa/icons/colormaps/afmhot.png +0 -0
  87. PaIRS_UniNa/icons/colormaps/autumn.png +0 -0
  88. PaIRS_UniNa/icons/colormaps/binary.png +0 -0
  89. PaIRS_UniNa/icons/colormaps/blackVector.png +0 -0
  90. PaIRS_UniNa/icons/colormaps/blueVector.png +0 -0
  91. PaIRS_UniNa/icons/colormaps/bone.png +0 -0
  92. PaIRS_UniNa/icons/colormaps/brg.png +0 -0
  93. PaIRS_UniNa/icons/colormaps/bwr.png +0 -0
  94. PaIRS_UniNa/icons/colormaps/cividis.png +0 -0
  95. PaIRS_UniNa/icons/colormaps/cool.png +0 -0
  96. PaIRS_UniNa/icons/colormaps/coolwarm.png +0 -0
  97. PaIRS_UniNa/icons/colormaps/copper.png +0 -0
  98. PaIRS_UniNa/icons/colormaps/cubehelix.png +0 -0
  99. PaIRS_UniNa/icons/colormaps/cyanVector.png +0 -0
  100. PaIRS_UniNa/icons/colormaps/flag.png +0 -0
  101. PaIRS_UniNa/icons/colormaps/gist_heat.png +0 -0
  102. PaIRS_UniNa/icons/colormaps/gray.png +0 -0
  103. PaIRS_UniNa/icons/colormaps/greenVector.png +0 -0
  104. PaIRS_UniNa/icons/colormaps/hot.png +0 -0
  105. PaIRS_UniNa/icons/colormaps/hsv.png +0 -0
  106. PaIRS_UniNa/icons/colormaps/inferno.png +0 -0
  107. PaIRS_UniNa/icons/colormaps/jet.png +0 -0
  108. PaIRS_UniNa/icons/colormaps/magentaVector.png +0 -0
  109. PaIRS_UniNa/icons/colormaps/magma.png +0 -0
  110. PaIRS_UniNa/icons/colormaps/ocean.png +0 -0
  111. PaIRS_UniNa/icons/colormaps/pink.png +0 -0
  112. PaIRS_UniNa/icons/colormaps/plasma.png +0 -0
  113. PaIRS_UniNa/icons/colormaps/prism.png +0 -0
  114. PaIRS_UniNa/icons/colormaps/rainbow.png +0 -0
  115. PaIRS_UniNa/icons/colormaps/redVector.png +0 -0
  116. PaIRS_UniNa/icons/colormaps/seismic.png +0 -0
  117. PaIRS_UniNa/icons/colormaps/spring.png +0 -0
  118. PaIRS_UniNa/icons/colormaps/summer.png +0 -0
  119. PaIRS_UniNa/icons/colormaps/tab10.png +0 -0
  120. PaIRS_UniNa/icons/colormaps/tab20.png +0 -0
  121. PaIRS_UniNa/icons/colormaps/tab20b.png +0 -0
  122. PaIRS_UniNa/icons/colormaps/tab20c.png +0 -0
  123. PaIRS_UniNa/icons/colormaps/terrain.png +0 -0
  124. PaIRS_UniNa/icons/colormaps/twilight.png +0 -0
  125. PaIRS_UniNa/icons/colormaps/viridis.png +0 -0
  126. PaIRS_UniNa/icons/colormaps/whiteVector.png +0 -0
  127. PaIRS_UniNa/icons/colormaps/winter.png +0 -0
  128. PaIRS_UniNa/icons/colormaps/yellowVector.png +0 -0
  129. PaIRS_UniNa/icons/common_region.png +0 -0
  130. PaIRS_UniNa/icons/common_region_off.png +0 -0
  131. PaIRS_UniNa/icons/completed.png +0 -0
  132. PaIRS_UniNa/icons/contourf_off.png +0 -0
  133. PaIRS_UniNa/icons/contourf_on.png +0 -0
  134. PaIRS_UniNa/icons/copy.png +0 -0
  135. PaIRS_UniNa/icons/copy_process.png +0 -0
  136. PaIRS_UniNa/icons/copy_process_off.png +0 -0
  137. PaIRS_UniNa/icons/copygrid.png +0 -0
  138. PaIRS_UniNa/icons/cursor_lamp.png +0 -0
  139. PaIRS_UniNa/icons/cut.png +0 -0
  140. PaIRS_UniNa/icons/cut_warnings.png +0 -0
  141. PaIRS_UniNa/icons/darkmode.png +0 -0
  142. PaIRS_UniNa/icons/debug_run.png +0 -0
  143. PaIRS_UniNa/icons/delete.png +0 -0
  144. PaIRS_UniNa/icons/deleteErr.png +0 -0
  145. PaIRS_UniNa/icons/disp_step.png +0 -0
  146. PaIRS_UniNa/icons/disp_step_off.png +0 -0
  147. PaIRS_UniNa/icons/down.png +0 -0
  148. PaIRS_UniNa/icons/edit_list.png +0 -0
  149. PaIRS_UniNa/icons/editing.png +0 -0
  150. PaIRS_UniNa/icons/example_list.png +0 -0
  151. PaIRS_UniNa/icons/find_all_planes.png +0 -0
  152. PaIRS_UniNa/icons/find_plane.png +0 -0
  153. PaIRS_UniNa/icons/flaticon_PaIRS.png +0 -0
  154. PaIRS_UniNa/icons/flaticon_PaIRS_beta.png +0 -0
  155. PaIRS_UniNa/icons/flaticon_PaIRS_download.png +0 -0
  156. PaIRS_UniNa/icons/flaticon_PaIRS_download_warning.png +0 -0
  157. PaIRS_UniNa/icons/flip_y_off.png +0 -0
  158. PaIRS_UniNa/icons/flip_y_on.png +0 -0
  159. PaIRS_UniNa/icons/focusErrr.png +0 -0
  160. PaIRS_UniNa/icons/folder_loop_cleanup.png +0 -0
  161. PaIRS_UniNa/icons/folder_loop_cleanup_off.png +0 -0
  162. PaIRS_UniNa/icons/gear.gif +0 -0
  163. PaIRS_UniNa/icons/gear.png +0 -0
  164. PaIRS_UniNa/icons/ger.png +0 -0
  165. PaIRS_UniNa/icons/greenv.png +0 -0
  166. PaIRS_UniNa/icons/guide.png +0 -0
  167. PaIRS_UniNa/icons/icon_CalVi.png +0 -0
  168. PaIRS_UniNa/icons/icon_PaIRS.png +0 -0
  169. PaIRS_UniNa/icons/import.png +0 -0
  170. PaIRS_UniNa/icons/import_set.png +0 -0
  171. PaIRS_UniNa/icons/information.png +0 -0
  172. PaIRS_UniNa/icons/information2.png +0 -0
  173. PaIRS_UniNa/icons/input_logo.png +0 -0
  174. PaIRS_UniNa/icons/issue.png +0 -0
  175. PaIRS_UniNa/icons/laser_NTR.png +0 -0
  176. PaIRS_UniNa/icons/laser_TR_double.png +0 -0
  177. PaIRS_UniNa/icons/laser_TR_single.png +0 -0
  178. PaIRS_UniNa/icons/link.png +0 -0
  179. PaIRS_UniNa/icons/linked.png +0 -0
  180. PaIRS_UniNa/icons/loaded.png +0 -0
  181. PaIRS_UniNa/icons/loading_2.gif +0 -0
  182. PaIRS_UniNa/icons/log_logo.png +0 -0
  183. PaIRS_UniNa/icons/logo_CalVi.png +0 -0
  184. PaIRS_UniNa/icons/logo_CalVi_completo.png +0 -0
  185. PaIRS_UniNa/icons/logo_CalVi_party.png +0 -0
  186. PaIRS_UniNa/icons/logo_PaIRS.png +0 -0
  187. PaIRS_UniNa/icons/logo_PaIRS_completo.png +0 -0
  188. PaIRS_UniNa/icons/logo_PaIRS_download.png +0 -0
  189. PaIRS_UniNa/icons/logo_PaIRS_party_rect.png +0 -0
  190. PaIRS_UniNa/icons/logo_PaIRS_rect.png +0 -0
  191. PaIRS_UniNa/icons/logo_opaco.png +0 -0
  192. PaIRS_UniNa/icons/mask.png +0 -0
  193. PaIRS_UniNa/icons/measure.png +0 -0
  194. PaIRS_UniNa/icons/measure_off.png +0 -0
  195. PaIRS_UniNa/icons/min_proc.png +0 -0
  196. PaIRS_UniNa/icons/min_proc_off.png +0 -0
  197. PaIRS_UniNa/icons/min_step.png +0 -0
  198. PaIRS_UniNa/icons/min_step_off.png +0 -0
  199. PaIRS_UniNa/icons/minus.png +0 -0
  200. PaIRS_UniNa/icons/mirror_u.png +0 -0
  201. PaIRS_UniNa/icons/mirror_v.png +0 -0
  202. PaIRS_UniNa/icons/mirror_x.png +0 -0
  203. PaIRS_UniNa/icons/mirror_y.png +0 -0
  204. PaIRS_UniNa/icons/mtplt.png +0 -0
  205. PaIRS_UniNa/icons/new.png +0 -0
  206. PaIRS_UniNa/icons/new_workspace.png +0 -0
  207. PaIRS_UniNa/icons/news.png +0 -0
  208. PaIRS_UniNa/icons/normal_run.png +0 -0
  209. PaIRS_UniNa/icons/open.png +0 -0
  210. PaIRS_UniNa/icons/open_image.png +0 -0
  211. PaIRS_UniNa/icons/open_new_window.png +0 -0
  212. PaIRS_UniNa/icons/open_result.png +0 -0
  213. PaIRS_UniNa/icons/open_workspace.png +0 -0
  214. PaIRS_UniNa/icons/output_logo.png +0 -0
  215. PaIRS_UniNa/icons/paste_above.png +0 -0
  216. PaIRS_UniNa/icons/paste_below.png +0 -0
  217. PaIRS_UniNa/icons/pause.png +0 -0
  218. PaIRS_UniNa/icons/paused.png +0 -0
  219. PaIRS_UniNa/icons/pencil_bw.png +0 -0
  220. PaIRS_UniNa/icons/piv_proc.png +0 -0
  221. PaIRS_UniNa/icons/piv_proc_off.png +0 -0
  222. PaIRS_UniNa/icons/piv_step.png +0 -0
  223. PaIRS_UniNa/icons/piv_step_off.png +0 -0
  224. PaIRS_UniNa/icons/plane.png +0 -0
  225. PaIRS_UniNa/icons/play.png +0 -0
  226. PaIRS_UniNa/icons/plus.png +0 -0
  227. PaIRS_UniNa/icons/process_logo.png +0 -0
  228. PaIRS_UniNa/icons/process_loop.png +0 -0
  229. PaIRS_UniNa/icons/project.png +0 -0
  230. PaIRS_UniNa/icons/pylog.png +0 -0
  231. PaIRS_UniNa/icons/python_warning.png +0 -0
  232. PaIRS_UniNa/icons/queue.png +0 -0
  233. PaIRS_UniNa/icons/quit.png +0 -0
  234. PaIRS_UniNa/icons/read.png +0 -0
  235. PaIRS_UniNa/icons/read_list.png +0 -0
  236. PaIRS_UniNa/icons/redo.png +0 -0
  237. PaIRS_UniNa/icons/redx.png +0 -0
  238. PaIRS_UniNa/icons/reset.png +0 -0
  239. PaIRS_UniNa/icons/reset_levels.png +0 -0
  240. PaIRS_UniNa/icons/resize_icon.png +0 -0
  241. PaIRS_UniNa/icons/restore.png +0 -0
  242. PaIRS_UniNa/icons/restore_undo.png +0 -0
  243. PaIRS_UniNa/icons/rotate_clock.png +0 -0
  244. PaIRS_UniNa/icons/rotate_counter.png +0 -0
  245. PaIRS_UniNa/icons/rotate_v_clock.png +0 -0
  246. PaIRS_UniNa/icons/rotate_v_counter.png +0 -0
  247. PaIRS_UniNa/icons/running.gif +0 -0
  248. PaIRS_UniNa/icons/running.png +0 -0
  249. PaIRS_UniNa/icons/running_warn.png +0 -0
  250. PaIRS_UniNa/icons/sandglass.png +0 -0
  251. PaIRS_UniNa/icons/save.png +0 -0
  252. PaIRS_UniNa/icons/save_and_stop.png +0 -0
  253. PaIRS_UniNa/icons/save_cfg.png +0 -0
  254. PaIRS_UniNa/icons/saveas.png +0 -0
  255. PaIRS_UniNa/icons/saveas_workspace.png +0 -0
  256. PaIRS_UniNa/icons/scale_all.png +0 -0
  257. PaIRS_UniNa/icons/scale_down.png +0 -0
  258. PaIRS_UniNa/icons/scale_up.png +0 -0
  259. PaIRS_UniNa/icons/scan_list.png +0 -0
  260. PaIRS_UniNa/icons/scan_path.png +0 -0
  261. PaIRS_UniNa/icons/scan_path_loop.png +0 -0
  262. PaIRS_UniNa/icons/scan_path_loop_off.png +0 -0
  263. PaIRS_UniNa/icons/search.png +0 -0
  264. PaIRS_UniNa/icons/showIW_off.png +0 -0
  265. PaIRS_UniNa/icons/showIW_on.png +0 -0
  266. PaIRS_UniNa/icons/show_all.png +0 -0
  267. PaIRS_UniNa/icons/sort.png +0 -0
  268. PaIRS_UniNa/icons/sort_reversed.png +0 -0
  269. PaIRS_UniNa/icons/spiv_proc.png +0 -0
  270. PaIRS_UniNa/icons/spiv_proc_off.png +0 -0
  271. PaIRS_UniNa/icons/spiv_setup_no.png +0 -0
  272. PaIRS_UniNa/icons/spiv_setup_ok.png +0 -0
  273. PaIRS_UniNa/icons/star.png +0 -0
  274. PaIRS_UniNa/icons/step_inheritance.png +0 -0
  275. PaIRS_UniNa/icons/subMIN_off.png +0 -0
  276. PaIRS_UniNa/icons/subMIN_on.png +0 -0
  277. PaIRS_UniNa/icons/tom.png +0 -0
  278. PaIRS_UniNa/icons/trash.png +0 -0
  279. PaIRS_UniNa/icons/undo.png +0 -0
  280. PaIRS_UniNa/icons/unedited.png +0 -0
  281. PaIRS_UniNa/icons/unina_dii.png +0 -0
  282. PaIRS_UniNa/icons/uninitialized.png +0 -0
  283. PaIRS_UniNa/icons/unlink.png +0 -0
  284. PaIRS_UniNa/icons/unwrap_items.png +0 -0
  285. PaIRS_UniNa/icons/up.png +0 -0
  286. PaIRS_UniNa/icons/updating_import.gif +0 -0
  287. PaIRS_UniNa/icons/updating_pairs.gif +0 -0
  288. PaIRS_UniNa/icons/vectorColor.png +0 -0
  289. PaIRS_UniNa/icons/vettore.png +0 -0
  290. PaIRS_UniNa/icons/view.png +0 -0
  291. PaIRS_UniNa/icons/view_off.png +0 -0
  292. PaIRS_UniNa/icons/vis_logo.png +0 -0
  293. PaIRS_UniNa/icons/waiting_circle.png +0 -0
  294. PaIRS_UniNa/icons/warning.png +0 -0
  295. PaIRS_UniNa/icons/warning_circle.png +0 -0
  296. PaIRS_UniNa/icons/window.png +0 -0
  297. PaIRS_UniNa/icons/workspace.png +0 -0
  298. PaIRS_UniNa/icons/wrap_items.png +0 -0
  299. PaIRS_UniNa/icons/write_list.png +0 -0
  300. PaIRS_UniNa/listLib.py +303 -0
  301. PaIRS_UniNa/mtfPIV.py +256 -0
  302. PaIRS_UniNa/parForMulti.py +435 -0
  303. PaIRS_UniNa/parForWorkers.py +593 -0
  304. PaIRS_UniNa/pivParFor.py +235 -0
  305. PaIRS_UniNa/plt_util.py +141 -0
  306. PaIRS_UniNa/preProcParFor.py +155 -0
  307. PaIRS_UniNa/procTools.py +1439 -0
  308. PaIRS_UniNa/readcfg.py +52 -0
  309. PaIRS_UniNa/rqrdpckgs.txt +9 -0
  310. PaIRS_UniNa/stereoPivParFor.py +227 -0
  311. PaIRS_UniNa/tAVarie.py +215 -0
  312. PaIRS_UniNa/tabSplitter.py +612 -0
  313. PaIRS_UniNa/ui_Calibration_Tab.py +578 -0
  314. PaIRS_UniNa/ui_Custom_Top.py +296 -0
  315. PaIRS_UniNa/ui_Input_Tab.py +1101 -0
  316. PaIRS_UniNa/ui_Input_Tab_CalVi.py +1283 -0
  317. PaIRS_UniNa/ui_Log_Tab.py +263 -0
  318. PaIRS_UniNa/ui_Output_Tab.py +2362 -0
  319. PaIRS_UniNa/ui_Process_Tab.py +3810 -0
  320. PaIRS_UniNa/ui_Process_Tab_CalVi.py +1549 -0
  321. PaIRS_UniNa/ui_Process_Tab_Disp.py +1141 -0
  322. PaIRS_UniNa/ui_Process_Tab_Min.py +437 -0
  323. PaIRS_UniNa/ui_ResizePopup.py +204 -0
  324. PaIRS_UniNa/ui_Vis_Tab.py +1628 -0
  325. PaIRS_UniNa/ui_Vis_Tab_CalVi.py +1251 -0
  326. PaIRS_UniNa/ui_Whatsnew.py +132 -0
  327. PaIRS_UniNa/ui_gPairs.py +877 -0
  328. PaIRS_UniNa/ui_infoPaIRS.py +551 -0
  329. PaIRS_UniNa/whatsnew.txt +4 -0
  330. pairs_unina-0.2.10.dist-info/METADATA +159 -0
  331. pairs_unina-0.2.10.dist-info/RECORD +333 -0
  332. pairs_unina-0.2.10.dist-info/WHEEL +5 -0
  333. pairs_unina-0.2.10.dist-info/top_level.txt +2 -0
@@ -0,0 +1,833 @@
1
+ ''' CalibView '''
2
+ # pylint: disable=pointless-string-statement, too-many-instance-attributes, no-name-in-module, multiple-imports
3
+ # pylint: disable= import-error
4
+ # pylint: disable=multiple-statements,c-extension-no-member
5
+ import sys, traceback
6
+ from typing import Callable
7
+ from enum import Enum
8
+ #import faulthandler # per capire da dove vengono gli errori c
9
+ import platform
10
+
11
+ from PySide6 import QtCore, QtGui, QtWidgets
12
+
13
+ from PySide6.QtCore import Slot, QThreadPool, QObject, Signal, QRunnable
14
+ from PySide6.QtWidgets import QLabel #,QWidget, QVBoxLayout, QHBoxLayout
15
+ from PySide6.QtWidgets import QSpinBox #,QApplication, QPushButton
16
+
17
+ from PIL import Image, ImageQt
18
+ import numpy as np
19
+
20
+
21
+ from .calib import Calib, CalibTasks, TYPE_ERR_STOP, CalibFunctions
22
+
23
+
24
+ try:
25
+ from .PaIRS_pypacks import pri, Flag_DEBUG_PARPOOL # type: ignore per ignorare il warning dy pylance
26
+ flagImageViewer=0
27
+ except ModuleNotFoundError as exc:
28
+ from .tAVarie import pri
29
+ flagImageViewer=1
30
+ Flag_DEBUG_PARPOOL=0 # pylint: disable=invalid-name
31
+ if Flag_DEBUG_PARPOOL:
32
+ import debugpy # pylint: disable=unused-import #nel caso mettere nel thread debugpy.debug_this_thread()
33
+
34
+ #faulthandler.enable() # per capire da dove vengono gli errori c
35
+ if __package__ or "." in __name__:
36
+ import PaIRS_UniNa.PaIRS_PIV as PaIRS_lib # pylint: disable=unused-import
37
+ from PaIRS_UniNa.PaIRS_PIV import Punto
38
+ from PaIRS_UniNa.PaIRS_PIV import CalFlags
39
+ else:
40
+ if platform.system() == "Darwin":
41
+ sys.path.append('../lib/mac')
42
+ else:
43
+ #sys.path.append('PaIRS_PIV')
44
+ sys.path.append('../lib')
45
+ import PaIRS_PIV as PaIRS_lib # pylint: disable=unused-import # type: ignore
46
+ from PaIRS_PIV import Punto # type: ignore
47
+ from PaIRS_PIV import CalFlags # type: ignore
48
+
49
+
50
+ class CircleType(Enum):
51
+ circle = 1 # pylint: disable=invalid-name
52
+ square= 2 # pylint: disable=invalid-name
53
+ filledCircle=3 # pylint: disable=invalid-name
54
+
55
+ mainInCircleColors=['#ff0000', '#ff00ff','#0000ff']
56
+ foundCircleColor='#ff0000'
57
+ maxErrorCircleColor='#ffff00'
58
+ OriginCircleColor='#00ff00'
59
+ mainInCircleType=[CircleType.circle, CircleType.square,CircleType.circle]
60
+ rFoundCircle=5
61
+ rInpCircle=15
62
+ penWidth=2
63
+ percLunFreccia=0.25#lunghezza testa
64
+ lunFreccia=100#scalatura freccia
65
+ angFreccia=30*np.pi/180
66
+ tanFreccia=percLunFreccia*np.tan(angFreccia)
67
+
68
+ class Circle():
69
+ def __init__(self,x,y,r:int=rInpCircle,col:str=foundCircleColor,ty:CircleType=CircleType.filledCircle):#'#EB5160'
70
+ self.r=r
71
+ self.col=col
72
+ self.type=ty
73
+ self.xe=x
74
+ self.ye=y
75
+ self.x=x
76
+ self.y=y
77
+ @classmethod
78
+ def fromPunto(cls, pu:Punto,r:int=5,col:str=foundCircleColor,ty:CircleType=CircleType.circle)->Punto:
79
+ ''' retrun a circle from a Punto'''
80
+ return cls(pu.x,pu.y,r,col,ty)
81
+
82
+ class SignalsImageViewer(QObject):
83
+ ''' signals used to comunicate form calib to view'''
84
+ pointFromView=Signal(object)
85
+ replyFromView=Signal(int)
86
+
87
+ class CalibView(QLabel):
88
+ ''' View class for the wrapper (calib)'''
89
+ def aa__del__(self):# should not be used because some times it is not called when deleting the object therefore I have changed the name
90
+ ''' destructor '''
91
+ pri.Time.red(0,'Destructor calibView')
92
+ pri.Info.white('Destructor CalibView.')
93
+ def __init__(self,parent:QObject=None, outFromCalibView:Callable=None,outToStatusBarFromCalibView:Callable=None,textFromCalib:Callable=None,workerCompleted:Callable=None,):
94
+ '''
95
+ outFromCalibView called by plotImg -- output function called to give some single line info und to update the interface
96
+ outToStatusBarFromCalibView output function with position and gray level
97
+ two other slot are passed and set when the worker is created
98
+ self.worker.signals.textFromCalib.connect(textFromCalib) instruction for the user
99
+ self.worker.signals.finished.connect(workerCompleted)
100
+ '''
101
+ super().__init__(parent)
102
+ self.textFromCalib=textFromCalib #Output function to status bar
103
+ self.outToCaller=outFromCalibView #output function to caller called by plot
104
+ self.workerCompleted=workerCompleted
105
+ self.outToStatusBarCaller=outToStatusBarFromCalibView #output function to caller called by mouseMoveEvent
106
+ self.setBackgroundRole(QtGui.QPalette.Base)
107
+ self.setSizePolicy(QtWidgets.QSizePolicy.Ignored, QtWidgets.QSizePolicy.Ignored)
108
+ self.setScaledContents(True)
109
+
110
+ # Threadpool
111
+ self.imageViewerThreadpool=QThreadPool()
112
+ self.imageViewerThreadpool.setMaxThreadCount(10)
113
+
114
+ self.rectMask=None
115
+ self.flagGetPoint=0# if true acquire points and pass them to calib
116
+
117
+ self.worker:CalibWorker=None
118
+ self.signals=SignalsImageViewer()
119
+ self.signals.pointFromView.connect(self.pointFromView)
120
+ self.signals.replyFromView.connect(self.replyFromView)
121
+
122
+ self.oldPos=QtCore.QPointF(0, 0)
123
+ self.contextMenu:QtWidgets.Qmenu=None
124
+ self.contextMenuActions:list[QAction]=[]
125
+ '''
126
+ # for now unused should be used to change the level and position
127
+ self.timer = QtCore.QTimer(self)
128
+ self.timer.timeout.connect( self.onTimer)
129
+ self.timer.start(100)
130
+ self.oldPos=QtGui.QCursor.pos()
131
+ '''
132
+ # Calib and the like
133
+ self.calib=Calib()
134
+ #flagOp=self.calib.readCfg()
135
+ #self.calib.readImgs()#todo verificare eventuali errori e dimensioni delle immagini in questo momento non da errore e l'img viene tagliata
136
+ self.flagFirstTask=CalibTasks.stop
137
+ self.flagCurrentTask=CalibTasks.stop
138
+
139
+ self.setMouseTracking(True)
140
+ self.flagButCalib=CalibTasks.findAllPlanes
141
+ self.puMiddleButton=Punto(-1,-1)# point found when pressing with the middle button
142
+ self.flagSearchMaskZone=False
143
+ self.scaleFactor=1.0
144
+ self.imgPlot=np.zeros((1,1),dtype=np.uint8)
145
+ pri.Time.cyan(0,'End Init calibView')
146
+
147
+ #pri.Callback.white (PaIRS_lib.Version(PaIRS_lib.MOD_Calib))
148
+
149
+ def resetScaleFactor(self,scrollAreaSize):
150
+ ''' reset the scale factor so that the image perfectly feet the window'''
151
+ if self.calib.flagPlotMask:
152
+ if len(self.calib.ccMask):
153
+ (h,w)=self.calib.ccMask[0].shape
154
+ else:
155
+ return
156
+ else:
157
+ if len(self.calib.imgs):
158
+ (h,w)=self.calib.imgs[0].shape
159
+ else:
160
+ return
161
+ delta=4# by tom maybe delta pixel are added ??
162
+ self.scaleFactor=min( scrollAreaSize.height()/(h+delta), scrollAreaSize.width()/(w+delta))
163
+
164
+ @Slot(int)
165
+ def drawCirclesFromCalib(self,plane:int):
166
+ ''' draw all the circles '''
167
+ self.drawCircles(plane)
168
+ @Slot(object)
169
+ def drawSingleCircleFromCalib(self,pu:Punto,flag:int,ind:int):
170
+ ''' draws a single Circle from a point received by calib '''
171
+ ci=Circle.fromPunto(pu) if flag else Circle.fromPunto(pu,r=rInpCircle,col=mainInCircleColors[ind],ty=mainInCircleType[ind])
172
+ self.drawSingleCircle(ci)
173
+
174
+ @Slot(object)
175
+ def flagGetPointFromCalib(self,flag:int):
176
+ ''' setter of flagGetPoint from calib'''
177
+ self.flagGetPoint=flag
178
+ @Slot(str)
179
+ def askFromCalib(self,text:str):
180
+ ''' ask if ok from Calib'''
181
+ msgBox=QtWidgets.QMessageBox(self)
182
+ okButton=QtWidgets.QMessageBox.Yes
183
+ msgBox.setStandardButtons(QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No )
184
+ msgBox.setDefaultButton(QtWidgets.QMessageBox.Yes)
185
+ msgBox.setText(text)
186
+ msgBox.setWindowTitle('CalVi')
187
+ msgBox.setIcon(QtWidgets.QMessageBox.Question)
188
+ okButton=msgBox.button(QtWidgets.QMessageBox.Yes)
189
+ msgBox.show()
190
+
191
+ #screenGeometry = QtGui.QGuiApplication.primaryScreen().availableGeometry()# screen
192
+ screenGeometry =self.window().geometry() #main window
193
+ screenGeo = screenGeometry.bottomRight()
194
+ #msgGeo = QtCore.QRect(QtCore.QPoint(0,0), msgBox.sizeHint())
195
+ msgGeo = QtCore.QRect(QtCore.QPoint(0,0), msgBox.size())
196
+ msgGeo.moveBottomRight(screenGeo)
197
+ #msgBox.move(msgGeo.bottomRight())
198
+ #msgBox.move(100,0)
199
+ a=msgBox.mapToGlobal(QtCore.QPoint(0, 0))
200
+ a=QtCore.QPoint(*(msgBox.size()).toTuple())
201
+
202
+ msgBox.move(msgGeo.bottomRight()-a-QtCore.QPoint(0,30))
203
+ oldPos=QtGui.QCursor.pos()
204
+ QtGui.QCursor.setPos(okButton.mapToGlobal(QtCore.QPoint(0, 0)+QtCore.QPoint(*(okButton.size()/2).toTuple())))
205
+ #self.window().mapToGlobal(QtCore.QPoint(0, 0)) #main window
206
+ #self.parentWidget().mapToGlobal(QtCore.QPoint(0, 0)) #parent widget
207
+ res=msgBox.exec()
208
+ QtGui.QCursor.setPos(oldPos)
209
+
210
+ #res=QtWidgets.QMessageBox.question(self, "Calib",text )
211
+ flag=1 if res == QtWidgets.QMessageBox.Yes else 0
212
+ self.signals.replyFromView.emit(flag)
213
+
214
+ def createWorker(self,flag:CalibTasks,textFromCalib:Callable,workerCompleted:Callable):
215
+ ''' create the worker, connects the signals and start'''
216
+ self.worker=CalibWorker()
217
+ self.worker.signals.drawSingleCircleFromCalib.connect(self.drawSingleCircleFromCalib)
218
+ self.worker.signals.drawCirclesFromCalib.connect(self.drawCirclesFromCalib)
219
+ self.worker.signals.flagGetPointFromCalib.connect(self.flagGetPointFromCalib)
220
+ self.worker.signals.askFromCalib.connect(self.askFromCalib)
221
+ self.worker.signals.plotImgFromCalib.connect(self.plotImg)
222
+ self.worker.setTask(self.calib,flag)
223
+
224
+ self.worker.signals.textFromCalib.connect(textFromCalib)
225
+ self.worker.signals.finished.connect(workerCompleted)
226
+ self.imageViewerThreadpool.start(self.worker)
227
+
228
+ def executeCalibTask(self,flag:CalibTasks):
229
+ ''' button pressed '''
230
+ #pri.Info.red(f'executeCalibTask {self.calib.flagExitFromView is True} {self.calib.cal.flagWorking } {self.calib.cal.flagWorking is True}')
231
+ if self.calib.flagExitFromView is True and self.calib.cal.flagWorking ==1:
232
+ pri.Info.red('still working let us wait')# never used? Maybe flagWorking is useless???
233
+ return False
234
+ if flag is self.flagCurrentTask or flag is CalibTasks.stop:# in this case always stop
235
+ self.calib.flagExitFromView=True
236
+ self.flagCurrentTask=flag=CalibTasks.stop
237
+ self.flagGetPoint=0# if true acquire points and pass them to calib
238
+ pri.Info.green('pressed stop')
239
+ return True
240
+ elif not self.flagCurrentTask is CalibTasks.stop: # already running a task simply exit function # pylint: disable=unneeded-not,superfluous-parens
241
+ return False
242
+
243
+
244
+
245
+ self.flagCurrentTask=flag
246
+ self.calib.flagExitFromView=False
247
+ self.createWorker(flag,self.textFromCalib,self.workerCompleted)
248
+ return True
249
+
250
+ def executeCalibFunction(self,flag:CalibFunctions):
251
+ ''' button pressed '''
252
+ if flag is CalibFunctions.removeMaxErrPoint and self.calib.cal.flagCalibrated:
253
+ self.calib.cal.vect.flag[self.calib.cal.data.kMax,self.calib.cal.data.jMax]=CalFlags.P_REMOVED
254
+ self.calib.cal.removeMaxErrPoint()
255
+
256
+ strPriErrCalib=self.calib.prettyPrintErrCalib()
257
+ pri.Process.blue (strPriErrCalib)
258
+ self.textFromCalib(strPriErrCalib)
259
+ self.plotPlane(self.calib.cal.data.kMax)
260
+ elif flag is CalibFunctions.findMaxErrPoint:
261
+ self.plotPlane(self.calib.cal.data.kMax)
262
+ elif flag is CalibFunctions.RemovePoint:
263
+ pu=Punto(*self.scaleToImg(self.contextMenuPos).toTuple())
264
+ if not self.insideImg(pu):
265
+ return
266
+ else:
267
+ self.calib.cal.removePoint(pu)
268
+ self.plotPlane(self.calib.plane)
269
+ #self.scaleToImg(mouseEv.position())
270
+
271
+ def plotPlane(self,plane):
272
+ ''' plot image of plane=plane'''
273
+ pri.Info.green('plotPlane call')
274
+ flagPlot=False
275
+ try:
276
+ if 0<=plane <self.calib.nPlanes:
277
+ self.calib.cal.data.piano=self.calib.plane=plane
278
+ self.calib.cal.initFindPoint(plane)
279
+ flagPlot=self.plotImg(plane)
280
+ if flagPlot and not self.calib.flagPlotMask:
281
+ self.drawCircles(plane)
282
+ except Exception as inst:
283
+ pri.Error.red(f'plotePlane call: error while plotting image\n{traceback.format_exc()}')
284
+ #XY=self.calib.cal.pointFromCalib([0,0,0],0)
285
+ #pri.Info.green(f"Punto (x,y,z)=(0,0,0) -> (X,Y)=({XY.x},{XY.y})")
286
+ #self.outToStatusBarCaller(f'Cam#:{self.calib.plane//self.calib.nPlanesPerCam} Plane:{self.calib.plane%self.calib.nPlanesPerCam}')
287
+ return flagPlot
288
+
289
+ @Slot(int)
290
+ def plotImg(self,plane,flagDrawRect=False):
291
+ ''' plot the image whenever the plane is changed '''
292
+ pri.Callback.white('+++ Plotting image in Vis +++')
293
+ img,flagPlot=self.preparePlot(plane)
294
+ if not flagPlot:
295
+ self.setPixmap(QtGui.QPixmap())
296
+ return flagPlot
297
+ dumStr='' if self.calib.cal.data.FlagCam else f'_cam{self.calib.cams[self.calib.plane//self.calib.nPlanesPerCam]}'
298
+ nomeImg=self.calib.cal.getImgRoot(self.calib.plane%self.calib.nPlanesPerCam)+dumStr+self.calib.cal.data.EstensioneIn
299
+ self.outToCaller(nomeImg)
300
+ img=ImageQt.ImageQt(Image.fromarray(img))
301
+ self.setPixmap(QtGui.QPixmap.fromImage(img))
302
+ if flagDrawRect:
303
+ self.drawRectangleCC(plane)
304
+ return flagPlot
305
+
306
+ #def onTimer(self):
307
+ ''' used to pri.Callback.white the position and the gray level'''
308
+ '''
309
+ newPos=QtGui.QCursor.pos()
310
+ if newPos!=self.oldPos:
311
+ self.oldPos=newPos
312
+ try:
313
+ pu = self.mapFrom(self, newPos)/self.scaleFactor
314
+ f= 0<=pu.x() <self.pixmap().width()
315
+ if not (f and (0<= pu.y() <self.pixmap().height())):
316
+ return
317
+ pri.Callback.white(f' {pu.x()}')
318
+ j=int(pu.x())
319
+ i=int(pu.y())
320
+ self.outToStatusBarCaller(f'({i},{j}) {self.calib.imgs[self.calib.plane][i,j]}')
321
+ except:
322
+ pri.Callback.white ('Exception in onTimer')
323
+ '''
324
+ def preparePlot(self,plane=0):
325
+ ''' build the background 8 bit image for plotting'''
326
+ self.imgPlot=np.zeros((1,1),dtype=np.uint8)#penso sia inutile e forse dannoso
327
+ calib=self.calib
328
+ FlagPlot=False
329
+ if len(calib.ccMask):
330
+ if calib.flagPlotMask:
331
+ mask=self.normalizeArray(calib.ccMask[plane],calib.LMax,calib.LMin)
332
+ elif calib.flagShowMask:
333
+ _,LMax,LMin=calib.calcLMinMax(plane,flagPlotMask=True)
334
+ mask=self.normalizeArray(calib.ccMask[plane],LMax,LMin)
335
+
336
+ if not calib.flagPlotMask:
337
+ if len(calib.imgs):
338
+ self.imgPlot=self.normalizeArray(calib.imgs[plane],calib.LMax,calib.LMin)
339
+ FlagPlot=bool(self.imgPlot.max()!=self.imgPlot.min())
340
+
341
+ if calib.flagShowMask and len(calib.ccMask):#todo TA ma se l'img è più piccola
342
+ self.imgPlot[0:mask.shape[0],0:mask.shape[1]]=mask # pylint: disable=unsupported-assignment-operation
343
+ else:
344
+ if len(calib.ccMask):
345
+ self.imgPlot=mask
346
+ FlagPlot=bool(self.imgPlot.max()!=self.imgPlot.min())
347
+
348
+ return self.imgPlot,FlagPlot
349
+
350
+ def normalizeArray(self,da,LMax=None,LMin=None):
351
+ #todo GP non è mai chiamata con None è necessario complicarla? Fra l'altro se decidiamo di valutare
352
+ # min e max in fase di assegnazione è inutile
353
+ a=da.copy()# todo GP perchè la copii?
354
+ if 'int' in a.dtype.name:
355
+ LLim=2**16-1
356
+ if not LMax:
357
+ LMax=max([min([a.max(),LLim]),-LLim+1])
358
+ if not LMin:
359
+ LMin=max([min([a.min(),LMax-1]),-LLim])
360
+ LMin=max([0,LMin])
361
+ LMax=max([LMin+1,LMax])
362
+ a[a>LMax]=LMax
363
+ a[a<LMin]=LMin
364
+ else:
365
+ LMax=a.max()
366
+ LMin=a.min()
367
+ if LMax==LMin: LMax=LMax+1
368
+
369
+ a=np.uint8(255.0*(a-LMin)/(LMax-LMin))
370
+ return a
371
+ def insideImg(self,pu:Punto)->bool:
372
+ ''' checks if a point is inside the image'''
373
+ f= 0<=pu.x <self.pixmap().width()
374
+ return f and (0<= pu.y <self.pixmap().height())
375
+
376
+ def contextMenuEvent(self, event):
377
+ # Show the context menu
378
+ if self.contextMenu:
379
+ self.contextMenuPos=event.position()
380
+ self.contextMenu.exec(event.globalPosition().toPoint())
381
+
382
+ def mouseMoveEvent(self, mouseEv):
383
+ ''' mouse move'''
384
+ if self.imgPlot.size==1:
385
+ return
386
+ try:
387
+ newPos=self.scaleToImg(mouseEv.position())
388
+ if newPos!=self.oldPos:
389
+ self.oldPos=newPos
390
+ pu=Punto(*newPos.toTuple())
391
+ j=int(pu.x)
392
+ i=int(pu.y)
393
+ try:
394
+ #self.outToStatusBarCaller(f'Cam #{self.calib.plane//self.calib.nPlanesPerCam} Plane #{self.calib.plane%self.calib.nPlanesPerCam}: ({i},{j}) {self.calib.imgs[self.calib.plane][i,j]}')
395
+ sAppo=f'{self.calib.ccMask[self.calib.plane][i,j]:.2f}' if self.calib.flagPlotMask else f'{self.calib.imgs[self.calib.plane][i,j]:d}'
396
+ self.outToStatusBarCaller(f'(x,y)=({i},{j}), Lev={sAppo}')
397
+ except IndexError as exc:
398
+ return #out of bounds I am not checking but exit from the function
399
+ if mouseEv.buttons()==QtCore.Qt.MiddleButton and not self.calib.flagPlotMask: # in this case use buttons instead of button !!!!
400
+ self.rectMask= QtCore.QRectF(min (self.puMiddleButton.x(),newPos.x()), min (self.puMiddleButton.y(),newPos.y()),abs(self.puMiddleButton.x()-newPos.x()),abs(self.puMiddleButton.y()-newPos.y()))
401
+ self.update()
402
+
403
+ except Exception as exc:# pylint: disable=broad-exception-caught
404
+ pri.Error.red(f'Exception in mouseMoveEvent {str(exc)}')# tin qt some exception are non propagated
405
+
406
+ def mousePressEvent(self, mouseEv):
407
+ ''' when mouse pressed'''
408
+ try:
409
+ if mouseEv.button()==QtCore.Qt.RightButton:
410
+ self.contextMenuEvent(mouseEv)
411
+ elif mouseEv.button()==QtCore.Qt.MiddleButton and not self.calib.flagPlotMask:
412
+ #self.puMiddleButton=self.scaleToImg(mouseEv.position())
413
+ self.puMiddleButton=self.scaleToImg(mouseEv.position())
414
+ self.flagSearchMaskZone=True
415
+ pri.Callback.white('Mouse pressed')
416
+ except Exception as exc:# pylint: disable=broad-exception-caught
417
+ pri.Error.red(f'Exception in mousePressEvent {str(exc)}')# tin qt some exception are non propagated
418
+
419
+ def paintEvent(self, event):
420
+ ''' called any time a repaint should be done used here in only to plot moving things on particular the rectangle defining the cc mask'''
421
+ super().paintEvent(event)
422
+ try:
423
+
424
+ if self.rectMask is None or self.calib.flagPlotMask:
425
+ return
426
+ painter = QtGui.QPainter(self)
427
+ pen = QtGui.QPen()
428
+ pen.setWidth(penWidth)
429
+ pen.setColor(QtGui.QColor(mainInCircleColors[2]))
430
+ painter.setPen(pen)
431
+
432
+ painter.drawRect(QtCore.QRectF(*self.scaleFromImgIterable(self.rectMask.getRect())))
433
+ except Exception as exc:# pylint: disable=broad-exception-caught
434
+ pri.Error.red(f'Exception in paintEvent {str(exc)}')# tin qt some exception are non propagated
435
+
436
+ def mouseReleaseEvent(self, mouseEv):
437
+ ''' exception raised in qt functions (slot?) are not propagated:
438
+ # https://stackoverflow.com/questions/45787237/exception-handled-surprisingly-in-pyside-slots
439
+ '''
440
+ try:
441
+ if mouseEv.button()==QtCore.Qt.LeftButton:
442
+ if self.flagGetPoint:
443
+ try:
444
+ pu=Punto(*self.scaleToImg(mouseEv.position()).toTuple())
445
+ if not self.insideImg(pu):
446
+ return
447
+ self.signals.pointFromView.emit(pu)
448
+ except Exception as exc:
449
+ pri.Error.red(str(exc))# the try should be useless but you never know since in qt some exception are non propagated
450
+ elif mouseEv.button()==QtCore.Qt.MiddleButton and not self.calib.flagPlotMask:
451
+ if (self.flagSearchMaskZone):
452
+ self.setMaskZone()
453
+ #todo add the code to revaluate the cc mask
454
+ pri.Callback.white('Middle use Released')
455
+ except Exception as exc:# pylint: disable=broad-exception-caught
456
+ pri.Error.red(f'Exception in mouseReleaseEvent {str(exc)}')# tin qt some exception are non propagated
457
+
458
+ #def drawRectangle(self, p,painter,pen):
459
+ def setMaskZone(self):
460
+ data=self.calib.cal.data
461
+ p=self.calib.plane
462
+
463
+ if (self.rectMask.height()< data.DimWinCC or self.rectMask.width()< data.DimWinCC ):
464
+ raise ValueError('Error the selected window is to small') #from exc
465
+
466
+ else:
467
+
468
+ self.calib.cal.setPuTrovaCC(self.rectMask.getRect(),p)
469
+ if self.calib.flagFindAllPlanes and p==0: #when starting select a mask for all the planes
470
+ for p1 in range(1,self.calib.nPlanes):
471
+ self.calib.cal.setPuTrovaCC(self.rectMask.getRect(),p1)
472
+ self.calib.cal.vect.flagPlane[p1]|= CalFlags.PLANE_NOT_INIT_TROVA_PUNTO|CalFlags.PLANE_NOT_FOUND
473
+ self.calib.changeMask(p)
474
+ self.plotPlane(p)
475
+
476
+ self.flagSearchMaskZone=False
477
+ self.rectMask=None# maybe is reduntant but we are using his to avoid plotting the rectangle
478
+
479
+ def setCirclePainter(self,canvas,cir):
480
+ ''' used to speed up drawCircles'''
481
+ painter = QtGui.QPainter(canvas)
482
+ pen = QtGui.QPen()
483
+ pen.setWidth(penWidth/self.scaleFactor)
484
+ pen.setColor(QtGui.QColor(cir.col))
485
+ painter.setPen(pen)
486
+ if cir.type==CircleType.circle:
487
+ def pCir(X:float, Y:float,r:float):
488
+ painter.drawRoundedRect(X-r, Y-r,2*r,2*r,r,r)
489
+ elif cir.type==CircleType.square:
490
+ def pCir(X:float, Y:float,r:float):
491
+ painter.drawRect(X-r, Y-r,2*r,2*r)
492
+ elif cir.type==CircleType.filledCircle:
493
+ def pCir(X:float, Y:float,r:float):
494
+ painter.drawRoundedRect(X-r, Y-r,2*r,2*r,r,r)
495
+ painter.setBrush(QtGui.QBrush(QtGui.QColor(cir.col)))
496
+ return (painter,pen,pCir)
497
+
498
+ def drawArrow(self,painter,l,x1,y1,x,y):
499
+ ''' draw arrow from x1 to x scaled with l'''
500
+ dx=(x-x1)*l
501
+ dy=(y-y1)*l
502
+ if abs(dx)>10**6 or abs(dy)>10**6:
503
+ dx=10**3
504
+ dy=10**3
505
+ x2=x1+dx
506
+ y2=y1+dy
507
+ painter.drawLine(x1,y1,x2,y2)
508
+ painter.drawLine(x2,y2,x2-dx*percLunFreccia+dy*tanFreccia ,y2-dy*percLunFreccia-dx*tanFreccia)
509
+ painter.drawLine(x2,y2,x2-dx*percLunFreccia-dy*tanFreccia ,y2-dy*percLunFreccia+dx*tanFreccia)
510
+
511
+ def drawAxis(self, p,painter,pen):
512
+ ''' draws the axis'''
513
+ calVect=self.calib.cal.vect
514
+ flagDrawCircles=True
515
+ percLine=0.25
516
+ def c1(x1,x2,percLine):
517
+
518
+ return x1 + (x2 - x1)*percLine
519
+ offSetText=4
520
+ def cLeftText( x1,x2,y1,y2 ):
521
+ return (c1(x1,x2,percLine if x2>x1 else (1-percLine))+offSetText,c1(y1,y2,percLine if y1>y2 else (1-percLine))-offSetText)
522
+ def c2( x1,x2,y1,y2 ):
523
+ return (c1(x1,x2,percLine),c1(y1,y2,percLine),c1(x1,x2,1-percLine),c1(y1,y2,1-percLine))
524
+
525
+ font = QtGui.QFont()
526
+ font.setFamily('Arial')
527
+ font.setPointSize(40)#todo dimesione testo e font
528
+ painter.setFont(font)
529
+ calVect=self.calib.cal.vect
530
+
531
+
532
+ #origin
533
+ ii=self.calib.cal.indFromCoord(0,0,p)
534
+ if calVect.flag[p,ii]==1:
535
+ puOr=Punto(calVect.XOr[p],calVect.YOr[p])
536
+ ind=0
537
+ #puOr=Punto(out.X[p,ii], out.Y[p,ii])
538
+ #for pp in range (0,self.calib.cal.data.Numpiani): pri.Info.green(out.X[pp,ii], out.Y[pp,ii])
539
+ #pri.Info.green(f'Or=({out.X[p,iOr]}, {out.Y[p,iOr]}) x=({out.X[p,ii]}, {out.Y[p,ii]}) y=({out.X[p,iOr+1]}, {out.Y[p,iOr+1]})')
540
+
541
+
542
+ if flagDrawCircles:
543
+ r=rInpCircle
544
+ def pCir(X:float, Y:float,r:float):
545
+ painter.drawRoundedRect(X-r, Y-r,2*r,2*r,r,r)
546
+ #pri.Info.green(X,Y)
547
+ pen.setColor(QtGui.QColor(mainInCircleColors[ind]))
548
+ painter.setPen(pen)
549
+ pCir(puOr.x,puOr.y,r)
550
+ # y axis
551
+ ind=2
552
+ ii=self.calib.cal.indFromCoord(1,0,p)
553
+ if calVect.flag[p,ii]==1:
554
+ pu=Punto(calVect.X[p,ii], calVect.Y[p,ii])
555
+ pen.setColor(QtGui.QColor(mainInCircleColors[ind]))
556
+ painter.setPen(pen)
557
+ self.drawArrow(painter,1,*c2( puOr.x ,pu.x ,puOr.y ,pu.y ))
558
+ painter.drawText(*cLeftText( puOr.x ,pu.x ,puOr.y ,pu.y ),'Y')
559
+
560
+ if flagDrawCircles:
561
+ pCir(pu.x,pu.y,r)
562
+ #asse x
563
+ ind=1
564
+ ii=self.calib.cal.indFromCoord(0,1,p)
565
+ if calVect.flag[p,ii]==1:
566
+ pu=Punto(calVect.X[p,ii], calVect.Y[p,ii])
567
+ pen.setColor(QtGui.QColor(mainInCircleColors[ind]))
568
+ painter.setPen(pen)
569
+
570
+ painter.drawText(*cLeftText( puOr.x ,pu.x ,puOr.y ,pu.y ),'X')
571
+ self.drawArrow(painter,1,*c2( puOr.x ,pu.x ,puOr.y ,pu.y ))
572
+ if flagDrawCircles:
573
+ pCir(pu.x,pu.y,r)
574
+ # origin shift
575
+ if (calVect.xOrShift[p] != 0 or calVect.yOrShift[p] != 0):#plot origin
576
+ ii=self.calib.cal.indFromCoord( int(calVect.yOrShift[p]), int(calVect.xOrShift[p]),p)
577
+ if calVect.flag[p,ii]==1:
578
+
579
+ pu=Punto(calVect.X[p,ii], calVect.Y[p,ii])
580
+ pen.setColor(QtGui.QColor(OriginCircleColor))
581
+ painter.setPen(pen)
582
+ r=2*rInpCircle
583
+ pCir(pu.x,pu.y,r)
584
+ r=rInpCircle
585
+ pCir(pu.x,pu.y,r)
586
+ def drawRectangleCC(self, p):
587
+ rect=QtCore.QRectF(*self.calib.cal.getPuTrovaCC(p))
588
+ if rect.height()!=0:
589
+ cir=Circle.fromPunto(Punto(0,0))
590
+ canvas = self.pixmap()
591
+ (painter,pen,pCir)=self.setCirclePainter(canvas,cir)
592
+ pen.setColor(QtGui.QColor(mainInCircleColors[2]))
593
+ painter.setPen(pen)
594
+ painter.drawRect(rect)
595
+ painter.end()
596
+ self.setPixmap(canvas)
597
+
598
+ ''' draw circles of the same type and color'''
599
+ def drawCircles(self, p,):
600
+ ''' draw circles of the same type and color and the axis with the main points'''
601
+ rect=QtCore.QRectF(*self.calib.cal.getPuTrovaCC(p))
602
+ if self.flagGetPoint:
603
+ for i in range(self.calib.flagRicerca):
604
+ #i=self.calib.flagRicerca-1
605
+ if self.calib.flagFoundPoints[i]:
606
+ pu=self.calib.foundPoints[i]
607
+ self.drawSingleCircleFromCalib(pu,0,i) # draws a circle on the detected points
608
+ self.drawSingleCircleFromCalib(pu,1,0) # draws a circle on the detected points
609
+
610
+ err=self.calib.tryFindPlane(p)# no exception only err in output
611
+ if err and rect.height()==0:
612
+ return # Cosa si deve fare? Forse va bene così in fondo non è stato possibile trovare il piano
613
+
614
+ calVect=self.calib.cal.vect
615
+ cir=Circle.fromPunto(Punto(0,0))
616
+ canvas = self.pixmap()
617
+ (painter,pen,pCir)=self.setCirclePainter(canvas,cir)
618
+
619
+ if not err:
620
+ r=cir.r#/self.scaleFactor
621
+ #try:
622
+ indOk=np.nonzero(calVect.flag[p]==1)[0]
623
+ for i in indOk:
624
+ pCir(calVect.X[p,i], calVect.Y[p,i],r)
625
+ if self.calib.cal.flagCalibrated:
626
+ data=self.calib.cal.data
627
+ for i in indOk:
628
+ x=float(calVect.Xc[p,i]-data.ColPart)
629
+ y=float(calVect.Yc[p,i]-data.RigaPart)
630
+ self.drawArrow(painter,lunFreccia,calVect.X[p,i], calVect.Y[p,i],x,y)
631
+ if p==data.kMax:
632
+ pen.setColor(QtGui.QColor(maxErrorCircleColor))
633
+ painter.setPen(pen)
634
+ r=rInpCircle
635
+ painter.drawRect(calVect.X[p,self.calib.cal.data.jMax]-r,calVect.Y[p,self.calib.cal.data.jMax]-r,2*r,2*r)
636
+ r*=2
637
+ painter.drawRoundedRect(calVect.X[p,self.calib.cal.data.jMax]-r,calVect.Y[p,self.calib.cal.data.jMax]-r,2*r,2*r,r,r)
638
+ self.drawAxis(p,painter,pen)
639
+
640
+ if rect.height()!=0:
641
+ pen.setColor(QtGui.QColor(mainInCircleColors[2]))
642
+ painter.setPen(pen)
643
+ painter.drawRect(rect)
644
+ #except: pri.Callback.white('u')
645
+ painter.end()
646
+ self.setPixmap(canvas)
647
+
648
+ def drawSingleCircle(self, cir):
649
+ ''' draws a single circle '''
650
+ #pri.Callback.white(cir)
651
+ canvas = self.pixmap()
652
+ (painter,_,pCir)=self.setCirclePainter(canvas,cir)
653
+ r=cir.r#/self.scaleFactor
654
+ pCir(cir.x, cir.y,r)
655
+ painter.end()
656
+ self.setPixmap(canvas)
657
+
658
+ def scaleToImg(self,point):
659
+ ''' from mouse position to image '''
660
+ #widgetPos = self.mapFrom(self, pos)# not needed any more since we are now plotting directly in the QLabel
661
+ #return Punto(widgetPos.x()/self.scaleFactor,widgetPos.y()/self.scaleFactor)
662
+ return point/self.scaleFactor
663
+ def scaleFromImg(self,point):
664
+ ''' from image to view '''
665
+ return point*self.scaleFactor
666
+ def scaleFromImgIterable(self,li):
667
+ ''' from image to view '''
668
+ return [d*self.scaleFactor for d in li]
669
+ if flagImageViewer:
670
+ def wheelEvent(self,event):
671
+ if event.angleDelta().y()/120>0:
672
+ self.plotPlane(self.calib.plane+1)
673
+ else:
674
+ self.plotPlane(self.calib.plane-1)
675
+
676
+
677
+
678
+
679
+ def spinImgChanged(self,plane):
680
+ ''' plot image of plane=plane'''
681
+ self.plotPlane(plane)
682
+
683
+ def spinOriginChanged(self,Off:int,spin:QSpinBox,flagX:bool,flagPlot=True):
684
+ ''' offset Origin '''
685
+ p=self.calib.plane
686
+ calVect=self.calib.cal.vect
687
+ ma=calVect.W[p] / 2 if flagX else calVect.H[p] / 2
688
+ if not -ma<Off<ma: # if inside
689
+ Off=int(-ma if Off < -ma else ma if Off > ma else Off)
690
+ spin.setValue(Off)
691
+ if flagX:
692
+ calVect.xOrShift[p]=Off
693
+ else:
694
+ calVect.yOrShift[p]=Off
695
+ if flagPlot: self.plotPlane(self.calib.plane)
696
+
697
+ def copyRemPoints(self):
698
+ p=self.calib.plane
699
+ calVect=self.calib.cal.vect
700
+
701
+ for pp in range(self.calib.nPlanes):
702
+ if pp is p :
703
+ continue
704
+ self.calib.cal.data.piano=pp
705
+
706
+ calVect.remPointsRi[pp]=calVect.remPointsRi[p]
707
+ calVect.remPointsLe[pp]=calVect.remPointsLe[p]
708
+ calVect.remPointsUp[pp]=calVect.remPointsUp[p]
709
+ calVect.remPointsDo[pp]=calVect.remPointsDo[p]
710
+ self.calib.cal.removeBulk()
711
+ self.calib.cal.data.piano=p
712
+ def spinRemPoints(self,Off:int,spin:QSpinBox,flagX:bool,flagPos:bool):
713
+ ''' Remove points '''
714
+ p=self.calib.plane
715
+ p=self.calib.cal.data.piano=p
716
+ calVect=self.calib.cal.vect
717
+ ma=calVect.W[p] / 2 if flagX else calVect.H[p] / 2
718
+ if not -ma<Off<ma: # if inside
719
+ Off=int(-ma if Off < -ma else ma if Off > ma else Off)
720
+ spin.setValue(Off)
721
+ if flagX:
722
+ if flagPos:
723
+ calVect.remPointsRi[p]=Off
724
+ else:
725
+ calVect.remPointsLe[p]=Off
726
+ else:
727
+ if flagPos:
728
+ calVect.remPointsUp[p]=Off
729
+ else:
730
+ calVect.remPointsDo[p]=Off
731
+ self.calib.cal.removeBulk()
732
+ if self.calib.cal.flagCalibrated:
733
+ self.calib.cal.checkCalibration() #needed because use the main thread and may exit with an exception
734
+ strPriCalib=self.calib.prettyPrintCalib()
735
+ strPriErrCalib=self.calib.prettyPrintErrCalib()
736
+ pri.Process.blue (strPriErrCalib)
737
+
738
+ self.calib.signals.textFromCalib.emit(strPriErrCalib+'\n'+strPriCalib)
739
+ self.plotPlane(self.calib.plane)
740
+
741
+ @Slot(int)
742
+ def replyFromView(self,ans:int):
743
+ ''' slot function called by the View when the answer is ready '''
744
+ #pri.Info.white(f'replyFromView {ans}')
745
+ self.calib.ans=ans
746
+ self.calib.flagAnsReady=True
747
+ @Slot(object)
748
+ def pointFromView(self,pu:Punto):
749
+ ''' slot function called by the View when the point is ready '''
750
+ #pri.Info.white(f'pointFromView {pu.x}')
751
+ self.calib.pu=pu
752
+ self.calib.flagPointReady=True
753
+
754
+ class SignalsCalibWorker(QObject):
755
+ drawSingleCircleFromCalib=Signal(object,int,int)
756
+ drawCirclesFromCalib=Signal(int)
757
+ flagGetPointFromCalib=Signal(int)
758
+ askFromCalib=Signal(str)
759
+ plotImgFromCalib=Signal(int,bool)
760
+ textFromCalib=Signal(str)
761
+ finished=Signal(bool)
762
+
763
+ class CalibWorker(QRunnable):
764
+ def __init__(self,):
765
+ #def __init__(self,mainFun:Callable,cal:Calib):
766
+
767
+ #def __init__(self,data:dataTreePar,indWorker:int,indProc:int,numUsedThreadsPIV:int,pfPool:ParForPool,parForMul:ParForMul,nameWorker:str,mainFun:Callable):
768
+ #super(MIN_ParFor_Worker,self).__init__(data,indWorker,indProc,pfPool=ParForPool,parForMul=ParForMul)
769
+ super(CalibWorker,self).__init__()
770
+ self.signals=SignalsCalibWorker()
771
+ self.isKilled = False
772
+ self.isStoreCompleted = False
773
+ self.calib:Calib=None
774
+ self.mainFun:Callable=None
775
+
776
+ def setTask(self,calib:Calib,flag:CalibTasks):
777
+ ''' set calib and chooses the task'''
778
+ self.calib=calib
779
+ self.calib.signals=self.signals
780
+ if flag is CalibTasks.findAllPlanes:
781
+ self.mainFun=self.calib.taskFindAllPlanes
782
+ elif flag is CalibTasks.findCurrentPlane:
783
+ self.mainFun=self.calib.taskFindCurrentPlane
784
+ elif flag is CalibTasks.calibrate:
785
+ self.mainFun=self.calib.taskCalibrate
786
+ elif flag is CalibTasks.findPlanesFromOrigin:
787
+ self.mainFun=self.calib.taskFindAllPlanesFromOrigin
788
+ elif flag is CalibTasks.savePoints:
789
+ self.mainFun=self.calib.taskSavePoints
790
+ pri.Callback.blue(f'setCal-> {self.mainFun.__func__.__name__} flag={flag}')
791
+ self.signals.textFromCalib.emit(f'')
792
+
793
+ @Slot()
794
+ def run(self):
795
+ ''' main running function'''
796
+ if Flag_DEBUG_PARPOOL:
797
+ try:
798
+ debugpy.debug_this_thread()
799
+ except Exception as inst:
800
+ pri.Error.red(f'Error with debugpy (CalibWorker):\n{inst}')
801
+ try:
802
+ #pr(f'ParForWorker.run self.isKilled={self.isKilled} self.indWorker={self.indWorker} self.indProc={self.indProc} ')
803
+ #self.parForMul.numUsedCores=self.numUsedThreadsPIV
804
+ '''
805
+ while self.indWorker!=self.indProc:# and not self.isKilled:
806
+ timesleep(SleepTime_Workers)
807
+ if self.isKilled:
808
+ self.signals.completed.emit()
809
+ return # in this case we are killing all the threads
810
+ pri.Process.blue(f'ParForWorker.run starting {self.nameWorker} self.isKilled={self.isKilled} self.indWorker={self.indWorker} self.indProc={self.indProc} ')
811
+ '''
812
+ flagErr=False
813
+ self.mainFun()
814
+
815
+
816
+ except ValueError as exc:
817
+ if exc.args[1]!=TYPE_ERR_STOP:
818
+ #traceback.print_exc()
819
+ pri.Info.white(f"run ->Unexpected {exc=}, {type(exc)=}")
820
+ self.signals.textFromCalib.emit(f'Calibration error:\n{exc}')
821
+ flagErr=True
822
+ except Exception as exc:
823
+ #traceback.print_exc()
824
+ pri.Info.white(f"run ->Unexpected {exc=}, {type(exc)=}")
825
+ self.signals.textFromCalib.emit(f'Calibration error:\n{exc}')
826
+ flagErr=True
827
+ #else: pass
828
+ #pri.Info.white("Normal termination of Worker")
829
+ finally:
830
+ self.signals.finished.emit(flagErr)
831
+ pri.Process.blue(f'End of Worker->{self.mainFun.__func__.__name__}() ')
832
+
833
+