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