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.
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/CHANGES.txt +15 -1
- {scipion_pyworkflow-3.10.5/scipion_pyworkflow.egg-info → scipion_pyworkflow-3.10.6}/PKG-INFO +12 -2
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/constants.py +11 -2
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/form.py +1 -1
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/project/searchprotocol.py +1 -1
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/project/viewprotocols_extra.py +1 -2
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/mapper/sqlite.py +9 -6
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/object.py +3 -2
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/plugin.py +1 -1
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/project/project.py +31 -34
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/project/scripts/fix_links.py +4 -1
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/protocol/constants.py +1 -1
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/protocol/executor.py +23 -7
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/protocol/hosts.py +2 -1
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/protocol/protocol.py +85 -26
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/utils/process.py +29 -8
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflowtests/objects.py +2 -2
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflowtests/tests/test_protocol_execution.py +7 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6/scipion_pyworkflow.egg-info}/PKG-INFO +12 -2
- scipion_pyworkflow-3.10.6/scipion_pyworkflow.egg-info/entry_points.txt +2 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/setup.py +0 -3
- scipion_pyworkflow-3.10.5/scipion_pyworkflow.egg-info/entry_points.txt +0 -5
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/LICENSE.txt +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/MANIFEST.in +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/README.rst +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/__init__.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/apps/__init__.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/apps/pw_manager.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/apps/pw_plot.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/apps/pw_project.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/apps/pw_protocol_list.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/apps/pw_protocol_run.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/apps/pw_run_tests.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/apps/pw_schedule_run.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/apps/pw_sleep.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/apps/pw_sync_data.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/apps/pw_viewer.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/config.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/exceptions.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/__init__.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/browser.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/canvas.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/dialog.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/graph.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/graph_layout.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/gui.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/matplotlib_image.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/plotter.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/project/__init__.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/project/base.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/project/constants.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/project/labels.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/project/project.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/project/searchrun.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/project/steps.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/project/utils.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/project/variables.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/project/viewdata.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/project/viewprojects.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/project/viewprotocols.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/text.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/tooltip.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/tree.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/widgets.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/mapper/__init__.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/mapper/mapper.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/mapper/sqlite_db.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/project/__init__.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/project/config.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/project/manager.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/project/scripts/clean_projects.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/project/scripts/config.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/project/scripts/create.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/project/scripts/edit_workflow.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/project/scripts/load.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/project/scripts/refresh.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/project/scripts/schedule.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/project/scripts/stack2volume.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/project/scripts/stop.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/protocol/__init__.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/protocol/bibtex.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/protocol/launch.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/protocol/package.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/protocol/params.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/Imagej.png +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/chimera.png +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/fa-exclamation-triangle_alert.png +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/fa-info-circle_alert.png +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/fa-search.png +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/fa-times-circle_alert.png +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/file_vol.png +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/loading.gif +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/no-image128.png +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/scipion_bn.png +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/scipion_icon.png +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/scipion_icon.svg +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/scipion_icon_proj.png +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/scipion_icon_projs.png +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/scipion_icon_prot.png +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/scipion_logo.png +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/scipion_logo_normal.png +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/scipion_logo_small.png +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/showj/arrowDown.png +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/showj/arrowUp.png +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/showj/background_section.png +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/showj/colRowModeOff.png +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/showj/colRowModeOn.png +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/showj/delete.png +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/showj/doc_icon.png +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/showj/download_icon.png +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/showj/enabled_gallery.png +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/showj/galleryViewOff.png +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/showj/galleryViewOn.png +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/showj/goto.png +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/showj/menu.png +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/showj/separator.png +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/showj/tableViewOff.png +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/showj/tableViewOn.png +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/showj/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/showj/ui-bg_glass_95_fef1ec_1x400.png +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/showj/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/showj/volumeOff.png +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/showj/volumeOn.png +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/sprites.png +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/sprites.xcf +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/resources/wait.gif +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/template.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/tests/__init__.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/tests/test_utils.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/tests/tests.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/utils/__init__.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/utils/dataset.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/utils/echo.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/utils/graph.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/utils/log.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/utils/path.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/utils/profiler.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/utils/progressbar.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/utils/properties.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/utils/reflection.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/utils/utils.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/utils/which.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/viewer.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/webservices/__init__.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/webservices/config.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/webservices/notifier.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/webservices/repository.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/webservices/workflowhub.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/wizard.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflowtests/__init__.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflowtests/bibtex.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflowtests/protocols.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflowtests/tests/__init__.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflowtests/tests/test_canvas.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflowtests/tests/test_domain.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflowtests/tests/test_logs.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflowtests/tests/test_mappers.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflowtests/tests/test_object.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflowtests/tests/test_project.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflowtests/tests/test_protocol_export.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflowtests/tests/test_protocol_output.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflowtests/tests/test_streaming.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflowtests/tests/test_utils.py +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/requirements.txt +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/scipion_pyworkflow.egg-info/SOURCES.txt +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/scipion_pyworkflow.egg-info/dependency_links.txt +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/scipion_pyworkflow.egg-info/requires.txt +0 -0
- {scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/scipion_pyworkflow.egg-info/top_level.txt +0 -0
- {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
|
-
-
|
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)
|
{scipion_pyworkflow-3.10.5/scipion_pyworkflow.egg-info → scipion_pyworkflow-3.10.6}/PKG-INFO
RENAMED
@@ -1,6 +1,6 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.4
|
2
2
|
Name: scipion-pyworkflow
|
3
|
-
Version: 3.10.
|
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.
|
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,
|
{scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/gui/project/searchprotocol.py
RENAMED
@@ -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/
|
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
|
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. """
|
@@ -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
|
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
|
309
|
+
# We store it in mem as datetime
|
310
310
|
self._creationTime = ctStr
|
311
311
|
|
312
312
|
else:
|
313
|
-
|
314
|
-
#
|
315
|
-
self.
|
316
|
-
|
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
|
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
|
-
|
1969
|
-
|
1970
|
-
|
1971
|
-
|
1972
|
-
|
1973
|
-
|
1974
|
-
|
1975
|
-
|
1976
|
-
|
1977
|
-
|
1978
|
-
|
1979
|
-
|
1980
|
-
|
1981
|
-
|
1982
|
-
|
1983
|
-
|
1984
|
-
|
1985
|
-
|
1986
|
-
|
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):
|
{scipion_pyworkflow-3.10.5 → scipion_pyworkflow-3.10.6}/pyworkflow/project/scripts/fix_links.py
RENAMED
@@ -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
|
@@ -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
|
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.
|
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
|
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(
|
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
|
-
|
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
|
-
|
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()[
|
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()[
|
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=
|
2462
|
+
gpuList=gpuList)
|
2455
2463
|
else:
|
2456
2464
|
executor = ThreadStepExecutor(hostConfig, nThreads - 1,
|
2457
|
-
gpuList=
|
2465
|
+
gpuList=gpuList)
|
2458
2466
|
|
2459
2467
|
if executor is None and protocol.useQueueForSteps():
|
2460
2468
|
executor = QueueStepExecutor(hostConfig, protocol.getSubmitDict(), 1,
|
2461
|
-
gpuList=
|
2469
|
+
gpuList=gpuList)
|
2462
2470
|
|
2463
2471
|
if executor is None:
|
2464
2472
|
executor = StepExecutor(hostConfig,
|
2465
|
-
gpuList=
|
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
|
-
|
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
|
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
|
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 = []
|