scipion-pyworkflow 3.10.5__tar.gz → 3.10.6__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (169) hide show
  1. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/CHANGES.txt +15 -1
  2. {scipion_pyworkflow-3.10.5/scipion_pyworkflow.egg-info → scipion_pyworkflow-3.10.6}/PKG-INFO +12 -2
  3. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/constants.py +11 -2
  4. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/form.py +1 -1
  5. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/project/searchprotocol.py +1 -1
  6. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/project/viewprotocols_extra.py +1 -2
  7. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/mapper/sqlite.py +9 -6
  8. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/object.py +3 -2
  9. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/plugin.py +1 -1
  10. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/project/project.py +31 -34
  11. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/project/scripts/fix_links.py +4 -1
  12. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/protocol/constants.py +1 -1
  13. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/protocol/executor.py +23 -7
  14. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/protocol/hosts.py +2 -1
  15. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/protocol/protocol.py +85 -26
  16. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/utils/process.py +29 -8
  17. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflowtests/objects.py +2 -2
  18. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflowtests/tests/test_protocol_execution.py +7 -0
  19. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6/scipion_pyworkflow.egg-info}/PKG-INFO +12 -2
  20. scipion_pyworkflow-3.10.6/scipion_pyworkflow.egg-info/entry_points.txt +2 -0
  21. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/setup.py +0 -3
  22. scipion_pyworkflow-3.10.5/scipion_pyworkflow.egg-info/entry_points.txt +0 -5
  23. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/LICENSE.txt +0 -0
  24. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/MANIFEST.in +0 -0
  25. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/README.rst +0 -0
  26. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/__init__.py +0 -0
  27. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/apps/__init__.py +0 -0
  28. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/apps/pw_manager.py +0 -0
  29. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/apps/pw_plot.py +0 -0
  30. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/apps/pw_project.py +0 -0
  31. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/apps/pw_protocol_list.py +0 -0
  32. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/apps/pw_protocol_run.py +0 -0
  33. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/apps/pw_run_tests.py +0 -0
  34. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/apps/pw_schedule_run.py +0 -0
  35. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/apps/pw_sleep.py +0 -0
  36. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/apps/pw_sync_data.py +0 -0
  37. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/apps/pw_viewer.py +0 -0
  38. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/config.py +0 -0
  39. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/exceptions.py +0 -0
  40. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/__init__.py +0 -0
  41. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/browser.py +0 -0
  42. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/canvas.py +0 -0
  43. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/dialog.py +0 -0
  44. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/graph.py +0 -0
  45. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/graph_layout.py +0 -0
  46. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/gui.py +0 -0
  47. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/matplotlib_image.py +0 -0
  48. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/plotter.py +0 -0
  49. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/project/__init__.py +0 -0
  50. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/project/base.py +0 -0
  51. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/project/constants.py +0 -0
  52. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/project/labels.py +0 -0
  53. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/project/project.py +0 -0
  54. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/project/searchrun.py +0 -0
  55. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/project/steps.py +0 -0
  56. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/project/utils.py +0 -0
  57. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/project/variables.py +0 -0
  58. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/project/viewdata.py +0 -0
  59. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/project/viewprojects.py +0 -0
  60. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/project/viewprotocols.py +0 -0
  61. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/text.py +0 -0
  62. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/tooltip.py +0 -0
  63. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/tree.py +0 -0
  64. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/widgets.py +0 -0
  65. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/mapper/__init__.py +0 -0
  66. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/mapper/mapper.py +0 -0
  67. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/mapper/sqlite_db.py +0 -0
  68. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/project/__init__.py +0 -0
  69. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/project/config.py +0 -0
  70. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/project/manager.py +0 -0
  71. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/project/scripts/clean_projects.py +0 -0
  72. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/project/scripts/config.py +0 -0
  73. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/project/scripts/create.py +0 -0
  74. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/project/scripts/edit_workflow.py +0 -0
  75. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/project/scripts/load.py +0 -0
  76. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/project/scripts/refresh.py +0 -0
  77. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/project/scripts/schedule.py +0 -0
  78. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/project/scripts/stack2volume.py +0 -0
  79. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/project/scripts/stop.py +0 -0
  80. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/protocol/__init__.py +0 -0
  81. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/protocol/bibtex.py +0 -0
  82. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/protocol/launch.py +0 -0
  83. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/protocol/package.py +0 -0
  84. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/protocol/params.py +0 -0
  85. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/Imagej.png +0 -0
  86. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/chimera.png +0 -0
  87. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/fa-exclamation-triangle_alert.png +0 -0
  88. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/fa-info-circle_alert.png +0 -0
  89. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/fa-search.png +0 -0
  90. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/fa-times-circle_alert.png +0 -0
  91. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/file_vol.png +0 -0
  92. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/loading.gif +0 -0
  93. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/no-image128.png +0 -0
  94. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/scipion_bn.png +0 -0
  95. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/scipion_icon.png +0 -0
  96. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/scipion_icon.svg +0 -0
  97. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/scipion_icon_proj.png +0 -0
  98. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/scipion_icon_projs.png +0 -0
  99. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/scipion_icon_prot.png +0 -0
  100. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/scipion_logo.png +0 -0
  101. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/scipion_logo_normal.png +0 -0
  102. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/scipion_logo_small.png +0 -0
  103. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/showj/arrowDown.png +0 -0
  104. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/showj/arrowUp.png +0 -0
  105. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/showj/background_section.png +0 -0
  106. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/showj/colRowModeOff.png +0 -0
  107. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/showj/colRowModeOn.png +0 -0
  108. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/showj/delete.png +0 -0
  109. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/showj/doc_icon.png +0 -0
  110. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/showj/download_icon.png +0 -0
  111. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/showj/enabled_gallery.png +0 -0
  112. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/showj/galleryViewOff.png +0 -0
  113. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/showj/galleryViewOn.png +0 -0
  114. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/showj/goto.png +0 -0
  115. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/showj/menu.png +0 -0
  116. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/showj/separator.png +0 -0
  117. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/showj/tableViewOff.png +0 -0
  118. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/showj/tableViewOn.png +0 -0
  119. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/showj/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  120. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/showj/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  121. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/showj/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  122. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/showj/volumeOff.png +0 -0
  123. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/showj/volumeOn.png +0 -0
  124. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/sprites.png +0 -0
  125. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/sprites.xcf +0 -0
  126. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/wait.gif +0 -0
  127. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/template.py +0 -0
  128. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/tests/__init__.py +0 -0
  129. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/tests/test_utils.py +0 -0
  130. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/tests/tests.py +0 -0
  131. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/utils/__init__.py +0 -0
  132. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/utils/dataset.py +0 -0
  133. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/utils/echo.py +0 -0
  134. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/utils/graph.py +0 -0
  135. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/utils/log.py +0 -0
  136. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/utils/path.py +0 -0
  137. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/utils/profiler.py +0 -0
  138. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/utils/progressbar.py +0 -0
  139. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/utils/properties.py +0 -0
  140. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/utils/reflection.py +0 -0
  141. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/utils/utils.py +0 -0
  142. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/utils/which.py +0 -0
  143. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/viewer.py +0 -0
  144. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/webservices/__init__.py +0 -0
  145. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/webservices/config.py +0 -0
  146. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/webservices/notifier.py +0 -0
  147. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/webservices/repository.py +0 -0
  148. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/webservices/workflowhub.py +0 -0
  149. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/wizard.py +0 -0
  150. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflowtests/__init__.py +0 -0
  151. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflowtests/bibtex.py +0 -0
  152. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflowtests/protocols.py +0 -0
  153. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflowtests/tests/__init__.py +0 -0
  154. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflowtests/tests/test_canvas.py +0 -0
  155. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflowtests/tests/test_domain.py +0 -0
  156. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflowtests/tests/test_logs.py +0 -0
  157. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflowtests/tests/test_mappers.py +0 -0
  158. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflowtests/tests/test_object.py +0 -0
  159. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflowtests/tests/test_project.py +0 -0
  160. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflowtests/tests/test_protocol_export.py +0 -0
  161. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflowtests/tests/test_protocol_output.py +0 -0
  162. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflowtests/tests/test_streaming.py +0 -0
  163. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflowtests/tests/test_utils.py +0 -0
  164. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/requirements.txt +0 -0
  165. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/scipion_pyworkflow.egg-info/SOURCES.txt +0 -0
  166. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/scipion_pyworkflow.egg-info/dependency_links.txt +0 -0
  167. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/scipion_pyworkflow.egg-info/requires.txt +0 -0
  168. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/scipion_pyworkflow.egg-info/top_level.txt +0 -0
  169. {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/setup.cfg +0 -0
@@ -1,3 +1,17 @@
1
+ V3.10.6:
2
+ - Improving subset creation
3
+ - PLUGIN_MODULE variable can be used in host.conf to customize mpirun command: mpirun.PLUGIN_MODULE --> mpirun.relion)
4
+ This approach implies having this pattern for all mpi plugins that use mpi.
5
+ - Alternatively, in the scipion.conf file a variable called PARALLEL_COMMAND_XXX could be defined for a more
6
+ versatile way to have a mpi command only for some plugins. Example:
7
+ PARALLEL_COMMAND_RELION=mpirun.relion -np %%(JOB_NODES)d --map-by node %%(COMMAND)s
8
+ NOTE: in this config file, %_ (valid and needed in host.conf) should be replaced by %%
9
+ - GPU Ids are automatically anonymized (0-len(GPUs)) when using queues
10
+ - Bug-fix: creation time is not loaded when loadig run.db (updating a protocol)
11
+ developers:
12
+ - Adding a Streaming section in ProtStreamingBase
13
+ - runJob call without %(GPU)s will not reserve GPU slots anymore.
14
+
1
15
  V3.10.5: cancel usage of SCIPION_PROJECT in the host template
