PaIRS-UniNa 0.2.7__cp313-cp313-macosx_11_0_universal2.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

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