PaIRS-UniNa 0.2.9__cp310-cp310-macosx_11_0_universal2.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (333) hide show
  1. PaIRS_UniNa/Calibration_Tab.py +346 -0
  2. PaIRS_UniNa/Changes.txt +162 -0
  3. PaIRS_UniNa/Custom_Top.py +303 -0
  4. PaIRS_UniNa/Explorer.py +3168 -0
  5. PaIRS_UniNa/FolderLoop.py +562 -0
  6. PaIRS_UniNa/Input_Tab.py +831 -0
  7. PaIRS_UniNa/Input_Tab_CalVi.py +786 -0
  8. PaIRS_UniNa/Input_Tab_tools.py +3022 -0
  9. PaIRS_UniNa/Log_Tab.py +110 -0
  10. PaIRS_UniNa/Output_Tab.py +922 -0
  11. PaIRS_UniNa/PaIRS.py +18 -0
  12. PaIRS_UniNa/PaIRS_PIV.py +873 -0
  13. PaIRS_UniNa/PaIRS_pypacks.py +1421 -0
  14. PaIRS_UniNa/Process_Tab.py +1757 -0
  15. PaIRS_UniNa/Process_Tab_CalVi.py +313 -0
  16. PaIRS_UniNa/Process_Tab_Disp.py +163 -0
  17. PaIRS_UniNa/Process_Tab_Min.py +120 -0
  18. PaIRS_UniNa/ResizePopup.py +55 -0
  19. PaIRS_UniNa/SPIVCalHelp.py +155 -0
  20. PaIRS_UniNa/Saving_tools.py +296 -0
  21. PaIRS_UniNa/TabTools.py +1254 -0
  22. PaIRS_UniNa/Vis_Tab.py +2169 -0
  23. PaIRS_UniNa/Vis_Tab_CalVi.py +983 -0
  24. PaIRS_UniNa/Whatsnew.py +130 -0
  25. PaIRS_UniNa/_PaIRS_PIV.so +0 -0
  26. PaIRS_UniNa/__init__.py +6 -0
  27. PaIRS_UniNa/__main__.py +45 -0
  28. PaIRS_UniNa/addwidgets_ps.py +1133 -0
  29. PaIRS_UniNa/calib.py +1488 -0
  30. PaIRS_UniNa/calibView.py +833 -0
  31. PaIRS_UniNa/gPaIRS.py +3914 -0
  32. PaIRS_UniNa/gPalette.py +189 -0
  33. PaIRS_UniNa/icons/abort.png +0 -0
  34. PaIRS_UniNa/icons/about.png +0 -0
  35. PaIRS_UniNa/icons/align_all.png +0 -0
  36. PaIRS_UniNa/icons/announcement.png +0 -0
  37. PaIRS_UniNa/icons/automatic_levels_off.png +0 -0
  38. PaIRS_UniNa/icons/automatic_levels_on.png +0 -0
  39. PaIRS_UniNa/icons/automatic_off.png +0 -0
  40. PaIRS_UniNa/icons/automatic_on.png +0 -0
  41. PaIRS_UniNa/icons/automatic_size_off.png +0 -0
  42. PaIRS_UniNa/icons/automatic_size_on.png +0 -0
  43. PaIRS_UniNa/icons/axes.png +0 -0
  44. PaIRS_UniNa/icons/background.png +0 -0
  45. PaIRS_UniNa/icons/background_vectors.png +0 -0
  46. PaIRS_UniNa/icons/bin_off.png +0 -0
  47. PaIRS_UniNa/icons/bin_on.png +0 -0
  48. PaIRS_UniNa/icons/browse_file_c.png +0 -0
  49. PaIRS_UniNa/icons/browse_folder_c.png +0 -0
  50. PaIRS_UniNa/icons/brush_cursor.png +0 -0
  51. PaIRS_UniNa/icons/bugfix.png +0 -0
  52. PaIRS_UniNa/icons/cal_proc.png +0 -0
  53. PaIRS_UniNa/icons/cal_proc_off.png +0 -0
  54. PaIRS_UniNa/icons/cal_step.png +0 -0
  55. PaIRS_UniNa/icons/cal_step_off.png +0 -0
  56. PaIRS_UniNa/icons/calibrate.png +0 -0
  57. PaIRS_UniNa/icons/calibration_logo.png +0 -0
  58. PaIRS_UniNa/icons/change_folder.png +0 -0
  59. PaIRS_UniNa/icons/change_folder_off.png +0 -0
  60. PaIRS_UniNa/icons/checklist.png +0 -0
  61. PaIRS_UniNa/icons/clean.png +0 -0
  62. PaIRS_UniNa/icons/clean_run.png +0 -0
  63. PaIRS_UniNa/icons/close.png +0 -0
  64. PaIRS_UniNa/icons/close_all.png +0 -0
  65. PaIRS_UniNa/icons/close_project.png +0 -0
  66. PaIRS_UniNa/icons/close_workspace.png +0 -0
  67. PaIRS_UniNa/icons/colormap.png +0 -0
  68. PaIRS_UniNa/icons/colormaps/Accent.png +0 -0
  69. PaIRS_UniNa/icons/colormaps/BrBG.png +0 -0
  70. PaIRS_UniNa/icons/colormaps/Dark2.png +0 -0
  71. PaIRS_UniNa/icons/colormaps/PRGn.png +0 -0
  72. PaIRS_UniNa/icons/colormaps/Paired.png +0 -0
  73. PaIRS_UniNa/icons/colormaps/Pastel1.png +0 -0
  74. PaIRS_UniNa/icons/colormaps/Pastel2.png +0 -0
  75. PaIRS_UniNa/icons/colormaps/PiYG.png +0 -0
  76. PaIRS_UniNa/icons/colormaps/PuOr.png +0 -0
  77. PaIRS_UniNa/icons/colormaps/RdBu.png +0 -0
  78. PaIRS_UniNa/icons/colormaps/RdGy.png +0 -0
  79. PaIRS_UniNa/icons/colormaps/RdYlBu.png +0 -0
  80. PaIRS_UniNa/icons/colormaps/RdYlGn.png +0 -0
  81. PaIRS_UniNa/icons/colormaps/Set1.png +0 -0
  82. PaIRS_UniNa/icons/colormaps/Set2.png +0 -0
  83. PaIRS_UniNa/icons/colormaps/Set3.png +0 -0
  84. PaIRS_UniNa/icons/colormaps/Spectral.png +0 -0
  85. PaIRS_UniNa/icons/colormaps/Wistia.png +0 -0
  86. PaIRS_UniNa/icons/colormaps/afmhot.png +0 -0
  87. PaIRS_UniNa/icons/colormaps/autumn.png +0 -0
  88. PaIRS_UniNa/icons/colormaps/binary.png +0 -0
  89. PaIRS_UniNa/icons/colormaps/blackVector.png +0 -0
  90. PaIRS_UniNa/icons/colormaps/blueVector.png +0 -0
  91. PaIRS_UniNa/icons/colormaps/bone.png +0 -0
  92. PaIRS_UniNa/icons/colormaps/brg.png +0 -0
  93. PaIRS_UniNa/icons/colormaps/bwr.png +0 -0
  94. PaIRS_UniNa/icons/colormaps/cividis.png +0 -0
  95. PaIRS_UniNa/icons/colormaps/cool.png +0 -0
  96. PaIRS_UniNa/icons/colormaps/coolwarm.png +0 -0
  97. PaIRS_UniNa/icons/colormaps/copper.png +0 -0
  98. PaIRS_UniNa/icons/colormaps/cubehelix.png +0 -0
  99. PaIRS_UniNa/icons/colormaps/cyanVector.png +0 -0
  100. PaIRS_UniNa/icons/colormaps/flag.png +0 -0
  101. PaIRS_UniNa/icons/colormaps/gist_heat.png +0 -0
  102. PaIRS_UniNa/icons/colormaps/gray.png +0 -0
  103. PaIRS_UniNa/icons/colormaps/greenVector.png +0 -0
  104. PaIRS_UniNa/icons/colormaps/hot.png +0 -0
  105. PaIRS_UniNa/icons/colormaps/hsv.png +0 -0
  106. PaIRS_UniNa/icons/colormaps/inferno.png +0 -0
  107. PaIRS_UniNa/icons/colormaps/jet.png +0 -0
  108. PaIRS_UniNa/icons/colormaps/magentaVector.png +0 -0
  109. PaIRS_UniNa/icons/colormaps/magma.png +0 -0
  110. PaIRS_UniNa/icons/colormaps/ocean.png +0 -0
  111. PaIRS_UniNa/icons/colormaps/pink.png +0 -0
  112. PaIRS_UniNa/icons/colormaps/plasma.png +0 -0
  113. PaIRS_UniNa/icons/colormaps/prism.png +0 -0
  114. PaIRS_UniNa/icons/colormaps/rainbow.png +0 -0
  115. PaIRS_UniNa/icons/colormaps/redVector.png +0 -0
  116. PaIRS_UniNa/icons/colormaps/seismic.png +0 -0
  117. PaIRS_UniNa/icons/colormaps/spring.png +0 -0
  118. PaIRS_UniNa/icons/colormaps/summer.png +0 -0
  119. PaIRS_UniNa/icons/colormaps/tab10.png +0 -0
  120. PaIRS_UniNa/icons/colormaps/tab20.png +0 -0
  121. PaIRS_UniNa/icons/colormaps/tab20b.png +0 -0
  122. PaIRS_UniNa/icons/colormaps/tab20c.png +0 -0
  123. PaIRS_UniNa/icons/colormaps/terrain.png +0 -0
  124. PaIRS_UniNa/icons/colormaps/twilight.png +0 -0
  125. PaIRS_UniNa/icons/colormaps/viridis.png +0 -0
  126. PaIRS_UniNa/icons/colormaps/whiteVector.png +0 -0
  127. PaIRS_UniNa/icons/colormaps/winter.png +0 -0
  128. PaIRS_UniNa/icons/colormaps/yellowVector.png +0 -0
  129. PaIRS_UniNa/icons/common_region.png +0 -0
  130. PaIRS_UniNa/icons/common_region_off.png +0 -0
  131. PaIRS_UniNa/icons/completed.png +0 -0
  132. PaIRS_UniNa/icons/contourf_off.png +0 -0
  133. PaIRS_UniNa/icons/contourf_on.png +0 -0
  134. PaIRS_UniNa/icons/copy.png +0 -0
  135. PaIRS_UniNa/icons/copy_process.png +0 -0
  136. PaIRS_UniNa/icons/copy_process_off.png +0 -0
  137. PaIRS_UniNa/icons/copygrid.png +0 -0
  138. PaIRS_UniNa/icons/cursor_lamp.png +0 -0
  139. PaIRS_UniNa/icons/cut.png +0 -0
  140. PaIRS_UniNa/icons/cut_warnings.png +0 -0
  141. PaIRS_UniNa/icons/darkmode.png +0 -0
  142. PaIRS_UniNa/icons/debug_run.png +0 -0
  143. PaIRS_UniNa/icons/delete.png +0 -0
  144. PaIRS_UniNa/icons/deleteErr.png +0 -0
  145. PaIRS_UniNa/icons/disp_step.png +0 -0
  146. PaIRS_UniNa/icons/disp_step_off.png +0 -0
  147. PaIRS_UniNa/icons/down.png +0 -0
  148. PaIRS_UniNa/icons/edit_list.png +0 -0
  149. PaIRS_UniNa/icons/editing.png +0 -0
  150. PaIRS_UniNa/icons/example_list.png +0 -0
  151. PaIRS_UniNa/icons/find_all_planes.png +0 -0
  152. PaIRS_UniNa/icons/find_plane.png +0 -0
  153. PaIRS_UniNa/icons/flaticon_PaIRS.png +0 -0
  154. PaIRS_UniNa/icons/flaticon_PaIRS_beta.png +0 -0
  155. PaIRS_UniNa/icons/flaticon_PaIRS_download.png +0 -0
  156. PaIRS_UniNa/icons/flaticon_PaIRS_download_warning.png +0 -0
  157. PaIRS_UniNa/icons/flip_y_off.png +0 -0
  158. PaIRS_UniNa/icons/flip_y_on.png +0 -0
  159. PaIRS_UniNa/icons/focusErrr.png +0 -0
  160. PaIRS_UniNa/icons/folder_loop_cleanup.png +0 -0
  161. PaIRS_UniNa/icons/folder_loop_cleanup_off.png +0 -0
  162. PaIRS_UniNa/icons/gear.gif +0 -0
  163. PaIRS_UniNa/icons/gear.png +0 -0
  164. PaIRS_UniNa/icons/ger.png +0 -0
  165. PaIRS_UniNa/icons/greenv.png +0 -0
  166. PaIRS_UniNa/icons/guide.png +0 -0
  167. PaIRS_UniNa/icons/icon_CalVi.png +0 -0
  168. PaIRS_UniNa/icons/icon_PaIRS.png +0 -0
  169. PaIRS_UniNa/icons/import.png +0 -0
  170. PaIRS_UniNa/icons/import_set.png +0 -0
  171. PaIRS_UniNa/icons/information.png +0 -0
  172. PaIRS_UniNa/icons/information2.png +0 -0
  173. PaIRS_UniNa/icons/input_logo.png +0 -0
  174. PaIRS_UniNa/icons/issue.png +0 -0
  175. PaIRS_UniNa/icons/laser_NTR.png +0 -0
  176. PaIRS_UniNa/icons/laser_TR_double.png +0 -0
  177. PaIRS_UniNa/icons/laser_TR_single.png +0 -0
  178. PaIRS_UniNa/icons/link.png +0 -0
  179. PaIRS_UniNa/icons/linked.png +0 -0
  180. PaIRS_UniNa/icons/loaded.png +0 -0
  181. PaIRS_UniNa/icons/loading_2.gif +0 -0
  182. PaIRS_UniNa/icons/log_logo.png +0 -0
  183. PaIRS_UniNa/icons/logo_CalVi.png +0 -0
  184. PaIRS_UniNa/icons/logo_CalVi_completo.png +0 -0
  185. PaIRS_UniNa/icons/logo_CalVi_party.png +0 -0
  186. PaIRS_UniNa/icons/logo_PaIRS.png +0 -0
  187. PaIRS_UniNa/icons/logo_PaIRS_completo.png +0 -0
  188. PaIRS_UniNa/icons/logo_PaIRS_download.png +0 -0
  189. PaIRS_UniNa/icons/logo_PaIRS_party_rect.png +0 -0
  190. PaIRS_UniNa/icons/logo_PaIRS_rect.png +0 -0
  191. PaIRS_UniNa/icons/logo_opaco.png +0 -0
  192. PaIRS_UniNa/icons/mask.png +0 -0
  193. PaIRS_UniNa/icons/measure.png +0 -0
  194. PaIRS_UniNa/icons/measure_off.png +0 -0
  195. PaIRS_UniNa/icons/min_proc.png +0 -0
  196. PaIRS_UniNa/icons/min_proc_off.png +0 -0
  197. PaIRS_UniNa/icons/min_step.png +0 -0
  198. PaIRS_UniNa/icons/min_step_off.png +0 -0
  199. PaIRS_UniNa/icons/minus.png +0 -0
  200. PaIRS_UniNa/icons/mirror_u.png +0 -0
  201. PaIRS_UniNa/icons/mirror_v.png +0 -0
  202. PaIRS_UniNa/icons/mirror_x.png +0 -0
  203. PaIRS_UniNa/icons/mirror_y.png +0 -0
  204. PaIRS_UniNa/icons/mtplt.png +0 -0
  205. PaIRS_UniNa/icons/new.png +0 -0
  206. PaIRS_UniNa/icons/new_workspace.png +0 -0
  207. PaIRS_UniNa/icons/news.png +0 -0
  208. PaIRS_UniNa/icons/normal_run.png +0 -0
  209. PaIRS_UniNa/icons/open.png +0 -0
  210. PaIRS_UniNa/icons/open_image.png +0 -0
  211. PaIRS_UniNa/icons/open_new_window.png +0 -0
  212. PaIRS_UniNa/icons/open_result.png +0 -0
  213. PaIRS_UniNa/icons/open_workspace.png +0 -0
  214. PaIRS_UniNa/icons/output_logo.png +0 -0
  215. PaIRS_UniNa/icons/paste_above.png +0 -0
  216. PaIRS_UniNa/icons/paste_below.png +0 -0
  217. PaIRS_UniNa/icons/pause.png +0 -0
  218. PaIRS_UniNa/icons/paused.png +0 -0
  219. PaIRS_UniNa/icons/pencil_bw.png +0 -0
  220. PaIRS_UniNa/icons/piv_proc.png +0 -0
  221. PaIRS_UniNa/icons/piv_proc_off.png +0 -0
  222. PaIRS_UniNa/icons/piv_step.png +0 -0
  223. PaIRS_UniNa/icons/piv_step_off.png +0 -0
  224. PaIRS_UniNa/icons/plane.png +0 -0
  225. PaIRS_UniNa/icons/play.png +0 -0
  226. PaIRS_UniNa/icons/plus.png +0 -0
  227. PaIRS_UniNa/icons/process_logo.png +0 -0
  228. PaIRS_UniNa/icons/process_loop.png +0 -0
  229. PaIRS_UniNa/icons/project.png +0 -0
  230. PaIRS_UniNa/icons/pylog.png +0 -0
  231. PaIRS_UniNa/icons/python_warning.png +0 -0
  232. PaIRS_UniNa/icons/queue.png +0 -0
  233. PaIRS_UniNa/icons/quit.png +0 -0
  234. PaIRS_UniNa/icons/read.png +0 -0
  235. PaIRS_UniNa/icons/read_list.png +0 -0
  236. PaIRS_UniNa/icons/redo.png +0 -0
  237. PaIRS_UniNa/icons/redx.png +0 -0
  238. PaIRS_UniNa/icons/reset.png +0 -0
  239. PaIRS_UniNa/icons/reset_levels.png +0 -0
  240. PaIRS_UniNa/icons/resize_icon.png +0 -0
  241. PaIRS_UniNa/icons/restore.png +0 -0
  242. PaIRS_UniNa/icons/restore_undo.png +0 -0
  243. PaIRS_UniNa/icons/rotate_clock.png +0 -0
  244. PaIRS_UniNa/icons/rotate_counter.png +0 -0
  245. PaIRS_UniNa/icons/rotate_v_clock.png +0 -0
  246. PaIRS_UniNa/icons/rotate_v_counter.png +0 -0
  247. PaIRS_UniNa/icons/running.gif +0 -0
  248. PaIRS_UniNa/icons/running.png +0 -0
  249. PaIRS_UniNa/icons/running_warn.png +0 -0
  250. PaIRS_UniNa/icons/sandglass.png +0 -0
  251. PaIRS_UniNa/icons/save.png +0 -0
  252. PaIRS_UniNa/icons/save_and_stop.png +0 -0
  253. PaIRS_UniNa/icons/save_cfg.png +0 -0
  254. PaIRS_UniNa/icons/saveas.png +0 -0
  255. PaIRS_UniNa/icons/saveas_workspace.png +0 -0
  256. PaIRS_UniNa/icons/scale_all.png +0 -0
  257. PaIRS_UniNa/icons/scale_down.png +0 -0
  258. PaIRS_UniNa/icons/scale_up.png +0 -0
  259. PaIRS_UniNa/icons/scan_list.png +0 -0
  260. PaIRS_UniNa/icons/scan_path.png +0 -0
  261. PaIRS_UniNa/icons/scan_path_loop.png +0 -0
  262. PaIRS_UniNa/icons/scan_path_loop_off.png +0 -0
  263. PaIRS_UniNa/icons/search.png +0 -0
  264. PaIRS_UniNa/icons/showIW_off.png +0 -0
  265. PaIRS_UniNa/icons/showIW_on.png +0 -0
  266. PaIRS_UniNa/icons/show_all.png +0 -0
  267. PaIRS_UniNa/icons/sort.png +0 -0
  268. PaIRS_UniNa/icons/sort_reversed.png +0 -0
  269. PaIRS_UniNa/icons/spiv_proc.png +0 -0
  270. PaIRS_UniNa/icons/spiv_proc_off.png +0 -0
  271. PaIRS_UniNa/icons/spiv_setup_no.png +0 -0
  272. PaIRS_UniNa/icons/spiv_setup_ok.png +0 -0
  273. PaIRS_UniNa/icons/star.png +0 -0
  274. PaIRS_UniNa/icons/step_inheritance.png +0 -0
  275. PaIRS_UniNa/icons/subMIN_off.png +0 -0
  276. PaIRS_UniNa/icons/subMIN_on.png +0 -0
  277. PaIRS_UniNa/icons/tom.png +0 -0
  278. PaIRS_UniNa/icons/trash.png +0 -0
  279. PaIRS_UniNa/icons/undo.png +0 -0
  280. PaIRS_UniNa/icons/unedited.png +0 -0
  281. PaIRS_UniNa/icons/unina_dii.png +0 -0
  282. PaIRS_UniNa/icons/uninitialized.png +0 -0
  283. PaIRS_UniNa/icons/unlink.png +0 -0
  284. PaIRS_UniNa/icons/unwrap_items.png +0 -0
  285. PaIRS_UniNa/icons/up.png +0 -0
  286. PaIRS_UniNa/icons/updating_import.gif +0 -0
  287. PaIRS_UniNa/icons/updating_pairs.gif +0 -0
  288. PaIRS_UniNa/icons/vectorColor.png +0 -0
  289. PaIRS_UniNa/icons/vettore.png +0 -0
  290. PaIRS_UniNa/icons/view.png +0 -0
  291. PaIRS_UniNa/icons/view_off.png +0 -0
  292. PaIRS_UniNa/icons/vis_logo.png +0 -0
  293. PaIRS_UniNa/icons/waiting_circle.png +0 -0
  294. PaIRS_UniNa/icons/warning.png +0 -0
  295. PaIRS_UniNa/icons/warning_circle.png +0 -0
  296. PaIRS_UniNa/icons/window.png +0 -0
  297. PaIRS_UniNa/icons/workspace.png +0 -0
  298. PaIRS_UniNa/icons/wrap_items.png +0 -0
  299. PaIRS_UniNa/icons/write_list.png +0 -0
  300. PaIRS_UniNa/listLib.py +303 -0
  301. PaIRS_UniNa/mtfPIV.py +256 -0
  302. PaIRS_UniNa/parForMulti.py +435 -0
  303. PaIRS_UniNa/parForWorkers.py +593 -0
  304. PaIRS_UniNa/pivParFor.py +235 -0
  305. PaIRS_UniNa/plt_util.py +141 -0
  306. PaIRS_UniNa/preProcParFor.py +155 -0
  307. PaIRS_UniNa/procTools.py +1439 -0
  308. PaIRS_UniNa/readcfg.py +52 -0
  309. PaIRS_UniNa/rqrdpckgs.txt +9 -0
  310. PaIRS_UniNa/stereoPivParFor.py +227 -0
  311. PaIRS_UniNa/tAVarie.py +215 -0
  312. PaIRS_UniNa/tabSplitter.py +612 -0
  313. PaIRS_UniNa/ui_Calibration_Tab.py +578 -0
  314. PaIRS_UniNa/ui_Custom_Top.py +296 -0
  315. PaIRS_UniNa/ui_Input_Tab.py +1101 -0
  316. PaIRS_UniNa/ui_Input_Tab_CalVi.py +1283 -0
  317. PaIRS_UniNa/ui_Log_Tab.py +263 -0
  318. PaIRS_UniNa/ui_Output_Tab.py +2362 -0
  319. PaIRS_UniNa/ui_Process_Tab.py +3810 -0
  320. PaIRS_UniNa/ui_Process_Tab_CalVi.py +1549 -0
  321. PaIRS_UniNa/ui_Process_Tab_Disp.py +1141 -0
  322. PaIRS_UniNa/ui_Process_Tab_Min.py +437 -0
  323. PaIRS_UniNa/ui_ResizePopup.py +204 -0
  324. PaIRS_UniNa/ui_Vis_Tab.py +1628 -0
  325. PaIRS_UniNa/ui_Vis_Tab_CalVi.py +1251 -0
  326. PaIRS_UniNa/ui_Whatsnew.py +132 -0
  327. PaIRS_UniNa/ui_gPairs.py +877 -0
  328. PaIRS_UniNa/ui_infoPaIRS.py +551 -0
  329. PaIRS_UniNa/whatsnew.txt +6 -0
  330. pairs_unina-0.2.9.dist-info/METADATA +166 -0
  331. pairs_unina-0.2.9.dist-info/RECORD +333 -0
  332. pairs_unina-0.2.9.dist-info/WHEEL +5 -0
  333. pairs_unina-0.2.9.dist-info/top_level.txt +2 -0