2
16
  V3.10.4: hotfix: Parallelization with GPUs is fixed and step queue executor fixed with the new implementation.
3
17
  V3.10.3: Failed hotfix
@@ -5,7 +19,7 @@ V3.10.2: hotfix: Executor frees the GPU/s used via step id instead of node.
5
19
  V3.10.1: hotfix: Avoid double Gpu assignment in scipion parallelize protocols with concurrent GPU steps
6
20
  V3.10.0
7
21
  developers:
8
- - stepsExecutionMode = STEPS_SERIAL at class level. Should a class attribute for future versions. Now both approaches are valid.
22
+ - stepsExecutionMode = STEPS_SERIAL at class level. Should be a class attribute for future versions. Now both approaches are valid.
9
23
 
10
24
  V3.9.2 - hotfix: rescue commented methods: Protocol._insertRunJobStep and Protocol._insertCopyFileStep
11
25
  V3.9.1 - hotfix: loading related objects (CTF - Mics in particle extraction)
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: scipion-pyworkflow
3
- Version: 3.10.5
3
+ Version: 3.10.6
4
4
  Summary: Simple workflow platform used in scientific applications, initially developed within the Scipion framework for image processing in Electron Microscopy.
5
5
  Home-page: https://github.com/scipion-em/scipion-pyworkflow