PaIRS_UniNa/gPaIRS.py ADDED
@@ -0,0 +1,3914 @@
1
+
2
+ from .ui_gPairs import *
3
+ from .ui_infoPaIRS import *
4
+ from .parForWorkers import *
5
+
6
+ from .TabTools import *
7
+ from .procTools import *
8
+ from .Explorer import *
9
+ from .Input_Tab import *
10
+ from .Output_Tab import *
11
+ from .Process_Tab import *
12
+ from .Log_Tab import *
13
+ from .Vis_Tab import *
14
+ from .Process_Tab_Min import *
15
+ from .Process_Tab_Disp import *
16
+ from .Calibration_Tab import *
17
+ from .Input_Tab_CalVi import *
18
+ from .Process_Tab_CalVi import *
19
+ from .Vis_Tab_CalVi import *
20
+ from .tabSplitter import *
21
+
22
+ from .ResizePopup import*
23
+ from .Whatsnew import*
24
+
25
+ from .gPalette import *
26
+
27
+ from .Saving_tools import*
28
+
29
+ import concurrent.futures
30
+
31
+ from .__init__ import __version__,__subversion__,__year__,__date__,__mail__,__website__
32
+
33
+ version=__version__
34
+ subversion=__subversion__
35
+ year=__year__
36
+ mail=__mail__
37
+ website=__website__
38
+ uicfg_version='0.2.0'
39
+ uicfg_version_to_load=uicfg_version
40
+ #uicfg_version_to_load='0.1.5'
41
+ Flag_fullDEBUG=False
42
+ FlagPrevPropagationTabSplitter=True
43
+
44
+ #********************************************* Additional windows (LEGACY)
45
+ class FloatingObject(QMainWindow):
46
+ def closeEvent(self, event):
47
+ self.hide()
48
+
49
+ def __init__(self,parent,tab):
50
+ super().__init__()
51
+ if parent is None:
52
+ self.gui=self.window()
53
+ else:
54
+ if hasattr(parent,'gui'):
55
+ self.gui:gPaIRS=parent.gui
56
+ else:
57
+ self.gui:gPaIRS=parent.window()
58
+
59
+ self.name=''
60
+ self.button=None
61
+ self.tab=tab
62
+ self.setup()
63
+
64
+ def setup(self):
65
+ tab=self.tab
66
+ if type(tab)==CollapsibleBox:
67
+ self.setWindowTitle(tab.toggle_button.text())
68
+ self.setWindowIcon(self.gui.windowIcon())
69
+ elif isinstance(tab,Calibration_Tab) or any([isinstance(tab,t) for t in self.gui.tabTypes[1:]]):
70
+ self.name=tab.ui.name_tab.text().replace(' ','')
71
+ self.setWindowTitle(tab.ui.name_tab.text())
72
+ self.setWindowIcon(tab.ui.icon.pixmap())
73
+ else:
74
+ self.setWindowTitle(self.gui.windowTitle())
75
+ self.setWindowIcon(self.gui.windowIcon())
76
+ if type(tab.parent()) in (QSplitter,QLayout,myQSplitter):
77
+ self.lay:QLayout=tab.parent()
78
+ else:
79
+ self.lay:QLayout=tab.parent().layout()
80
+ self.pa=tab
81
+ self.index=self.lay.indexOf(tab)
82
+ #self.setCentralWidget(tab)
83
+
84
+ self.setBaseSize(tab.baseSize())
85
+ self.setAutoFillBackground(False)
86
+ self.setMinimumSize(tab.minimumSize())
87
+ self.setMaximumSize(tab.maximumSize())
88
+
89
+ #if self.name:
90
+ # self.button=getattr(self.gui.ui,'button_'+self.name)
91
+
92
+ def setFloat(self):
93
+ self.setCentralWidget(self.pa)
94
+ self.centralWidget().setMinimumSize(self.pa.minimumSize())
95
+ self.centralWidget().setMaximumSize(self.pa.maximumSize())
96
+
97
+ class FloatingWidget(FloatingObject):
98
+ def closeEvent(self, event):
99
+ index=min([self.index,self.lay.count()-1])
100
+ self.lay.insertWidget(index,self.pa)
101
+ self.close()
102
+ i=self.gui.FloatingWindows.index(self)
103
+ self.gui.FloatingWindows.pop(i)
104
+ #self.gui.undockTabs()
105
+
106
+ def __init__(self,parent,tab):
107
+ super().__init__(parent,tab)
108
+
109
+ geo=self.pa.geometry()
110
+ geoP=self.gui.geometry()
111
+ x=geoP.x()+int(geoP.width()*0.5)-int(geo.width()*0.5)
112
+ y=geoP.y()+int(geoP.height()*0.5)-int(geo.height()*0.5)
113
+ self.setGeometry(x,y,geo.width(),geo.height())
114
+ self.setFloat()
115
+ self.show()
116
+
117
+ class infoPaIRS(QMainWindow):
118
+ def __init__(self,gui):
119
+ super().__init__()
120
+ ui=Ui_InfoPaiRS()
121
+ ui.setupUi(self)
122
+ self.ui=ui
123
+ setupWid(self)
124
+
125
+ subv=f"(.{subversion})" if int(subversion) else ""
126
+ infotext=self.ui.info.text().replace('#.#.#',version+subv)
127
+ infotext=infotext.replace('yyyy',year)
128
+ infotext=infotext.replace('dddd/dd/dd',__date__)
129
+ mailString=f'<a href="mailto:{mail}"><span style=" text-decoration: underline; color:#0000ff; font-size:11pt">{mail}</a>'
130
+ infotext=infotext.replace('mmmm',mailString)
131
+ websiteString=f'<a href="{website}"><span style=" text-decoration: underline; color:#0000ff; font-size:11pt">{website}</a>'
132
+ infotext=infotext.replace('wwww',websiteString)
133
+ self.ui.info.setText(infotext)
134
+ if Flag_ISEXE:
135
+ #self.ui.tabWidget.removeTab(3)
136
+ self.ui.tabWidget.setTabText(3,'Packages')
137
+ self.ui.req.setText(self.distPackages())
138
+ else:
139
+ self.ui.tabWidget.setTabText(3,'Requirements')
140
+ self.ui.req.setText(self.requirements())
141
+
142
+ self.fontPixelSize=gui.GPApar.fontPixelSize
143
+ self.setFontSizeText()
144
+
145
+ self.gui=gui
146
+ for w in self.findChildren(QObject):
147
+ if hasattr(w,'keyPressEvent'):
148
+ def createKeyPressFun(w):
149
+ def KeyPressFun(e):
150
+ if w.hasFocus():
151
+ #pri.Info.yellow(w)
152
+ type(w).keyPressEvent(w,e)
153
+ #if not e.key() in self.gui.blockedKeys:
154
+ # self.gui.keyPressEvent(e)
155
+ return KeyPressFun
156
+ w.keyPressEvent=createKeyPressFun(w)
157
+
158
+ def setFontSizeText(self):
159
+ fPixSize=self.fontPixelSize
160
+ setFontPixelSize(self,fPixSize)
161
+ setFontSizeText(self.ui.info,[fPixSize+6,fPixSize*2])
162
+ setFontSizeText(self.ui.info_uni,[fPixSize+4])
163
+ setFontSizeText(self.ui.ger_cv,[fPixSize+1])
164
+ setFontSizeText(self.ui.tom_cv,[fPixSize+1])
165
+ setFontSizeText(self.ui.list_ref,[fPixSize+1])
166
+
167
+ def distPackages(self):
168
+ # Read the contents of the file and split by lines
169
+ with open(rqrdpckgs_filename, 'r') as file:
170
+ lines = file.readlines()
171
+
172
+ # Introductory sentence
173
+ intro_text = """
174
+ <p style="font-size: 12pt; font-weight: normal; text-align: justify;">
175
+ Python packages included in the current executable:
176
+ </p>
177
+ <p>
178
+
179
+ </p>
180
+ """
181
+
182
+ # Start the HTML table with improved styling
183
+ html_table = intro_text + """
184
+ <table border="1" style="width: 100%; align-items: center;">
185
+ <thead>
186
+ <tr>
187
+ <th style="padding: 10px; font-size: 11pt; font-weight: bold;">Package</th>
188
+ <th style="padding: 10px; font-size: 11pt; font-weight: bold;">Version</th>
189
+ </tr>
190
+ </thead>
191
+ <tbody>
192
+ """
193
+
194
+ # Iterate over each line in the file
195
+ for line in lines:
196
+ # Split each line into package name, min vers11pt max version, and other info
197
+ package_info = line.strip().split()
198
+
199
+ # Ensure the line has the expected format
200
+ if len(package_info) >= 3:
201
+ package_name = package_info[0]
202
+ if package_name[0]=='#': continue
203
+ max_version = package_info[2]
204
+
205
+ # Append a row to the HTML table
206
+ html_table += f"""
207
+ <tr>
208
+ <td style="padding: 10px; font-size: 11pt">{package_name}</td>
209
+ <td style="padding: 10px; font-size: 11pt">{max_version}</td>
210
+ </tr>
211
+ """
212
+
213
+ # Close the table tags
214
+ html_table += """
215
+ </tbody>
216
+ </table>
217
+ """
218
+ return html_table
219
+
220
+ def requirements(self):
221
+ # Read the contents of the file and split by lines
222
+ with open(rqrdpckgs_filename, 'r') as file:
223
+ lines = file.readlines()
224
+
225
+ # Introductory sentence
226
+ intro_text = """
227
+ <p style="font-size: 12pt; font-weight: normal; text-align: justify;">
228
+ Required Python packages with their minimum and maximum supported versions:
229
+ </p>
230
+ <p>
231
+
232
+ </p>
233
+ """
234
+
235
+ # Start the HTML table with improved styling
236
+ html_table = intro_text + """
237
+ <table border="1" style="width: 100%; align-items: center;">
238
+ <thead>
239
+ <tr>
240
+ <th style="padding: 10px; font-size: 11pt; font-weight: bold;">Package</th>
241
+ <th style="padding: 10px; font-size: 11pt; font-weight: bold;">Minimum version</th>
242
+ <th style="padding: 10px; font-size: 11pt; font-weight: bold;">Maximum version</th>
243
+ <th style="padding: 10px; font-size: 11pt; font-weight: bold;">Installed version</th>
244
+ </tr>
245
+ </thead>
246
+ <tbody>
247
+ """
248
+
249
+ # Iterate over each line in the file
250
+ for line in lines:
251
+ # Split each line into package name, min vers11pt max version, and other info
252
+ package_info = line.strip().split()
253
+
254
+ # Ensure the line has the expected format
255
+ if len(package_info) >= 3:
256
+ package_name = package_info[0]
257
+ if package_name[0]=='#': continue
258
+ min_version = package_info[1]
259
+ max_version = package_info[2]
260
+ curr_version = package_info[3]
261
+
262
+ # Append a row to the HTML table
263
+ html_table += f"""
264
+ <tr>
265
+ <td style="padding: 10px; font-size: 11pt">{package_name}</td>
266
+ <td style="padding: 10px; font-size: 11pt">{min_version}</td>
267
+ <td style="padding: 10px; font-size: 11pt">{max_version}</td>
268
+ <td style="padding: 10px; font-size: 11pt">{curr_version}</td>
269
+ </tr>
270
+ """
271
+
272
+ # Close the table tags
273
+ html_table += """
274
+ </tbody>
275
+ </table>
276
+ """
277
+ return html_table
278
+
279
+ #********************************************* GPaIRS
280
+ class gPaIRS(QMainWindow):
281
+
282
+ def eventFilter(self, obj, event:QKeyEvent):
283
+ # Check if the event is a KeyPress event
284
+ if event.type() == QEvent.KeyPress:
285
+ if event.modifiers() & Qt.KeyboardModifier.ControlModifier:
286
+ if event.modifiers() & Qt.KeyboardModifier.ShiftModifier and event.key() == Qt.Key.Key_F:
287
+ self.setDefaultSizes()
288
+ return True
289
+ FlagSetFont=False
290
+ if event.key() == Qt.Key.Key_0:
291
+ FlagSetFont=self.GPApar.fontPixelSize!=fontPixelSize
292
+ self.GPApar.fontPixelSize=fontPixelSize
293
+ elif event.key() == Qt.Key.Key_1 or event.key() == Qt.Key.Key_Minus:
294
+ if event.modifiers() & Qt.KeyboardModifier.ShiftModifier:
295
+ FlagSetFont=self.GPApar.fontPixelSize!=fontPixelSize_lim[0]
296
+ self.GPApar.fontPixelSize=fontPixelSize_lim[0]
297
+ else:
298
+ FlagSetFont=self.GPApar.fontPixelSize>fontPixelSize_lim[0]
299
+ if FlagSetFont: self.GPApar.fontPixelSize-=1
300
+ elif event.key() == Qt.Key.Key_9 or event.key() == Qt.Key.Key_Plus:
301
+ if event.modifiers() & Qt.KeyboardModifier.ShiftModifier:
302
+ FlagSetFont=self.GPApar.fontPixelSize!=fontPixelSize_lim[1]
303
+ self.GPApar.fontPixelSize=fontPixelSize_lim[1]
304
+ else:
305
+ FlagSetFont=self.GPApar.fontPixelSize<fontPixelSize_lim[1]
306
+ if FlagSetFont: self.GPApar.fontPixelSize+=1
307
+ if FlagSetFont:
308
+ self.app.processEvents()
309
+ self.setFontPixelSize()
310
+ return True
311
+
312
+ # Pass the event on to the parent class
313
+ return super().eventFilter(obj, event)
314
+
315
+ def resizeEvent(self,event):
316
+ if self.FlagGeometryInit:
317
+ self.FlagGeometryInit=False
318
+ #self.setFontPixelSize()
319
+ super().resizeEvent(event)
320
+ #self.updateGPAparGeom()
321
+
322
+ def showEvent(self, event):
323
+ super().showEvent(event)
324
+ if event.type() == QEvent.Show:
325
+ QTimer.singleShot(0, lambda: self.ui.tabAreaWidget.setSPLlayout())
326
+ pass
327
+
328
+ def closeEvent(self,event):
329
+ if self.completingTask!=self.correctClose:
330
+ self.pauseQuestion('quitting',self.correctClose,FlagFirstQuestion=True)
331
+ event.ignore()
332
+ return
333
+
334
+ def correctClose(self):
335
+ if self.pfPool: self.pfPool.closeParPool()
336
+ print('\nClosing PaIRS...')
337
+ self.save_last_workspace()
338
+ self.closeAll()
339
+ if self.GPApar.FlagOutDated:
340
+ warningLatestVersion(self,self.app,flagExit=1,flagWarning=self.GPApar.FlagOutDated in (-1,1,-1000))
341
+ self.close()
342
+ self.app.processEvents()
343
+ self.app.SecondaryThreads=self.SecondaryThreads
344
+ self.app.quit()
345
+
346
+ def closeAll(self):
347
+ if hasattr(self,"FloatingTabs"):
348
+ for w in self.FloatingTabs:
349
+ w.close()
350
+ if hasattr(self,"FloatingWindows"):
351
+ for w in self.FloatingWindows:
352
+ w.close()
353
+
354
+ class gPaIRS_signals(QObject):
355
+ killOrResetParForWorker=Signal(bool)#used to kill or reset he parForWorker
356
+ progress=Signal(int)
357
+ indProc=Signal(int)
358
+ parPoolInit=Signal()
359
+ guiInit=Signal()
360
+ setMapVar=Signal()
361
+ pause_proc=Signal()
362
+ printOutDated=Signal()
363
+
364
+ def __init__(self,flagDebug=False,app=None, standardPalette=None):
365
+ self.app:QApplication=app
366
+ self.name='PaIRS'
367
+ self.flagSimpleFor=False # normally false, True only if you are checking the c library or the parpool therefore I have added a long print at the end of this function
368
+ #todo gerardo spostare la stampa alla fine di tutto anche se ripetuta
369
+ activateFlagDebug(flagDebug)
370
+ self.PIVvers=PaIRS_lib.Version(PaIRS_lib.MOD_PIV).split('\n')[0]
371
+ pri.Time.blue(2,f'gPaIRS init PaIRS-PIV {self.PIVvers}')
372
+ super().__init__()
373
+
374
+ #------------------------------------- Launching Parallel Pool
375
+ self.previousPlotTime=time() #previous time for plotting
376
+ self.FlagGeometryInit=True
377
+ self.FlagOpenedWorkspace=False
378
+
379
+ self.FlagGuiInit=False
380
+ self.signals=self.gPaIRS_signals()
381
+ #self.numUsedThreadsPIV=NUMTHREADS_MAX #now is called numMaxProcs
382
+
383
+ self.numMaxProcs=NUMTHREADS_MAX #number of cores that the user has selected should be larger than numUsedProcs*numPivOmpCores
384
+ self.numUsedProcs=NUMTHREADS_MAX #number of really used processor (Threads parfor)
385
+ self.numPivOmpCores=1 # number of PIV internal cores used by omp
386
+
387
+ self.FlagParPoolInit=False
388
+ self.launchParPool(NUMTHREADS_MAX)
389
+
390
+ self.procdata:dataTreePar=None
391
+ self.currind:list=None
392
+ #self.numProcOrErrTot=0 # at the end should be equal to the number of images to be processed
393
+ self.numCallBackTotOk=0 # Callbacks that are relative to a normal termination
394
+ self.SecondaryThreads=[]
395
+
396
+ self.FlagPackIssue=False
397
+
398
+ #------------------------------------- Graphical interface: widgets
399
+ ui=Ui_gPairs()
400
+ ui.setupUi(self)
401
+ self.ui=ui
402
+ self.ui.button_Run.setVisible(False)
403
+ self.ui.button_Run.setEnabled(False)
404
+
405
+ self.buttonSizeCallbacks=[]
406
+ def createCallback(k):
407
+ return lambda: self.setPresetSizes(k)
408
+ for k in range(6):
409
+ self.buttonSizeCallbacks.append(createCallback(k))
410
+ #self.ResizePopup=ResizePopup(self.buttonSizeCallbacks)
411
+ self.ResizePopup=None
412
+
413
+ self.cfgname=lastcfgname
414
+ self.FlagHappyLogo=False
415
+ self.setupLogo()
416
+ self.startHappyLogoWatcher()
417
+
418
+ self.GPApar_old=GPApar()
419
+ self.GPApar=GPApar()
420
+ self.GPApar.NumCores=self.numMaxProcs
421
+ self.TABpar=self.GPApar
422
+
423
+ pri.Time.blue(2,f'gPaIRS inizio generazione tabs')
424
+ self.defineTabs()
425
+ self.defineMenuActions()
426
+ self.ui.title_workspace.updateLabel=self.updateWorkspaceTitle
427
+
428
+ setupWid(self) #---------------- IMPORTANT
429
+ self.setFurtherFontPixelSizes(fontPixelSize)
430
+
431
+ pri.Time.blue(2,f'gPaIRS fine generazione tabs')
432
+
433
+ #for the keyboard shortcut
434
+ """
435
+ self.FlagKeyCallbackExec=False
436
+ self.blockedKeys=[Qt.Key.Key_Up,Qt.Key.Key_Down,Qt.Key.Key_Left,Qt.Key.Key_Right]
437
+ for w in self.findChildren(QObject):
438
+ if hasattr(w,'keyPressEvent'):
439
+ def createKeyPressFun(w):
440
+ def KeyPressFun(e):
441
+ if w.hasFocus():
442
+ #pri.Info.yellow(w)
443
+ if not self.FlagKeyCallbackExec:
444
+ self.FlagKeyCallbackExec=True
445
+ type(w).keyPressEvent(w,e)
446
+ if not e.key() in self.blockedKeys:
447
+ self.keyPressEvent(e)
448
+ self.FlagKeyCallbackExec=False
449
+ return KeyPressFun
450
+ w.keyPressEvent=createKeyPressFun(w)
451
+ """
452
+ self.ui.spin_nworkers.setValue(self.numMaxProcs)
453
+ self.ui.spin_nworkers.setMinimum(1)
454
+ self.ui.spin_nworkers.setMaximum(NUMTHREADS_MAX)
455
+ self.ui.spin_nworkers.valueChanged.connect(self.spin_nworkers_action)
456
+
457
+ self.ui.button_pause.hide()
458
+ self.ui.w_progress_Proc.hide()
459
+
460
+ #for positioning and resizing
461
+ #window=QWindow()
462
+ #window.showMaximized()
463
+ #self.maximumGeometry=window.geometry()
464
+ #window.close()
465
+ self.maximumGeometry=self.app.primaryScreen().geometry()
466
+
467
+ self.minW=self.minimumWidth()
468
+ self.maxW=self.maximumGeometry.width()
469
+ self.ui.Explorer.setMinimumWidth(0)
470
+ margins=self.ui.centralLayout.contentsMargins()
471
+ self.minW_ManTabs=self.minimumWidth()-margins.left()-margins.right()
472
+
473
+ self.splash=None
474
+
475
+ #------------------------------------- Graphical interface: miscellanea
476
+ self.flaticon_PaIRS_download=QIcon()
477
+ self.flaticon_PaIRS_download.addFile(icons_path+'flaticon_PaIRS_download.png')
478
+ self.flaticon_PaIRS_download_warning=QIcon()
479
+ self.flaticon_PaIRS_download_warning.addFile(icons_path+'flaticon_PaIRS_download_warning.png')
480
+ self.flaticon_PaIRS_beta=QIcon()
481
+ self.flaticon_PaIRS_beta.addFile(icons_path+'flaticon_PaIRS_beta.png')
482
+
483
+ self.icon_play=QIcon()
484
+ self.icon_play.addFile(u""+ icons_path +"play.png", QSize(), QIcon.Normal, QIcon.Off)
485
+ self.icon_pause=QIcon()
486
+ self.icon_pause.addFile(u""+ icons_path +"pause.png", QSize(), QIcon.Normal, QIcon.Off)
487
+ self.icon_save_and_stop=QIcon()
488
+ self.icon_save_and_stop.addFile(u""+ icons_path +"save_and_stop.png", QSize(), QIcon.Normal, QIcon.Off)
489
+
490
+ self.ui.tabAreaWidget.icon_link=QIcon()
491
+ self.ui.tabAreaWidget.icon_link.addFile(u""+ icons_path +"link.png", QSize(), QIcon.Normal, QIcon.Off)
492
+ self.ui.tabAreaWidget.icon_unlink=QIcon()
493
+ self.ui.tabAreaWidget.icon_unlink.addFile(u""+ icons_path +"unlink.png", QSize(), QIcon.Normal, QIcon.Off)
494
+
495
+ self.updating_import_gif = QMovie(u""+ icons_path +"updating_import.gif")
496
+ self.updating_import_gif.setScaledSize(self.ui.label_updating_import.size())
497
+ #self.ui.label_updating_import.setScaledContents(True)
498
+ self.updating_import_gif.start()
499
+ self.ui.label_updating_import.setMovie(self.updating_import_gif)
500
+ self.ui.label_updating_import.setVisible(False)
501
+
502
+ self.updating_pairs_gif = QMovie(u""+ icons_path +"updating_pairs.gif")
503
+ self.updating_pairs_gif.setScaledSize(self.ui.label_updating_pairs.size())
504
+ #self.ui.label_updating_pairs.setScaledContents(True)
505
+ self.updating_pairs_gif.start()
506
+ self.ui.label_updating_pairs.setMovie(self.updating_pairs_gif)
507
+ self.ui.label_updating_pairs.setVisible(False)
508
+
509
+ self.runningMovie = QMovie(icons_path+'running.gif')
510
+ self.runningMovie.setScaledSize(QSize(StepItemWidget.label_size,StepItemWidget.label_size))
511
+ self.runningMovie.start()
512
+
513
+ self.gearMovie = QMovie(icons_path+'gear.gif')
514
+ self.gearMovie.setScaledSize(QSize(StepItemWidget.label_size,StepItemWidget.label_size))
515
+ self.gearMovie.start()
516
+
517
+ self.palettes=[lightPalette(),darkPalette(),standardPalette]
518
+ self.paletteNames=['Light','Dark','System']
519
+ #self.ui.logo.contextMenuEvent=self.paletteContextMenuEvent
520
+ self.ui.button_colormode.mousePressEvent=self.paletteContextMenuEvent
521
+ self.ui.button_packissue.mousePressEvent=lambda e: checkRequiredPackages(self,FlagDisplay=True)
522
+ self.ui.logo.setCursor(QCursor(Qt.CursorShape.PointingHandCursor))
523
+ self.ui.logo.mousePressEvent=lambda e: self.about()
524
+ #self.ui.logo.mousePressEvent=self.paletteContextMenuEvent
525
+ #cursor_lamp_pixmap=QtGui.QPixmap(''+ icons_path +'cursor_lamp.png').scaled(QSize(24,24), Qt.KeepAspectRatio)
526
+ #cursor_lamp = QtGui.QCursor(cursor_lamp_pixmap,-1,-1)
527
+ #self.ui.logo.setCursor(cursor_lamp)
528
+
529
+ self.aboutDialog=None
530
+ self.logChanges:Log_Tab=None
531
+ self.whatsNew=lambda: whatsNew(self)
532
+
533
+ self.ui.button_PaIRS_download.setCursor(Qt.CursorShape.PointingHandCursor)
534
+ self.ui.button_PaIRS_download.setVisible(False)
535
+ self.signals.printOutDated.connect(self.setButtonDownload)
536
+
537
+ self.fontPixelSize=fontPixelSize
538
+ self.setDefaultSizes()
539
+
540
+ self.ui.title_workspace.bullet=GPApar().saveBullet()
541
+
542
+ #------------------------------------- Declaration of parameters
543
+ self.PaIRS_threadpool=QThreadPool()
544
+ if NUMTHREADS_gPaIRS:
545
+ self.PaIRS_threadpool.setMaxThreadCount(NUMTHREADS_gPaIRS)
546
+
547
+ self.FlagRun=0
548
+ self.procWorkers=[]
549
+ self.contProc=self.nProc=0
550
+ self.procdata=None
551
+ self.FlagResetPlot=False
552
+ self.FlagProcInit=False
553
+ self.FlagProcPlot=False
554
+ self.procFields=['numProcOrErrTot','Log','list_print','list_pim','numCallBackTotOk','numFinalized','flagRun','flagParForCompleted']
555
+ self.namesPIV=NamesPIV()
556
+
557
+ #self.defineFloatings()
558
+ self.FloatingTabs=[]
559
+ self.FloatingWindows=[]
560
+
561
+ self.menuDebug=None
562
+ self.completingTask=None
563
+ self.waitingDialog=None
564
+
565
+ #------------------------------------- Callbacks
566
+ self.ui.Explorer.adjustProcessSelection=self.adjustProcessSelection
567
+ self.ui.Explorer.projectTree.adjustSelection=self.adjustProjectSelection
568
+ self.projectTree.editingFinished=self.adjustProcessSelection
569
+ self.processTree.editingFinished=lambda: self.editingFinished(self.processTree)
570
+ self.binTree.editingFinished=lambda: self.editingFinished(self.binTree)
571
+
572
+ self.ui.button_Run.clicked.connect(self.button_run_pause_action)
573
+ self.ui.button_pause.clicked.connect(self.button_run_pause_action)
574
+
575
+ self.ui.workspace_icon.setCursor(QCursor(Qt.CursorShape.PointingHandCursor))
576
+ self.ui.workspace_icon.pressed.connect(lambda btn=self.ui.workspace_icon: btn.setStyleSheet("border: none; background: #dcdcdc;"))
577
+ self.ui.workspace_icon.released.connect(lambda btn=self.ui.workspace_icon: btn.setStyleSheet("border: none; background: none;"))
578
+ pixmap_workspace=QPixmap(icons_path+'workspace.png')
579
+ self.ui.workspace_icon.clicked.connect(lambda: self.warningDialog(self.GPApar.InfoMessage(),pixmap=pixmap_workspace,title='Workspace information'))
580
+
581
+ self.currITEpar=self.TREpar
582
+ self.ui.title_icon.setCursor(QCursor(Qt.CursorShape.PointingHandCursor))
583
+ self.ui.title_icon.pressed.connect(lambda btn=self.ui.title_icon: btn.setStyleSheet("border: none; background: #dcdcdc;"))
584
+ self.ui.title_icon.released.connect(lambda btn=self.ui.title_icon: btn.setStyleSheet("border: none; background: none;"))
585
+ pixmap_workspace=QPixmap(icons_path+'workspace.png')
586
+ self.ui.title_icon.clicked.connect(lambda: self.warningDialog(self.currITEpar.InfoMessage(),pixmap=TreeIcons.pixmaps[self.currITEpar.icon],title=f"{self.currITEpar.basename} information"))
587
+
588
+ class RCLbar:
589
+ buttons={0: self.ui.button_reset_step,
590
+ 1: self.ui.button_step_inherit,
591
+ 2: self.ui.button_copy_step,
592
+ 3: self.ui.button_link_step}
593
+ buttonData={0: {'name': 'Reset step'},
594
+ 1: {'name': 'Copy input/output data from...'},
595
+ 2: {'name': 'Copy step from...'},
596
+ 3: {'name': 'Link step to...'}}
597
+ self.RCLbar=RCLbar()
598
+ self.ui.Explorer.processActionBar.additionalButtonBars['items'].append(self.RCLbar)
599
+
600
+ self.installEventFilter(self)
601
+
602
+ #------------------------------------- Initialization
603
+ from .PaIRS_pypacks import basefold
604
+ basefold=myStandardPath(basefold)
605
+ self.initialize()
606
+
607
+ #------------------------------------- Debug
608
+ self.addDebugMenu()
609
+ self.menuDebug.setFont(self.ui.menuFile.font())
610
+ self.menuDebug.menuAction().setVisible(Flag_DEBUG)
611
+ self.userDebugShortcut = QShortcut(QKeySequence('Shift+Alt+D'), self)
612
+ self.userDebugShortcut.activated.connect(self.userDebugMode)
613
+ self.developerDebugShortcut = QShortcut(QKeySequence('Alt+D, Alt+E, Alt+B, Alt+Return'), self)
614
+ self.developerDebugShortcut.activated.connect(lambda:self.setDebugMode(True))
615
+ #self.exitDebugShortcut = QShortcut(QKeySequence('Shift+Alt+D'), self)
616
+ #self.exitDebugShortcut.activated.connect(lambda:self.setDebugMode(False))
617
+ self.setDebugMode(flagDebug)# should be put not upper than here
618
+ pri.Time.blue(0,'dopo setupUi')
619
+ self.FlagClosing=[False]
620
+ #self.setupPathCompleter()
621
+
622
+ self.FlagGuiInit=True
623
+ self.load_gif = QMovie(u""+ icons_path +"loading_2.gif")
624
+ self.load_gif.start()
625
+ self.loaded_map=QPixmap(u""+ icons_path + "loaded.png")
626
+ self.parPoolInitSetup()
627
+ #todo gerardo spostare questa stampa alla fine di tutto anche se ripetuta
628
+ if self.flagSimpleFor:print('\n\n\n\n\n\nflagSimplefor=True \nAre you really working with the c library?\n\n\n\n\n\n\n\n')
629
+ pri.Time.blue(0,'fine di tutto init')
630
+
631
+ def initialize(self):
632
+ pri.Info.yellow('||| Initializing gPaIRS |||')
633
+ if os.path.exists(lastcfgname):
634
+ self.open_workspace(filename=lastcfgname,FlagSetGeometry=True)
635
+ self.GPApar_old.copyfrom(self.GPApar)
636
+ else:
637
+ self.adjustProjectSelection()
638
+ self.setGPaIRSPalette()
639
+ return
640
+
641
+ def disableDropping(self,FlagDisableed=True):
642
+ self.projectTree.setDragEnabled(not FlagDisableed)
643
+ self.processTree.setDragEnabled(not FlagDisableed)
644
+
645
+ def setSwitchEnabled(self,FlagEnabled=True):
646
+ for k in range(len(self.projectTree.itemList[0])):
647
+ topLevelItem=self.projectTree.topLevelItem(k)
648
+ itemWidget=self.projectTree.itemWidget(topLevelItem,1)
649
+ if itemWidget:
650
+ switch:ModernSwitch=itemWidget.findChildren(ModernSwitch)[0]
651
+ if switch:
652
+ switch.setEnabled(FlagEnabled)
653
+ for k in range(self.processTree.topLevelItemCount()):
654
+ topLevelItem=self.processTree.topLevelItem(k)
655
+ itemWidget=self.processTree.itemWidget(topLevelItem,1)
656
+ if itemWidget:
657
+ switch:ModernSwitch=itemWidget.findChildren(ModernSwitch)[0]
658
+ if switch:
659
+ switch.setEnabled(FlagEnabled)
660
+
661
+ def setButtonRunVisible(self):
662
+ FlagButtonRun=any([tre.FlagRunnable and tre.FlagQueue for tre in self.projectTree.itemList[0]])
663
+ if not FlagButtonRun:
664
+ self.ui.button_Run.setVisible(False)
665
+ self.ui.button_pause.setVisible(False)
666
+ self.ui.w_progress_Proc.setVisible(False)
667
+ self.ui.progress_Proc.setValue(0)
668
+ self.ui.time_stamp.setText('Initializing...')
669
+ else:
670
+ FlagButtonRun=self.ui.progress_Proc.value() in (0,self.ui.progress_Proc.maximum()) and self.FlagRun==0
671
+ self.ui.button_Run.setVisible(FlagButtonRun)
672
+ self.ui.button_pause.setVisible(not FlagButtonRun)
673
+ self.ui.w_progress_Proc.setVisible(not FlagButtonRun)
674
+ self.ui.tabAreaWidget.display_controls()
675
+
676
+ def editingFinished(self,tree):
677
+ self.ui.Explorer.arrangeCurrentProcess(tree)
678
+ self.adjustProcessSelection()
679
+
680
+ def defineFloatings(self):
681
+ self.FloatingTabs=[]
682
+ for wid in self.tabWidgets[:-1]:
683
+ self.FloatingTabs.append(FloatingObject(self,wid))
684
+ self.GPApar.FloatGeometry.append(self.geometry())
685
+ self.GPApar.FloatingsVis.append(self.isVisible())
686
+
687
+ #********************************************* TAB definitions
688
+ def defineTabs(self):
689
+ self.w_Input = Input_Tab(self,False)
690
+ pri.Time.magenta('Input')
691
+ self.w_Output = Output_Tab(self,False)
692
+ pri.Time.magenta('Output')
693
+ self.w_Process = Process_Tab(self,False)
694
+ pri.Time.magenta('Process')
695
+ self.w_Log = Log_Tab(self,False)
696
+ pri.Time.magenta('Log')
697
+ self.w_Vis = Vis_Tab(self,False)
698
+ pri.Time.magenta('Vis')
699
+ self.w_Process_Min = Process_Tab_Min(self,False)
700
+ pri.Time.magenta('Process_Min')
701
+ self.w_Process_Disp = Process_Tab_Disp(self,False)
702
+ pri.Time.magenta('Process_Disp')
703
+ self.w_Calibration = Calibration_Tab(self,False)
704
+ pri.Time.magenta('Calibration')
705
+ self.w_Input_CalVi = Input_Tab_CalVi(self,False)
706
+ pri.Time.magenta('Input_CalVi')
707
+ self.w_Process_CalVi = Process_Tab_CalVi(self,False)
708
+ pri.Time.magenta('Process_CalVi')
709
+ self.w_Vis_CalVi = Vis_Tab_CalVi(self,False)
710
+ pri.Time.magenta('Vis_CalVi')
711
+ self.tabWidgets=[ self.w_Calibration,
712
+ self.w_Input,self.w_Input_CalVi,
713
+ self.w_Output,
714
+ self.w_Process,self.w_Process_Min,self.w_Process_Disp,self.w_Process_CalVi,
715
+ self.w_Log,
716
+ self.w_Vis,self.w_Vis_CalVi ]
717
+ self.tabTypes=[type(w) for w in self.tabWidgets]
718
+ pri.Time.blue(2,f'gPaIRS generazione tabs')
719
+
720
+ icons=[w.TABname.split('_')[0].lower()+'_logo' for w in self.tabWidgets]
721
+ self.ui.tabAreaWidget.setupTabArea(self.tabWidgets,icons)
722
+ self.ui.tabAreaWidget.gui=self
723
+ self.tabWidgets=self.tabWidgets+[self.ui.tabAreaWidget]
724
+ self.tabNames=[tab.TABname for tab in self.tabWidgets]
725
+
726
+ self.w_Input.ui.imTreeWidget.disableTab=self.disableTab_ImTree
727
+
728
+ self.ui.projectPage.ITEM_HEIGHT=80
729
+ self.ui.projectPage.title.setText("Select a project")
730
+ self.ui.projectPage.setupPage(projectPageButtons,self.ui.Explorer.projectPageActions)
731
+ self.ui.processPage.title.setText("Select a process")
732
+ self.ui.processPage.setupPage(processData,self.ui.Explorer.processPageActions)
733
+ self.ui.stepPage.title.setText("Set up each step of the process")
734
+ self.ui.stepPage.setupPage(stepData,self.ui.Explorer.stepPageActions)
735
+ self.ui.Explorer.stepPage=self.ui.stepPage
736
+
737
+ self.projectTree=self.ui.Explorer.projectTree
738
+ self.processTree=self.ui.Explorer.processTree
739
+ self.binTree=self.ui.Explorer.binTree
740
+ self.TREpar=self.ui.Explorer.TREpar
741
+
742
+ self.ui.Explorer.gui=self
743
+ self.projectTree.gui=self
744
+ self.processTree.gui=self
745
+ self.binTree.gui=self
746
+
747
+ for w in self.tabWidgets:
748
+ w:gPaIRS_Tab
749
+ w.TABpar_prev=[]
750
+ self.processTree.itemList=[]
751
+ self.binTree.itemList=[]
752
+
753
+ self.ui.Explorer.widgets=self.tabWidgets
754
+ self.projectTree.setupWidgets(self.tabWidgets)
755
+ self.processTree.setupWidgets(self.tabWidgets)
756
+ self.binTree.setupWidgets(self.tabWidgets)
757
+
758
+ self.projectTree.modifyWorkspace=self.modifyWorkspace
759
+ self.projectTree.adjustSwitches=self.adjustSwitches
760
+ self.processTree.adjustSwitches=self.adjustSwitches
761
+ self.projectTree.signals.updateLists.connect(self.updateWorkspace)
762
+ self.processTree.signals.updateLists.connect(self.updateProjectItemWidget)
763
+
764
+ #self.ui.button_back.hide()
765
+ #self.ui.button_forward.hide()
766
+
767
+ self.ui.w_header.layout().removeWidget(self.ui.logo_CalVi)
768
+ self.ui.w_header.layout().removeWidget(self.ui.button_Run_CalVi)
769
+ self.ui.w_header.layout().removeWidget(self.ui.button_Abort_CalVi)
770
+ self.ui.tabAreaWidget.buttonBar_layout.addWidget(self.ui.logo_CalVi)
771
+ self.ui.tabAreaWidget.buttonBar_layout.addWidget(self.ui.button_Run_CalVi)
772
+ self.ui.tabAreaWidget.buttonBar_layout.addWidget(self.ui.button_Abort_CalVi)
773
+ self.ui.button_Run_CalVi.setFixedHeight(TabAreaWidget.buttonSize[1])
774
+ self.ui.button_Abort_CalVi.setFixedHeight(TabAreaWidget.buttonSize[1])
775
+ self.ui.tabAreaWidget.buttonBar.setMaximumHeight(TabAreaWidget.buttonSize[1])
776
+
777
+ self.ui.logo_CalVi.setVisible(False)
778
+ self.ui.button_Run_CalVi.setVisible(False)
779
+ self.ui.button_Abort_CalVi.setVisible(False)
780
+ self.ui.button_Run_CalVi.clicked.connect(self.runCalVi)
781
+ self.ui.button_Abort_CalVi.clicked.connect(self.abortCalVi)
782
+ self.w_Input_CalVi.setRunCalViButtonText=lambda: self.setRunCalViButtonText(False)
783
+ setattr(self.w_Calibration,'logo_CalVi',self.ui.logo_CalVi)
784
+ setattr(self.w_Calibration,'button_Run_CalVi',self.ui.button_Run_CalVi)
785
+
786
+ for w in self.tabWidgets:
787
+ w:gPaIRS_Tab
788
+ w.FlagDisplayControls=False
789
+ self.w_Input.ui.w_Mode.layout().removeWidget(self.w_Input.ui.button_back)
790
+ self.w_Input.ui.w_Mode.layout().removeWidget(self.w_Input.ui.button_forward)
791
+ self.w_Input.ui.button_back.clicked.disconnect()
792
+ self.w_Input.ui.button_forward.clicked.disconnect()
793
+ self.w_Input.display_controls=lambda:None
794
+
795
+ self.ui.w_header.layout().removeWidget(self.ui.button_restore_undo)
796
+ self.ui.tabAreaWidget.buttonBar_layout.addWidget(self.ui.button_restore_undo)
797
+ self.ui.button_restore_undo.setFixedWidth(TabAreaWidget.buttonSize[1])
798
+ self.ui.button_restore_undo.setFixedHeight(TabAreaWidget.buttonSize[1])
799
+ self.ui.button_restore_undo.clicked.connect(self.fullCallback)
800
+ self.ui.tabAreaWidget.ui.button_restore_undo=self.ui.button_restore_undo
801
+
802
+ self.ui.tabAreaWidget.FlagDisplayControls=True
803
+ self.ui.tabAreaWidget.ui.button_back=self.w_Input.ui.button_back
804
+ self.ui.tabAreaWidget.ui.button_back.clicked.connect(lambda: self.button_back_forward_action(-1))
805
+ self.ui.tabAreaWidget.ui.button_back.contextMenuEvent=lambda e: self.bfContextMenu(-1,e)
806
+
807
+ self.ui.tabAreaWidget.ui.button_forward=self.w_Input.ui.button_forward
808
+ self.ui.tabAreaWidget.ui.button_forward.clicked.connect(lambda: self.button_back_forward_action(+1))
809
+ self.ui.tabAreaWidget.ui.button_forward.contextMenuEvent=lambda e: self.bfContextMenu(+1,e)
810
+
811
+ self.onlyReadLabel=QLabel('Read-Only')
812
+ font=self.onlyReadLabel.font()
813
+ font.setBold(True)
814
+ font.setItalic(True)
815
+ font.setPixelSize(fontPixelSize)
816
+ self.onlyReadLabel.setFont(font)
817
+ self.onlyReadLabel.setStyleSheet('color: rgb(51, 102, 255)') #('color: rgb(255,51,51);')
818
+ #self.ui.tabAreaWidget.buttonBar_layout.addWidget(self.onlyReadLabel)
819
+ self.ui.tabAreaWidget.onlyReadLabel=self.onlyReadLabel
820
+ self.ui.tabAreaWidget.button_reset_step=self.ui.button_reset_step
821
+ self.ui.tabAreaWidget.button_step_inherit=self.ui.button_step_inherit
822
+ self.ui.tabAreaWidget.button_copy_step=self.ui.button_copy_step
823
+ self.ui.tabAreaWidget.button_link_step=self.ui.button_link_step
824
+
825
+ self.w_RCL = QWidget(self) #CLR: copy, link, reset
826
+ self.RCL_layout = QHBoxLayout()
827
+ self.RCL_layout.setContentsMargins(0, 0, 0, 0)
828
+ self.RCL_layout.setSpacing(actionButtonSpacing*2)
829
+ self.w_RCL.setLayout(self.RCL_layout)
830
+
831
+ self.RCL_layout.addSpacerItem(QSpacerItem(projectActionButtonSize[1], projectActionButtonSize[1], QSizePolicy.Expanding, QSizePolicy.Minimum))
832
+ self.RCL_layout.addWidget(self.onlyReadLabel)
833
+ self.RCL_layout.addSpacerItem(QSpacerItem(5, projectActionButtonSize[1], QSizePolicy.Minimum, QSizePolicy.Minimum))
834
+ for b in [self.ui.button_reset_step,self.ui.button_step_inherit,self.ui.button_copy_step,self.ui.button_link_step]:
835
+ self.ui.w_header.layout().removeWidget(b)
836
+ #self.ui.tabAreaWidget.buttonBar_layout.addWidget(b)
837
+ #b.setFixedSize(TabAreaWidget.buttonSize[1],TabAreaWidget.buttonSize[1])
838
+ #b.setIconSize(QSize(TabAreaWidget.buttonSize[1]-8,TabAreaWidget.buttonSize[1]-8))
839
+ self.RCL_layout.addWidget(b)
840
+ b.setFixedSize(projectActionButtonSize[1],projectActionButtonSize[1])
841
+ b.setIconSize(QSize(projectActionButtonSize[0],projectActionButtonSize[0]))
842
+ if hasattr(self,b.objectName()+'_action'):
843
+ b.clicked.connect(getattr(self,b.objectName()+'_action'))
844
+ self.ui.Explorer.processTree_layout.addWidget(self.w_RCL)
845
+
846
+ self.w_Input.ui.button_back.setFixedSize(TabAreaWidget.buttonSize[1],TabAreaWidget.buttonSize[1])
847
+ self.w_Input.ui.button_back.setIconSize(QSize(TabAreaWidget.buttonSize[1]-2,TabAreaWidget.buttonSize[1]-2))
848
+ self.w_Input.ui.button_forward.setFixedSize(TabAreaWidget.buttonSize[1],TabAreaWidget.buttonSize[1])
849
+ self.w_Input.ui.button_forward.setIconSize(QSize(TabAreaWidget.buttonSize[1]-2,TabAreaWidget.buttonSize[1]-2))
850
+ self.ui.tabAreaWidget.buttonBar_layout.addWidget(self.w_Input.ui.button_back)
851
+ self.ui.tabAreaWidget.buttonBar_layout.addWidget(self.w_Input.ui.button_forward)
852
+
853
+ self.ui.tabAreaWidget.FlagPrevPropagation=FlagPrevPropagationTabSplitter
854
+ self.ui.Explorer.inheritance=self.inheritance
855
+
856
+ self.brush_icon=QIcon(icons_path+"brush_cursor.png")
857
+ self.w_Vis.ui.icon.addfuncclick['copy_VIS']=lambda: self.copy_link_action(self.w_Vis.ui.name_tab,lambda isl,ima: self.copy_VIS(isl,ima),menuTitle='Copy graphical settings from...',icon=self.brush_icon)
858
+ self.w_Vis.ui.icon.setCustomCursor()
859
+
860
+ self.defineTABbridges()
861
+
862
+ for c in self.findChildren(PaIRSTree):
863
+ c:PaIRSTree
864
+ c.gui=self
865
+
866
+ def fullCallback(self):
867
+ for w in self.tabWidgets:
868
+ w:gPaIRS_Tab
869
+ TABpar_ind=w.TABpar_at(w.TABpar.ind[:-1]+[-1])
870
+ if TABpar_ind:
871
+ if w.TABpar.isDifferentFrom(TABpar_ind,exceptions=w.TABpar.unchecked_fields+['ind']):
872
+ w.TABpar.ind[-1]=-1
873
+ w.fullCallback('Restored configuration')
874
+ break
875
+ ind=[i for i in w.TABpar.ind]
876
+ ind[-1]=-1
877
+ self.setTABpars_at(ind)
878
+
879
+ def defineMenuActions(self):
880
+ self.projectTree.button_open_action=self.open_project
881
+ self.projectTree.button_save_action=self.save_project
882
+ self.projectTree.button_saveas_action=self.saveas_project
883
+ self.projectTree.button_close_action=self.close_project
884
+ self.projectTree.button_clean_action=self.clean_projects
885
+
886
+ self.processTree.button_delete_action=self.delete_process
887
+ self.processTree.button_clean_action=self.clean_processes
888
+
889
+ self.ui.actionPaIRS_Run.triggered.connect(lambda: runPaIRS(self,))
890
+ self.ui.actionPaIRS_Clean_run.triggered.connect(lambda: runPaIRS(self,'-c'))
891
+ self.ui.actionPaIRS_Debug_run.triggered.connect(lambda: runPaIRS(self,'-d'))
892
+
893
+ actions=self.ui.menuFile.actions()
894
+ for a in actions:
895
+ aName=a.objectName().replace('action','').lower()
896
+ if hasattr(self,'menu_'+aName+'_action'):
897
+ a.triggered.connect(getattr(self,'menu_'+aName+'_action'))
898
+ self.ui.aExit.triggered.connect(lambda: self.close())
899
+
900
+ self.showChanges=lambda: changes(self,Log_Tab,fileChanges)
901
+ self.ui.actionChanges.triggered.connect(self.showChanges)
902
+ self.ui.actionGuide.triggered.connect(self.guide)
903
+ self.ui.actionDownload.setVisible(not Flag_ISEXE)
904
+ if not Flag_ISEXE:
905
+ self.ui.menuHelp.insertSeparator(self.ui.actionDownload)
906
+ self.ui.actionDownload.triggered.connect(self.downloadApp)
907
+ self.ui.actionAbout.triggered.connect(self.about)
908
+
909
+ self.ui.button_PaIRS_download.clicked.connect(lambda: button_download_PaIRS_action(self,self.app))
910
+
911
+ def disableTab_ImTree(self,Flag=True):
912
+ self.ui.w_Managing_Tabs.setEnabled(not Flag)
913
+ for w in self.tabWidgets:
914
+ w:gPaIRS_Tab
915
+ if w!=self.w_Input and w!=self.ui.tabAreaWidget:
916
+ w.setEnabled(not Flag)
917
+ self.w_Input.ui.CollapBox_ImSet.setEnabled(not Flag)
918
+ self.w_Input.ui.w_InputFold_Button.setEnabled(not Flag)
919
+ self.w_Input.ui.imTreeWidget.setEnabled(True)
920
+
921
+ self.w_Input.ui.button_back.setEnabled(not Flag)
922
+ self.w_Input.ui.button_forward.setEnabled(not Flag)
923
+
924
+ self.ui.menubar.setEnabled(not Flag)
925
+
926
+ #evita TABpar.FlagSettingPar=Flag così che sai dove FlagSettingPar è settato True o False
927
+ ImageTreeWidget.disableTab(self.w_Input.ui.imTreeWidget,Flag)
928
+
929
+ def button_back_forward_action(self,step):
930
+ self.w_Input.FlagSettingPar=True
931
+ self.setFocus()
932
+ self.w_Input.FlagSettingPar=False
933
+ for w in self.tabWidgets:
934
+ w:gPaIRS_Tab
935
+ if not w.TABpar.FlagNone:
936
+ ind=w.TABpar.ind
937
+ ind[-1]+=step
938
+ w.TABpar.copyfrom(w.TABpar_at(ind))
939
+ FlagAdjustPar=w.TABpar.FlagInit==False or w.TABpar.Process==ProcessTypes.cal #w.TABpar.ind[-1]==0
940
+ FlagBridge=w.TABpar.Process==ProcessTypes.cal #False
941
+ if FlagAdjustPar or FlagBridge:
942
+ for w in self.tabWidgets:
943
+ if not w.TABpar.FlagNone:
944
+ w:gPaIRS_Tab
945
+ if FlagAdjustPar:
946
+ FlagSettingPar=TABpar.FlagSettingPar
947
+ TABpar.FlagSettingPar=True
948
+ w.adjustTABpar()
949
+ TABpar.FlagSettingPar=FlagSettingPar
950
+ if FlagBridge: self.bridge(w.TABname)
951
+ FlagAdjustPar=False
952
+ FlagBridge=False
953
+ for w in self.tabWidgets:
954
+ w:gPaIRS_Tab
955
+ if not w.TABpar.FlagNone:
956
+ w.setTABpar(FlagAdjustPar,FlagBridge)
957
+ self.ui.Explorer.setITElayout()
958
+ return
959
+
960
+ def bfContextMenu(self,bf,event):
961
+ ind=self.ui.tabAreaWidget.TABpar.ind
962
+ i=ind[-1]
963
+ TABpar_prev=self.ui.tabAreaWidget.TABpar_prev_at(ind)
964
+
965
+ if bf==-1:
966
+ b=self.ui.tabAreaWidget.ui.button_back
967
+ kin=max([0,i-Num_Prevs_back_forw])
968
+ krange=[k for k in range(i-1,kin,-1)]+[0]
969
+ icon=self.ui.tabAreaWidget.undo_icon
970
+ d=1
971
+ elif bf==1:
972
+ b=self.ui.tabAreaWidget.ui.button_forward
973
+ kfin=min([len(TABpar_prev)-1,i+Num_Prevs_back_forw])
974
+ krange=[k for k in range(i+1,kfin)]+[len(TABpar_prev)-1]
975
+ icon=self.ui.tabAreaWidget.redo_icon
976
+ d=0
977
+
978
+ menu=QMenu(b)
979
+ act=[]
980
+ nur=len(krange)
981
+ flag=nur==Num_Prevs_back_forw
982
+ for j,k in enumerate(krange):
983
+ if j==nur-1:
984
+ if flag: menu.addSeparator()
985
+ if k==0: s=' (first)'
986
+ else: s=' (current)'
987
+ else:
988
+ if j==nur-2 and flag:
989
+ s=' (...)'
990
+ else:
991
+ s=''
992
+ n=f"{k-i:+d}: "
993
+ name=n+TABpar_prev[k+d].tip+s
994
+ act.append(QAction(icon,name,b))
995
+ menu.addAction(act[-1])
996
+
997
+ action = menu.exec_(b.mapToGlobal(event.pos()))
998
+ for k,a in zip(krange,act):
999
+ if a==action:
1000
+ self.button_back_forward_action(-i+k)
1001
+
1002
+ def defineTABbridges(self):
1003
+ for w in self.tabWidgets: #[:-1] except tabArea
1004
+ w:gPaIRS_Tab
1005
+ self.define_add_TABpar_bridge(w)
1006
+ self.define_setTABpar_bridge(w)
1007
+
1008
+ def setTABpars_at(self,ind,FlagAdjustPar=False,FlagBridge=True,widget:gPaIRS_Tab=None):
1009
+ for w in self.tabWidgets:
1010
+ w:gPaIRS_Tab
1011
+ TABpar_ind:TABpar=w.TABpar_at(ind)
1012
+ if TABpar_ind:
1013
+ if not TABpar_ind.FlagNone:
1014
+ w.TABpar.copyfrom(TABpar_ind)
1015
+ ITE_ind:ITEpar=self.ui.Explorer.ITEfromInd(ind)
1016
+ self.ui.Explorer.ITEpar.copyfrom(ITE_ind,exceptions=['procdata'])
1017
+ self.ui.Explorer.ITEpar.procdata=dataTreePar(ITE_ind.Process,ITE_ind.Step)
1018
+ self.ui.Explorer.ITEpar.procdata.ind=self.ui.Explorer.ITEpar.ind
1019
+ self.ui.Explorer.ITEpar.procdata.copyfrom(ITE_ind.procdata)
1020
+ if widget is None:
1021
+ self.ui.tabAreaWidget.setTABpar(FlagAdjustPar,FlagBridge)
1022
+ else:
1023
+ widget.setTABpar(FlagAdjustPar,FlagBridge)
1024
+ self.ui.tabAreaWidget.display_controls()
1025
+
1026
+ def define_add_TABpar_bridge(self,tab:gPaIRS_Tab):
1027
+ def add_TABpar_bridge(tip,ind):
1028
+ tab.TABpar.parentTab=tab.TABname
1029
+ for w in self.tabWidgets:
1030
+ w:gPaIRS_Tab
1031
+ if w!=tab:
1032
+ w:gPaIRS_Tab
1033
+ w.TABpar.ind=[i for i in ind]
1034
+ ind_new=w.add_TABpar_copy(tip,ind) #setting parameters without bridge
1035
+ ITE:ITEpar=self.ui.Explorer.ITEfromInd(ind)
1036
+ ITE.ind[-1]=ind_new[-1]
1037
+ self.ui.Explorer.ITEpar.ind[-1]=ind_new[-1]
1038
+ ITEs:ITEpar=self.ui.Explorer.ITEsfromInd(ind)
1039
+ ITEs[0].modifiedDate=currentTimeString()
1040
+ ITEs[0].date=f'Modified: {ITE.modifiedDate}'
1041
+
1042
+ TRE:TREpar=self.projectTree.itemList[0][ITE.ind[0]]
1043
+ TRE.modifiedDate=ITEs[0].modifiedDate
1044
+ TRE.date=ITEs[0].date
1045
+ TRE.FlagSaved=False
1046
+
1047
+ self.GPApar.modifiedDate=ITEs[0].modifiedDate
1048
+ self.GPApar.date=ITEs[0].date
1049
+ self.GPApar.FlagSaved=False
1050
+
1051
+ self.ui.Explorer.ITEpar.copyfrom(ITE)
1052
+ self.TREpar.copyfrom(TRE)
1053
+ self.adjustItemWidgets(ind)
1054
+
1055
+ self.inheritance(ind)
1056
+ self.IOVinheritance(ind)
1057
+ self.adjustDependencies(ITE)
1058
+ #self.checkFutureProc()
1059
+ tab.add_TABpar_bridge=add_TABpar_bridge
1060
+
1061
+ def define_setTABpar_bridge(self,tab:gPaIRS_Tab):
1062
+ def setTABpar_bridge(FlagAdjustPar,FlagCallback=False):
1063
+ focusWidget=self.focusWidget()
1064
+ TABname=tab.TABname
1065
+ self.bridge(TABname)
1066
+ if FlagAdjustPar:
1067
+ FlagSettingPar=TABpar.FlagSettingPar
1068
+ TABpar.FlagSettingPar=True
1069
+ for w in self.tabWidgets:
1070
+ if w.TABpar.FlagNone: continue
1071
+ w:gPaIRS_Tab
1072
+ if w!=tab:
1073
+ w.adjustTABpar()
1074
+ self.bridge(w.TABname)
1075
+ TABpar.FlagSettingPar=FlagSettingPar
1076
+ FlagAdjustPar=False
1077
+ FlagBridge=False
1078
+ FlagDisplayControls=False
1079
+ for w in self.tabWidgets:
1080
+ w:gPaIRS_Tab
1081
+ if not w.TABpar.FlagNone and w!=self.w_Log:
1082
+ if w.TABpar_old.isDifferentFrom(w.TABpar,exceptions=['ind'],FlagStrictDiff=True):
1083
+ w.setTABpar(FlagAdjustPar,FlagBridge,FlagCallback,FlagDisplayControls) #setting parameters without bridge
1084
+ else:
1085
+ if w==self.w_Vis_CalVi and w.TABpar.plane and w.TABpar.cam:
1086
+ self.w_Vis_CalVi.calibView.show()
1087
+ w.TABpar_old.copyfrom(w.TABpar,exceptions=['ind'])
1088
+ if not FlagCallback:
1089
+ w.adjustTABparInd()
1090
+ self.ui.Explorer.ITEpar.FlagInit=False
1091
+ self.ui.Explorer.setITElayout()
1092
+ if not self.w_Log.TABpar.FlagNone:
1093
+ if self.w_Log.LOGpar.flagRun!=-2:
1094
+ self.logBridge()
1095
+ if self.w_Log.TABpar_old.isDifferentFrom(self.w_Log.TABpar,FlagStrictDiff=True):
1096
+ self.w_Log.setTABpar(FlagAdjustPar,FlagBridge,FlagCallback)
1097
+ else:
1098
+ self.w_Log.TABpar_old.copyfrom(self.w_Log.TABpar,exceptions=['ind'])
1099
+ if not FlagCallback: self.w_Log.adjustTABparInd()
1100
+ else:
1101
+ self.w_Log.setTABpar(FlagAdjustPar=False,FlagBridge=False,FlagCallback=False)
1102
+ if not FlagCallback:
1103
+ self.inheritance(tab.TABpar.ind)
1104
+ ITE_ind:ITEpar=self.ui.Explorer.ITEfromInd(tab.TABpar.ind)
1105
+ self.adjustDependencies(ITE_ind)
1106
+ self.ui.tabAreaWidget.display_controls()
1107
+
1108
+ if focusWidget:
1109
+ self.app.processEvents()
1110
+ focusWidget.setFocus()
1111
+ tab.setTABpar_bridge=setTABpar_bridge
1112
+
1113
+ def logBridge(self):
1114
+ OUT:OUTpar = self.w_Output.TABpar
1115
+ LOG:LOGpar = self.w_Log.TABpar
1116
+ VIS:VISpar = self.w_Vis.TABpar
1117
+ ITE:ITEpar = self.ui.Explorer.ITEpar #self.ui.Explorer.ITEfromTRE(self.TREpar)
1118
+
1119
+ if ITE.flagRun==0:
1120
+ warningMessages=[]
1121
+ errorMessages=[]
1122
+ for w in self.tabWidgets[:-1]:
1123
+ w:gPaIRS_Tab
1124
+ par:TABpar= w.TABpar
1125
+ if w!=self.w_Log and not par.FlagNone:
1126
+ if par.OptionDone==0: errorMessages.append('--- '+w.TABname+' ---\n'+par.warningMessage)
1127
+ elif par.OptionDone!=1: warningMessages.append('--- '+w.TABname+' ---\n'+par.warningMessage)
1128
+
1129
+
1130
+ warnigText='\n\n'.join(warningMessages)
1131
+ if warnigText:
1132
+ warnigText='\n\n'+ITE.procdata.headerSection('WARNINGS',warnigText,'!')
1133
+ errorText='\n\n'.join(errorMessages)
1134
+ if errorText:
1135
+ errorText='\n\n'+ITE.procdata.headerSection('CRITICAL ISSUES',errorText,'X')
1136
+ LOG.text=PaIRS_Header+ITE.procdata.itemname+warnigText+errorText
1137
+ if VIS.FlagView:
1138
+ outPathRoot=myStandardRoot(OUT.path+OUT.subfold+OUT.root)
1139
+ logfile=ITE.procdata.procOutName()+'.log'
1140
+ if ITE.procdata.outPathRoot=='': logfile=outPathRoot+logfile
1141
+ border='o' #·●⦁᛫
1142
+ headerWidth=54
1143
+ result_text = '\n\n\n\n\n'+ITE.procdata.eyeHeaderSection('EXISTING PROCESS LOG',width=headerWidth,border=border) +f"\nLog file: '{os.path.basename(logfile)}'\n\n"
1144
+ if os.path.isfile(logfile):
1145
+ try:
1146
+ with open(logfile, 'r', encoding='utf-8') as f:
1147
+ log_content = f.read()
1148
+ result_text += "\n" + log_content
1149
+ except Exception as e:
1150
+ result_text += f"\nError reading log file '{os.path.basename(logfile)}:'\n{e}"
1151
+ else:
1152
+ result_text += f"\nLog file '{os.path.basename(logfile)}' not found!"
1153
+ LOG.text+=result_text+'\n\n'+ITE.procdata.headerSection('END of EXISTING PROCESS LOG',' ',border,headerWidth)
1154
+ else:
1155
+ LOG.text=ITE.procdata.Log
1156
+
1157
+ def bridge(self,TABname:str,ind:list=None):
1158
+ if ind is None:
1159
+ INP:INPpar = self.w_Input.TABpar
1160
+ OUT:OUTpar = self.w_Output.TABpar
1161
+ PRO:PROpar = self.w_Process.TABpar
1162
+ VIS:VISpar = self.w_Vis.TABpar
1163
+
1164
+ PRO_Min:PROpar_Min = self.w_Process_Min.TABpar
1165
+ PRO_Disp:PROpar_Disp = self.w_Process_Disp.TABpar
1166
+
1167
+ CAL:CALpar = self.w_Calibration.TABpar
1168
+ INP_CalVi:INPpar_CalVi = self.w_Input_CalVi.TABpar
1169
+ PRO_CalVi:PROpar_CalVi = self.w_Process_CalVi.TABpar
1170
+ VIS_CalVi:VISpar_CalVi = self.w_Vis_CalVi.TABpar
1171
+
1172
+ ITE:ITEpar = self.ui.Explorer.TABpar #self.ui.Explorer.ITEfromTRE(self.TREpar)
1173
+ SPL:SPLpar = self.ui.tabAreaWidget.TABpar
1174
+ else:
1175
+ INP:INPpar = self.w_Input.TABpar_at(ind)
1176
+ OUT:OUTpar = self.w_Output.TABpar_at(ind)
1177
+ PRO:PROpar = self.w_Process.TABpar_at(ind)
1178
+ VIS:VISpar = self.w_Vis.TABpar_at(ind)
1179
+
1180
+ PRO_Min:PROpar_Min = self.w_Process_Min.TABpar_at(ind)
1181
+ PRO_Disp:PROpar_Disp = self.w_Process_Disp.TABpar_at(ind)
1182
+
1183
+ CAL:CALpar = self.w_Calibration.TABpar_at(ind)
1184
+ INP_CalVi:INPpar_CalVi = self.w_Input_CalVi.TABpar_at(ind)
1185
+ PRO_CalVi:PROpar_CalVi = self.w_Process_CalVi.TABpar_at(ind)
1186
+ VIS_CalVi:VISpar_CalVi = self.w_Vis_CalVi.TABpar_at(ind)
1187
+
1188
+ ITE:ITEpar = self.ui.Explorer.ITEfromInd(ind) #self.ui.Explorer.ITEfromTRE(self.TREpar)
1189
+ SPL:SPLpar = self.ui.tabAreaWidget.TABpar_at(ind)
1190
+
1191
+ if ITE.Step in [StepTypes.min,StepTypes.piv,StepTypes.disp,StepTypes.spiv]:
1192
+ if TABname=='Input':
1193
+ OUT.inputPath=INP.path
1194
+ OUT.imageFile=None
1195
+ if INP.nimg:
1196
+ for c in range(len(INP.imList)):
1197
+ for f in range(len(INP.imList[c])):
1198
+ for k in range(len(INP.imList[c][f])):
1199
+ if INP.imEx[c][f][k]:
1200
+ OUT.imageFile=INP.imList[c][f][k]
1201
+ break
1202
+
1203
+ VIS.img=INP.selection[0]
1204
+ VIS.cam=INP.selection[1]
1205
+ VIS.frame=INP.selection[2]
1206
+ VIS.ncam=INP.ncam
1207
+ VIS.path=INP.path
1208
+ VIS.imList=copy.deepcopy(INP.imList)
1209
+ VIS.nimg=INP.nimg
1210
+ VIS.Out.copyfrom(OUT)
1211
+ elif TABname=='Output':
1212
+ if VIS.Out.isDifferentFrom(OUT):
1213
+ VIS.Out.copyfrom(OUT)
1214
+ self.w_Vis.FlagResetSizes=True
1215
+ if ITE.Step in [StepTypes.piv,StepTypes.disp,StepTypes.spiv]:
1216
+ outPathRoot=myStandardRoot(OUT.path+OUT.subfold+OUT.root)
1217
+ ndig=len(str(VIS.nimg))
1218
+ outExt=list(outType_dict)[OUT.outType]
1219
+ VIS.outPathRoot=outPathRoot
1220
+ VIS.name_proc=ITE.procdata.name_proc
1221
+ VIS.fres=[outPathRoot+'_', ndig, outExt] #lambda i: f"{outPathRoot}_{i:0{ndig:d}d}{outExt}"
1222
+ elif ITE.Step == StepTypes.min:
1223
+ imListMin=[]
1224
+ outPathRoot=myStandardRoot(OUT.path+OUT.subfold+OUT.root)
1225
+ for c in range(INP.ncam):
1226
+ imListMin.append([outPathRoot+f'_cam{c+1}_a_min.png',outPathRoot+f'_cam{c+1}_b_min.png'])
1227
+
1228
+ INP.FlagMIN = True
1229
+ INP.FlagTR = PRO_Min.FlagTR
1230
+ INP.LaserType = PRO_Min.LaserType
1231
+ INP.imListMin = deep_duplicate(imListMin)
1232
+
1233
+ VIS.FlagMIN = ITE.procdata.flagRun>0
1234
+ VIS.FlagTR = PRO_Min.FlagTR
1235
+ VIS.LaserType = PRO_Min.LaserType
1236
+ VIS.imListMin = deep_duplicate(imListMin)
1237
+ elif TABname=='Process_Min':
1238
+ INP.FlagTR=PRO_Min.FlagTR
1239
+ INP.LaserType=PRO_Min.LaserType
1240
+ VIS.FlagTR=PRO_Min.FlagTR
1241
+ VIS.LaserType=PRO_Min.LaserType
1242
+ elif TABname=='Process_Disp':
1243
+ if VIS.Pro.isDifferentFrom(PRO_Disp,exceptions=['FlagBordo']):
1244
+ VIS.Pro.copyfrom(PRO_Disp,exceptions=['FlagBordo'])
1245
+ VIS.Nit=PRO_Disp.Nit if VIS.flagRun!=-2 else ITE.procdata.numFinalized
1246
+ elif TABname=='Process':
1247
+ if VIS.Pro.isDifferentFrom(PRO):
1248
+ VIS.Pro.copyfrom(PRO)
1249
+ elif TABname=='Vis':
1250
+ INP.selection=[VIS.img,VIS.cam,VIS.frame]
1251
+ self.w_Input.InputAdjustSelection(INP)
1252
+ pass
1253
+ elif ITE.Step in [StepTypes.cal]:
1254
+ INP_CalVi.FlagReadCalib=PRO_CalVi.CalibProcType>=2
1255
+ INP_CalVi.CalibProcType=PRO_CalVi.CalibProcType
1256
+ if TABname=='Calibration':
1257
+ #FlagPrev=CAL.ind[-1]==len(self.w_Calibration.TABpar_prev_at(CAL.ind))-1
1258
+ self.ui.logo_CalVi.setVisible(CAL.FlagCalVi and CAL.flagRun==0 and not CAL.link) #and FlagPrev)
1259
+ self.ui.button_Run_CalVi.setVisible(CAL.FlagCalVi and CAL.flagRun==0 and not CAL.link) #and FlagPrev)
1260
+ if CAL.isDifferentFrom(self.w_Calibration.CALpar_old,fields=['FlagCalVi','flagRun']) or not INP_CalVi.FlagInit:
1261
+ for w in [self.w_Input_CalVi,self.w_Process_CalVi,self.w_Vis_CalVi]:
1262
+ k=self.ui.tabAreaWidget.widgets.index(w)
1263
+ SPL.FlagVisible[k]=CAL.FlagCalVi
1264
+ w.buttonTab.setVisible(CAL.FlagCalVi)
1265
+ self.ui.tabAreaWidget.splitterResize(FlagReleased=False)
1266
+ width=sum([s if f else 0 for s,f in zip(SPL.sizes,SPL.FlagVisible)])
1267
+ if width<self.ui.tabAreaWidget.width():
1268
+ SPL.sizes[-1]= self.ui.tabAreaWidget.width()-width
1269
+ else: SPL.sizes[-1]=0
1270
+ #ITE.ncam=CAL.ncam
1271
+ #ITE.progress=len(CAL.calList)
1272
+ elif TABname=='Input_CalVi':
1273
+ VIS_CalVi.plane=int(INP_CalVi.row)*(1+PRO_CalVi.TargetType)+1
1274
+ VIS_CalVi.FlagResetLevels=INP_CalVi.isDifferentFrom(self.w_Input_CalVi.INPpar_old,fields=['path']) or len(self.w_Input_CalVi.INPpar_old.filenames)==0
1275
+ VIS_CalVi.FlagResetZoom=INP_CalVi.isDifferentFrom(self.w_Input_CalVi.INPpar_old,fields=['x','y','w','h','W','H']) or len(self.w_Input_CalVi.INPpar_old.filenames)==0
1276
+ pass
1277
+ elif TABname=='Process_CalVi':
1278
+ INP_CalVi.FlagOptPlane=PRO_CalVi.CalibProcType>0
1279
+ if len(INP_CalVi.plapar):
1280
+ if INP_CalVi.FlagOptPlane:
1281
+ for k,p in enumerate(INP_CalVi.plapar):
1282
+ if len(p)==1:
1283
+ INP_CalVi.plapar[k]=[float(0)]*5+[p[0]]
1284
+ else:
1285
+ for k,p in enumerate(INP_CalVi.plapar):
1286
+ if len(p)>1:
1287
+ INP_CalVi.plapar[k]=[p[-1]]
1288
+ pass
1289
+ elif TABname=='Vis_CalVi':
1290
+ if VIS_CalVi.plane-1!=INP_CalVi.row:
1291
+ INP_CalVi.row=int( (VIS_CalVi.plane-1)/(1+PRO_CalVi.TargetType) )
1292
+ INP_CalVi.rows=[INP_CalVi.row]
1293
+ #INP_CalVi.col=0
1294
+ #INP_CalVi.cols=[INP_CalVi.col]
1295
+ pass
1296
+ else:
1297
+ pass
1298
+ return
1299
+
1300
+ def getInheritance(self, ind):
1301
+ indpar=[j for j in ind]
1302
+ for j in range(indpar[-2]):
1303
+ indpar[-2]=j
1304
+ self.inheritance(indpar)
1305
+
1306
+ def inheritance(self,indpar):
1307
+ ITE:ITEpar = self.ui.Explorer.ITEfromInd(indpar) #self.ui.Explorer.ITEfromTRE(self.TREpar)
1308
+ if ITE.FlagNone: return
1309
+ ind=copy.deepcopy(ITE.ind)
1310
+ Process=ITE.Process
1311
+ Step=ITE.Step
1312
+
1313
+ if Process in (ProcessTypes.piv,ProcessTypes.spiv) and Step == StepTypes.min:
1314
+ if ITE.active:
1315
+ FlagMIN=True
1316
+ INP:INPpar = self.w_Input.TABpar_at(ind)
1317
+ OUT:OUTpar = self.w_Output.TABpar_at(ind)
1318
+ PRO_Min:PROpar_Min = self.w_Process_Min.TABpar_at(ind)
1319
+ FlagTR=PRO_Min.FlagTR
1320
+ LaserType=PRO_Min.LaserType
1321
+ imListMin=[]
1322
+ outPathRoot=myStandardRoot(OUT.path+OUT.subfold+OUT.root)
1323
+ for c in range(INP.ncam):
1324
+ imListMin.append([outPathRoot+f'_cam{c+1}_a_min.png',outPathRoot+f'_cam{c+1}_b_min.png'])
1325
+ imageFileMin=INP.path
1326
+ FlagImage=False
1327
+ for c in range(len(INP.imList)):
1328
+ for f in range(len(INP.imList[c])):
1329
+ if INP.imList[c][f]:
1330
+ imageFileMin+=INP.imList[c][f][0]
1331
+ FlagImage=True
1332
+ break
1333
+ if FlagImage: break
1334
+ else:
1335
+ FlagMIN=False
1336
+ FlagTR=False
1337
+ LaserType=0 #0 single, 1 double
1338
+ imListMin=[]
1339
+ imageFileMin=None
1340
+ if Process==ProcessTypes.piv:
1341
+ children=[+1] #piv step
1342
+ else:
1343
+ children=[+1,+2] #disparity, spiv steps
1344
+ for c in children:
1345
+ ind_child=copy.deepcopy(ind)
1346
+ ind_child[-2]+=c
1347
+ TABpar_prev=self.w_Input.TABpar_prev_at(ind_child)
1348
+
1349
+ for d in range(len(TABpar_prev)):
1350
+ ind_child[-1]=d
1351
+ INP_child:INPpar=self.w_Input.TABpar_at(ind_child)
1352
+ INP_child.FlagMIN = FlagMIN
1353
+ INP_child.FlagTR = FlagTR
1354
+ INP_child.LaserType = LaserType
1355
+ INP_child.imListMin = deep_duplicate(imListMin)
1356
+ #INP_child.FlagInit = False
1357
+
1358
+ OUT_child:OUTpar=self.w_Output.TABpar_at(ind_child)
1359
+ OUT_child.imageFileMin = imageFileMin
1360
+
1361
+ VIS_child:VISpar=self.w_Vis.TABpar_at(ind_child)
1362
+ VIS_child.FlagMIN = ITE.procdata.flagRun>0
1363
+ VIS_child.FlagTR = FlagTR
1364
+ VIS_child.LaserType = LaserType
1365
+ VIS_child.imListMin = deep_duplicate(imListMin)
1366
+ #VIS_child.FlagInit = False
1367
+
1368
+ elif Process == ProcessTypes.spiv and Step == StepTypes.cal:
1369
+ if ITE.active:
1370
+ CAL:CALpar = self.w_Calibration.TABpar_at(ind)
1371
+ FlagCAL=ITE.procdata.flagRun>0
1372
+
1373
+ calList=CAL.calList
1374
+ calEx=CAL.calEx
1375
+ else:
1376
+ FlagCAL=False
1377
+ calList=[]
1378
+ calEx=[]
1379
+ children=[+1,+2,+3] #disparity, spiv steps
1380
+ for c in children:
1381
+ ind_child=copy.deepcopy(ind)
1382
+ ind_child[-2]+=c
1383
+
1384
+ for d in range(len(self.w_Input.TABpar_prev_at(ind_child))):
1385
+ ind_child[-1]=d
1386
+
1387
+ INP_child:INPpar=self.w_Input.TABpar_at(ind_child)
1388
+ INP_child.FlagCAL = FlagCAL
1389
+ INP_child.calList = copy.deepcopy(calList)
1390
+ INP_child.calEx = copy.deepcopy(calEx)
1391
+ #INP_child.FlagInit = False
1392
+
1393
+ VIS_child:VISpar=self.w_Vis.TABpar_at(ind_child)
1394
+ VIS_child.FlagCAL = FlagCAL
1395
+ VIS_child.calList = copy.deepcopy(calList)
1396
+ VIS_child.calEx = copy.deepcopy(calEx)
1397
+ #VIS_child.FlagInit = False
1398
+
1399
+ elif Process == ProcessTypes.spiv and Step == StepTypes.disp:
1400
+ if ITE.active:
1401
+ FlagDISP=True
1402
+ else:
1403
+ FlagDISP=False
1404
+ children=[+1] #disparity, spiv steps
1405
+ for c in children:
1406
+ ind_child=copy.deepcopy(ind)
1407
+ ind_child[-2]+=c
1408
+ TABpar_prev=self.w_Input.TABpar_prev_at(ind_child)
1409
+
1410
+ for d in range(len(TABpar_prev)):
1411
+ ind_child[-1]=d
1412
+ OUT_child:OUTpar=self.w_Output.TABpar_at(ind_child)
1413
+ OUT_child.FlagDISP = FlagDISP
1414
+ """
1415
+ elif Process == ProcessTypes.spiv and Step == StepTypes.disp:
1416
+ if ITE.active:
1417
+ FlagDISP=True
1418
+ INP:INPpar = self.w_Input.TABpar_at(ind)
1419
+ OUT:OUTpar = self.w_Output.TABpar_at(ind)
1420
+ zconst=OUT.zconst
1421
+ xterm=OUT.xterm
1422
+ yterm=OUT.yterm
1423
+ outPathRoot=myStandardRoot(OUT.path+OUT.subfold+OUT.root)
1424
+ dispFile=outPathRoot+'.clz'
1425
+ else:
1426
+ FlagDISP=False
1427
+ zconst=0.0
1428
+ xterm=0.0
1429
+ yterm=0.0
1430
+ dispFile=''
1431
+ children=[+1] #disparity, spiv steps
1432
+ FlagInit=True
1433
+ for c in children:
1434
+ ind_child=copy.deepcopy(ind)
1435
+ ind_child[-2]+=c
1436
+ TABpar_prev=self.w_Input.TABpar_prev_at(ind_child)
1437
+
1438
+ for d in range(len(TABpar_prev)):
1439
+ ind_child[-1]=d
1440
+
1441
+ INP_child:INPpar=self.w_Input.TABpar_at(ind_child)
1442
+ INP_child.FlagDISP = FlagDISP
1443
+ INP_child.dispFile = dispFile
1444
+ #INP_child.FlagInit = False
1445
+
1446
+ OUT_child:OUTpar=self.w_Output.TABpar_at(ind_child)
1447
+ OUT_child.FlagDISP = FlagDISP
1448
+ OUT_child.zconst= zconst
1449
+ OUT_child.xterm = xterm
1450
+ OUT_child.yterm = yterm
1451
+
1452
+ VIS_child:VISpar=self.w_Vis.TABpar_at(ind_child)
1453
+ VIS_child.FlagDISP = FlagDISP
1454
+ VIS_child.dispFile = dispFile
1455
+ #VIS_child.FlagInit = False
1456
+
1457
+ pass
1458
+ """
1459
+
1460
+ ITEs=self.ui.Explorer.ITEsfromInd(indpar)
1461
+ #currInd=list(ITEs[0].children).index(ITE.Step)+1
1462
+ for c in range(len(ITEs)): #range(currInd+1,len(ITEs))
1463
+ ITE_ind:ITEpar=ITEs[c]
1464
+ self.checkProcesses(FlagInit=True,ind=ITE_ind.ind)
1465
+ #self.checkProcesses(FlagInit=False,ind=ITE_ind.ind)
1466
+ self.ui.Explorer.setITElayout(ITE_ind)
1467
+ return
1468
+
1469
+ def IOVinheritance(self,indpar):
1470
+ ITE:ITEpar = self.ui.Explorer.ITEfromInd(indpar) #self.ui.Explorer.ITEfromTRE(self.TREpar)
1471
+ if ITE.FlagNone: return
1472
+ ind=copy.deepcopy(ITE.ind)
1473
+ Step=ITE.Step
1474
+ #inverse inheritance
1475
+ if Step not in (StepTypes.cal,) and ITE.active:
1476
+ INP:INPpar = self.w_Input.TABpar_at(ind)
1477
+ OUT:OUTpar = self.w_Output.TABpar_at(ind)
1478
+ VIS:VISpar = self.w_Vis.TABpar_at(ind)
1479
+
1480
+ #children=[-2, -1] if Step==StepTypes.spiv else [-1] #disparity, spiv steps #*
1481
+ for c in range(len(processData[ITE.Process]['children'])): #in children: #*
1482
+ ind_child=copy.deepcopy(ind)
1483
+ #ind_child[-2]+=c #*
1484
+ ind_child[-2]=c
1485
+ TABpar_prev=self.w_Input.TABpar_prev_at(ind_child)
1486
+ if TABpar_prev[0] is None: continue
1487
+
1488
+ FlagInit=len(TABpar_prev)==1 and TABpar_prev[0].flagRun==0
1489
+ if FlagInit:
1490
+ ind_child[-1]=0
1491
+ INP_child:INPpar=self.w_Input.TABpar_at(ind_child)
1492
+ INP_child.copyfrom(INP,exceptions=['Process','Step']+INP_child.parFields)
1493
+
1494
+ OUT_child:OUTpar=self.w_Output.TABpar_at(ind_child)
1495
+ OUT_child.copyfrom(OUT,exceptions=['Process','Step']+OUT_child.parFields)
1496
+
1497
+ VIS_child:VISpar=self.w_Vis.TABpar_at(ind_child)
1498
+ VIS_child.copyfrom(VIS,exceptions=['Process','Step']+VIS_child.parFields)
1499
+
1500
+ self.checkProcesses(FlagInit=True,ind=ind_child)
1501
+ self.checkProcesses(FlagInit=False,ind=ind_child)
1502
+ ITE_ind:ITEpar = self.ui.Explorer.ITEfromInd(ind_child)
1503
+ self.ui.Explorer.setITElayout(ITE_ind)
1504
+ self.inheritance(ind_child)
1505
+
1506
+ def IOVcopy(self,ind_slave,ind_master):
1507
+ ITE:ITEpar = self.ui.Explorer.ITEfromInd(ind_master) #self.ui.Explorer.ITEfromTRE(self.TREpar)
1508
+ if ITE.FlagNone: return
1509
+
1510
+ #Input/Output/Vis inheritance
1511
+ INP:INPpar = self.w_Input.TABpar_at(ind_master)
1512
+ OUT:OUTpar = self.w_Output.TABpar_at(ind_master)
1513
+ VIS:VISpar = self.w_Vis.TABpar_at(ind_master)
1514
+
1515
+ self.w_Input.INPpar.copyfrom(INP,exceptions=['Process','Step']+INP.parFields)
1516
+ self.w_Output.OUTpar.copyfrom(OUT,exceptions=['Process','Step']+OUT.parFields)
1517
+ self.w_Vis.VISpar.copyfrom(VIS,exceptions=['Process','Step']+VIS.parFields)
1518
+
1519
+ FlagNewPar=self.w_Input.isNewPar() or self.w_Output.isNewPar()
1520
+ ind_slave=self.w_Input.add_TABpar('Copy input/output data from step',FlagNewPar)
1521
+ self.setTABpars_at(ind_slave,FlagAdjustPar=True,FlagBridge=True,widget=self.w_Input)
1522
+
1523
+ ITE_slave:ITEpar = self.ui.Explorer.ITEfromInd(ind_slave) #self.ui.Explorer.ITEfromTRE(self.TREpar)
1524
+ self.ui.Explorer.setITElayout(ITE_slave)
1525
+ return
1526
+
1527
+ #*************************************************** Update workspace and projects
1528
+ def updateWorkspace(self):
1529
+ self.GPApar.modifiedDate=currentTimeString()
1530
+ self.GPApar.date=f'Modified: {self.GPApar.modifiedDate}'
1531
+ self.GPApar.FlagSaved=False
1532
+
1533
+ self.adjustWorkspaceHeader()
1534
+
1535
+ def adjustWorkspaceHeader(self):
1536
+ if self.GPApar.outName and self.GPApar.outName!=lastcfgname:
1537
+ title=self.GPApar.name+self.GPApar.saveBullet()
1538
+ subtitle=self.GPApar.date
1539
+ icon=self.GPApar.icon
1540
+ FlagVisible=True
1541
+ else:
1542
+ title=''
1543
+ subtitle=''
1544
+ icon=None
1545
+ FlagVisible=False
1546
+ self.ui.title_workspace.setVisible(FlagVisible)
1547
+ self.ui.subtitle_workspace.setVisible(FlagVisible)
1548
+ self.ui.title_workspace.setText(title)
1549
+ self.ui.subtitle_workspace.setText(subtitle)
1550
+
1551
+ InfoMessage=self.GPApar.InfoMessage()
1552
+ self.ui.title_workspace.setToolTip(InfoMessage)
1553
+ self.ui.title_workspace.setStatusTip(InfoMessage)
1554
+ self.ui.subtitle_workspace.setToolTip(InfoMessage)
1555
+ self.ui.subtitle_workspace.setStatusTip(InfoMessage)
1556
+
1557
+ self.ui.workspace_icon.setVisible(icon is not None)
1558
+ self.adjustMenuFile()
1559
+
1560
+ self.setGPaIRSTitle()
1561
+
1562
+ def adjustMenuFile(self):
1563
+ self.ui.actionSave.setEnabled(not self.GPApar.FlagSaved)
1564
+ self.ui.actionClose.setEnabled(self.GPApar.outName not in ('',lastcfgname))
1565
+
1566
+ def updateProjectItemWidget(self):
1567
+ TRE:TREpar=self.projectTree.itemList[0][self.TREpar.project]
1568
+ TRE.modifiedDate=currentTimeString()
1569
+ TRE.date=f'Modified: {TRE.modifiedDate}'
1570
+ TRE.FlagSaved=False
1571
+ self.TREpar.copyfrom(TRE)
1572
+
1573
+ self.GPApar.modifiedDate=TRE.modifiedDate
1574
+ self.GPApar.date=TRE.date
1575
+ self.GPApar.FlagSaved=False
1576
+
1577
+ self.adjustItemWidgets()
1578
+
1579
+ def adjustItemWidgets(self,ind=None):
1580
+ if ind is None: ind=[self.TREpar.project, self.TREpar.tree, self.TREpar.process, self.TREpar.step, -1]
1581
+ TRE:TREpar=self.projectTree.itemList[0][ind[0]]
1582
+ topLevelItem=self.projectTree.topLevelItem(ind[0])
1583
+ itemWidget=self.projectTree.itemWidget(topLevelItem,1)
1584
+ if itemWidget:
1585
+ title:QLabel=itemWidget.findChildren(QLabel,'title_project')[0]
1586
+ title.setText(TRE.name+TRE.saveBullet())
1587
+ subtitle:QLabel=itemWidget.findChildren(QLabel,'subtitle_project')[0]
1588
+ subtitle.setText(TRE.date)
1589
+ InfoMessage=TRE.InfoMessage()
1590
+ title.setToolTip(InfoMessage)
1591
+ title.setStatusTip(InfoMessage)
1592
+ subtitle.setToolTip(InfoMessage)
1593
+ subtitle.setStatusTip(InfoMessage)
1594
+ if self.TREpar.project==ind[0] and self.TREpar.tree==ind[1] and self.TREpar.process is not None:
1595
+ self.adjustTitleHeader()
1596
+ self.projectTree.actionBar.button_save.setEnabled(not self.TREpar.FlagSaved)
1597
+ topLevelItem=self.processTree.topLevelItem(ind[2])
1598
+ itemWidget=self.processTree.itemWidget(topLevelItem,1)
1599
+ if itemWidget:
1600
+ title:QLabel=itemWidget.findChildren(QLabel,'title_process')[0]
1601
+ subtitle:QLabel=itemWidget.findChildren(QLabel,'subtitle_process')[0]
1602
+ subtitle.setText(TRE.date)
1603
+ ITE:ITEpar=self.ui.Explorer.ITEfromTRE(TRE)
1604
+ InfoMessage=ITE.InfoMessage()
1605
+ title.setToolTip(InfoMessage)
1606
+ title.setStatusTip(InfoMessage)
1607
+ subtitle.setToolTip(InfoMessage)
1608
+ subtitle.setStatusTip(InfoMessage)
1609
+ self.adjustTitleHeader()
1610
+ self.adjustWorkspaceHeader()
1611
+
1612
+ def adjustTitleHeader(self):
1613
+ if self.TREpar.project is None:
1614
+ title='Welcome to PaIRS'
1615
+ subtitle='Particle Image Reconstruction Software'
1616
+ icon=None
1617
+ self.currITEpar=None
1618
+ else:
1619
+ title=self.TREpar.name+self.TREpar.saveBullet()
1620
+ if self.TREpar.process is None or self.TREpar.step is None:
1621
+ subtitle=self.TREpar.date
1622
+ icon=self.TREpar.icon
1623
+ self.currITEpar=self.TREpar
1624
+ else:
1625
+ ITEs:ITEpar=self.ui.Explorer.ITEsfromTRE(self.TREpar)
1626
+ title+=': '+ITEs[0].name
1627
+ subtitle=self.TREpar.date
1628
+ icon=ITEs[self.TREpar.step].icon
1629
+ self.currITEpar=ITEs[self.TREpar.step]
1630
+ self.ui.title.setText(title)
1631
+ self.ui.subtitle.setText(subtitle)
1632
+
1633
+ if self.currITEpar:
1634
+ InfoMessage=self.currITEpar.InfoMessage()
1635
+ else:
1636
+ InfoMessage=''
1637
+ self.ui.title.setToolTip(InfoMessage)
1638
+ self.ui.title.setStatusTip(InfoMessage)
1639
+ self.ui.subtitle.setToolTip(InfoMessage)
1640
+ self.ui.subtitle.setStatusTip(InfoMessage)
1641
+
1642
+ self.ui.title_icon.setVisible(icon is not None)
1643
+ self.ui.title_icon.setIcon(TreeIcons.icons[icon])
1644
+
1645
+ def adjustProcessSelection(self):
1646
+ FlagVisible=[False,False,False,False]
1647
+ if self.TREpar.project is None:
1648
+ FlagVisible[0]=True
1649
+ self.ui.Explorer.hideStepButtons()
1650
+ else:
1651
+ if self.TREpar.process is None:
1652
+ FlagVisible[1]=True
1653
+ self.ui.Explorer.hideStepButtons()
1654
+ else:
1655
+ if self.TREpar.step is None or self.TREpar.step==0:
1656
+ FlagVisible[2]=True
1657
+ else:
1658
+ FlagVisible[3]=True
1659
+ self.ui.projectPage.setVisible(FlagVisible[0])
1660
+ self.ui.processPage.setVisible(FlagVisible[1])
1661
+ self.ui.stepPage.setVisible(FlagVisible[2])
1662
+ self.ui.tabAreaWidget.setVisible(FlagVisible[3])
1663
+ self.w_RCL.setVisible(FlagVisible[3])
1664
+ #if FlagVisible[3]:
1665
+ # self.ui.tabAreaWidget.scrollArea.splitter.splitterResize()
1666
+
1667
+ self.adjustWorkspaceHeader()
1668
+ self.adjustTitleHeader()
1669
+ self.adjustSwitches()
1670
+
1671
+ self.ui.Explorer.cancelUndo()
1672
+
1673
+ def adjustProjectSelection(self):
1674
+ self.adjustProcessSelection()
1675
+ self.ui.Explorer.adjustProjectSelection()
1676
+
1677
+ def adjustSwitches(self):
1678
+ for k in range(len(self.projectTree.itemList[0])):
1679
+ topLevelItem=self.projectTree.topLevelItem(k)
1680
+ itemWidget=self.projectTree.itemWidget(topLevelItem,1)
1681
+ if itemWidget:
1682
+ switch:ModernSwitch=itemWidget.findChildren(ModernSwitch)[0]
1683
+ if switch:
1684
+ FlagVisible=any([i[0].flagRun<=0 and i[0].Process!=ProcessTypes.cal for i in self.projectTree.itemList[1][k][0]])
1685
+ self.projectTree.itemList[0][k].FlagRunnable=FlagVisible
1686
+ if not self.FlagRun:
1687
+ FlagQueue=len(self.projectTree.itemList[1][k][0])==0 or not FlagVisible or any([i[0].flagRun<=0 and i[0].Process!=ProcessTypes.cal and i[0].FlagQueue for i in self.projectTree.itemList[1][k][0]])
1688
+ else:
1689
+ FlagQueue=switch._checked
1690
+
1691
+ switch.setVisible(FlagVisible)
1692
+ switch.setSwitch(FlagQueue)
1693
+ self.projectTree.itemList[0][k].FlagQueue=FlagQueue
1694
+ if self.TREpar.project==k:
1695
+ self.TREpar.FlagQueue=FlagQueue
1696
+ #switch.setEnabled(self.FlagRun==0)
1697
+ if len(self.processTree.itemList):
1698
+ for k,i in enumerate(self.processTree.itemList[0]):
1699
+ topLevelItem=self.processTree.topLevelItem(k)
1700
+ itemWidget=self.processTree.itemWidget(topLevelItem,1)
1701
+ if itemWidget:
1702
+ switch:ModernSwitch=itemWidget.findChildren(ModernSwitch)[0]
1703
+ if switch:
1704
+ ITE:ITEpar=i[0]
1705
+ switch.setVisible(ITE.flagRun<=0 and ITE.Process!=ProcessTypes.cal and any([j.active and len(j.link)==0 for j in i[1:]]))
1706
+ #self.swithcEnabled(self.FlagRun==0)
1707
+ self.setButtonRunVisible()
1708
+
1709
+ #*************************************************** Link and copy
1710
+ def adjustDependencies(self,ITE:ITEpar):
1711
+ for ind_slave in ITE.dependencies:
1712
+ self.copy_pars(ind_slave,ITE.ind)
1713
+ #self.inheritance(ind_slave) #useless, already performed in copy_pars
1714
+ self.setLinks(ind_slave,ITE.ind)
1715
+
1716
+ def button_reset_step_action(self):
1717
+ if self.questionDialog('Are you sure you want to reset the current process step? This operation will affect all the subsequent steps in the process and it is irreversible!'):
1718
+ self.reset_step(self.ui.Explorer.ITEpar.ind)
1719
+ return
1720
+
1721
+ def reset_step(self,ind):
1722
+ FlagSettingPar=TABpar.FlagSettingPar
1723
+ TABpar.FlagSettingPar=True
1724
+ ITEs_ind:ITEpar=self.ui.Explorer.ITEsfromInd(ind)
1725
+ ind_child=copy.deepcopy(ind)
1726
+ for j in range(ind[-2],0,-1):
1727
+ ind_child[-2]=j-1
1728
+ ITE_ind:ITEpar=ITEs_ind[j]
1729
+ if not ITE_ind.active and ITE_ind.flagRun<0:
1730
+ ITE_ind.procdata=data=dataTreePar(ITE_ind.Process,ITE_ind.Step)
1731
+ ITE_ind.procdata.ind=ITE_ind.ind
1732
+ ITE_ind.progress=0
1733
+ self.setFlagRun(data,0,flagPrev=True)
1734
+ else:
1735
+ break
1736
+ for j in range(len(ITEs_ind)-1,ind[-2],-1):
1737
+ ind_child[-2]=j-1
1738
+ ITE_ind:ITEpar=ITEs_ind[j]
1739
+ ITE_ind.procdata=data=dataTreePar(ITE_ind.Process,ITE_ind.Step)
1740
+ ITE_ind.procdata.ind=ITE_ind.ind
1741
+ ITE_ind.progress=0
1742
+ self.setFlagRun(data,0,flagPrev=True)
1743
+ self.adjustDependencies(ITE_ind)
1744
+ self.inheritance(ind_child)
1745
+ ind_child[-1]=-1
1746
+ LOG_ind:LOGpar=self.w_Log.TABpar_at(ind_child)
1747
+ if LOG_ind:
1748
+ LOG_ind.progress=0
1749
+ if self.w_Log.LOGpar.ind[:-1]==LOG_ind.ind[:-1]:
1750
+ self.w_Log.setLOGlayout()
1751
+ self.ui.progress_Proc.setValue(0)
1752
+ self.setTABpars_at(ITE_ind.ind,FlagAdjustPar=True,widget=self.w_Calibration if ITE_ind.Step==StepTypes.cal else self.w_Vis)
1753
+ if data.ind[:-2]==self.ui.tabAreaWidget.TABpar.ind[:-2]:
1754
+ self.ui.Explorer.arrangeCurrentProcess(self.processTree)
1755
+
1756
+ self.adjustSwitches()
1757
+
1758
+ TABpar.FlagSettingPar=FlagSettingPar
1759
+
1760
+ def IOVheritableSteps(self):
1761
+ ITE=self.ui.Explorer.ITEpar
1762
+ stepList={}
1763
+ if len(self.processTree.itemList) and ITE.ind[2]<len(self.processTree.itemList[0]):
1764
+ for step in self.processTree.itemList[0][ITE.ind[2]]:
1765
+ step:ITEpar
1766
+ if step.active and ITE.ind[:-1]!=step.ind[:-1]:
1767
+ INP:INPpar = self.w_Input.TABpar_at(step.ind)
1768
+ OUT:OUTpar = self.w_Output.TABpar_at(step.ind)
1769
+ VIS:VISpar = self.w_Vis.TABpar_at(step.ind)
1770
+ if INP is not None and OUT is not None and VIS is not None:
1771
+ stepList[step.name]={'ind': step.ind, 'icon': step.icon}
1772
+ return stepList
1773
+
1774
+ def linkableSteps(self,FlagExcludeLinked=False):
1775
+ ITE=self.ui.Explorer.ITEpar
1776
+ stepList={}
1777
+ if len(self.processTree.itemList):
1778
+ for process in self.processTree.itemList[0]:
1779
+ ITE0:ITEpar=process[0]
1780
+ for step in process[1:]:
1781
+ step:ITEpar
1782
+ FlagNoOverLink=True if not FlagExcludeLinked else len(step.link)==0
1783
+ if step.active and step.Step==ITE.Step and ITE.ind[:-2]!=ITE0.ind[:-2] and FlagNoOverLink:
1784
+ stepList[f'{step.ind[-3]+1}: '+ITE0.name]={'ind': step.ind, 'icon': ITE0.icon}
1785
+ return stepList
1786
+
1787
+ def copy_link_action(self,button:QPushButton, fun=lambda ind_slave, ind_master:None, FlagExcludeLinked=False, menuTitle='Copy step from...',icon=None,message='No process step available!', stepListType=0):
1788
+ if stepListType==1:
1789
+ stepList=self.IOVheritableSteps()
1790
+ else:
1791
+ stepList=self.linkableSteps(FlagExcludeLinked=FlagExcludeLinked)
1792
+ ITE=self.ui.Explorer.ITEpar
1793
+ if len(stepList)==0:
1794
+ showTip(self,message)
1795
+ return None
1796
+ menu = QMenu(self)
1797
+ title_action = QAction(menuTitle, self)
1798
+ if icon: title_action.setIcon(icon)
1799
+ title_action.setDisabled(True) # Disabilita l'azione per evitare l'interazione
1800
+ menu.addAction(title_action)
1801
+ menu.addSeparator()
1802
+ for key, item in stepList.items():
1803
+ #for colormap in VIS_ColorMaps[colorMapClass]:
1804
+ nameItem=' '+key
1805
+ action:QAction = menu.addAction(TreeIcons.icons[item['icon']], nameItem)
1806
+ action.triggered.connect(lambda _, name=key: fun(ITE.ind,stepList[name]['ind']))
1807
+ return menu.exec(QCursor.pos()) #menu.exec(button.mapToGlobal(button.rect().bottomLeft()))
1808
+
1809
+ def button_step_inherit_action(self):
1810
+ self.copy_link_action(self.ui.button_step_inherit,lambda isl,ima: self.IOVcopy(isl,ima),menuTitle='Copy input/output data from...', message='No process step available!', stepListType=1)
1811
+
1812
+ def button_copy_step_action(self):
1813
+ self.copy_link_action(self.ui.button_copy_step,lambda isl,ima: self.copy_pars_proc(isl,ima,FlagNew=True))
1814
+
1815
+ def checkCamCompatibility(self,ind_slave,ind_master):
1816
+ ITE_slave:ITEpar=self.ui.Explorer.ITEfromInd(ind_slave)
1817
+ isCompatible=True
1818
+ if ITE_slave.Step==StepTypes.min:
1819
+ INP_slave:INPpar=self.w_Input.TABpar_at(ind_slave)
1820
+ ncam_slave=INP_slave.ncam
1821
+ INP_master:INPpar=self.w_Input.TABpar_at(ind_master)
1822
+ ncam_master=INP_master.ncam
1823
+ isCompatible=ncam_slave==ncam_master
1824
+ elif ITE_slave.Step==StepTypes.cal:
1825
+ CAL_slave:CALpar=self.w_Calibration.TABpar_at(ind_slave)
1826
+ ncam_slave=CAL_slave.ncam
1827
+ CAL_master:CALpar=self.w_Calibration.TABpar_at(ind_master)
1828
+ ncam_master=CAL_master.ncam
1829
+ isCompatible=ncam_slave==ncam_master
1830
+ if not isCompatible:
1831
+ warningMessage=f'The number of cameras in the current step (={ncam_slave}) is different from that in the selected step (={ncam_master}). Please, select a different step or modify the number of cameras in the selected step before proceeding!'
1832
+ self.warningDialog(warningMessage)
1833
+ return isCompatible
1834
+
1835
+ def copy_pars(self,ind_slave,ind_master,FlagNew=False):
1836
+ ind_new=[i for i in ind_slave]
1837
+ if FlagNew: ind_new[-1]+=1
1838
+ for w in self.tabWidgets:
1839
+ w:gPaIRS_Tab
1840
+ TAB_slave_curr:TABpar=w.TABpar_at(ind_slave)
1841
+ if TAB_slave_curr:
1842
+ if FlagNew: w.gen_TABpar(ind_new,Process=TAB_slave_curr.Process,Step=TAB_slave_curr.Step)
1843
+ TAB_slave:TABpar=w.TABpar_at(ind_new)
1844
+ TAB_slave.copyfrom(w.TABpar_at(ind_master),exceptions=['ind','link','Process'])
1845
+ ITE_master:ITEpar=self.ui.Explorer.ITEfromInd(ind_master)
1846
+ ITE_slave:ITEpar=self.ui.Explorer.ITEfromInd(ind_new)
1847
+ ITE_slave.ind=[i for i in ind_new]
1848
+ ITE_slave.copyfrom(ITE_master,exceptions=['procdata','ind','link','Process','dependencies'])
1849
+ ITE_slave.procdata.copyfrom(ITE_master.procdata,exceptions=['ind','link','Process'])
1850
+ self.getInheritance(ind_slave)
1851
+ self.ui.Explorer.undoInd=None
1852
+ self.inheritance(ind_slave)
1853
+ self.ui.Explorer.setITElayout(ITE_slave)
1854
+ self.adjustSwitches() #useless?
1855
+ return ind_new
1856
+
1857
+ def copy_pars_proc(self,ind_slave,ind_master,FlagNew=False,FlagSet=True):
1858
+ if not self.checkCamCompatibility(ind_slave,ind_master): return
1859
+ ITEs_slave=self.ui.Explorer.ITEsfromInd(ind_slave)
1860
+ ITEs_master=self.ui.Explorer.ITEsfromInd(ind_master)
1861
+ for c in range(ind_slave[-2]+1):
1862
+ ind_slave=ITEs_slave[c+1].ind
1863
+ ind_master=ITEs_master[c+1].ind
1864
+ ind_new=self.copy_pars(ind_slave,ind_master,FlagNew=True)
1865
+
1866
+ if FlagSet:
1867
+ self.ui.Explorer.arrangeCurrentProcess(self.ui.Explorer.processTree)
1868
+ self.ui.Explorer.selectStep()
1869
+ self.adjustSwitches()
1870
+ return ind_new
1871
+
1872
+ def copy_VIS(self,ind_slave,ind_master):
1873
+ ind_new=[i for i in ind_slave]
1874
+ w=self.w_Vis
1875
+ w:gPaIRS_Tab
1876
+ TAB_slave_curr:VISpar=w.TABpar_at(ind_slave)
1877
+ if TAB_slave_curr:
1878
+ TAB_slave:VISpar=w.TABpar_at(ind_new)
1879
+ TAB_slave.copyfromfields(w.TABpar_at(ind_master),fields=TAB_slave.graphics_fields)
1880
+ self.w_Vis.setTABpar_at(ind_new,FlagAdjustPar=True,FlagBridge=True)
1881
+ return ind_new
1882
+
1883
+ def button_link_step_action(self):
1884
+ if self.ui.button_link_step.isChecked():
1885
+ result=self.copy_link_action(self.ui.button_link_step,self.link_pars,FlagExcludeLinked=True,menuTitle='Link step to...')
1886
+ FlagUnlink=result is None
1887
+ else:
1888
+ FlagUnlink=True
1889
+ if FlagUnlink:
1890
+ ITE=self.ui.Explorer.ITEpar
1891
+ self.unlink_pars(ITE.ind)
1892
+ self.ui.button_link_step.setChecked(False)
1893
+
1894
+ def link_pars(self,ind_slave,ind_master,FlagSet=True):
1895
+ if not self.checkCamCompatibility(ind_slave,ind_master): return
1896
+ ITEs_slave=self.ui.Explorer.ITEsfromInd(ind_slave)
1897
+ ITEs_master=self.ui.Explorer.ITEsfromInd(ind_master)
1898
+ for c in range(ind_slave[-2]+1):
1899
+ ind_slave=ITEs_slave[c+1].ind
1900
+ ind_master=ITEs_master[c+1].ind
1901
+ ind_new=self.copy_pars(ind_slave,ind_master,FlagNew=True)
1902
+ self.setLinks(ind_new,ind_master)
1903
+ #item=self.processTree.topLevelItem(ind_new[2])
1904
+ #child=item.child(ind_new[3])
1905
+ #child.setIcon(0,self.processTree.linkedIcon)
1906
+
1907
+ #self.setTABpars_at(ind_new)
1908
+ if FlagSet:
1909
+ self.ui.Explorer.arrangeCurrentProcess(self.ui.Explorer.processTree)
1910
+ self.ui.Explorer.selectStep()
1911
+ self.adjustSwitches()
1912
+ return ind_new
1913
+
1914
+ def setLinks(self,ind_slave,ind_master,FlagUnlink=False,ind_slave_new=None,ind_master_new=None):
1915
+ if ind_slave_new is None: ind_slave_new=copy.deepcopy(ind_slave)
1916
+ if ind_master_new is None: ind_master_new=copy.deepcopy(ind_master)
1917
+ ITE_master:ITEpar=self.ui.Explorer.ITEfromInd(ind_master_new)
1918
+ if FlagUnlink and ind_slave in ITE_master.dependencies:
1919
+ ITE_master.dependencies.remove(ind_slave)
1920
+ elif not FlagUnlink and ind_slave not in ITE_master.dependencies:
1921
+ ITE_master.dependencies.append(copy.deepcopy(ind_slave))
1922
+ for w in self.tabWidgets:
1923
+ w:gPaIRS_Tab
1924
+ TABpar_ind:TABpar=w.TABpar_at(ind_slave_new)
1925
+ if TABpar_ind:
1926
+ if FlagUnlink:
1927
+ TABpar_ind.link=[]
1928
+ TABpar_ind.linkInfo=''
1929
+ else:
1930
+ TABpar_ind.link=copy.deepcopy(ind_master)
1931
+ ITE_ind:ITEpar=self.ui.Explorer.ITEfromInd(ind_slave_new)
1932
+ if FlagUnlink:
1933
+ ITE_ind.link=[]
1934
+ ITE_ind.procdata.link=[]
1935
+ else:
1936
+ ITE_ind.link=copy.deepcopy(ind_master)
1937
+ ITE_ind.procdata.link=copy.deepcopy(ind_master)
1938
+
1939
+ def unlink_pars(self,ind_slave):
1940
+ ITE_slave:ITEpar=self.ui.Explorer.ITEfromInd(ind_slave)
1941
+ ind_master=ITE_slave.link
1942
+ if ind_master:
1943
+ self.setLinks(ind_slave,ind_master,FlagUnlink=True)
1944
+ #item=self.processTree.topLevelItem(ind_slave[2])
1945
+ #child=item.child(ind_slave[3])
1946
+ #child.setIcon(0,QIcon())
1947
+ self.setTABpars_at(ind_slave)
1948
+ self.adjustSwitches()
1949
+
1950
+ #*************************************************** PROCESS
1951
+ #********************************** Launching
1952
+ def button_run_pause_action(self):
1953
+ # FlagRun = 0 no procWorkers (all workers have been closed or never launched)
1954
+ # FlagRun = 1 procWorkers working
1955
+ # FlagRun = 2 pause pressed, waiting for procWorkers to be completed
1956
+ pri.Process.magenta(f'button_RunPause_callback self.FlagRun={self.FlagRun} ')
1957
+ self.ui.button_pause.setEnabled(False) #ta disabilitato sempre lo riabilita il worker prima di iniziare
1958
+
1959
+ if self.FlagRun==0:
1960
+ self.FlagRun=1
1961
+ self.setButtonPause(False)
1962
+ self.run()
1963
+ elif self.FlagRun==1:
1964
+ self.FlagRun=2
1965
+ self.signals.killOrResetParForWorker.emit(True)
1966
+ self.setButtonPause(True)
1967
+
1968
+ def setButtonPause(self,flagPlay):
1969
+ if flagPlay:
1970
+ self.ui.label_updating_pairs.setVisible(False)
1971
+ self.ui.button_pause.setIcon(self.icon_play)
1972
+ stringa='Restart'
1973
+ else:
1974
+ self.ui.label_updating_pairs.setVisible(True)
1975
+ self.ui.button_pause.setIcon(self.icon_pause)
1976
+ stringa='Pause'
1977
+ tip=f'{stringa} process queue'+' ('+self.ui.button_pause.shortcut().toString(QKeySequence.NativeText)+')'
1978
+ self.ui.button_pause.setToolTip(tip)
1979
+ self.ui.button_pause.setStatusTip(tip)
1980
+ self.setButtonRunVisible()
1981
+ self.processTree.setProcessActionButtonLayout()
1982
+ """
1983
+ FlagButtonRun=self.ui.progress_Proc.value()==0
1984
+ self.ui.button_Run.setVisible(FlagButtonRun)
1985
+ self.ui.button_pause.setVisible(not FlagButtonRun)
1986
+ self.ui.w_progress_Proc.setVisible(not FlagButtonRun)
1987
+ """
1988
+
1989
+ def run(self):
1990
+ self.setSwitchEnabled(False)
1991
+ self.disableDropping(True)
1992
+ if self.initializeWorkers():
1993
+ self.indProc=-1
1994
+ self.updateIndProc()
1995
+ else:
1996
+ self.FlagRun=0
1997
+ self.setButtonPause(True)
1998
+ #self.button_run_pause_action()
1999
+ self.stopProcs()
2000
+
2001
+ def updateIndProc(self):
2002
+ self.indWorker+=1
2003
+ data=self.dataQueue[self.indWorker]
2004
+ self.initialize_proc(data)
2005
+ ITE_ind:ITEpar=self.ui.Explorer.ITEfromInd(data.ind)
2006
+ self.ui.Explorer.setITElayout(ITE_ind)
2007
+
2008
+ self.indProc+=1
2009
+ data:dataTreePar
2010
+ self.ui.Explorer.updateSwitchMovies(self.currind,FlagStart=False)
2011
+ self.procdata=None
2012
+ self.procdata=data=self.dataQueue[self.indProc]
2013
+ self.currind=data.ind
2014
+ self.checkProcesses(FlagInit=True,ind=self.currind)
2015
+ ITE:ITEpar=self.ui.Explorer.ITEfromInd(data.ind)
2016
+ self.ui.Explorer.setITElayout(ITE)
2017
+ if ITE.OptionDone==0:
2018
+ self.stopProcs()
2019
+ self.nextProc()
2020
+ return
2021
+
2022
+ self.procdata.uncopied_fields+=self.procFields
2023
+ self.ui.Explorer.updateSwitchMovies(self.currind,FlagStart=True)
2024
+
2025
+ self.resetProc(data)
2026
+ self.setProgressBar(data)
2027
+ data.resetLog()
2028
+ try:
2029
+ with open(data.stepOutName()+'.log', 'w') as file:
2030
+ file.write(data.Log)
2031
+ except:
2032
+ pri.Error.red(f'Error while trying to save the process log file: {data.stepOutName()}.log.\n{traceback.format_exc()}\n')
2033
+
2034
+ self.FlagResetPlot=True
2035
+ self.setFlagRun(data,-2)
2036
+ self.ui.Explorer.setITElayout(ITE)
2037
+ ITEs_ind:ITEpar=self.ui.Explorer.ITEsfromInd(self.currind)
2038
+ ind_child=copy.deepcopy(self.currind)
2039
+ for j in range(1,self.currind[-2]+1):
2040
+ ind_child[-2]=j-1
2041
+ ITE_child:ITEpar=ITEs_ind[j]
2042
+ data_child=ITE_child.procdata
2043
+ if data_child.flagRun==0:
2044
+ self.setFlagRun(data_child,-1)
2045
+ self.checkProcesses(FlagInit=True,ind=ind_child)
2046
+ self.ui.Explorer.setITElayout(ITE_child)
2047
+ if data_child.ind==self.ui.tabAreaWidget.TABpar.ind:
2048
+ self.w_Log.LOGpar.text=data_child.Log
2049
+ self.setTABpars_at(data_child.ind,FlagAdjustPar=True)
2050
+
2051
+ FlagCurrent=data.ind==self.ui.tabAreaWidget.TABpar.ind
2052
+ if FlagCurrent:
2053
+ self.w_Log.LOGpar.text=data.Log
2054
+ self.setTABpars_at(data.ind,FlagAdjustPar=True)
2055
+ self.w_Log.buttonAction()
2056
+ self.FlagProcInit=True
2057
+ self.signals.indProc.emit(self.indProc)
2058
+ if data.flagRun==0:#not launched
2059
+ data.resetTimeStat()
2060
+ data.onStartTimeStat()
2061
+
2062
+ def setFlagRun(self,data:dataTreePar,flagRun,flagPrev=False):
2063
+ data.flagRun=flagRun #come ultimo o comunque dopo resetProc
2064
+ for w in self.tabWidgets:
2065
+ w:gPaIRS_Tab
2066
+ if flagPrev:
2067
+ TABpar_prev=w.TABpar_prev_at(data.ind)
2068
+ for TABpar_ind in TABpar_prev:
2069
+ if TABpar_ind: TABpar_ind.flagRun=flagRun
2070
+ else:
2071
+ TABpar_ind:TABpar=w.TABpar_at(data.ind)
2072
+ if TABpar_ind: TABpar_ind.flagRun=flagRun
2073
+ ITE_ind:ITEpar=self.ui.Explorer.ITEfromInd(data.ind)
2074
+ ITE_ind.flagRun=flagRun
2075
+
2076
+ self.ui.Explorer.setProcessFlagRun(data.ind)
2077
+ return
2078
+
2079
+ def nextProc(self):
2080
+ self.UpdatingImage=True
2081
+
2082
+ if self.indProc<self.nProc-1 and self.FlagRun==1:
2083
+ try:
2084
+ self.updateIndProc()
2085
+ except:
2086
+ errMessage=f"{traceback.format_exc()}"
2087
+ self.procdata.warnings[0]+='\n\n'+self.procdata.headerSection('CRITICAL ERROR',errMessage,'X')
2088
+ self.store_proc(self.procdata)
2089
+ self.stopProcs()
2090
+ self.nextProc()
2091
+ else:
2092
+ self.ui.button_pause.setEnabled(False)
2093
+
2094
+ def resetProc(self,data:dataTreePar):
2095
+ data.warnings[0]=data.warnings[1]
2096
+ data.warnings[1]=''
2097
+ data.flagParForCompleted=False
2098
+ data.numCallBackTotOk=data.numFinalized
2099
+ self.signals.progress.emit(data.numFinalized)
2100
+ data.numProcOrErrTot=0
2101
+ self.procWorkers[self.indProc].data=data
2102
+ self.ui.time_stamp.hide()
2103
+ return
2104
+
2105
+ def setProgressBar(self,data:dataTreePar):
2106
+ self.ui.progress_Proc.setMinimum(0)
2107
+ self.ui.progress_Proc.setMaximum(data.nsteps)
2108
+ self.ui.progress_Proc.setValue(data.numFinalized)
2109
+ self.w_Log.TABpar_at(data.ind).nimg=data.nsteps
2110
+ #ITE:ITEpar=self.ui.Explorer.ITEfromInd(data.ind)
2111
+ return
2112
+
2113
+ def setLogProgressBar(self,data:dataTreePar):
2114
+ self.w_Log.ui.progress_Proc.setMinimum(0)
2115
+ self.w_Log.ui.progress_Proc.setMaximum(data.nsteps)
2116
+ self.w_Log.ui.progress_Proc.setValue(data.numFinalized)
2117
+ return
2118
+
2119
+ #********************************** Initialization of workers
2120
+ def initializeWorkers(self):
2121
+ self.indWorker=-1
2122
+ self.indProc=-1
2123
+ while self.pfPool is None:
2124
+ #TBD serve lo sleep? Se non ci sono errori cancellare
2125
+ pri.Error.white('****************\n****************\n****************\nwhile self.pfPool is None\n****************\n****************\n******************\n')
2126
+ if Flag_DEBUG: 1/0
2127
+ sleep(0.5)
2128
+ self.procWorkers=[]
2129
+ self.nProc=0
2130
+ nError=0
2131
+ nValid=0
2132
+ nTot=0
2133
+ self.dataQueue=[]
2134
+ for project in self.projectTree.itemList[1]:
2135
+ for process in project[0]:
2136
+ for step in process[1:]:
2137
+ step:ITEpar
2138
+ self.ui.Explorer.setITElayout(step)
2139
+ nTot+=int(process[0].FlagQueue and step.active)
2140
+ nError+=int(process[0].FlagQueue and step.active and step.flagRun<=0 and step.Step!=StepTypes.cal and step.OptionDone==0)
2141
+ nValid+=int((process[0].FlagQueue and step.active and step.flagRun>0) or step.Step==StepTypes.cal)
2142
+ if process[0].FlagQueue and step.active and step.flagRun<=0 and step.Step!=StepTypes.cal and step.OptionDone!=0 and len(step.link)==0:
2143
+ self.nProc+=1
2144
+ data=step.procdata
2145
+ data.ind=step.ind
2146
+ self.dataQueue.append(data)
2147
+ elif step.Process!=ProcessTypes.cal and step.Step==StepTypes.cal and step.OptionDone==1:
2148
+ data=step.procdata
2149
+ data.ind=step.ind
2150
+ self.setFlagRun(data,2)
2151
+ CAL:CALpar=self.w_Calibration.TABpar_at(step.ind)
2152
+ CAL.FlagCalVi=False
2153
+ if self.nProc==0 and nValid==0:
2154
+ self.warningDialog('No valid process found in the present projects!\nPlease, check for critical issues related to each step of the defined processes.',pixmap=icons_path+'issue.png')
2155
+ elif self.nProc==0 and nError>0:
2156
+ self.warningDialog(f'{nError} process step{"s" if nError>1 else ""} present{"" if nError>1 else "s"} critical issues!\nNo further valid process found in the present projects.\nPlease, check before running again.',pixmap=icons_path+'issue.png')
2157
+ elif self.nProc>0 and nError>0:
2158
+ if not self.questionDialog(f'{nError} process step{"s" if nError>1 else ""} present{"" if nError>1 else "s"} critical issues!\n{"They" if nError>1 else "It"} will not be executed. Do you want to proceed with processing?'):
2159
+ self.contProc=self.nProc-1 #necessario per far funzionare stopProc in run quando il risultato di questa funzione è False
2160
+ return False
2161
+ elif self.nProc==0:
2162
+ self.warningDialog(f'All the processes found in the present projects have been already executed!',pixmap=icons_path+'completed.png')
2163
+ FlagQueue=len(self.dataQueue)!=0
2164
+ self.contProc=-1 if not FlagQueue else 0
2165
+ self.putStepsInQueue()
2166
+ """
2167
+ for data in self.dataQueue:
2168
+ data:dataTreePar
2169
+ self.indWorker+=1
2170
+ self.initialize_proc(data)
2171
+ ITE_ind:ITEpar=self.ui.Explorer.ITEfromInd(data.ind)
2172
+ self.ui.Explorer.setITElayout(ITE_ind)
2173
+ """
2174
+ return FlagQueue
2175
+
2176
+ def initialize_proc(self,data:dataTreePar):
2177
+ self.set_proc(data)
2178
+ self.setFlagRun(data,-1)
2179
+
2180
+ if data.ind[:-2]==self.ui.tabAreaWidget.TABpar.ind[:-2]:
2181
+ self.ui.Explorer.arrangeCurrentProcess(self.processTree)
2182
+
2183
+ currpath=data.outPath
2184
+ if not os.path.exists(currpath):
2185
+ try:
2186
+ os.mkdir(currpath)
2187
+ except Exception as inst:
2188
+ pri.Error.red(f'It was not possible to make the directory {currpath}:\n{traceback.format_exc()}\n\n{inst}')
2189
+ pfPool = None if self.flagSimpleFor else self.pfPool
2190
+ if data.Step==StepTypes.min:
2191
+ self.numUsedProcs=self.numMaxProcs
2192
+ data.numPivOmpCores=1
2193
+ data.numUsedProcs=self.numMaxProcs
2194
+ procWorker=MIN_ParFor_Worker(data,self.indWorker,self.indProc,self.numMaxProcs,pfPool,self.parForMul)
2195
+ elif data.Step ==StepTypes.piv or data.Step ==StepTypes.spiv:
2196
+ data.numPivOmpCores,data.numUsedProcs=optimalPivCores(self.numMaxProcs,data.nimg,penCore=0.95)
2197
+ #data.numUsedProcs=3 # data.numUsedProcs is used for output should be the number of parfor threads used
2198
+ #data.numPivOmpCores=7#self.numMaxProcs
2199
+ self.numUsedProcs=data.numUsedProcs
2200
+ procWorker=PIV_ParFor_Worker(data,self.indWorker,self.indProc,self.numMaxProcs,pfPool,self.parForMul)
2201
+ elif data.Step ==StepTypes.disp:
2202
+ data.numPivOmpCores=NUMTHREADS_MAX
2203
+ data.numUsedProcs=1
2204
+ procWorker=StereoDisparity_ParFor_Worker(data,self.indWorker,self.indProc,self.numMaxProcs,pfPool,self.parForMul)
2205
+
2206
+
2207
+ procWorker.signals.progress.connect(self.progress_proc)
2208
+ self.signals.progress.connect(procWorker.setNumCallBackTot)
2209
+ procWorker.signals.finished.connect(self.pause_proc)
2210
+ procWorker.signals.initialized.connect(self.buttonPauseHideShow)
2211
+ procWorker.signals.completed.connect(self.stopProcs)
2212
+ self.signals.pause_proc.connect(procWorker.storeCompleted)
2213
+ #self.ui.button_pause.clicked.connect(MIN_worker.die)
2214
+ self.signals.killOrResetParForWorker.connect(procWorker.killOrReset)
2215
+ self.signals.indProc.connect(procWorker.updateIndProc)
2216
+ self.FlagInitialized=True
2217
+ self.procWorkers.append(procWorker)
2218
+ self.PaIRS_threadpool.start(procWorker)
2219
+
2220
+ def set_proc(self,data:dataTreePar,ind=None,FlagLog=True):
2221
+ if ind is None: ind=data.ind
2222
+ k=self.dataQueue.index(data)
2223
+ if self.dataFlagRuns[k]==0:
2224
+ self.getInheritance(ind)
2225
+ data.namesPIV=NamesPIV(Process=data.Process,Step=data.Step)
2226
+ INP_ind=self.w_Input.TABpar_at(ind)
2227
+ OUT_ind=self.w_Output.TABpar_at(ind)
2228
+ PRO_ind=self.w_Process.TABpar_at(ind)
2229
+ PRO_Min_ind=self.w_Process_Min.TABpar_at(ind)
2230
+ PRO_Disp_ind=self.w_Process_Disp.TABpar_at(ind)
2231
+ data.setProc(INP_ind,OUT_ind,PRO_ind,PRO_Min_ind,PRO_Disp_ind)
2232
+ data.assignDataName()
2233
+
2234
+ if FlagLog:
2235
+ ITE_ind:ITEpar=self.ui.Explorer.ITEfromInd(ind)
2236
+ data.warnings[1]=ITE_ind.warningMessage
2237
+ data.setCompleteLog()
2238
+
2239
+ LOG_ind=self.w_Log.TABpar_at(ind)
2240
+ if LOG_ind:
2241
+ LOG_ind.text=data.Log
2242
+
2243
+ #********************************** Progress
2244
+ @Slot(int,int,int,list,str)
2245
+ def progress_proc(self,procId,i,pim,Var,stampa):
2246
+ ''' E' la funzione chiamata alla fine di ogni elaborazione dai vari threads in parfor è chiamata wrapUp CallBack'''
2247
+ data=self.procdata
2248
+ pri.Info.yellow(f'[progress_proc] {data.ind} {self.procdata is self.dataQueue[self.indProc]} {self.currind}')
2249
+ #******************** Updating total number of tasks passed to the pool
2250
+ data.numProcOrErrTot+=1
2251
+ #pri.Time.blue(0,f'progress_proc start i={i} pim={hex(pim)} {"*"*25} {procId} FlagRun={self.FlagRun}')
2252
+
2253
+ if i<0: return #When restarting a process return immediately if the images have been already processed
2254
+ #******************** Updating Log
2255
+ data.Log+=stampa+'\n'
2256
+ self.w_Log.TABpar_at(data.ind).text=data.Log
2257
+
2258
+ data.list_print[i]=stampa
2259
+ data.list_pim[i]=pim
2260
+
2261
+ if not pim&FLAG_CALLBACK_INTERNAL: return #c'è un errore prima della fine di tutti i processi relativi ad i
2262
+ #******************** Updating Progress Bar
2263
+ data.numCallBackTotOk+=1 #Always at the end the progress bar will go back to the correct value
2264
+ self.signals.progress.emit(data.numCallBackTotOk) #fundamental in multithreading
2265
+
2266
+ ITE_ind:ITEpar=self.ui.Explorer.ITEfromInd(data.ind)
2267
+ LOG_ind:LOGpar=self.w_Log.TABpar_at(data.ind)
2268
+ if self.FlagRun==1:
2269
+ self.ui.progress_Proc.setValue(data.numProcOrErrTot)
2270
+ LOG_ind.progress=data.numProcOrErrTot
2271
+ ITE_ind.progress=data.numProcOrErrTot
2272
+ else:
2273
+ self.ui.progress_Proc.setValue(data.numFinalized)
2274
+ LOG_ind.progress=data.numFinalized
2275
+ ITE_ind.progress=data.numFinalized
2276
+ LOG_ind.nimg=data.nsteps
2277
+ self.ui.Explorer.updateItemWidget(ITE_ind)
2278
+ self.adjustDependencies(ITE_ind)
2279
+
2280
+ flagSelected=data.hasIndexOf(self.ui.Explorer.ITEpar)
2281
+ if flagSelected:
2282
+ self.w_Log.LOGpar.progress=LOG_ind.progress
2283
+ self.w_Log.LOGpar.nimg=data.nimg
2284
+ self.w_Log.setProgressProc()
2285
+
2286
+ if data.Step==StepTypes.min:
2287
+ flagFinalized=(pim&FLAG_FINALIZED[0]) and (pim&FLAG_FINALIZED[1])
2288
+ elif data.Step in (StepTypes.piv,StepTypes.disp,StepTypes.spiv):
2289
+ flagFinalized=pim&FLAG_FINALIZED[0]
2290
+
2291
+ if not flagFinalized: return
2292
+ #******************** Updating numFinalized
2293
+ data.numFinalized+=1
2294
+
2295
+ if data.flagParForCompleted: return
2296
+ #******************** updating log
2297
+ if flagSelected:
2298
+ self.w_Log.LOGpar.text=data.Log
2299
+ self.w_Log.setLogText(FlagMoveToBottom=True)
2300
+
2301
+ pri.Process.green(f'progress_proc {i} data.numProcOrErrTot={data.numProcOrErrTot} self.numFinalized={data.numFinalized}')
2302
+ # prLock ha smesso di funzionare perchè?
2303
+ #prLock(f'progress_proc {i} data.numProcOrErrTot={data.numProcOrErrTot} self.numCallBackTotOk={self.numCallBackTotOk}')
2304
+
2305
+ if self.FlagRun==0 or (procId%self.numUsedProcs and data.Step!=StepTypes.disp): return #evitare aggiornamento tempo
2306
+ #if self.FlagRun==0: return #evitare aggiornamento tempo
2307
+ #******************** Updating time counter and stats
2308
+ actualTime=time()
2309
+ self.showTimeToEnd(data,time=actualTime)
2310
+
2311
+ if not Flag_GRAPHICS and not self.w_Vis.VISpar.FlagVis: return
2312
+ if actualTime<self.previousPlotTime+deltaTimePlot: return
2313
+ if not flagSelected: return
2314
+ # fra l'altro mi sembra che queata funzione sia abbastanza onerosa
2315
+ #updating plot
2316
+ pri.Time.green(f'plotting the field {i} over {data.numProcOrErrTot} ')
2317
+
2318
+ self.plotCurrent(data,i,Var)
2319
+ self.previousPlotTime=time()
2320
+ return
2321
+ #pri.Time.green(0,f'progress_proc end i={i} pim={hex(pim)} {"-"*25} {procId} FlagRun={self.FlagRun}')
2322
+
2323
+ def plotCurrent(self,data=None,i=-1,Var=None,FlagBridge=False):
2324
+ if Var==[]: return
2325
+ if data is None:
2326
+ data=self.procdata
2327
+ try:
2328
+ FlagCurrent=data.hasIndexOf(self.ui.Explorer.ITEpar)
2329
+ VIS_ind:VISpar=self.w_Vis.TABpar_at(data.ind)
2330
+ if data.Step==StepTypes.min:
2331
+ if i>-1:
2332
+ VIS_ind.image_file_Current=data.inpPath+data.list_Image_Files[i]
2333
+ self.w_Vis.image_Current_raw=Var
2334
+ else:
2335
+ VIS_ind.FlagMIN = True
2336
+ VIS_ind.image_file_Current=''
2337
+ self.w_Vis.image_Current_raw=None
2338
+ #if Var: #todo GP: per i==-1 Var deve essere l'immagine giusta
2339
+ # self.w_Vis.getImageInfo(Var,data.ind)
2340
+ # self.w_Vis.resetAllLevels(data.ind)
2341
+ # self.w_Vis.resetAllXYLims(data.ind)
2342
+
2343
+ if self.FlagResetPlot:
2344
+ VIS_ind.img=0
2345
+ VIS_ind.type=0
2346
+ VIS_ind.variable=self.namesPIV.combo_dict[self.namesPIV.img]
2347
+ VIS_ind.variableKey=self.namesPIV.combo_dict_keys[VIS_ind.variable]
2348
+ VIS_ind.FlagResetLevels=VIS_ind.FlagResetSizes=True
2349
+ self.FlagResetPlot=False
2350
+ pass
2351
+ elif data.Step in (StepTypes.piv,StepTypes.disp,StepTypes.spiv):
2352
+ if i>-1:
2353
+ if data.Step==StepTypes.disp:
2354
+ VIS_ind.result_file_Current=VIS_ind.resF(f'it{i+1}')
2355
+ VIS_ind.Nit=i+1
2356
+ VIS_ind.it=i+1
2357
+ else:
2358
+ VIS_ind.result_file_Current=VIS_ind.resF(i)
2359
+ fields=data.namesPIV.instVel
2360
+ result={}
2361
+ for f,v in zip(fields,Var):
2362
+ result[f]=v
2363
+ result=self.w_Vis.calcMagnitude(result)
2364
+ FlagUnit=VIS_ind.Out.xres!=1.0 or VIS_ind.Out.pixAR!=1.0
2365
+ result=self.w_Vis.calcZVorticity(result,FlagUnit)
2366
+ self.w_Vis.result_Current=result
2367
+ else:
2368
+ VIS_ind.result_file_Current=''
2369
+ self.w_Vis.result_Current=None
2370
+ #if Var: #todo GP: per i==-1 Var deve essere result
2371
+ # self.w_Vis.getResultInfo(result,data.ind)
2372
+ # self.w_Vis.resetAllLevels(data.ind)
2373
+ # self.w_Vis.resetAllXYLims(data.ind)
2374
+
2375
+ if self.FlagResetPlot:
2376
+ VIS_ind.img=0
2377
+ VIS_ind.type=1
2378
+ if data.Step==StepTypes.disp:
2379
+ VIS_ind.variable=self.namesPIV.combo_dict[self.namesPIV.z]
2380
+ else:
2381
+ VIS_ind.variable=self.namesPIV.combo_dict[self.namesPIV.Mod]
2382
+ VIS_ind.variableKey=self.namesPIV.combo_dict_keys[VIS_ind.variable]
2383
+ VIS_ind.FlagResetLevels=VIS_ind.FlagResetSizes=True
2384
+ self.FlagResetPlot=False
2385
+ pass
2386
+ else:
2387
+ pri.Info.red(f'Current process type ({data.Step}) has no plot function available!')
2388
+ return
2389
+ if FlagCurrent:
2390
+ self.w_Vis.FlagReset=i==-1
2391
+ self.setTABpars_at(data.ind,FlagAdjustPar=True,widget=self.w_Vis)
2392
+ pri.Process.yellow(f'{"*"*50} Result plotted!')
2393
+ except Exception as inst:
2394
+ pri.Error.red('Error Plotting in progress_proc',color=PrintTA.red)
2395
+ traceback.print_exc()
2396
+ if Flag_fullDEBUG: pri.Error.red(f'\n{inst}')
2397
+
2398
+ def showTimeToEnd(self,data:dataTreePar,time=0):
2399
+ if data.numCallBackTotOk:
2400
+ eta=data.deltaTime2String(data.eta) if time==0 else data.calcTimeStat(time,data.numCallBackTotOk)
2401
+ else:
2402
+ eta='no info'
2403
+ self.ui.time_stamp.show()
2404
+ self.ui.time_stamp.setText(f'Time to the end: {eta}')
2405
+
2406
+ #********************************** Pause
2407
+ @Slot(dataTreePar)
2408
+ def pause_proc(self,data:dataTreePar,errMessage=''):
2409
+ ''' pause_proc also when ends '''
2410
+ pri.Time.red(f'pause_proc Begin ')
2411
+ if errMessage:
2412
+ self.procdata.warnings[0]+='\n\n'+data.headerSection('CRITICAL ERROR',errMessage,'X')
2413
+ self.store_proc(data)
2414
+
2415
+ if data.FlagFinished or errMessage!='': #save and continue
2416
+ if self.FlagRun==0: # bug noto se uno mette in pausa mentre sta finendo di salvare (al 100%) da errore, basta ripremere play oppure eliminare il check
2417
+ pri.Process.red('**************************** pause_proc Error ****************************')
2418
+ else:
2419
+ self.nextProc()
2420
+ else:
2421
+ """
2422
+ if data.hasIndexOf(self.w_Tree.TABpar):
2423
+ self.w_Tree.selectFuture(0)
2424
+ if data.flagRun==-1:
2425
+ i:QTreeWidgetItem=self.w_Tree.TREpar.future[0]
2426
+ data.icon_type=self.Tree_icons.icontype('paused')
2427
+ i.setIcon(0,self.Tree_icons.paused)
2428
+ self.setButtons(data)
2429
+ """
2430
+
2431
+ pri.Time.red(f'pause_proc END')
2432
+ self.signals.pause_proc.emit()
2433
+
2434
+ def store_proc(self,data_worker:dataTreePar):
2435
+ data=self.procdata #self.w_Tree.TABpar_prev[idata.indTree][idata.indItem][-1]
2436
+ for f in self.procFields:
2437
+ if f in self.procdata.uncopied_fields:
2438
+ i=self.procdata.uncopied_fields.index(f)
2439
+ self.procdata.uncopied_fields.pop(i)
2440
+ #Aggiusto ciò che deve essere aggiornato
2441
+ #if not data.numFinalized: return
2442
+ pri.Time.yellow(f'{"-"*100} store PROC')
2443
+
2444
+ data.onPauseTimeStat()
2445
+
2446
+ #Copio ciò che è stato modificato nel worker
2447
+ #siccome data_worker sarà distrutto non faccio una deepcopy con copyfrom
2448
+ data.compMin=data_worker.compMin
2449
+ data.mediaPIV=data_worker.mediaPIV
2450
+ data.FlagFinished=data_worker.FlagFinished
2451
+
2452
+ if data.Step == StepTypes.disp:
2453
+ data.res=data_worker.res
2454
+ data.laserConst=[const for const in data_worker.laserConst]
2455
+ indpar=[i for i in data.ind]
2456
+ OUT_ind:OUTpar=self.w_Output.TABpar_at(indpar)
2457
+ OUT_ind.res=data.res
2458
+ if OUT_ind.unit==0:
2459
+ OUT_ind.xres=data.res
2460
+ if 'zconst' in data.OUT_dict and 'xterm' in data.OUT_dict and 'yterm' in data.OUT_dict:
2461
+ OUT_ind.zconst=data.OUT_dict['zconst']
2462
+ OUT_ind.xterm=data.OUT_dict['xterm']
2463
+ OUT_ind.yterm=data.OUT_dict['yterm']
2464
+ indpar[-2]+=1
2465
+ indpar[-1]=-1
2466
+ OUT_ind:OUTpar=self.w_Output.TABpar_at(indpar)
2467
+ OUT_ind.res=data.res
2468
+ if OUT_ind.unit==0:
2469
+ OUT_ind.xres=data.res
2470
+ if 'zconst' in data.OUT_dict and 'xterm' in data.OUT_dict and 'yterm' in data.OUT_dict:
2471
+ OUT_ind.zconst=data.OUT_dict['zconst']
2472
+ OUT_ind.xterm=data.OUT_dict['xterm']
2473
+ OUT_ind.yterm=data.OUT_dict['yterm']
2474
+ ITE_ind:ITEpar=self.ui.Explorer.ITEfromInd(indpar)
2475
+ ITE_ind.procdata.res=data.res
2476
+ ITE_ind.procdata.laserConst=[const for const in data_worker.laserConst]
2477
+ if 'zconst' in data.OUT_dict and 'xterm' in data.OUT_dict and 'yterm' in data.OUT_dict:
2478
+ ITE_ind.procdata.OUT_dict['zconst']=data.OUT_dict['zconst']
2479
+ ITE_ind.procdata.OUT_dict['xterm']=data.OUT_dict['xterm']
2480
+ ITE_ind.procdata.OUT_dict['yterm']=data.OUT_dict['yterm']
2481
+
2482
+ #Aggiusto ciò che deve essere aggiornato
2483
+ if data.nsteps==data.numCallBackTotOk: #data.FlagFinished: #todo TA da GP: secondo te è corretto?
2484
+ flagRun=int(data.numFinalized==data.nsteps)+1
2485
+ else:
2486
+ flagRun=-1
2487
+ self.setFlagRun(data,flagRun)
2488
+ data.warnings[1]=''
2489
+ data.setCompleteLog()
2490
+ self.adjustSwitches()
2491
+
2492
+ Process=[]
2493
+ for l in self.projectTree.itemList[1:]:
2494
+ Process.append([ l[data.ind[0]][data.ind[1]][data.ind[2]] ])
2495
+ filename=data.procOutName()
2496
+ try:
2497
+ saveList(Process,filename)
2498
+ except Exception as inst:
2499
+ #warningDialog(self,f'Error while saving the configuration file {filename}!')
2500
+ pri.Error.red(f'Error while saving the configuration file {filename}!\n{inst}')
2501
+
2502
+ try:
2503
+ with open(data.outPathRoot+'.log', 'a') as file:
2504
+ file.write(data.Log)
2505
+ except:
2506
+ pri.Error.red(f'Error while trying to save the process log file: {data.outPathRoot}.log.\n{traceback.format_exc()}\n')
2507
+ try:
2508
+ with open(data.stepOutName()+'.log', 'w') as file:
2509
+ file.write(data.Log)
2510
+ except:
2511
+ pri.Error.red(f'Error while trying to save the process log file: {data.stepOutName()}.log.\n{traceback.format_exc()}\n')
2512
+ if data.Step in (StepTypes.piv,StepTypes.spiv):
2513
+ data.writeCfgProcPiv()
2514
+
2515
+ LOG_ind:LOGpar=self.w_Log.TABpar_at(data.ind)
2516
+ LOG_ind.text=data.Log
2517
+ self.w_Log.setLogText(FlagMoveToBottom=True)
2518
+ self.plotCurrent(data,-1,None,FlagBridge=True)
2519
+
2520
+ #if not data.hasIndexOf(self.ui.Explorer.ITEpar):
2521
+ ITE:ITEpar=self.ui.Explorer.ITEfromInd(data.ind)
2522
+ self.ui.Explorer.setITElayout(ITE)
2523
+ self.inheritance(data.ind)
2524
+ self.adjustDependencies(ITE)
2525
+ self.ui.time_stamp.setText('')
2526
+
2527
+ self.adjustSwitches()
2528
+
2529
+ pri.Time.yellow(f'{"-"*100} store PROC END')
2530
+
2531
+ @Slot()
2532
+ def buttonPauseHideShow(self):
2533
+ #pr ('buttonPauseHideShow')
2534
+ self.ui.button_pause.setEnabled(True) #.show()
2535
+
2536
+ @Slot()
2537
+ def stopProcs(self):
2538
+ self.contProc+=1
2539
+ if self.procdata:
2540
+ pri.Time.red(f'stopProcs self.contProc={self.contProc}/{self.nProc} self.numCallBackTotOk={self.numCallBackTotOk} numFinalized={self.procdata.numFinalized} {self.FlagRun}')
2541
+
2542
+ FlagEnd = self.contProc==self.indProc+1 if self.FlagRun==2 else self.contProc==self.nProc
2543
+ if FlagEnd:
2544
+ self.ui.Explorer.updateSwitchMovies(self.currind,FlagStart=False)
2545
+ self.setSwitchEnabled(True)
2546
+ self.disableDropping(False)
2547
+ self.procdata=None
2548
+ self.currind=None
2549
+
2550
+ self.setEnabled(True)
2551
+ self.procWorkers=[]
2552
+ self.FlagRun=0
2553
+ self.putStepsInQueue()
2554
+ self.ui.button_pause.setEnabled(True)
2555
+ self.ui.button_Run.setEnabled(True)
2556
+ self.setButtonPause(True)
2557
+
2558
+ self.closeIfRequested()
2559
+
2560
+ def putStepsInQueue(self):
2561
+ if self.FlagRun:
2562
+ self.dataFlagRuns=[]
2563
+ for k,data in enumerate(self.dataQueue):
2564
+ if self.FlagRun:
2565
+ self.dataFlagRuns.append(data.flagRun)
2566
+ self.setFlagRun(data,-10)
2567
+ elif data.flagRun==-10:
2568
+ self.setFlagRun(data,self.dataFlagRuns[k])
2569
+ else:
2570
+ continue
2571
+ ITE_ind:ITEpar=self.ui.Explorer.ITEfromInd(data.ind)
2572
+ self.ui.Explorer.setITElayout(ITE_ind)
2573
+ self.ui.Explorer.arrangeCurrentProcess(self.processTree)
2574
+
2575
+ def closeIfRequested(self):
2576
+ self.ui.label_updating_pairs.setVisible(False)
2577
+ if self.waitingDialog:
2578
+ self.waitingDialog.done(0)
2579
+ self.waitingDialog=None
2580
+ if self.completingTask:
2581
+ self.completingTask()
2582
+ self.completingTask=None
2583
+ """
2584
+ if self.FlagClosing[0]:
2585
+ self.correctClose()
2586
+ """
2587
+
2588
+ #********************************************* CalVi
2589
+ def runCalVi(self):
2590
+ self.w_Vis_CalVi.VISpar.FlagRunning=not self.w_Vis_CalVi.VISpar.FlagRunning
2591
+ if self.w_Vis_CalVi.VISpar.FlagRunning:
2592
+ """
2593
+ prev=self.w_Vis_CalVi.TABpar_prev_at(self.w_Vis_CalVi.TABpar.ind)
2594
+ step=len(prev)-1-self.w_Vis_CalVi.TABpar.ind[-1]
2595
+ self.button_back_forward_action(step)
2596
+ self.w_Vis_CalVi.VISpar.FlagRunning=True
2597
+ """
2598
+ self.w_Vis_CalVi.VISpar.FlagRunning=False
2599
+ self.w_Calibration.fullCallback()
2600
+ self.w_Vis_CalVi.VISpar.FlagRunning=True
2601
+
2602
+ self.disableTab_Vis(self.w_Vis_CalVi.VISpar.FlagRunning)
2603
+
2604
+ self.initDataAndSetImgFromGui(self.w_Input_CalVi.INPpar,self.w_Process_CalVi.PROpar)
2605
+ FlagResume=self.w_Vis_CalVi.FlagResume
2606
+ def removeQuestion():
2607
+ if FlagResume!=1: return
2608
+ camString=''
2609
+ cams=self.w_Input_CalVi.INPpar.cams
2610
+ if self.w_Input_CalVi.INPpar.FlagCam:
2611
+ if len(cams)==1: camString=f'_cam{cams[0]}'
2612
+ else:
2613
+ cams=[-1]
2614
+ data=self.w_Vis_CalVi.calibView.calib.cal.data
2615
+ varName=f'{data.percorsoOut}{data.NomeFileOut}{camString}{outExt.calvi}'
2616
+ questionMessage=f'The calibration result file:\n{varName}\nalready exists in the current output path. The above error could arise from the attempt of loading such a file.\n\nDo you want to remove the file from the disk?\n\n(Please, consider to choose a different output name root for your process)'
2617
+ if questionDialog(self,questionMessage):
2618
+ os.remove(varName)
2619
+ if self.w_Input_CalVi.INPpar.errorMessage:
2620
+ warningDialog(self,self.w_Input_CalVi.INPpar.errorMessage)
2621
+ self.abortCalVi()
2622
+ return removeQuestion()
2623
+ if self.w_Vis_CalVi.VISpar.errorMessage:
2624
+ warningDialog(self,self.w_Vis_CalVi.VISpar.errorMessage)
2625
+ self.abortCalVi()
2626
+ return removeQuestion()
2627
+ if not all([all(imExc) for imExc in self.w_Vis_CalVi.VISpar.imEx]):
2628
+ imageFile=''
2629
+ for k in range(len(self.w_Vis_CalVi.VISpar.imEx)):
2630
+ for j in range(len(self.w_Vis_CalVi.VISpar.imEx[k])):
2631
+ if not self.w_Vis_CalVi.VISpar.imEx[k][j]:
2632
+ imageFile=self.w_Vis_CalVi.VISpar.imList[k][j]
2633
+ break
2634
+ if imageFile: break
2635
+ Message=f'No valid image files found!\n[{imageFile},...]'
2636
+ warningDialog(self,Message)
2637
+ self.abortCalVi()
2638
+ return removeQuestion()
2639
+ self.w_Vis_CalVi.buttonAction()
2640
+ pri.Info.cyan(f'Running calibration FlagRestart={self.w_Vis_CalVi.FlagResume}')
2641
+ if self.w_Vis_CalVi.FlagResume>-1:
2642
+ self.w_Vis_CalVi.runCalVi(flagMod=bool(self.w_Vis_CalVi.FlagResume))
2643
+ else:
2644
+ flagYes=self.questionDialog('A calibration result file already exists in the current output path. Do you want to overwrite it?')
2645
+ if flagYes:
2646
+ self.w_Vis_CalVi.FlagResume=0
2647
+ self.w_Vis_CalVi.runCalVi(flagMod=False)
2648
+ else:
2649
+ self.runCalVi()
2650
+ else:
2651
+ self.disableTab_Vis(self.w_Vis_CalVi.VISpar.FlagRunning)
2652
+
2653
+ if self.w_Vis_CalVi.FlagResume>-1:
2654
+ self.saveCal()
2655
+ if self.w_Vis_CalVi.calibView.calib.FlagCalibration and ( (self.w_Process_CalVi.PROpar.FlagPlane and not self.w_Process_CalVi.PROpar.CalibProcType==0) or self.w_Process_CalVi.PROpar.CamMod==4 ):
2656
+ if self.w_Input_CalVi.INPpar.FlagOptPlane: self.savePlanePar()
2657
+ self.updateINPpar()
2658
+ self.saveCal('_Mod')
2659
+ if self.w_Vis_CalVi.calibView.calib.FlagCalibration:
2660
+ self.appendCalibration()
2661
+ #indTree,indItem,ind=self.w_Import.INPpar.indexes()
2662
+ #self.actualBridge('Import',indTree,indItem,ind)
2663
+ self.initDataAndSetImgFromGui(self.w_Input_CalVi.INPpar,self.w_Process_CalVi.PROpar)
2664
+ self.w_Vis_CalVi.stopCalVi()
2665
+
2666
+ self.closeIfRequested()
2667
+
2668
+ def abortCalVi(self):
2669
+ self.w_Vis_CalVi.FlagResume=-1
2670
+ self.runCalVi()
2671
+
2672
+ def updateINPpar(self):
2673
+ if self.w_Process_CalVi.PROpar.FlagPlane:
2674
+ costPlanes=self.w_Vis_CalVi.calibView.calib.cal.vect.costPlanes
2675
+ for i in range(len(self.w_Input_CalVi.INPpar.filenames)):
2676
+ self.w_Input_CalVi.INPpar.plapar[i]=[round(p,3) for p in costPlanes[i]]
2677
+ if self.w_Process_CalVi.PROpar.CamMod==4:
2678
+ cost=self.w_Vis_CalVi.calibView.calib.cal.vect.cost[0]
2679
+ self.w_Process_CalVi.PROpar.CylRad=cost[21]
2680
+ self.w_Process_CalVi.PROpar.CylThick=cost[22]
2681
+ self.w_Process_CalVi.PROpar.CylNRatio=cost[23]
2682
+ self.w_Input_CalVi.fullCallback()
2683
+
2684
+ def appendCalibration(self):
2685
+ INP=self.w_Input_CalVi.INPpar
2686
+ data=self.w_Vis_CalVi.calibView.calib.cal.data
2687
+ if INP.FlagCam:
2688
+ outFiles=[f'{data.percorsoOut}{data.NomeFileOut}{c}.cal' for c in INP.cams]
2689
+ else:
2690
+ outFiles=[f'{data.percorsoOut}{data.NomeFileOut}{1}.cal']
2691
+ appendedFiles=[f for f in outFiles if f not in self.w_Calibration.CALpar.calList]
2692
+ self.w_Calibration.buttonAction()
2693
+ if len(appendedFiles)==0: return
2694
+ if self.w_Calibration.CALpar.ncam==len(self.w_Calibration.CALpar.calList):
2695
+ warningDialog(self,f'The calibration file list already contains a number of files equal to the number of cameras specified ({self.w_Calibration.CALpar.ncam}). The results of the current CalVi process will not be appended to the list.')
2696
+ else:
2697
+ self.w_Calibration.ui.calTree.importLists(appendedFiles)
2698
+ self.w_Calibration.copyListsFromTree()
2699
+ #self.w_Calibration.nullCallback()
2700
+ self.w_Calibration.adjustTABparInd()
2701
+
2702
+ def saveCal(self,add_str=''):
2703
+ VIS=self.w_Vis_CalVi.VISpar
2704
+ data=self.w_Vis_CalVi.calibView.calib.cal.data
2705
+ calVect=self.w_Vis_CalVi.calibView.calib.cal.vect
2706
+ VIS.orPosAndShift=[]
2707
+ VIS.angAndMask=[]
2708
+ VIS.spotDistAndRemoval=[]
2709
+ for c in range(data.NCam):
2710
+ for p1 in range(data.Numpiani_PerCam):
2711
+ p=p1+c*data.Numpiani_PerCam
2712
+ VIS.orPosAndShift.append([])
2713
+ VIS.angAndMask.append([])
2714
+ VIS.spotDistAndRemoval.append([])
2715
+
2716
+ VIS.orPosAndShift[p].append(float(calVect.XOr[p] - data.ColPart))
2717
+ VIS.orPosAndShift[p].append(float(calVect.YOr[p] - data.RigaPart))
2718
+ VIS.orPosAndShift[p].append(float(calVect.xOrShift[p]))
2719
+ VIS.orPosAndShift[p].append(float(calVect.yOrShift[p]))
2720
+
2721
+ VIS.angAndMask[p].append(float(calVect.angCol[p]))
2722
+ VIS.angAndMask[p].append(float(calVect.angRow[p]))
2723
+ for i in self.w_Vis_CalVi.calibView.calib.cal.getPuTrovaCC(p):
2724
+ VIS.angAndMask[p].append(float(i))
2725
+
2726
+ VIS.spotDistAndRemoval[p].append(float(calVect.dColPix[p]))
2727
+ VIS.spotDistAndRemoval[p].append(float(calVect.dRigPix[p]))
2728
+ VIS.spotDistAndRemoval[p].append(float(calVect.remPointsUp[p]))
2729
+ VIS.spotDistAndRemoval[p].append(float(calVect.remPointsDo[p]))
2730
+ VIS.spotDistAndRemoval[p].append(float(calVect.remPointsLe[p]))
2731
+ VIS.spotDistAndRemoval[p].append(float(calVect.remPointsRi[p]))
2732
+
2733
+ INP=self.w_Input_CalVi.INPpar
2734
+ camString=''
2735
+ if INP.FlagCam:
2736
+ if len(INP.cams)==1: camString=f'_cam{INP.cams[0]}'
2737
+ varName=f'{data.percorsoOut}{data.NomeFileOut}{camString}{add_str}{outExt.calvi}'
2738
+ var=[INP,self.w_Process_CalVi.PROpar,VIS,myStandardPath(os.path.dirname(varName))]
2739
+ try:
2740
+ with open(varName,'wb') as file:
2741
+ pickle.dump(var,file)
2742
+ pri.Info.blue(f'>>> Saving calibration process file {varName}')
2743
+ except:
2744
+ pri.Error.red(f'Error while trying to save the calibration process file: {varName}.\n{traceback.format_exc()}\n')
2745
+
2746
+ self.w_Input_CalVi.adjustTABparInd()
2747
+ self.w_Process_CalVi.adjustTABparInd()
2748
+ self.w_Vis_CalVi.adjustTABparInd()
2749
+ Process=[]
2750
+ for l in self.projectTree.itemList[1:]:
2751
+ Process.append([ l[INP.ind[0]][INP.ind[1]][INP.ind[2]] ])
2752
+ filename=f'{data.percorsoOut}{data.NomeFileOut}{camString}{add_str}{outExt.cal}'
2753
+ try:
2754
+ saveList(Process,filename)
2755
+ except Exception as inst:
2756
+ #warningDialog(self,f'Error while saving the configuration file {filename}!')
2757
+ pri.Error.red(f'Error while saving the configuration file {filename}!\n{inst}')
2758
+ return
2759
+
2760
+ def savePlanePar(self):
2761
+ data=self.w_Vis_CalVi.calibView.calib.cal.data
2762
+ calVect=self.w_Vis_CalVi.calibView.calib.cal.vect
2763
+ INP=self.w_Input_CalVi.INPpar
2764
+ if len(INP.cams)==1: camString=f'_cam{INP.cams[0]}'
2765
+ else: camString=''
2766
+ plaparRad=f'{data.percorsoOut}{data.NomeFileOut}{camString}_plane'
2767
+ plapar_names=['beta (°)','alpha (°)','gamma (°)','x (mm)','y (mm)','z (mm)']
2768
+ for i,c in enumerate(calVect.costPlanes):
2769
+ dp={}
2770
+ for p,v in zip(plapar_names,c):
2771
+ dp[p]=v
2772
+ plaparName=plaparRad+f"{i+1:d}_z{dp['z (mm)']:.2f}{outExt.pla}"
2773
+ try:
2774
+ with open(plaparName,'w') as file:
2775
+ file.write(str(dp).replace('{','{\n ').replace(',',',\n').replace('}','\n}'))
2776
+ except:
2777
+ pri.Error.red(f'Error while trying to save the plane parameter file: {plaparName}.\n{traceback.format_exc()}\n')
2778
+ pri.Info.blue(f' Saving plane data file {plaparName}')
2779
+
2780
+ def setRunCalViButtonText(self,FlagRunning=True):
2781
+ button=self.ui.button_Run_CalVi
2782
+ if not FlagRunning:
2783
+ flag=bool(self.w_Vis_CalVi.VISpar.errorMessage) or bool(self.w_Input_CalVi.INPpar.errorMessage)
2784
+ if flag:
2785
+ fPixSize=button.font().pixelSize()
2786
+ s=f'<sup><span style=" font-size:{fPixSize-2}px"> ⚠</span></sup>'
2787
+ else:
2788
+ s=''
2789
+ text='Run'
2790
+ button.setIcon(self.icon_play)
2791
+ tooltip=f'Run CalVi{" (some issues detected!)" if flag else ""}'
2792
+ else:
2793
+ s=''
2794
+ text='Save'
2795
+ button.setIcon(self.icon_save_and_stop)
2796
+ tooltip='Quit CalVi and save results'
2797
+ button.setText(text+s)
2798
+ tooltip+=' ('+button.shortcut().toString(QKeySequence.NativeText)+')'
2799
+ button.setToolTip(tooltip)
2800
+ button.setStatusTip(tooltip)
2801
+
2802
+ def disableTab_Vis(self,Flag=True):
2803
+ self.ui.w_Managing_Tabs.setEnabled(not Flag)
2804
+ for w in self.tabWidgets:
2805
+ w:gPaIRS_Tab
2806
+ if w!=self.w_Vis_CalVi and w!=self.ui.tabAreaWidget:
2807
+ w.setEnabled(not Flag)
2808
+ self.w_Input.ui.button_back.setEnabled(not Flag)
2809
+ self.w_Input.ui.button_forward.setEnabled(not Flag)
2810
+ self.ui.button_Run_CalVi.setVisible(not Flag)
2811
+ self.ui.button_Abort_CalVi.setVisible(Flag)
2812
+ self.setRunCalViButtonText(FlagRunning=Flag)
2813
+
2814
+ self.ui.tabAreaWidget.FlagDisplayControls=not Flag
2815
+ self.ui.tabAreaWidget.ui.button_restore_undo.setVisible(not Flag)
2816
+ self.ui.tabAreaWidget.ui.button_back.setVisible(not Flag)
2817
+ self.ui.tabAreaWidget.ui.button_forward.setVisible(not Flag)
2818
+ self.ui.tabAreaWidget.display_controls()
2819
+
2820
+ self.ui.label_updating_pairs.setVisible(Flag)
2821
+
2822
+ def initDataAndSetImgFromGui(self,INP,PRO):
2823
+ self.w_Vis_CalVi.initDataFromGui(INP,PRO)
2824
+ inddel=self.w_Vis_CalVi.setImgFromGui()
2825
+ if len(inddel): #todo GP: migliorare? (setto due volte le immagini e faccio in calib il check)
2826
+ Message=f'The following image files encountered issues while importing (they may have incompatible sizes with the first image file of the list "{self.w_Input_CalVi.INPpar.filenames[0]}" or be not in grayscale format):\n'
2827
+ for k in inddel:
2828
+ if k==inddel[-1]: colon='.'
2829
+ else: colon=';'
2830
+ Message+=f'- {self.w_Input_CalVi.INPpar.filenames[k]}{colon}\n'
2831
+ Message+='They will not be added to the list.'
2832
+ self.warningDialog(Message)
2833
+ for i in range(len(inddel)-1,-1,-1):
2834
+ k=inddel[i]
2835
+ self.w_Input_CalVi.INPpar.filenames.pop(k)
2836
+ self.w_Input_CalVi.INPpar.plapar.pop(k)
2837
+ self.w_Input_CalVi.adjust_list_images()
2838
+ #self.w_Input_CalVi.nullCallback()
2839
+ self.w_Input_CalVi.adjustTABparInd()
2840
+ self.w_Vis_CalVi.initDataFromGui(INP,PRO)
2841
+ self.w_Vis_CalVi.setImgFromGui()
2842
+
2843
+ #********************************************* LEGACY
2844
+ def setUpdatingState(self,flagUpdating):
2845
+ if Flag_DISABLE_onUpdate:
2846
+ for tname in self.TABnames:
2847
+ w: gPaIRS_Tab
2848
+ wname='w_'+tname
2849
+ w=getattr(self,wname)
2850
+ if tname=='Vis':
2851
+ w.ui.w_plot.setEnabled(not flagUpdating)
2852
+ else:
2853
+ w.ui.scrollArea.setEnabled(not flagUpdating)
2854
+ #w.setVisible(not flag)
2855
+ self.ui.label_updating_import.setVisible(flagUpdating)
2856
+ pass
2857
+
2858
+ #*************************************************** Parallel Pool
2859
+ def launchParPool(self,nworkers):
2860
+ # TA ho deciso di utilizzare concurrent.futures per lanciare il processo in parallelo perchè non ho capito bene come usare
2861
+ # quello di QT
2862
+ # Avevo provato anche Thread ma non sono stato capace di capire come lanciare
2863
+ # Ho provato a lanciare le due operazioni all'interno di initParForAsync in parallelo ma mi sembra che sia molto lento
2864
+ # Alla fine ho adottato una configurazione mista con initParForAsync scritta in mod asincrono
2865
+ # Quando initParForAsync termina chiama initParForComplete che effettua le ultime cose
2866
+
2867
+ if hasattr(self, 'pfPool'):#this function should be called only once but just in case we check and close the parPool
2868
+ self.pfPool.closeParPool()
2869
+ else:
2870
+ self.pfPool=None
2871
+ self.parForMul=None
2872
+ self.FlagParPoolInit=False
2873
+ self.signals.parPoolInit.connect(self.parPoolInitSetup)
2874
+ executor = concurrent.futures.ThreadPoolExecutor(max_workers=2)
2875
+ f3=executor.submit(asyncio.run,initParForAsync(nworkers))
2876
+ def initParForComplete(_f3):
2877
+ pri.Time.blue(0,'fine initParFor1')
2878
+ (pfPool,parForMul)=f3.result()
2879
+ #timesleep(5)
2880
+ pri.Time.blue(0,'PIV_ParFor_Worker dopo ParForMul')
2881
+ parForMul.sleepTime=ParFor_sleepTime #time between calls of callBack
2882
+ self.pfPool=pfPool
2883
+ self.parForMul=parForMul
2884
+ self.parForMul.numUsedCores=self.numMaxProcs # =NUMTHREADS_MAX#potrebbe essere minore di NUMTHREADS_PIV_MAX con cui è stato impostato
2885
+ self.FlagParPoolInit=True
2886
+ self.signals.parPoolInit.emit()
2887
+ f3.add_done_callback(initParForComplete)
2888
+
2889
+ @Slot(int)
2890
+ def parPoolInitSetup(self):
2891
+ if self.FlagGuiInit:
2892
+ if not self.FlagParPoolInit:
2893
+ self.FlagParPoolInit=False
2894
+
2895
+ self.ui.label_gif.setPixmap(QPixmap())
2896
+ self.ui.label_gif.setMovie(self.load_gif)
2897
+
2898
+ self.ui.label_loading.setText('Starting parallel pool with')
2899
+ self.ui.spin_nworkers.setEnabled(False)
2900
+ self.ui.label_loading_2.setText('workers...')
2901
+ else:
2902
+ self.ui.button_Run.setEnabled(True)
2903
+
2904
+ self.ui.label_gif.setMovie(QMovie())
2905
+ self.ui.label_gif.setPixmap(self.loaded_map)
2906
+
2907
+ self.ui.label_loading.setText('Parallel pool with')
2908
+ self.ui.spin_nworkers.setEnabled(True)
2909
+ self.ui.label_loading_2.setText('workers started!')
2910
+ #self.repaint()
2911
+
2912
+ def spin_nworkers_action(self):
2913
+ val=self.ui.spin_nworkers.value()
2914
+ self.GPApar.NumCores=val
2915
+ if val <=NUMTHREADS_MAX:
2916
+ self.numMaxProcs=val
2917
+
2918
+ #*************************************************** Warnings
2919
+ def warningDialog(self,Message,time_milliseconds=0,flagScreenCenter=False,icon=QIcon(),palette=None,pixmap=None,title='Warning!',flagRichText=False,flagNoButtons=False,addButton:dict=None):
2920
+ return warningDialog(self,Message,time_milliseconds,flagScreenCenter,icon,palette,pixmap,title,flagRichText,flagNoButtons,addButton)
2921
+
2922
+ def questionDialog(self,Message):
2923
+ flagYes=questionDialog(self,Message)
2924
+ return flagYes
2925
+
2926
+ #*************************************************** Checking
2927
+ def checkProcesses(self,FlagInit=False,ind=None):
2928
+ FlagCheck=ind is None
2929
+ if ind is not None: projects=self.projectTree.itemList[1][ind[0]:ind[0]+1]
2930
+ else: projects=self.projectTree.itemList[1]
2931
+ for ITEs_project in projects:
2932
+ if ind is not None: ITEs_project_ind=ITEs_project[ind[1]:ind[1]+1]
2933
+ else: ITEs_project_ind=ITEs_project
2934
+ for ITEs_tree in ITEs_project_ind:
2935
+ if ind is not None: ITEs_tree_ind=ITEs_tree[ind[2]:ind[2]+1]
2936
+ else: ITEs_tree_ind=ITEs_tree
2937
+ for ITEs in ITEs_tree_ind:
2938
+ if ind is not None: ITEs_ind=ITEs[ind[3]+1:ind[3]+2]
2939
+ else: ITEs_ind=ITEs
2940
+ for ITE in ITEs_ind:
2941
+ ITE:ITEpar
2942
+ ITE.FlagInit=FlagInit
2943
+ indITE=ITE.ind
2944
+ if ind is not None: FlagCheck=True
2945
+ for w in self.tabWidgets:
2946
+ w:gPaIRS_Tab
2947
+ TABpar_ind:TABpar=w.TABpar_at(indITE)
2948
+ if TABpar_ind:
2949
+ if FlagInit:
2950
+ w.checkTABpar(indITE)
2951
+ w.setTABwarn(indITE)
2952
+ TABpar_ind.FlagInit=True
2953
+ else:
2954
+ TABpar_ind.FlagInit=False
2955
+ return FlagCheck
2956
+
2957
+ #*************************************************** Projects
2958
+ def pauseQuestion(self,taskDescription='continuing',task=lambda:None,FlagFirstQuestion=False):
2959
+ if FlagFirstQuestion:
2960
+ if not self.questionDialog(f'Are you sure you want to proceed with {taskDescription}?'):
2961
+ return
2962
+ if self.FlagRun or self.w_Vis_CalVi.VISpar.FlagRunning:
2963
+ if self.FlagRun: currentTaskDescription='PaIRS is currently executing the processes in the current workspace. '
2964
+ elif self.w_Vis_CalVi.VISpar.FlagRunning: currentTaskDescription='CalVi is currently running. '
2965
+ if self.questionDialog(f'{currentTaskDescription}Do you want to pause them before {taskDescription}?'):
2966
+ if self.FlagRun: self.button_run_pause_action()
2967
+ self.setEnabled(False)
2968
+ self.completingTask=task
2969
+ self.waitingDialog=self.warningDialog('Please, wait while stopping the running processes!',pixmap=''+ icons_path +'sandglass.png',flagNoButtons=True)
2970
+ if self.w_Vis_CalVi.VISpar.FlagRunning: self.abortCalVi()
2971
+ else:
2972
+ task()
2973
+ return
2974
+
2975
+ def open_project(self):
2976
+ filename, _ = QFileDialog.getOpenFileName(self,\
2977
+ "Select a PaIRS project file", filter=f'*{outExt.proj}',\
2978
+ #dir=self.w_Input.INPpar.path,\
2979
+ options=optionNativeDialog)
2980
+ if not filename: return
2981
+ errorString=''
2982
+ try:
2983
+ data, errorMessage=loadList(filename)
2984
+ errorString+=errorMessage
2985
+ except:
2986
+ errorString+=traceback.format_exc()
2987
+ if errorString:
2988
+ WarningMessage=f'Error with loading the file: {filename}\n'
2989
+ warningDialog(self,WarningMessage)
2990
+ pri.Error.red(f'{WarningMessage}\n{errorString}\n')
2991
+ try:
2992
+ ind=self.projectTree.topLevelItemCount()
2993
+ insert_at_depth(self.projectTree.itemList,self.projectTree.listDepth,ind,data)
2994
+ self.modifyWorkspace()
2995
+ TRE:TREpar=self.projectTree.itemList[0][ind]
2996
+ TRE.project=ind
2997
+ self.projectTree.createProjectItem(ind,FlagNewItem=False)
2998
+ item=self.projectTree.topLevelItem(ind)
2999
+ self.projectTree.setCurrentItem(item)
3000
+ item.setSelected(True)
3001
+ self.adjustItemWidgets()
3002
+ except Exception as inst:
3003
+ WarningMessage=f'Error while retrieving the project "{data[0][0].name}" from the file: {filename}\n'
3004
+ warningDialog(self,WarningMessage)
3005
+ pri.Error.red(f'{WarningMessage}\n{traceback.format_exc()}\n')
3006
+ return
3007
+
3008
+ def saveas_current_structure(self,name:str='',ext='',saveList=lambda f:None,par:TABpar=None,FlagSave=True):
3009
+ Title=f"Select location and name of the {name} file to save"
3010
+ filename, _ = QFileDialog.getSaveFileName(self,Title,
3011
+ dir=par.name.replace(' ','_'), #self.w_Input.INPpar.path+par.name.replace(' ','_'),
3012
+ filter=f'*{ext}',\
3013
+ options=optionNativeDialog)
3014
+ if not filename: return
3015
+ if len(filename)>=len(ext):
3016
+ if filename[-len(ext):]==ext: filename=filename[:-len(ext)] #per adattarlo al mac
3017
+ filename=myStandardRoot('{}'.format(str(filename)))
3018
+ if not outExt.cfg in filename:
3019
+ filename=filename+ext
3020
+ if FlagSave:saveList(filename)
3021
+ return filename
3022
+
3023
+ def updateWorkspaceTitle(self):
3024
+ self.GPApar.name=self.ui.title_workspace.label.text().replace(self.GPApar.saveBullet(),'')
3025
+ self.GPApar.FlagSaved=False
3026
+ self.adjustWorkspaceHeader()
3027
+
3028
+ def save_current_project(self,filename):
3029
+ Project=[]
3030
+ FlagSaved=False
3031
+ for l in self.projectTree.itemList:
3032
+ Project.append([l[self.TREpar.project]])
3033
+ try:
3034
+ TRE:TREpar=self.projectTree.itemList[0][self.TREpar.project]
3035
+ TRE.outName=filename
3036
+ TRE.savedDate=currentTimeString()
3037
+ TRE.FlagSaved=True
3038
+ saveList(Project,filename)
3039
+ except Exception as inst:
3040
+ warningDialog(self,f'Error while saving the file {filename}!\nPlease, retry.')
3041
+ pri.Error.red(f'Error while saving the file {filename}!\n{inst}')
3042
+ else:
3043
+ self.TREpar.copyfrom(TRE)
3044
+ self.adjustItemWidgets()
3045
+ FlagSaved=True
3046
+ return FlagSaved
3047
+
3048
+ def saveas_current_project(self):
3049
+ self.saveas_current_structure(name='project',ext=outExt.proj,saveList=lambda f: self.save_current_project(f),par=self.TREpar)
3050
+
3051
+ def save_project(self):
3052
+ FlagSaved=False
3053
+ if self.TREpar.outName:
3054
+ filename=self.TREpar.outName
3055
+ if self.TREpar.FlagRunnable and self.TREpar.FlagQueue:
3056
+ self.pauseQuestion('saving the selected project',lambda: self.save_current_project(filename),FlagFirstQuestion=self.FlagRun!=0)
3057
+ else:
3058
+ FlagSaved=self.save_current_project(filename)
3059
+ else:
3060
+ FlagSaved=self.saveas_project()
3061
+ return FlagSaved
3062
+
3063
+ def saveas_project(self):
3064
+ FlagSaved=False
3065
+ if self.TREpar.FlagRunnable and self.TREpar.FlagQueue:
3066
+ self.pauseQuestion('saving the selected project',self.saveas_current_project)
3067
+ else:
3068
+ FlagSaved=self.saveas_current_project()
3069
+ return FlagSaved
3070
+
3071
+ def close_project(self):
3072
+ self.pauseQuestion('closing the selected project',lambda: ProjectTree.button_close_action(self.projectTree))
3073
+
3074
+ def clean_projects(self):
3075
+ self.pauseQuestion('closing all the projects',lambda: ProjectTree.button_clean_action(self.projectTree))
3076
+
3077
+ def copy_process(self):
3078
+ if self.ui.Explorer.ITEpar.FlagQueue and self.ui.Explorer.currentTree==self.processTree:
3079
+ self.pauseQuestion('copying the selected process',lambda: ProcessTree.button_copy_action(self.processTree))
3080
+
3081
+ def delete_process(self):
3082
+ if self.ui.Explorer.currentTree==self.processTree:
3083
+ #if self.ui.Explorer.ITEpar.FlagQueue: self.ui.Explorer.ITEpar.FlagQueue=False
3084
+ self.pauseQuestion('deleting the selected process',lambda: ProcessTree.button_delete_action(self.processTree))
3085
+
3086
+ def clean_processes(self):
3087
+ if self.ui.Explorer.currentTree==self.processTree:
3088
+ self.pauseQuestion('cleaning the whole process list',lambda: ProcessTree.button_clean_action(self.processTree))
3089
+
3090
+ #*************************************************** Sizes, font & layout
3091
+ def updateGPAparGeometry(self):
3092
+ self.GPApar.Geometry=self.saveGeometry().toBase64().data().decode()
3093
+ self.GPApar.WindowState=self.saveState().toBase64().data().decode()
3094
+ #g=self.geometry()
3095
+ #self.GPApar.Geometry=[g.x(), g.y(), g.width(), g.height()]
3096
+ #self.GPApar.WindowState=[self.windowState().value,self.windowState().name]
3097
+ splitterSizes={}
3098
+ for s in self.ui.Explorer.findChildren(QSplitter)+[self.ui.main_splitter,self.ui.Operating_Tabs_splitter]:
3099
+ s:QSplitter
3100
+ pri.Coding.green(f'splitterSizes: {s.objectName()}')
3101
+ splitterSizes[s.objectName()]=s.sizes()
3102
+ self.GPApar.SplitterSizes=splitterSizes
3103
+ scrollAreaValues={}
3104
+ for a in self.ui.Explorer.findChildren(QScrollArea):
3105
+ a:QScrollArea
3106
+ pri.Coding.blue(f'scrollArea: {a.objectName()}')
3107
+ scrollAreaValues[a.objectName()]=[a.horizontalScrollBar().value(),a.verticalScrollBar().value()]
3108
+ self.GPApar.ScrollAreaValues=scrollAreaValues
3109
+ return
3110
+
3111
+ def setFontPixelSize(self):
3112
+ if self.fontPixelSize==self.GPApar.fontPixelSize: return
3113
+ fPixSize=self.GPApar.fontPixelSize
3114
+ font=QFont()
3115
+ font.setFamily(fontName)
3116
+ font.setPixelSize(fPixSize)
3117
+ if self.app: self.app.setFont(font)
3118
+ setFontPixelSize(self,fPixSize)
3119
+ self.setFurtherFontPixelSizes(fPixSize)
3120
+ if self.aboutDialog:
3121
+ self.aboutDialog.fontPixelSize=self.GPApar.fontPixelSize
3122
+ self.aboutDialog.setFontSizeText()
3123
+ if self.logChanges: self.logChanges.setFontPixelSize(fPixSize)
3124
+ if self.menuDebug: self.menuDebug.setFont(self.ui.menuFile.font())
3125
+ self.fontPixelSize=fPixSize
3126
+
3127
+ def setFurtherFontPixelSizes(self,fPixSize):
3128
+ self.setTabFontPixelSize(fPixSize)
3129
+
3130
+ lab:QLabel=self.ui.title
3131
+ fPixSize_TabNames=min([fPixSize*2,30])
3132
+ font=lab.font()
3133
+ font.setFamily(fontName)
3134
+ font.setPixelSize(fPixSize_TabNames)
3135
+ lab.setFont(font)
3136
+ self.ui.title_workspace.setFont(font)
3137
+
3138
+ lab:QLabel=self.ui.subtitle
3139
+ font=lab.font()
3140
+ font.setFamily(fontName)
3141
+ font.setPixelSize(fPixSize+4)
3142
+ lab.setFont(font)
3143
+ self.ui.subtitle_workspace.setFont(font)
3144
+
3145
+ lab:QLabel=self.onlyReadLabel
3146
+ font=lab.font()
3147
+ font.setFamily(fontName)
3148
+ font.setPixelSize(fPixSize+1)
3149
+ lab.setFont(font)
3150
+
3151
+ self.ui.projectPage.setFontPixelSize(fPixSize)
3152
+ self.ui.processPage.setFontPixelSize(fPixSize)
3153
+ self.ui.stepPage.setFontPixelSize(fPixSize)
3154
+
3155
+ self.w_Log.setLogFont(fontPixelSize-dfontLog)
3156
+ self.w_Vis_CalVi.setLogFont(fontPixelSize-dfontLog)
3157
+
3158
+ def setTabFontPixelSize(self,fPixSize):
3159
+ fPixSize_TabNames=min([fPixSize*2,30])
3160
+ for w in self.ui.tabAreaWidget.widgets:
3161
+ setFontPixelSize(w,fPixSize)
3162
+ w:gPaIRS_Tab
3163
+ for lab in w.findChildren(QLabel):
3164
+ lab:QLabel
3165
+ if 'name_tab' in lab.objectName():
3166
+ #lab:QLabel=w.ui.name_tab
3167
+ font=lab.font()
3168
+ font.setPixelSize(fPixSize_TabNames)
3169
+ lab.setFont(font)
3170
+
3171
+ def falseShow(self):
3172
+ FlagHidden=not self.isVisible()
3173
+ total_rect = QGuiApplication.primaryScreen().geometry()
3174
+ for screen in QGuiApplication.screens():
3175
+ total_rect = total_rect.united(screen.geometry())
3176
+ self.move(total_rect.right() + 100, total_rect.bottom() + 100)
3177
+ self.updateGeometry()
3178
+ self.show()
3179
+ self.repaint()
3180
+ return FlagHidden
3181
+
3182
+ def setDefaultSizes(self):
3183
+ margins=self.ui.centralLayout.contentsMargins()
3184
+ main_splitter_sizes=[self.ui.w_Managing_Tabs.baseSize().width(),self.ui.tabAreaWidget.widgetMinimumWidth*2+self.ui.tabAreaWidget.margin*2+self.ui.tabAreaWidget.handleWidth*2] #processTree, main_sep, tabAreaWidget
3185
+ w=margins.left()+self.ui.main_splitter.handleWidth()*2+sum(main_splitter_sizes)+margins.right()
3186
+ h=margins.top()+self.ui.w_header.minimumHeight()+self.ui.tabAreaWidget.tabAreaHeight+self.ui.tabAreaWidget.buttonSize[1]+self.ui.tabAreaWidget.buttonSpacing+self.ui.tabAreaWidget.margin*2+self.ui.w_Operating_Tabs.layout().spacing()+self.ui.statusbar.minimumHeight()+margins.bottom()
3187
+ self.resize(w,h)
3188
+ self.ui.main_splitter.setSizes(main_splitter_sizes)
3189
+ self.updateGeometry()
3190
+ x=(self.maximumGeometry.width()-w)*0.5
3191
+ y=(self.maximumGeometry.height()-h)*0.5
3192
+ if self.falseShow(): self.hide()
3193
+ self.move(x,y)
3194
+ self.app.processEvents()
3195
+ self.updateGPAparGeometry()
3196
+
3197
+ def setGPaIRSTitle(self):
3198
+ cfgString=f': {self.GPApar.outName}' if self.GPApar.outName and self.GPApar.outName!=lastcfgname else ''
3199
+ if not self.GPApar.FlagSaved: cfgString+='*'
3200
+ if Flag_DEBUG:#TA per non incasinarmi
3201
+ windowTitle=f'PaIRS (v{version}.{__subversion__} - {__date__}) -- cfg v{uicfg_version} -- PIV {self.PIVvers} -- {platform.system()} -- Python {platform.python_version()}'
3202
+ else:
3203
+ windowTitle=f'PaIRS (v{version})'
3204
+ windowTitle+=cfgString
3205
+ self.setWindowTitle(windowTitle)
3206
+
3207
+ #*************************************************** Menus
3208
+ #********************* File
3209
+ def setGPAlayout(self):
3210
+ self.setFontPixelSize()
3211
+ self.setGPaIRSPalette()
3212
+
3213
+ geometry=QByteArray.fromBase64(self.GPApar.Geometry.encode())
3214
+ self.restoreGeometry(geometry)
3215
+ #if isinstance(self.GPApar.Geometry,list) and len(self.GPApar.Geometry)==4:
3216
+ # g=self.GPApar.Geometry
3217
+ # try:
3218
+ # self.setGeometry(g[0],g[1],g[2],g[3])
3219
+ # except:
3220
+ # pri.Info.yellow(f'Error while restoring geometry:\n{traceback.format_exc()}\n\nDefault sizes will be set!\n\n')
3221
+ # self.setDefaultSizes()
3222
+ #else:
3223
+ # self.setDefaultSizes()
3224
+
3225
+ windowState = QByteArray.fromBase64(self.GPApar.WindowState.encode())
3226
+ self.restoreState(windowState)
3227
+ #try:
3228
+ # s=self.GPApar.WindowState
3229
+ # self.setWindowState(Qt.WindowState(s[0]))
3230
+ #except:
3231
+ # pri.Info.yellow(f'Error while restoring window state:\n{traceback.format_exc()}\n\nDefault window state will be set!\n\n')
3232
+
3233
+ for s in self.ui.Explorer.findChildren(QSplitter)+[self.ui.main_splitter,self.ui.Operating_Tabs_splitter]:
3234
+ s:QSplitter
3235
+ if s.objectName() in self.GPApar.SplitterSizes:
3236
+ s.setSizes(self.GPApar.SplitterSizes[s.objectName()])
3237
+ for a in self.ui.Explorer.findChildren(QScrollArea):
3238
+ a:QScrollArea
3239
+ if a.objectName() in self.GPApar.ScrollAreaValues:
3240
+ scrollAreaValues=self.GPApar.ScrollAreaValues[a.objectName()]
3241
+ a.horizontalScrollBar().setValue(scrollAreaValues[0])
3242
+ a.verticalScrollBar().setValue(scrollAreaValues[1])
3243
+ self.setNumCores()
3244
+
3245
+ def setNumCores(self):
3246
+ if self.GPApar.NumCores >NUMTHREADS_MAX:
3247
+ self.GPApar.NumCores=NUMTHREADS_MAX
3248
+ self.numTotUsedThreads=self.GPApar.NumCores
3249
+ self.ui.spin_nworkers.setValue(self.GPApar.NumCores)
3250
+
3251
+ def modifyWorkspace(self):
3252
+ self.GPApar.modifiedDate=currentTimeString()
3253
+ self.GPApar.date=f'Modified : {self.GPApar.modifiedDate}'
3254
+ self.GPApar.FlagSaved=False
3255
+
3256
+ def new_workspace(self):
3257
+ filename=self.saveas_current_structure(name='workspace',ext=outExt.wksp,saveList=lambda f: self.save_current_workspace(f),par=self.GPApar,FlagSave=False)
3258
+ self.GPApar.copyfrom(GPApar(),exceptions=self.GPApar.stateFields)
3259
+ self.GPApar.outName=filename
3260
+ self.GPApar.createdDate=currentTimeString()
3261
+ self.GPApar.modifiedDate=self.GPApar.createdDate
3262
+ self.GPApar.date=f'Modified : {self.GPApar.modifiedDate}'
3263
+ self.projectTree.clean_workspace()
3264
+ self.adjustProjectSelection()
3265
+
3266
+ def new_workspace_debug(self):
3267
+ self.GPApar.copyfrom(GPApar(),exceptions=self.GPApar.stateFields)
3268
+ self.projectTree.clean_workspace()
3269
+ self.adjustProjectSelection()
3270
+
3271
+ def menu_new_action(self):
3272
+ taskDescription='creating a new workspace'
3273
+ if not self.GPApar.FlagSaved:
3274
+ if self.questionDialog(f'The current workspace is unsaved. Do you want to save it before {taskDescription}?'):
3275
+ self.menu_save_action()
3276
+ self.pauseQuestion(taskDescription,self.new_workspace,FlagFirstQuestion=True)
3277
+
3278
+ def open_workspace(self,filename='',FlagSetGeometry=False):
3279
+ pri.Time.cyan('Open workspace: init')
3280
+ if filename=='':
3281
+ filename, _ = QFileDialog.getOpenFileName(self,\
3282
+ "Select a PaIRS workspace file", filter=f'*{outExt.wksp}',\
3283
+ #dir=self.w_Input.INPpar.path,\
3284
+ options=optionNativeDialog)
3285
+ if not filename: return
3286
+ waitingWindow=warningDialog(self,'Please, wait while retrieving previous workspace!\n(If this action takes too much time, please consider to close the workspace before quitting PaIRS next time.)',pixmap=''+ icons_path +'sandglass.png',flagNoButtons=True,flagScreenCenter=True)
3287
+ self.app.processEvents()
3288
+ errorString=''
3289
+ try:
3290
+ data, errorMessage=loadList(filename)
3291
+ errorString+=errorMessage
3292
+ pri.Time.cyan('Open workspace: load')
3293
+ except:
3294
+ errorString+=traceback.format_exc()
3295
+ if errorString:
3296
+ WarningMessage=f'Error with loading the file: {filename}\n'
3297
+ warningDialog(self,WarningMessage)
3298
+ pri.Error.red(f'{WarningMessage}\n{errorString}\n')
3299
+ try:
3300
+ self.projectTree.clean_action()
3301
+ #all_indexes=[i for i in range(len(data[2]))]
3302
+ insert_at_depth(self.projectTree.itemList,self.projectTree.listDepth,0,data[2])
3303
+ self.checkProcesses()
3304
+ self.ui.Explorer.ITEpar.FlagInit=False
3305
+ for _ in range(len(self.projectTree.itemList[0])):
3306
+ self.projectTree.createProjectItem(FlagNewItem=False)
3307
+ """
3308
+ item=self.projectTree.topLevelItem(0)
3309
+ self.projectTree.setCurrentItem(item)
3310
+ item.setSelected(True)
3311
+ """
3312
+ self.GPApar.copyfrom(data[0])
3313
+ self.TREpar.copyfrom(data[1])
3314
+
3315
+ #FlagHidden=not self.isVisible()
3316
+ #if FlagHidden:
3317
+ # self.move(0, -1e6) #todo: capire come aggiornare la geometria senza lo show
3318
+ # self.show()
3319
+ pri.Time.cyan('Open workspace: set data')
3320
+ #self.TREpar.step=None
3321
+ #FlagShown=self.falseShow()
3322
+ if FlagSetGeometry: self.setGPAlayout()
3323
+ self.adjustProjectSelection()
3324
+ #if FlagShown: self.hide()
3325
+ pri.Time.cyan('Open workspace: selection')
3326
+ pri.Time.cyan('Open workspace: geometry (end)')
3327
+ except Exception as inst:
3328
+ if filename==lastcfgname:
3329
+ WarningMessage='Error with loading the last configuration file.\n'
3330
+ os.remove(lastcfgname)
3331
+ else:
3332
+ WarningMessage=f'Error while retrieving the workspace "{data[0].name}" from the file: {filename}\n'
3333
+ warningDialog(self,WarningMessage)
3334
+ pri.Error.red(f'{WarningMessage}\n{traceback.format_exc()}\n')
3335
+ self.new_workspace_debug()
3336
+ self.setGPAlayout()
3337
+ return waitingWindow.done(0)
3338
+
3339
+ def menu_open_action(self):
3340
+ taskDescription='loading a previous workspace'
3341
+ if not self.GPApar.FlagSaved:
3342
+ if self.questionDialog(f'The current workspace is unsaved. Do you want to save it before {taskDescription}?'):
3343
+ self.menu_save_action()
3344
+ self.pauseQuestion(taskDescription,self.open_workspace,FlagFirstQuestion=True)
3345
+
3346
+ def save_current_workspace(self,filename,FlagAdjustHeader=True):
3347
+ self.updateGPAparGeometry()
3348
+ if filename!=lastcfgname:
3349
+ if not self.GPApar.outName:
3350
+ self.GPApar.name=os.path.splitext(os.path.basename(filename))[0]
3351
+ self.GPApar.outName=filename
3352
+ self.GPApar.savedDate=currentTimeString()
3353
+ self.GPApar.FlagSaved=True
3354
+ Workspace=[self.GPApar.duplicate(),self.TREpar.duplicate(),self.projectTree.itemList]
3355
+ try:
3356
+ saveList(Workspace,filename)
3357
+ except Exception as inst:
3358
+ warningDialog(self,f'Error while saving the file {filename}!\nPlease, retry.')
3359
+ pri.Error.red(f'Error while saving the file {filename}!\n{inst}')
3360
+ else:
3361
+ if FlagAdjustHeader: self.adjustWorkspaceHeader()
3362
+ FlagSaved=True
3363
+ return FlagSaved
3364
+
3365
+ def save_last_workspace(self):
3366
+ self.save_current_workspace(lastcfgname,FlagAdjustHeader=False)
3367
+ pri.Info.white(f' >>>>> Saving last ui configuration to file:\t{lastcfgname}')
3368
+
3369
+ def saveas_current_workspace(self):
3370
+ self.saveas_current_structure(name='workspace',ext=outExt.wksp,saveList=lambda f: self.save_current_workspace(f),par=self.GPApar)
3371
+
3372
+ def menu_save_action(self):
3373
+ if self.GPApar.outName:
3374
+ filename=self.GPApar.outName
3375
+ self.pauseQuestion('saving the current workspace',lambda: self.save_current_workspace(filename),FlagFirstQuestion=False)
3376
+ else:
3377
+ self.menu_saveas_action()
3378
+ return False
3379
+
3380
+ def menu_saveas_action(self):
3381
+ self.pauseQuestion('saving the current workspace',self.saveas_current_workspace,FlagFirstQuestion=False)
3382
+ return False
3383
+
3384
+ def close_workspace(self):
3385
+ self.GPApar.copyfrom(GPApar(),exceptions=self.GPApar.stateFields)
3386
+ self.projectTree.clean_workspace()
3387
+
3388
+ def menu_close_action(self):
3389
+ taskDescription='closing the current workspace'
3390
+ if not self.GPApar.FlagSaved:
3391
+ if self.questionDialog(f'The current workspace is unsaved. Do you want to save it before {taskDescription}?'):
3392
+ self.menu_save_action()
3393
+ self.pauseQuestion(taskDescription,self.close_workspace,FlagFirstQuestion=True)
3394
+
3395
+ #********************* Help
3396
+ def guide(self):
3397
+ #url = QUrl("http://wpage.unina.it/etfd/PaIRS/PaIRS-UniNa-Guide.pdf")
3398
+ url = QUrl("https://www.pairs.unina.it/web/PaIRS-UniNa-v020-Guide.pdf")
3399
+ QDesktopServices.openUrl(url)
3400
+
3401
+ def downloadApp(self):
3402
+ #url = QUrl("http://wpage.unina.it/etfd/PaIRS/PaIRS-UniNa-Guide.pdf")
3403
+ url = QUrl(EXEurl)
3404
+ QDesktopServices.openUrl(url)
3405
+
3406
+ def about(self):
3407
+ if self.aboutDialog:
3408
+ self.aboutDialog.hide()
3409
+ self.aboutDialog.show()
3410
+ else:
3411
+ self.aboutDialog=infoPaIRS(self)
3412
+ self.aboutDialog.show()
3413
+
3414
+ #********************* Debug
3415
+ def addDebugMenu(self):
3416
+ global Flag_fullDEBUG, pri
3417
+ menubar=self.ui.menubar
3418
+ self.menuDebug=menubar.addMenu("Debug")
3419
+
3420
+ #--------------------------- new ui cfg
3421
+ self.menuDebug.addSeparator()
3422
+ self.ui.aNew = self.menuDebug.addAction("New")
3423
+ self.ui.aNew.triggered.connect(self.new_workspace_debug)
3424
+
3425
+ #--------------------------- last ui cfg
3426
+ self.menuDebug.addSeparator()
3427
+ self.ui.aSaveLastCfg = self.menuDebug.addAction("Save lastWorkspace"+outExt.cfg)
3428
+ self.ui.aSaveLastCfg.triggered.connect(self.save_last_workspace)
3429
+
3430
+ self.ui.aDeleteLastCfg = self.menuDebug.addAction("Delete lastWorkspace"+outExt.cfg)
3431
+ def delete_lastcfg():
3432
+ if os.path.exists(lastcfgname):
3433
+ os.remove(lastcfgname)
3434
+ pri.Info.white(f' xxxxx Deleting last ui configuration file:\t{lastcfgname}')
3435
+ else:
3436
+ pri.Info.white(f' xxxxx Last ui configuration file:\t{lastcfgname}\t already deleted!')
3437
+ self.delete_lastcfg=delete_lastcfg
3438
+ self.ui.aDeleteLastCfg.triggered.connect(delete_lastcfg)
3439
+
3440
+ self.ui.aReloadLastCfg = self.menuDebug.addAction("Reload lastWorkspace"+outExt.cfg)
3441
+ def reloadLastCfg():
3442
+ if os.path.exists(lastcfgname): self.initialize()
3443
+ else: self.new_workspace_debug()
3444
+ self.ui.aReloadLastCfg.triggered.connect(reloadLastCfg)
3445
+
3446
+ #--------------------------- printings
3447
+ self.menuDebug.addSeparator()
3448
+ self.ui.printMenu=self.menuDebug.addMenu('Print')
3449
+ printTypes_list=list(self.GPApar.printTypes)
3450
+ printActions=[]
3451
+ printCallbacks=[]
3452
+ def setPrint(name,act,k):
3453
+ flag=act.isChecked()
3454
+ self.GPApar.printTypes[name]=flag
3455
+ flagTime=getattr(getattr(pri,name),'flagTime')
3456
+ faceStd=getattr(getattr(pri,name),'faceStd')
3457
+ if flag:
3458
+ setattr(pri,name,ColorPrint(flagTime=flagTime,prio=PrintTAPriority.medium,faceStd=faceStd))
3459
+ else:
3460
+ setattr(pri,name,ColorPrint(flagTime=flagTime,prio=PrintTAPriority.never,faceStd=faceStd))
3461
+ #print(f'{name} {flag}')
3462
+ #pri.Callback.white(f'pri.Callback.white(): setPrint')
3463
+ return
3464
+ def genCallback(name,act,k):
3465
+ n=name
3466
+ a=act
3467
+ j=k
3468
+ def callback():
3469
+ setPrint(n,a,j)
3470
+ self.menuDebug.popup(self.menuDebug.pos())
3471
+ self.ui.printMenu.exec_()
3472
+ return callback
3473
+ for k,name in enumerate(printTypes_list):
3474
+ if not hasattr(pri,name): continue
3475
+ flagFullDebug=getattr(getattr(pri,name),'flagFullDebug')
3476
+ if flagFullDebug and not Flag_fullDEBUG: continue
3477
+ act=self.ui.printMenu.addAction(name)
3478
+ printActions.append(act)
3479
+ act.setCheckable(True)
3480
+ flag=self.GPApar.printTypes[name]
3481
+ act.setChecked(flag)
3482
+ setPrint(name,act,k)
3483
+ printCallbacks.append(genCallback(name,act,k))
3484
+ act.triggered.connect(printCallbacks[-1])
3485
+ self.ui.printMenu.addSeparator()
3486
+ allPrintsAct=self.ui.printMenu.addAction('All printings')
3487
+ allPrintsAct.setCheckable(True)
3488
+ def setAllPrints():
3489
+ flag=allPrintsAct.isChecked()
3490
+ for a in printActions:
3491
+ a:QAction
3492
+ a.setChecked(flag)
3493
+ setPrint(a.text(),a,None)
3494
+ self.menuDebug.popup(self.menuDebug.pos())
3495
+ self.ui.printMenu.exec_()
3496
+ return
3497
+ allPrintsAct.triggered.connect(setAllPrints)
3498
+
3499
+ #--------------------------- operation
3500
+ if Flag_fullDEBUG:
3501
+ self.menuDebug.addSeparator()
3502
+ self.ui.simpleFor = self.menuDebug.addAction("Dummy it will be change after")
3503
+ def changeFlagSingleFor():
3504
+ self.flagSimpleFor=not self.flagSimpleFor
3505
+ if self.flagSimpleFor:
3506
+ self.ui.simpleFor.setText("reactivate multi processor")
3507
+ else:
3508
+ self.ui.simpleFor.setText("Simple For (no Multi processor usefull to debug c code)")
3509
+ self.flagSimpleFor=not self.flagSimpleFor
3510
+ changeFlagSingleFor()
3511
+ self.ui.simpleFor.triggered.connect(changeFlagSingleFor)
3512
+
3513
+ self.menuDebug.addSeparator()
3514
+ self.ui.aShowDownload = self.menuDebug.addAction("Show/hide download button")
3515
+ def aShowDownload():
3516
+ self.ui.button_PaIRS_download.setVisible(not self.ui.button_PaIRS_download.isVisible())
3517
+ self.ui.aShowDownload.triggered.connect(aShowDownload)
3518
+
3519
+ self.ui.aBetaDownload = self.menuDebug.addAction("Change download button icon")
3520
+ def aBetaDownload():
3521
+ b=self.ui.button_PaIRS_download
3522
+ if b.icon().pixmap(b.size()).toImage()==self.flaticon_PaIRS_download.pixmap(b.size()).toImage():
3523
+ b.setIcon(self.flaticon_PaIRS_beta)
3524
+ else:
3525
+ b.setIcon(self.flaticon_PaIRS_download)
3526
+ self.ui.aBetaDownload.triggered.connect(aBetaDownload)
3527
+
3528
+ self.ui.aResetFlagOutDated = self.menuDebug.addAction("Reset FlagOutDated")
3529
+ def aResetFlagOutDated():
3530
+ self.GPApar.FlagOutDated=0 if self.GPApar.currentVersion==self.GPApar.latestVersion else 1 if self.GPApar.FlagOutDated>0 else -1
3531
+ packageName='PaIRS-UniNa'
3532
+ currentVersion=self.GPApar.currentVersion
3533
+ latestVersion=self.GPApar.latestVersion
3534
+ if self.GPApar.FlagOutDated==1:
3535
+ sOut=f'{packageName} the current version ({currentVersion}) of {packageName} is obsolete! Please, install the latest version: {latestVersion} by using:\npython -m pip install --upgrade {packageName}'
3536
+ elif self.GPApar.FlagOutDated==1:
3537
+ sOut=f'The version of the current instance of {packageName} ({currentVersion}) is newer than the latest official releas ({latestVersion})!\nYou should contact Tommaso and Gerardo if you are a developer and some relevant change is made by yourself!\nIf you are a user, enjoy this beta version and please report any issue!'
3538
+ else:
3539
+ sOut=f'{packageName} The current version ({currentVersion}) of {packageName} is up-to-date! Enjoy it!'
3540
+ pri.Info.yellow(f'[{self.GPApar.FlagOutDated}] '+sOut)
3541
+ self.ui.aResetFlagOutDated.triggered.connect(aResetFlagOutDated)
3542
+
3543
+ self.ui.aCheckOutDated = self.menuDebug.addAction("Check for new packages")
3544
+ def aCheckOutDated():
3545
+ self.GPApar.FlagOutDated=0
3546
+ self.ui.button_PaIRS_download.hide()
3547
+ checkLatestVersion(self,__version__,self.app,splash=None)
3548
+ self.ui.aCheckOutDated.triggered.connect(aCheckOutDated)
3549
+
3550
+ self.menuDebug.addSeparator()
3551
+ self.ui.aResetWhatsNew = self.menuDebug.addAction("Reset whatsnew.txt")
3552
+ def aResetWhatsNew():
3553
+ if os.path.exists(fileWhatsNew[1]):
3554
+ try:
3555
+ os.rename(fileWhatsNew[1],fileWhatsNew[0])
3556
+ except Exception as inst:
3557
+ pri.Error.red(f'There was a problem while renaming the file {fileWhatsNew[1]}:\n{inst}')
3558
+ self.ui.aResetWhatsNew.triggered.connect(aResetWhatsNew)
3559
+
3560
+ self.ui.aShowWhatsNew = self.menuDebug.addAction("Show What's new window")
3561
+ def aShowWhatsNew():
3562
+ self.whatsNew()
3563
+ self.ui.aShowWhatsNew.triggered.connect(aShowWhatsNew)
3564
+
3565
+ self.menuDebug.addSeparator()
3566
+ self.ui.aKill = self.menuDebug.addAction("Stop processes and close")
3567
+ def aKill():
3568
+ self.FlagClosing[0]=True
3569
+ self.signals.killOrResetParForWorker.emit(True)
3570
+ self.aKill=aKill
3571
+ self.ui.aKill.triggered.connect(aKill)
3572
+
3573
+ self.ui.aFocusWid = self.menuDebug.addAction("Print widget with focus")
3574
+ def aFocusWid():
3575
+ pri.Info.yellow(f"The widget with focus is: {self.focusWidget()}")
3576
+ self.aCheckConnections=aFocusWid
3577
+ self.ui.aFocusWid.triggered.connect(aFocusWid)
3578
+
3579
+ if not Flag_ISEXE:
3580
+ self.menuDebug.addSeparator()
3581
+ self.ui.aResetRequiredPackagesFile = self.menuDebug.addAction("Reset rqrdpckgs.txt file")
3582
+ def aResetRequiredPackagesFile():
3583
+ resetRequiredPackagesFile()
3584
+ self.ui.aResetRequiredPackagesFile.triggered.connect(aResetRequiredPackagesFile)
3585
+
3586
+ self.ui.aCheckRequiredPackages = self.menuDebug.addAction("Requirements' version check")
3587
+ def aCheckRequiredPackages():
3588
+ checkRequiredPackages(self,FlagDisplay=True)
3589
+ self.ui.aCheckRequiredPackages.triggered.connect(aCheckRequiredPackages)
3590
+
3591
+ self.ui.aShowPackIssue = self.menuDebug.addAction("Show/hide version check button")
3592
+ def aShowPackIssue():
3593
+ self.FlagPackIssue=not self.FlagPackIssue
3594
+ self.ui.button_packissue.setVisible(self.FlagPackIssue)
3595
+ self.ui.aShowPackIssue.triggered.connect(aShowPackIssue)
3596
+
3597
+ self.ui.aTryCheckRequiredPackages = self.menuDebug.addAction("Try requirements' version check")
3598
+ def aTryCheckRequiredPackages():
3599
+ checkRequiredPackages(self,FlagDisplay=True,FlagForcePrint=True)
3600
+ self.ui.aTryCheckRequiredPackages.triggered.connect(aTryCheckRequiredPackages)
3601
+
3602
+ #--------------------------- graphics
3603
+ if Flag_fullDEBUG:
3604
+ self.menuDebug.addSeparator()
3605
+
3606
+ self.ui.aDefSizes = self.menuDebug.addAction("Set default sizes")
3607
+ self.ui.aDefSizes.triggered.connect(self.setDefaultSizes)
3608
+
3609
+ self.ui.aUndock = self.menuDebug.addAction("Undock a widget")
3610
+ self.ui.aUndock.triggered.connect(self.extractWidget)
3611
+
3612
+ self.ui.aLogo = self.menuDebug.addAction("Change PaIRS logo")
3613
+ self.ui.aLogo.triggered.connect(self.happyLogo)
3614
+
3615
+ self.ui.aGifs = self.menuDebug.addAction("Show/hide gifs")
3616
+ def showGifs():
3617
+ flag=not self.ui.label_updating_import.isVisible()
3618
+ self.ui.label_updating_import.setVisible(flag)
3619
+ self.ui.label_updating_pairs.setVisible(flag)
3620
+ self.ui.aGifs.triggered.connect(showGifs)
3621
+
3622
+ #--------------------------- exit
3623
+ self.menuDebug.addSeparator()
3624
+
3625
+ self.ui.aExitDebug = self.menuDebug.addAction("Exit debug mode")
3626
+ self.ui.aExitDebug.triggered.connect(lambda:self.setDebugMode(False))
3627
+
3628
+ def extractWidget(self):
3629
+ title="Undock a widget"
3630
+ label="Enter the widget name:"
3631
+ words = ["self.w_Input",
3632
+ "self.w_Input.ui.CollapBox_ImSet",
3633
+ "self.w_Output",
3634
+ "self.w_Process",
3635
+ "self.w_Process.ui.CollapBox_IntWind",
3636
+ "self.w_Process.ui.CollapBox_FinIt",
3637
+ "self.w_Process.ui.CollapBox_top",
3638
+ "self.w_Process.ui.CollapBox_Interp",
3639
+ "self.w_Process.ui.CollapBox_Validation",
3640
+ "self.w_Process.ui.CollapBox_Windowing",
3641
+ "self.w_Vis", "self.w_Vis.ui.CollapBox_PlotTools",
3642
+ "self.w_Process", "self.w_Log",
3643
+ "self.w_Process_Min","self.w_Process_Disp",
3644
+ "self.w_Calibration",
3645
+ "self.w_Input_CalVi", "self.w_Process_CalVi", "self.w_Vis_CalVi",
3646
+ "self.ui.w_Managing_Tabs",
3647
+ ]
3648
+
3649
+ ok,text=inputDialog(self,title,label,completer_list=words,width=500)
3650
+ if ok:
3651
+ try:
3652
+ ts=text.split('.')
3653
+ parent=".".join(ts[:-1])
3654
+ child=ts[-1]
3655
+ tab=getattr(eval(parent),child)
3656
+ self.FloatingWindows.append(FloatingWidget(self,tab))
3657
+ pass
3658
+ except Exception as inst:
3659
+ pri.Error.red(f'Error while undocking the widget <{tab}>\n{inst}')
3660
+ pass
3661
+
3662
+ def userDebugMode(self):
3663
+ if not Flag_DEBUG:
3664
+ self.inputDebugMode()
3665
+ else:
3666
+ self.setDebugMode(False)
3667
+
3668
+ def inputDebugMode(self):
3669
+ _,text=inputDialog(self,'Debug','Insert password for debug mode:',width=300,flagScreenCenter=not self.isVisible())
3670
+ if text==pwddbg:
3671
+ self.setDebugMode(True)
3672
+ else:
3673
+ warningDialog(self,'Password for debug mode is wrong!\nPaIRS will stay in normal mode.',time_milliseconds=5000)
3674
+ self.setDebugMode(False)
3675
+
3676
+ def setDebugMode(self,Flag):
3677
+ global Flag_DEBUG
3678
+ Flag_DEBUG=Flag
3679
+ activateFlagDebug(Flag_DEBUG)
3680
+ self.setGPaIRSTitle()
3681
+ self.menuDebug.menuAction().setVisible(Flag)
3682
+
3683
+ def setButtonDownload(self,):
3684
+ self.ui.button_PaIRS_download.setVisible(self.GPApar.FlagOutDated!=0)
3685
+ if self.GPApar.FlagOutDated>0:
3686
+ self.ui.button_PaIRS_download.setIcon(self.flaticon_PaIRS_download)
3687
+ self.ui.button_PaIRS_download.setToolTip("Download the latest version of PaIRS-UniNa.")
3688
+ elif self.GPApar.FlagOutDated==-1000:
3689
+ self.ui.button_PaIRS_download.setIcon(self.flaticon_PaIRS_download_warning)
3690
+ self.ui.button_PaIRS_download.setToolTip("Issue with verifying the latest release!")
3691
+ else:
3692
+ self.ui.button_PaIRS_download.setIcon(self.flaticon_PaIRS_beta)
3693
+ self.ui.button_PaIRS_download.setToolTip("A beta version is currently used!")
3694
+ self.ui.button_PaIRS_download.setStatusTip(self.ui.button_PaIRS_download.toolTip())
3695
+
3696
+ #*************************************************** Greetings
3697
+ def setupLogo(self):
3698
+ today = datetime.date.today()
3699
+ d=today.strftime("%d/%m/%Y")
3700
+ happy_days=[
3701
+ #[d, 'Happy birthday to PaIRS! 🎈🎂🍾'], #to test
3702
+ ['20/12/1991', 'Happy birthday to Gerardo! 🎈🎂🍾'],
3703
+ ['05/02/1969', 'Happy birthday to Tommaso! 🎈🎂🍾'],
3704
+ ['11/07/1987', 'Happy birthday to Carlo! 🎈🎂🍾'],
3705
+ ['19/09/1963', 'Happy birthday to Gennaro! 🎈🎂🍾'],
3706
+ ['27/11/1940', 'Happy birthday to prof. Carlomagno! 🎈🎂🍾'],
3707
+ ['01/12/1969', 'Happy birthday to Giuseppe S.! 🎈🎂🍾'],
3708
+ ['28/02/1981', 'Happy birthday to Rosaria! 🎈🎂🍾'],
3709
+ ['18/10/1985', 'Happy birthday to Stefano! 🎈🎂🍾'],
3710
+ ['13/08/1985', 'Happy birthday to Andrea! 🎈🎂🍾'],
3711
+ ['22/12/1988', 'Happy birthday to Jack! 🎈🎂🍾'],
3712
+ ['03/09/1991', 'Happy birthday to Giusy! 🎈🎂🍾'],
3713
+ ['03/11/1989', 'Happy birthday to Massimo! 🎈🎂🍾'],
3714
+ ['15/06/1991', 'Happy birthday to Mattia! 🎈🎂🍾'],
3715
+ ['14/07/1993', 'Happy birthday to Mirko! 🎈🎂🍾'],
3716
+ ['13/03/1997', 'Happy birthday to Giosuè! 🎈🎂🍾'],
3717
+ ['24/09/1998', 'Happy birthday to Piergiorgio! 🎈🎂🍾'],
3718
+ ['15/01/1999', 'Happy birthday to Alessandro! 🎈🎂🍾'],
3719
+ ['20/02/1999', 'Happy birthday to Cristina! 🎈🎂🍾'],
3720
+ ['20/09/2000', 'Happy birthday to Antonio M.! 🎈🎂🍾'],
3721
+ ['21/09/2000', 'Happy birthday to Gabriele! 🎈🎂🍾'],
3722
+ ['16/11/2000', 'Happy birthday to Antonio D.! 🎈🎂🍾'],
3723
+ ['01/01', 'Happy New Year! 🎊🧨'],
3724
+ ['25/12', 'Merry Christmas! 🎄✨'],
3725
+ ['31/10', 'Happy Halloween! 🎃👻'],
3726
+ ['22/06', 'Hello, Summer! 🌞🌊'],
3727
+ ]
3728
+
3729
+ i=-1
3730
+ for j,l in enumerate(happy_days):
3731
+ if l[0][:6]==d[:6]:
3732
+ i=j
3733
+ break
3734
+
3735
+ if i>-1:
3736
+ self.FlagHappyLogo=True
3737
+ self.ui.logo.setPixmap(QPixmap(u""+ icons_path +"logo_PaIRS_party_rect.png"))
3738
+ self.ui.lab_happy_days.show()
3739
+ self.ui.lab_happy_days.setText(happy_days[i][1])
3740
+ else:
3741
+ self.FlagHappyLogo=False
3742
+ self.ui.logo.setPixmap(QPixmap(u""+ icons_path +"logo_PaIRS_rect.png"))
3743
+ self.ui.lab_happy_days.hide()
3744
+
3745
+ def startHappyLogoWatcher(self):
3746
+ """Re-check date at next midnight and periodically as keep-alive."""
3747
+ # one-shot timer to just-after-midnight (00:01)
3748
+ def _schedule_midnight():
3749
+ now=QDateTime.currentDateTime()
3750
+ next_day = now.date().addDays(1)
3751
+ next_midnight = QDateTime(next_day, QTime(0, 0))
3752
+ msec=now.msecsTo(next_midnight.addSecs(60)) # 00:01
3753
+ if msec<60_000: msec=60_000 # safety minimum
3754
+ self._happy_midnight=QTimer(self)
3755
+ self._happy_midnight.setSingleShot(True)
3756
+ self._happy_midnight.timeout.connect(_on_tick)
3757
+ self._happy_midnight.start(msec)
3758
+
3759
+ def _on_tick():
3760
+ # Re-apply logo state and reschedule
3761
+ self.setupLogo()
3762
+ _schedule_midnight()
3763
+
3764
+ # keep-alive each few hours (handles sleep/wake or clock drift)
3765
+ self._happy_keepalive=QTimer(self)
3766
+ self._happy_keepalive.setInterval(3*60*60*1000) # 3h
3767
+ self._happy_keepalive.timeout.connect(self.setupLogo)
3768
+ self._happy_keepalive.start()
3769
+
3770
+ # initial schedule
3771
+ _schedule_midnight()
3772
+
3773
+ def happyLogo(self):
3774
+ self.FlagHappyLogo=not self.FlagHappyLogo
3775
+ if self.FlagHappyLogo:
3776
+ self.ui.logo.setPixmap(QPixmap(u""+ icons_path +"logo_PaIRS_party_rect.png"))
3777
+ self.ui.lab_happy_days.show()
3778
+ self.ui.lab_happy_days.setText('Greetings! Today is a great day! 🎈🎉')
3779
+ else:
3780
+ self.ui.logo.setPixmap(QPixmap(u""+ icons_path +"logo_PaIRS_rect.png"))
3781
+ self.ui.lab_happy_days.hide()
3782
+
3783
+ #*************************************************** Palette
3784
+ def setGPaIRSPalette(self):
3785
+ setAppGuiPalette(self,self.palettes[self.GPApar.paletteType])
3786
+
3787
+ def paletteContextMenuEvent(self, event):
3788
+ contextMenu = QMenu(self)
3789
+ act=[]
3790
+ for n in self.paletteNames:
3791
+ act.append(contextMenu.addAction(f"{n} mode"))
3792
+ act[self.GPApar.paletteType].setCheckable(True)
3793
+ act[self.GPApar.paletteType].setChecked(True)
3794
+ #userAct = contextMenu.exec(self.mapToGlobal(event.pos()))
3795
+ userAct = contextMenu.exec(self.ui.button_colormode.mapToGlobal(self.ui.button_colormode.rect().center()))
3796
+ for k,a in enumerate(act):
3797
+ if a==userAct:
3798
+ self.GPApar.paletteType=k
3799
+ self.setGPaIRSPalette()
3800
+
3801
+ def launchPaIRS(flagDebug=False,flagInputDebug=False):
3802
+ print('\n'+PaIRS_Header+'Starting the interface...')
3803
+ app=PaIRSApp.instance()
3804
+ if not app:app = QApplication(sys.argv)
3805
+ app.setStyle('Fusion')
3806
+ font=QFont()
3807
+ font.setFamily(fontName)
3808
+ font.setPixelSize(fontPixelSize)
3809
+ app.setFont(font)
3810
+ app.pyicon=app.windowIcon()
3811
+ icon=QIcon()
3812
+ icon.addFile(''+ icons_path +'icon_PaIRS.png',QSize(), QIcon.Normal, QIcon.Off)
3813
+ app.setWindowIcon(icon)
3814
+ try:
3815
+ if (platform.system() == "Windows"):
3816
+ import ctypes
3817
+ ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID('PaIRS')
3818
+ except:
3819
+ pri.Info.red('It was not possible to set the application icon')
3820
+
3821
+ if not flagDebug or Flag_SHOWSPLASH:
3822
+ splash=showSplash()
3823
+ app.processEvents()
3824
+ else:
3825
+ splash=None
3826
+
3827
+ standardPalette=app.style().standardPalette()
3828
+ global Flag_fullDEBUG
3829
+ Flag_fullDEBUG=flagDebug
3830
+ for n in printTypes:
3831
+ p:ColorPrint=getattr(pri,n)
3832
+ if p.flagFullDebug and not Flag_fullDEBUG:
3833
+ p.prio=PrintTAPriority.never
3834
+ p.setPrints()
3835
+
3836
+ if FlagAddMotherBoard and Flag_fullDEBUG:
3837
+ pri.Info.yellow(f"{'-'*50}\nHi, developer!\nMaybe it could be useful for you to add the current computer identifier:\n{currentID}\nto the 'developerIDs' dictionary in PaIRS_pypacks.py!\n{'-'*50}\n")
3838
+
3839
+ if flagInputDebug:
3840
+ _,text=inputDialog(None,'Debug','Insert password for debug mode:',icon=icon,palette=standardPalette,width=300)
3841
+ flagDebug=text==pwddbg
3842
+ if not flagDebug:
3843
+ warningDialog(None,'Password for debug mode is wrong!\nPaIRS will be started in normal mode.',icon=icon,time_milliseconds=5000)
3844
+ gui=gPaIRS(flagDebug,app, standardPalette)
3845
+
3846
+ currentVersion=__version__ #if __subversion__=='0' else __version__+'.'+__subversion__
3847
+ flagStopAndDownload=checkLatestVersion(gui,currentVersion,app,splash)
3848
+ if flagStopAndDownload:
3849
+ gui.correctClose()
3850
+ runPaIRS(gui,flagQuestion=False)
3851
+ return [app,gui,False]
3852
+
3853
+ gui.splash=splash
3854
+ #warningDlg.setModal(True)
3855
+ if splash:
3856
+ splash.setWindowFlags(splash.windowFlags()|Qt.WindowStaysOnTopHint)
3857
+ splash.show()
3858
+ app.processEvents()
3859
+
3860
+ if splash:
3861
+ gui.ui.logo.hide()
3862
+ #gui.adjustGeometry()
3863
+ gui.show()
3864
+ gui.setFontPixelSize()
3865
+ if splash:
3866
+ splashAnimation(splash,gui.ui.logo)
3867
+ #QTimer.singleShot(time_showSplashOnTop,splash.hide)
3868
+ print('\nWelcome to PaIRS!\nEnjoy it!')
3869
+ if not getattr(sys, 'frozen', False): #made by pyInstaller
3870
+ checkRequiredPackages(gui)
3871
+ else:
3872
+ gui.FlagPackIssue=False
3873
+ gui.ui.button_packissue.setVisible(gui.FlagPackIssue)
3874
+ if os.path.exists(fileWhatsNew[0]): gui.whatsNew()
3875
+ app.exec()
3876
+ return [app,gui,True]
3877
+
3878
+ def splashAnimation(self:QLabel,logo:QLabel):
3879
+ margin=23
3880
+ ml=logo.width()/self.width()*margin
3881
+ wl=logo.width()+2*ml
3882
+ hl=wl/self.width()*self.height()
3883
+
3884
+ self.anim = QPropertyAnimation(self, b"pos")
3885
+ pos=logo.mapToGlobal(logo.geometry().topLeft())
3886
+ pos.setX(pos.x()-ml)
3887
+ self.anim.setEndValue(pos)
3888
+ self.anim.setDuration(time_showSplashOnTop)
3889
+ self.anim_2 = QPropertyAnimation(self, b"size")
3890
+
3891
+ self.anim_2.setEndValue(QSize(wl, hl))
3892
+ self.anim_2.setDuration(time_showSplashOnTop)
3893
+ self.anim_group = QParallelAnimationGroup()
3894
+ self.anim_group.addAnimation(self.anim)
3895
+ self.anim_group.addAnimation(self.anim_2)
3896
+ self.anim_group.finished.connect(self.hide)
3897
+ self.anim_group.finished.connect(logo.show)
3898
+ self.anim_group.start()
3899
+
3900
+ def quitPaIRS(app:QApplication,flagPrint=True):
3901
+ app.setWindowIcon(app.pyicon)
3902
+ app.quit()
3903
+ if flagPrint: print('\nPaIRS closed.\nSee you soon!')
3904
+ if hasattr(app,'SecondaryThreads'):
3905
+ if len(app.SecondaryThreads):
3906
+ while any([s.isRunning for s in app.SecondaryThreads]):
3907
+ timesleep(.1)
3908
+ pass
3909
+ app=None
3910
+ return
3911
+
3912
+ if __name__ == "__main__":
3913
+ app,gui,flagPrint=launchPaIRS(True)
3914
+ quitPaIRS(app,flagPrint)