6
6
  Author: J.M. De la Rosa Trevin, Roberto Marabini, Grigory Sharov, Josue Gomez Blanco, Pablo Conesa, Yunior Fonseca Reyna
@@ -30,6 +30,16 @@ Requires-Dist: requests==2.31.0; python_version >= "3.8"
30
30
  Requires-Dist: tkcolorpicker
31
31
  Requires-Dist: distro<=1.8
32
32
  Requires-Dist: importlib-metadata<=6.8.0
33
+ Dynamic: author
34
+ Dynamic: author-email
35
+ Dynamic: classifier
36
+ Dynamic: description
37
+ Dynamic: home-page
38
+ Dynamic: keywords
39
+ Dynamic: license-file
40
+ Dynamic: project-url
41
+ Dynamic: requires-dist
42
+ Dynamic: summary
33
43
 
34
44
  .. image:: https://img.shields.io/pypi/v/scipion-pyworkflow.svg
35
45
  :target: https://pypi.python.org/pypi/scipion-pyworkflow
@@ -43,7 +43,7 @@ VERSION_1 = '1.0.0'
43
43
  VERSION_1_1 = '1.1.0'
44
44
  VERSION_1_2 = '1.2.0'
45
45
  VERSION_2_0 = '2.0.0'
46
- VERSION_3_0 = '3.10.5'
46
+ VERSION_3_0 = '3.10.6'
47
47
 
48
48
  # For a new release, define a new constant and assign it to LAST_VERSION
49
49
  # The existing one has to be added to OLD_VERSIONS list.
@@ -73,6 +73,16 @@ SCIPION_HOME_VAR = 'SCIPION_HOME'
73
73
  SCIPION_TESTS = 'SCIPION_TESTS'
74
74
  SCIPION_SCRATCH = 'SCIPION_SCRATCH'
75
75
 
76
+ # VARIABLE names in host.conf
77
+ PARALLEL_COMMAND_VAR = 'PARALLEL_COMMAND'
78
+ PLUGIN_MODULE_VAR = 'PLUGIN_MODULE'
79
+ QUEUE_FOR_JOBS = 'QUEUE_FOR_JOBS'
80
+
81
+
82
+ # Launching constants
83
+ RUN_JOB_GPU_PARAM = 'GPU' # Param name to "place" GPU ids used to build a run command.
84
+ RUN_JOB_GPU_PARAM_SEARCH = "%("+ RUN_JOB_GPU_PARAM +")s"
85
+
76
86
  # FONT
77
87
  SCIPION_DEFAULT_FONT_SIZE = 10
78
88
 
@@ -215,4 +225,3 @@ DEFAULT_EXECUTION_ACTION_ALL = 3
215
225
  # Id field/attribute constants
216
226
  ID_COLUMN='id'
217
227
  ID_ATTRIBUTE='_objId'
218
-
@@ -1743,7 +1743,7 @@ class FormWindow(Window):
1743
1743
  entry = self._createBoundEntry(procFrame, pwutils.Message.VAR_MPI)
1744
1744
  entry.grid(row=r2, column=c2 + 1, padx=(0, 5), sticky='w')
1745
1745
 
1746
- helpMessage += pwutils.Message.HELP_PARALLEL_MPI
1746
+ helpMessage += '\n' + pwutils.Message.HELP_PARALLEL_MPI
1747
1747
 
1748
1748
 
1749
1749
  btnHelp = IconButton(procFrame, pwutils.Message.TITLE_COMMENT,
@@ -139,7 +139,7 @@ class SearchProtocolWindow(SearchBaseWindow):
139
139
  def _addProtocolToTree(self, protList):
140
140
  """ Adds the items in protList to the tree
141
141
 
142
- :param protList: List of tuples with all the values/colunms used in search ans shown in the tree"""
142
+ :param protList: List of tuples with all the values/columns used in the search search to show in the tree"""
143
143
 
144
144
  for key, label, installed, help, streamified, beta, new, updated, weight in protList:
145
145
  tag = ProtocolTreeConfig.getProtocolTag(installed == 'installed',
@@ -167,7 +167,7 @@ class RunIOTreeProvider(pwgui.tree.TreeProvider):
167
167
  that is more readable for the user to pick the desired object.
168
168
  """
169
169
  label = 'None'
170
- if obj:
170
+ if obj is not None:
171
171
  label = obj.getObjLabel()
172
172
  if not len(label.strip()):
173
173
  parentLabel = parent.getObjLabel() if parent else 'None'
@@ -241,7 +241,6 @@ class RunIOTreeProvider(pwgui.tree.TreeProvider):
241
241
 
242
242
  return infoPtr
243
243
 
244
-
245
244
  if obj is None or not obj.hasValue():
246
245
  return None
247
246
 
@@ -1027,13 +1027,16 @@ class SqliteFlatMapper(Mapper):
1027
1027
 
1028
1028
  return obj
1029
1029
 
1030
- def __iterObjectsFromRows(self, objRows, objectFilter=None):
1030
+ def __iterObjectsFromRows(self, objRows, objectFilter=None, rowFilter=None):
1031
1031
  for objRow in objRows:
1032
+ if rowFilter and not rowFilter(objRow):
1033
+ continue
1034
+
1032
1035
  obj = self.__objFromRow(objRow)
1033
1036
  if objectFilter is None or objectFilter(obj):
1034
1037
  yield obj
1035
1038
 
1036
- def __objectsFromRows(self, objRows, iterate=False, objectFilter=None):
1039
+ def __objectsFromRows(self, objRows, iterate=False, objectFilter=None, rowFilter=None):
1037
1040
  """Create a set of object from a set of rows
1038
1041
  Params:
1039
1042
  objRows: rows result from a db select.
@@ -1043,9 +1046,9 @@ class SqliteFlatMapper(Mapper):
1043
1046
  """
1044
1047
  if not iterate:
1045
1048
  return [obj.clone()
1046
- for obj in self.__iterObjectsFromRows(objRows, objectFilter)]
1049
+ for obj in self.__iterObjectsFromRows(objRows, objectFilter, rowFilter)]
1047
1050
  else:
1048
- return self.__iterObjectsFromRows(objRows, objectFilter)
1051
+ return self.__iterObjectsFromRows(objRows, objectFilter, rowFilter)
1049
1052
 
1050
1053
  def selectBy(self, iterate=False, objectFilter=None, **args):
1051
1054
  """Select object meetings some criteria"""
@@ -1053,7 +1056,7 @@ class SqliteFlatMapper(Mapper):
1053
1056
  return self.__objectsFromRows(objRows, iterate, objectFilter)
1054
1057
 
1055
1058
  def selectAll(self, iterate=True, objectFilter=None, orderBy=ID,
1056
- direction='ASC', where='1', limit=None):
1059
+ direction='ASC', where='1', limit=None, rowFilter=None):
1057
1060
  # Just a sanity check for emtpy sets, that doesn't contains
1058
1061
  # 'Properties' table
1059
1062
  if not self.db.hasTable('Properties'):
@@ -1076,7 +1079,7 @@ and restarting scipion. Export command:
1076
1079
  export SQLITE_TMPDIR=. """ % str(e)
1077
1080
  raise OperationalError(msg)
1078
1081
 
1079
- return self.__objectsFromRows(objRows, iterate, objectFilter)
1082
+ return self.__objectsFromRows(objRows, iterate, objectFilter, rowFilter)
1080
1083
 
1081
1084
  def unique(self, labels, where=None):
1082
1085
  """ Returns a list (for a single label) or a dictionary with unique values for the passed labels.
@@ -1233,12 +1233,13 @@ class Set(Object):
1233
1233
  return self._getMapper().exists(itemId)
1234
1234
 
1235
1235
  def iterItems(self, orderBy='id', direction='ASC', where=None,
1236
- limit=None, iterate=True):
1236
+ limit=None, iterate=True, rowFilter=None):
1237
1237
  return self._getMapper().selectAll(orderBy=orderBy,
1238
1238
  direction=direction,
1239
1239
  where=where,
1240
1240
  limit=limit,
1241
- iterate=iterate) # has flat mapper, iterate is true
1241
+ iterate=iterate,
1242
+ rowFilter=rowFilter) # has flat mapper, iterate is true
1242
1243
 
1243
1244
  def getFirstItem(self):
1244
1245
  """ Return the first item in the Set. """
@@ -508,7 +508,7 @@ class Domain:
508
508
 
509
509
  raiseMsg = "%s\n %s\n%s\n" % (msgStr, calling, hint)
510
510
  if doRaise:
511
- raise Exception("\n\n" + raiseMsg)
511
+ raise ImportError("\n\n" + raiseMsg)
512
512
  else:
513
513
  logger.info(raiseMsg)
514
514
 
@@ -48,7 +48,7 @@ from pyworkflow.mapper import SqliteMapper
48
48
  from pyworkflow.protocol.constants import (MODE_RESTART, MODE_RESUME,
49
49
  STATUS_INTERACTIVE, ACTIVE_STATUS,
50
50
  UNKNOWN_JOBID, INITIAL_SLEEP_TIME, STATUS_FINISHED)
51
- from pyworkflow.protocol.protocol import ProtImportBase, Protocol
51
+ from pyworkflow.protocol.protocol import Protocol
52
52
 
53
53
  from . import config
54
54
 
@@ -306,14 +306,17 @@ class Project(object):
306
306
  if creationTime: # CreationTime was found in project.sqlite
307
307
  ctStr = creationTime[0] # This is our String type instance
308
308
 
309
- # We store it in mem as dateime
309
+ # We store it in mem as datetime
310
310
  self._creationTime = ctStr
311
311
 
312
312
  else:
313
- # We should read the creation time from settings.sqlite and
314
- # update the CreationTime in the project.sqlite
315
- self._creationTime = pwobj.String(self.getSettingsCreationTime())
316
- self._storeCreationTime()
313
+
314
+ # If connected to project.sqlite and not any or the run.db
315
+ if self.path.endswith(PROJECT_DBNAME):
316
+ # We should read the creation time from settings.sqlite and
317
+ # update the CreationTime in the project.sqlite
318
+ self._creationTime = pwobj.String(self.getSettingsCreationTime())
319
+ self._storeCreationTime()
317
320
 
318
321
  # ---- Helper functions to load different pieces of a project
319
322
  def _loadDb(self, dbPath):
@@ -1961,37 +1964,31 @@ class Project(object):
1961
1964
  self.settings.setReadOnly(value)
1962
1965
 
1963
1966
  def fixLinks(self, searchDir):
1964
- logger.info("Fixing project links. Searching at %s" % searchDir)
1967
+ logger.info(f"Fixing links for project {self.getShortName()}. Searching in: {searchDir}")
1965
1968
  runs = self.getRuns()
1966
1969
 
1970
+ counter = 0
1967
1971
  for prot in runs:
1968
- print (prot)
1969
- broken = False
1970
- if isinstance(prot, ProtImportBase) or prot.getClassName() == "ProtImportMovies":
1971
- logger.info("Import detected")
1972
- for _, attr in prot.iterOutputAttributes():
1973
- for f in attr.getFiles():
1974
- if ':' in f:
1975
- f = f.split(':')[0]
1976
-
1977
- if not os.path.exists(f):
1978
- if not broken:
1979
- broken = True
1980
- logger.info("Found broken links in run: %s" %
1981
- pwutils.magenta(prot.getRunName()))
1982
- logger.info(" Missing: %s" % pwutils.magenta(f))
1983
-
1984
- if os.path.islink(f):
1985
- sourceFile = os.path.realpath(f)
1986
- logger.info(" -> %s" % pwutils.red(sourceFile))
1987
-
1988
- newFile = pwutils.findFile(os.path.basename(sourceFile),
1989
- searchDir,
1990
- recursive=True)
1991
- if newFile:
1992
- logger.info(" Found file %s, creating link... %s" % (newFile,
1993
- pwutils.green(" %s -> %s" % (f, newFile))))
1994
- pwutils.createAbsLink(newFile, f)
1972
+ if prot.getClassName().startswith("ProtImport"):
1973
+ runName = prot.getRunName()
1974
+ logger.info(f"Found protocol {runName}")
1975
+ for f in prot.getOutputFiles():
1976
+ if ':' in f:
1977
+ f = f.split(':')[0]
1978
+
1979
+ if not os.path.exists(f):
1980
+ logger.info(f"\tMissing link: {f}")
1981
+
1982
+ if os.path.islink(f):
1983
+ sourceFile = os.path.realpath(f)
1984
+ newFile = pwutils.findFileRecursive(os.path.basename(sourceFile),
1985
+ searchDir)
1986
+ if newFile:
1987
+ counter += 1
1988
+ logger.info(f"\t\tCreating link: {f} -> {newFile}")
1989
+ pwutils.createAbsLink(newFile, f)
1990
+
1991
+ logger.info(f"Fixed {counter} broken links")
1995
1992
 
1996
1993
  @staticmethod
1997
1994
  def cleanProjectName(projectName):
@@ -3,12 +3,15 @@
3
3
  import sys
4
4
  import os
5
5
  import logging
6
- logging.basicConfig(level="INFO")
7
6
 
7
+ from pyworkflow.config import Config
8
8
  from pyworkflow.project import Manager
9
9
  import pyworkflow.utils as pwutils
10
10
 
11
11
 
12
+ logging.basicConfig(level=Config.SCIPION_LOG_LEVEL, format=Config.SCIPION_LOG_FORMAT)
13
+
14
+
12
15
  def usage(error):
13
16
  print("""
14
17
  ERROR: %s
@@ -84,4 +84,4 @@ UNKNOWN_JOBID = -1
84
84
  SIZE_1KB = 1024
85
85
  SIZE_1MB = SIZE_1KB * SIZE_1KB
86
86
  SIZE_1GB = SIZE_1MB * SIZE_1KB
87
- SIZE_1TB = SIZE_1GB * SIZE_1KB
87
+ SIZE_1TB = SIZE_1GB * SIZE_1KB
@@ -39,6 +39,7 @@ import os
39
39
 
40
40
  import pyworkflow.utils.process as process
41
41
  from pyworkflow.utils.path import getParentFolder, removeExt
42
+ from pyworkflow.constants import PLUGIN_MODULE_VAR, RUN_JOB_GPU_PARAM_SEARCH
42
43
  from . import constants as cts
43
44
 
44
45
  from .launch import _submit, UNKNOWN_JOBID, _checkJobStatus
@@ -59,16 +60,26 @@ class StepExecutor:
59
60
  """ Set protocol to append active jobs to its jobIds. """
60
61
  self.protocol = protocol
61
62
 
62
- def runJob(self, log, programName, params,
63
+ def getRunContext(self):
64
+ return {PLUGIN_MODULE_VAR: self.protocol.getPlugin().getName()}
65
+
66
+ def runJob(self, log, programName, params,
63
67
  numberOfMpi=1, numberOfThreads=1,
64
68
  env=None, cwd=None, executable=None):
65
69
  """ This function is a wrapper around runJob,
66
70
  providing the host configuration.
67
71
  """
68
72
  process.runJob(log, programName, params,
69
- numberOfMpi, numberOfThreads,
73
+ numberOfMpi, numberOfThreads,
70
74
  self.hostConfig,
71
- env=env, cwd=cwd, gpuList=self.getGpuList(), executable=executable)
75
+ env=env, cwd=cwd, gpuList=self._getGPUListForCommand(programName, params), executable=executable, context=self.protocol.getSubmitDict())
76
+
77
+ def _getGPUListForCommand(self, program, params):
78
+ """ Returns the list of GPUs if the program or the params have the GPU placeholder %(GPU)s """
79
+ if RUN_JOB_GPU_PARAM_SEARCH in params or RUN_JOB_GPU_PARAM_SEARCH in program:
80
+ return self.getGpuList()
81
+ else:
82
+ return []
72
83
 
73
84
  def _getRunnable(self, steps, n=1):
74
85
  """ Return the n steps that are 'new' and all its
@@ -258,7 +269,7 @@ class ThreadStepExecutor(StepExecutor):
258
269
 
259
270
  gpus = self.getFreeGpuSlot(nodeId)
260
271
  if gpus is None:
261
- logger.warning("Step on node %s is requesting GPUs but there isn't any available. Review configuration of threads/GPUs. Returning and empty list." % nodeId)
272
+ logger.warning("Step on node %s is requesting GPUs but there isn't any available. Review configuration of threads/GPUs. Returning an empty list." % nodeId)
262
273
  return []
263
274
  else:
264
275
  return gpus
@@ -422,15 +433,20 @@ class QueueStepExecutor(ThreadStepExecutor):
422
433
  threadId = threading.current_thread().thId
423
434
  submitDict = dict(self.hostConfig.getQueuesDefault())
424
435
  submitDict.update(self.submitDict)
425
- submitDict['JOB_COMMAND'] = process.buildRunCommand(programName, params, numberOfMpi,
426
- self.hostConfig, env,
427
- gpuList=self.getGpuList())
428
436
  threadJobId = self.getThreadJobId(threadId)
429
437
  subthreadId = '-%s-%s' % (threadId, threadJobId)
430
438
  submitDict['JOB_NAME'] = submitDict['JOB_NAME'] + subthreadId
431
439
  submitDict['JOB_SCRIPT'] = os.path.abspath(removeExt(submitDict['JOB_SCRIPT']) + subthreadId + ".job")
432
440
  submitDict['JOB_LOGS'] = os.path.join(getParentFolder(submitDict['JOB_SCRIPT']), submitDict['JOB_NAME'])
433
441
 
442
+ logger.debug("Variables available for replacement in submission command are: %s" % submitDict)
443
+
444
+ submitDict['JOB_COMMAND'] = process.buildRunCommand(programName, params, numberOfMpi,
445
+ self.hostConfig, env,
446
+ gpuList=self._getGPUListForCommand(programName, params),
447
+ context=submitDict)
448
+
449
+
434
450
  jobid = _submit(self.hostConfig, submitDict, cwd, env)
435
451
  self.protocol.appendJobId(jobid) # append active jobs
436
452
  self.protocol._store(self.protocol._jobId)
@@ -36,6 +36,7 @@ from configparser import RawConfigParser
36
36
  from collections import OrderedDict
37
37
 
38
38
  import pyworkflow as pw
39
+ from pyworkflow import PARALLEL_COMMAND_VAR
39
40
  from pyworkflow.object import Object, String, Integer
40
41
 
41
42
 
@@ -199,7 +200,7 @@ class HostConfig(Object):
199
200
  # Read the address of the remote hosts,
200
201
  # using 'localhost' as default for backward compatibility
201
202
  host.setAddress(get('ADDRESS', 'localhost'))
202
- host.mpiCommand.set(get('PARALLEL_COMMAND'))
203
+ host.mpiCommand.set(get(PARALLEL_COMMAND_VAR))
203
204
  host.queueSystem = QueueSystemConfig()
204
205
  hostQueue = host.queueSystem # shortcut
205
206
  hostQueue.name.set(get('NAME'))
@@ -36,13 +36,15 @@ from pyworkflow.exceptions import ValidationException, PyworkflowException
36
36
  from pyworkflow.object import *
37
37
  import pyworkflow.utils as pwutils
38
38
  from pyworkflow.utils.log import getExtraLogInfo, STATUS, setDefaultLoggingContext
39
+ from pyworkflow.constants import PLUGIN_MODULE_VAR, QUEUE_FOR_JOBS
39
40
  from .executor import StepExecutor, ThreadStepExecutor, QueueStepExecutor
40
41
  from .constants import *
41
- from .params import Form
42
+ from .params import Form, IntParam
42
43
  from ..utils import getFileSize
43
44
 
44
45
 
45
46
  import logging
47
+
46
48
  # Get the root logger
47
49
  logger = logging.getLogger(__name__)
48
50
 
@@ -67,6 +69,7 @@ class Step(Object):
67
69
 
68
70
  def needsGPU(self) -> bool:
69
71
  return self._needsGPU.get()
72
+
70
73
  def getIndex(self):
71
74
  return self._index
72
75
 
@@ -1117,10 +1120,7 @@ class Protocol(Step):
1117
1120
  def _getRelPathExecutionDir(self, *path):
1118
1121
  """ Return a relative path from the projdir. """
1119
1122
  # TODO must be a bettis
1120
- return os.path.relpath(
1121
- self._getPath(*path),
1122
- os.path.dirname(os.path.dirname(self.workingDir.get()))
1123
- )
1123
+ return os.path.relpath(self._getPath(*path), os.path.dirname(os.path.dirname(self.workingDir.get())))
1124
1124
 
1125
1125
  def _getBasePath(self, path):
1126
1126
  """ Take the basename of the path and get the path
@@ -1617,7 +1617,6 @@ class Protocol(Step):
1617
1617
  prot_id=self.getObjId(),
1618
1618
  prot_name=self.getClassName()))
1619
1619
 
1620
-
1621
1620
  def getLogPaths(self):
1622
1621
  return [self.getStdoutLog(),self.getStderrLog() , self.getScheduleLog()]
1623
1622
 
@@ -1638,7 +1637,6 @@ class Protocol(Step):
1638
1637
  """ Return the steps.sqlite file under logs directory. """
1639
1638
  return self._getLogsPath('steps.sqlite')
1640
1639
 
1641
-
1642
1640
  def _addChunk(self, txt, fmt=None):
1643
1641
  """
1644
1642
  Add text txt to self._buffer, with format fmt.
@@ -1921,21 +1919,26 @@ class Protocol(Step):
1921
1919
  queueName, queueParams = self.getQueueParams()
1922
1920
  hc = self.getHostConfig()
1923
1921
 
1924
- script = self._getLogsPath(hc.getSubmitPrefix() + self.strId() + '.job')
1925
- d = {'JOB_SCRIPT': script,
1926
- 'JOB_LOGS': self._getLogsPath(hc.getSubmitPrefix() + self.strId()),
1927
- 'JOB_NODEFILE': os.path.abspath(script.replace('.job', '.nodefile')),
1928
- 'JOB_NAME': self.strId(),
1922
+ d = {'JOB_NAME': self.strId(),
1929
1923
  'JOB_QUEUE': queueName,
1930
1924
  'JOB_NODES': self.numberOfMpi.get(),
1931
1925
  'JOB_THREADS': self.numberOfThreads.get(),
1932
1926
  'JOB_CORES': self.numberOfMpi.get() * self.numberOfThreads.get(),
1933
1927
  'JOB_HOURS': 72,
1934
1928
  'GPU_COUNT': len(self.getGpuList()),
1935
- 'QUEUE_FOR_JOBS': 'N',
1929
+ QUEUE_FOR_JOBS: 'N',
1936
1930
  'SCIPION_PROJECT': "SCIPION_PROJECT", # self.getProject().getShortName(),
1937
- 'SCIPION_PROTOCOL': self.getRunName()
1931
+ 'SCIPION_PROTOCOL': self.getRunName(),
1932
+ PLUGIN_MODULE_VAR: self.getPlugin().getName()
1938
1933
  }
1934
+
1935
+ # Criteria in HostConfig.load to load or not QUEUE variables
1936
+ if hc.getQueueSystem().hasName():
1937
+ job_logs = self._getLogsPath(hc.getSubmitPrefix() + self.strId())
1938
+ d['JOB_SCRIPT'] = job_logs + '.job'
1939
+ d['JOB_LOGS'] = job_logs
1940
+ d['JOB_NODEFILE'] = os.path.abspath(job_logs +'.nodefile')
1941
+
1939
1942
  d.update(queueParams)
1940
1943
  return d
1941
1944
 
@@ -1946,12 +1949,12 @@ class Protocol(Step):
1946
1949
  def useQueueForSteps(self):
1947
1950
  """ This function will return True if the protocol has been set
1948
1951
  to be launched through a queue by steps """
1949
- return self.useQueue() and (self.getSubmitDict()["QUEUE_FOR_JOBS"] == "Y")
1952
+ return self.useQueue() and (self.getSubmitDict()[QUEUE_FOR_JOBS] == "Y")
1950
1953
 
1951
1954
  def useQueueForProtocol(self):
1952
1955
  """ This function will return True if the protocol has been set
1953
1956
  to be launched through a queue """
1954
- return self.useQueue() and (self.getSubmitDict()["QUEUE_FOR_JOBS"] == "N")
1957
+ return self.useQueue() and (self.getSubmitDict()[QUEUE_FOR_JOBS] != "Y")
1955
1958
 
1956
1959
  def getQueueParams(self):
1957
1960
  if self._queueParams.hasValue():
@@ -2441,6 +2444,11 @@ def runProtocolMain(projectPath, protDbPath, protId):
2441
2444
  setDefaultLoggingContext(protId, protocol.getProject().getShortName())
2442
2445
 
2443
2446
  hostConfig = protocol.getHostConfig()
2447
+ gpuList = protocol.getGpuList()
2448
+
2449
+ #If queue is to be used
2450
+ if protocol.useQueue():
2451
+ gpuList = anonimizeGPUs(gpuList)
2444
2452
 
2445
2453
  # Create the steps executor
2446
2454
  executor = None
@@ -2451,18 +2459,18 @@ def runProtocolMain(projectPath, protDbPath, protId):
2451
2459
  executor = QueueStepExecutor(hostConfig,
2452
2460
  protocol.getSubmitDict(),
2453
2461
  nThreads - 1,
2454
- gpuList=protocol.getGpuList())
2462
+ gpuList=gpuList)
2455
2463
  else:
2456
2464
  executor = ThreadStepExecutor(hostConfig, nThreads - 1,
2457
- gpuList=protocol.getGpuList())
2465
+ gpuList=gpuList)
2458
2466
 
2459
2467
  if executor is None and protocol.useQueueForSteps():
2460
2468
  executor = QueueStepExecutor(hostConfig, protocol.getSubmitDict(), 1,
2461
- gpuList=protocol.getGpuList())
2469
+ gpuList=gpuList)
2462
2470
 
2463
2471
  if executor is None:
2464
2472
  executor = StepExecutor(hostConfig,
2465
- gpuList=protocol.getGpuList())
2473
+ gpuList=gpuList)
2466
2474
 
2467
2475
  logger.info("Running protocol using the %s executor." % executor)
2468
2476
  protocol.setStepsExecutor(executor)
@@ -2470,6 +2478,22 @@ def runProtocolMain(projectPath, protDbPath, protId):
2470
2478
  protocol.run()
2471
2479
 
2472
2480
 
2481
+ def anonimizeGPUs(gpuList):
2482
+
2483
+ renamedGPUs=dict()
2484
+ anonimousGPUs = []
2485
+
2486
+ for gpu in gpuList:
2487
+
2488
+ if gpu not in renamedGPUs:
2489
+ renamedGPUs[gpu] = len(renamedGPUs)
2490
+
2491
+ anonimousGPUs.append(renamedGPUs[gpu])
2492
+
2493
+ return anonimousGPUs
2494
+
2495
+
2496
+
2473
2497
  def getProtocolFromDb(projectPath, protDbPath, protId, chdir=False):
2474
2498
  """ Retrieve the Protocol object from a given .sqlite file
2475
2499
  and the protocol id.
@@ -2535,6 +2559,7 @@ def isProtocolUpToDate(protocol):
2535
2559
  class ProtImportBase(Protocol):
2536
2560
  """ Base Import protocol"""
2537
2561
 
2562
+
2538
2563
  class ProtStreamingBase(Protocol):
2539
2564
  """ Base protocol to implement streaming protocols.
2540
2565
  stepsGeneratorStep should be implemented (see its description) and output
@@ -2544,18 +2569,35 @@ class ProtStreamingBase(Protocol):
2544
2569
  """
2545
2570
 
2546
2571
  stepsExecutionMode = STEPS_PARALLEL
2572
+
2573
+ def _defineStreamingParams(self, form):
2574
+ """ This function can be called during the _defineParams method
2575
+ of some protocols that support stream processing.
2576
+ It will add a Streaming section together with the following
2577
+ params:
2578
+ streamingSleepOnWait: Some streaming protocols are quite fast,
2579
+ so, checking input/output updates creates an IO overhead.
2580
+ This params allows them to sleep (without consuming resources)
2581
+ to wait for new work to be done.
2582
+ """
2583
+ form.addSection("Streaming")
2584
+ form.addParam("streamingSleepOnWait", IntParam, default=10,
2585
+ label="Sleep when waiting (secs)",
2586
+ help="If you specify a value greater than zero, "
2587
+ "it will be the number of seconds that the "
2588
+ "protocol will sleep when waiting for new "
2589
+ "input data in streaming mode. ")
2590
+
2547
2591
  def _insertAllSteps(self):
2548
- # Insert the step that generates the steps
2592
+ """ Insert the step that generates the steps """
2549
2593
  self._insertFunctionStep(self.resumableStepGeneratorStep, str(datetime.now()), needsGPU=False)
2550
2594
 
2551
2595
  def resumableStepGeneratorStep(self, ts):
2552
- """ This allow to resume protocols. ts is the time stamp so this stap is alway different form previous exceution"""
2596
+ """ This allow to resume protocols. ts is the time stamp so this stap is always different form previous execution"""
2553
2597
  self.stepsGeneratorStep()
2554
2598
 
2555
-
2556
2599
  def _stepsCheck(self):
2557
-
2558
- # Just store steps created in checkNewInputStep
2600
+ """ Just store steps created in checkNewInputStep"""
2559
2601
  if self._newSteps:
2560
2602
  self.updateSteps()
2561
2603
 
@@ -2569,11 +2611,28 @@ class ProtStreamingBase(Protocol):
2569
2611
  """
2570
2612
  pass
2571
2613
 
2572
- def _validateThreads(self, messages:list):
2614
+ def _getStreamingSleepOnWait(self):
2615
+ """ Retrieves the configured sleep duration for waiting during streaming.
2616
+ Returns:
2617
+ - int: The sleep duration in seconds during streaming wait.
2618
+ """
2619
+ return self.getAttributeValue('streamingSleepOnWait', 0)
2620
+
2621
+ def _streamingSleepOnWait(self):
2622
+ """ This method should be used by protocols that want to sleep
2623
+ when there is not more work to do.
2624
+ """
2625
+ sleepOnWait = self._getStreamingSleepOnWait()
2626
+ if sleepOnWait > 0:
2627
+ self.info("Waiting %s now before checking again for new input" % sleepOnWait)
2628
+ time.sleep(sleepOnWait)
2629
+
2630
+ def _validateThreads(self, messages: list):
2573
2631
 
2574
2632
  if self.numberOfThreads.get() < 2:
2575
2633
  messages.append("At least 2 threads are needed for running this protocol. "
2576
2634
  "1 for the 'stepsGenerator step' and one more for the actual processing" )
2635
+
2577
2636
  def _validate(self):
2578
2637
  """ If you want to implement a validate method do it but call _validateThreads or validate threads value."""
2579
2638
  errors = []