scipion-pyworkflow 3.3.1__tar.gz → 3.5.0__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.3.1/scipion_pyworkflow.egg-info → scipion-pyworkflow-3.5.0}/PKG-INFO +1 -1
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/apps/pw_project.py +3 -8
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/config.py +68 -8
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/constants.py +10 -1
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/gui/browser.py +3 -11
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/gui/canvas.py +1 -1
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/gui/dialog.py +36 -27
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/gui/form.py +9 -97
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/gui/graph_layout.py +39 -28
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/gui/gui.py +36 -13
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/gui/project/base.py +1 -1
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/gui/project/project.py +0 -10
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/gui/project/searchrun.py +19 -12
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/gui/project/viewdata.py +1 -34
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/gui/project/viewprotocols.py +47 -110
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/gui/project/viewprotocols_extra.py +1 -1
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/gui/tree.py +2 -2
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/gui/widgets.py +1 -1
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/object.py +37 -11
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/plugin.py +9 -9
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/project/__init__.py +1 -1
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/project/config.py +0 -15
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/project/project.py +172 -12
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/protocol/executor.py +12 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/protocol/launch.py +32 -25
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/protocol/protocol.py +32 -8
- scipion-pyworkflow-3.5.0/pyworkflow/resources/sprites.png +0 -0
- scipion-pyworkflow-3.5.0/pyworkflow/resources/sprites.xcf +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/template.py +1 -1
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/utils/log.py +2 -2
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/utils/path.py +28 -2
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/utils/properties.py +164 -99
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/utils/utils.py +10 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/viewer.py +7 -1
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflowtests/tests/test_object.py +8 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflowtests/tests/test_utils.py +74 -4
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0/scipion_pyworkflow.egg-info}/PKG-INFO +1 -1
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/scipion_pyworkflow.egg-info/SOURCES.txt +2 -86
- scipion-pyworkflow-3.3.1/pyworkflow/resources/backward-solid.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/beta.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/binoculares.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/bookmark.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/broom-solid.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/class_obj.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/clipboard-regular.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/code-branch-solid.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/debug.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/fa-arrow-down.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/fa-arrow-left.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/fa-arrow-up.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/fa-ban.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/fa-bars.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/fa-check.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/fa-checked.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/fa-cog.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/fa-cogs.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/fa-database.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/fa-delete-operation.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/fa-download.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/fa-external-link.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/fa-eye.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/fa-failure.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/fa-file-o.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/fa-files-o.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/fa-folder-open.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/fa-home.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/fa-install.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/fa-installed.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/fa-lightbulb-o.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/fa-list-ul.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/fa-magic.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/fa-minus-square.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/fa-next.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/fa-pencil.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/fa-play-circle-o.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/fa-plus-square.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/fa-previous.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/fa-processing.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/fa-question-circle.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/fa-refresh.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/fa-rocket.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/fa-save.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/fa-sign-in.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/fa-sign-out.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/fa-sitemap.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/fa-stop-workflow.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/fa-stop.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/fa-tags.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/fa-times.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/fa-to_install.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/fa-trash-o.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/fa-unchecked.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/fa-undo.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/fa-uninstall.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/fa-update.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/fa-upload.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/file.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/file_folder.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/file_folder_link.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/file_generic.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/file_generic_link.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/file_image.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/file_image_link.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/file_java.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/file_log.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/file_md.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/file_md_link.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/file_python.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/file_sqlite.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/file_stack.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/file_stack_link.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/file_text.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/new.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/no-image.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/paste-solid.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/power-off-solid.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/production.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/prot_disabled.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/question.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/rename.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/root.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/updated.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/users.png +0 -0
- scipion-pyworkflow-3.3.1/pyworkflow/resources/workflow.png +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/LICENSE.txt +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/MANIFEST.in +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/README.rst +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/__init__.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/apps/__init__.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/apps/pw_manager.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/apps/pw_plot.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/apps/pw_protocol_list.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/apps/pw_protocol_run.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/apps/pw_run_tests.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/apps/pw_schedule_run.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/apps/pw_sleep.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/apps/pw_sync_data.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/apps/pw_viewer.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/exceptions.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/gui/__init__.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/gui/graph.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/gui/matplotlib_image.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/gui/plotter.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/gui/project/__init__.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/gui/project/constants.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/gui/project/labels.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/gui/project/searchprotocol.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/gui/project/steps.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/gui/project/utils.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/gui/project/viewprojects.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/gui/text.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/gui/tooltip.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/mapper/__init__.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/mapper/mapper.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/mapper/sqlite.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/mapper/sqlite_db.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/mapper/xmlmapper.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/project/manager.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/project/scripts/clean_projects.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/project/scripts/config.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/project/scripts/create.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/project/scripts/edit_workflow.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/project/scripts/fix_links.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/project/scripts/load.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/project/scripts/refresh.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/project/scripts/schedule.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/project/scripts/stack2volume.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/project/scripts/stop.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/protocol/__init__.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/protocol/bibtex.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/protocol/constants.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/protocol/hosts.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/protocol/package.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/protocol/params.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/resources/Imagej.png +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/resources/chimera.png +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/resources/fa-exclamation-triangle_alert.png +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/resources/fa-info-circle_alert.png +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/resources/fa-search.png +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/resources/fa-times-circle_alert.png +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/resources/file_vol.png +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/resources/loading.gif +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/resources/no-image128.png +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/resources/scipion_bn.png +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/resources/scipion_icon.png +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/resources/scipion_icon.svg +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/resources/scipion_icon_proj.png +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/resources/scipion_icon_projs.png +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/resources/scipion_icon_prot.png +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/resources/scipion_logo.png +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/resources/scipion_logo_normal.png +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/resources/scipion_logo_small.png +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/resources/showj/arrowDown.png +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/resources/showj/arrowUp.png +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/resources/showj/background_section.png +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/resources/showj/colRowModeOff.png +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/resources/showj/colRowModeOn.png +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/resources/showj/delete.png +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/resources/showj/doc_icon.png +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/resources/showj/download_icon.png +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/resources/showj/enabled_gallery.png +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/resources/showj/galleryViewOff.png +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/resources/showj/galleryViewOn.png +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/resources/showj/goto.png +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/resources/showj/menu.png +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/resources/showj/separator.png +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/resources/showj/tableViewOff.png +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/resources/showj/tableViewOn.png +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/resources/showj/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/resources/showj/ui-bg_glass_95_fef1ec_1x400.png +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/resources/showj/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/resources/showj/volumeOff.png +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/resources/showj/volumeOn.png +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/resources/wait.gif +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/tests/__init__.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/tests/test_utils.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/tests/tests.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/utils/__init__.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/utils/dataset.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/utils/echo.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/utils/graph.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/utils/process.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/utils/profiler.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/utils/progressbar.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/utils/reflection.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/utils/which.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/webservices/__init__.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/webservices/config.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/webservices/notifier.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/webservices/repository.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflow/wizard.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflowtests/__init__.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflowtests/bibtex.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflowtests/objects.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflowtests/protocols.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflowtests/tests/__init__.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflowtests/tests/test_canvas.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflowtests/tests/test_domain.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflowtests/tests/test_logs.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflowtests/tests/test_mappers.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflowtests/tests/test_project.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflowtests/tests/test_protocol_execution.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflowtests/tests/test_protocol_export.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflowtests/tests/test_protocol_output.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/pyworkflowtests/tests/test_streaming.py +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/requirements.txt +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/scipion_pyworkflow.egg-info/dependency_links.txt +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/scipion_pyworkflow.egg-info/entry_points.txt +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/scipion_pyworkflow.egg-info/requires.txt +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/scipion_pyworkflow.egg-info/top_level.txt +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/setup.cfg +0 -0
- {scipion-pyworkflow-3.3.1 → scipion-pyworkflow-3.5.0}/setup.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: scipion-pyworkflow
|
3
|
-
Version: 3.
|
3
|
+
Version: 3.5.0
|
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
|
@@ -36,19 +36,14 @@ from pyworkflow.project import Manager
|
|
36
36
|
from pyworkflow.gui.project import ProjectWindow
|
37
37
|
import pyworkflow.utils as pwutils
|
38
38
|
|
39
|
-
import logging
|
40
|
-
|
41
39
|
HERE = 'here'
|
42
|
-
|
43
40
|
LAST = 'last'
|
44
|
-
|
45
41
|
LIST = 'list'
|
46
|
-
logger = logging.getLogger(__name__)
|
47
42
|
|
48
43
|
def openProject(projectName):
|
49
44
|
""" Opens a scipion project:
|
50
45
|
|
51
|
-
:param projectName: Name of
|
46
|
+
:param projectName: Name of an existing project to open,
|
52
47
|
or "here" to create a project in the current working dir,
|
53
48
|
or "last" to open the most recent project
|
54
49
|
|
@@ -97,7 +92,7 @@ def openProject(projectName):
|
|
97
92
|
projWindow = ProjectWindow(projPath)
|
98
93
|
projWindow.show()
|
99
94
|
else:
|
100
|
-
|
95
|
+
print("Can't open project %s. It does not exist" % projPath)
|
101
96
|
|
102
97
|
#Show the list of projects
|
103
98
|
showProjectList(manager)
|
@@ -115,4 +110,4 @@ if __name__ == '__main__':
|
|
115
110
|
if len(sys.argv) > 1:
|
116
111
|
openProject(sys.argv[1])
|
117
112
|
else:
|
118
|
-
|
113
|
+
print("usage: pw_project.py PROJECT_NAME or %s or %s or %s" % (HERE, LAST, LIST))
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
import enum
|
2
2
|
import logging
|
3
3
|
logger = logging.getLogger(__file__)
|
4
4
|
import ast
|
@@ -20,12 +20,15 @@ def join(*paths):
|
|
20
20
|
return os.path.join(HOME, *paths)
|
21
21
|
|
22
22
|
|
23
|
-
__resourcesPath =
|
23
|
+
__resourcesPath = join('resources')
|
24
|
+
|
25
|
+
def getResourcesPath(file=None):
|
24
26
|
|
27
|
+
return __resourcesPath if file is None else os.path.join(__resourcesPath, file)
|
25
28
|
|
26
29
|
def findResource(filename):
|
27
30
|
from .utils.path import findFile
|
28
|
-
return findFile(filename, *__resourcesPath)
|
31
|
+
return findFile(filename, *[__resourcesPath])
|
29
32
|
|
30
33
|
|
31
34
|
def genNotesHeading():
|
@@ -62,6 +65,49 @@ def getModuleFolder(moduleName):
|
|
62
65
|
spec = importlib.util.find_spec(moduleName)
|
63
66
|
return os.path.dirname(spec.origin)
|
64
67
|
|
68
|
+
class VarTypes(enum.Enum):
|
69
|
+
STRING = 1
|
70
|
+
INTEGER = 2
|
71
|
+
BOOLEAN = 3
|
72
|
+
PATH = 4
|
73
|
+
|
74
|
+
class Variable(object):
|
75
|
+
""" Class for variables of the Config class."""
|
76
|
+
def __init__(self, value, varType:VarTypes=VarTypes.STRING):
|
77
|
+
"""
|
78
|
+
:param value: Value of the variable
|
79
|
+
:param type: Type of the variable"""
|
80
|
+
super().__init__()
|
81
|
+
self.value = value
|
82
|
+
self.varType = varType
|
83
|
+
def __bool__(self):
|
84
|
+
return bool(self.value)
|
85
|
+
|
86
|
+
def __int__(self):
|
87
|
+
return int(self.value)
|
88
|
+
def __str__(self):
|
89
|
+
return str(self.value)
|
90
|
+
|
91
|
+
def __eq__(self, other):
|
92
|
+
return other == self.value
|
93
|
+
|
94
|
+
def __repr__(self):
|
95
|
+
return self.__str__()
|
96
|
+
|
97
|
+
def __fspath__(self):
|
98
|
+
return self.__str__()
|
99
|
+
|
100
|
+
" We migth need to imlement more like this--> https://docs.python.org/3.3/reference/datamodel.html#object.__truediv__"
|
101
|
+
def __truediv__(self, other):
|
102
|
+
return float(self.value)/other
|
103
|
+
|
104
|
+
def __rtruediv__(self, other):
|
105
|
+
return other / float(self.value)
|
106
|
+
|
107
|
+
def __add__(self, other):
|
108
|
+
return self.value+other
|
109
|
+
def __radd__(self, other):
|
110
|
+
return other+self.value
|
65
111
|
|
66
112
|
class Config:
|
67
113
|
""" Main Config for pyworkflow. It contains the main Scipion configuration variables
|
@@ -104,7 +150,7 @@ class Config:
|
|
104
150
|
SCIPION_HOME_DEFINED = _get(SCIPION_HOME_VAR, False)
|
105
151
|
"False if SCIPION_HOME is not found in the environment"
|
106
152
|
|
107
|
-
_root = Root(SCIPION_HOME)
|
153
|
+
_root = Root(str(SCIPION_HOME))
|
108
154
|
_join = _root.join
|
109
155
|
|
110
156
|
# Internal cached variables, use __ so they are not returned in getVars
|
@@ -157,8 +203,6 @@ class Config:
|
|
157
203
|
|
158
204
|
SCIPION_SUPPORT_EMAIL = _get('SCIPION_SUPPORT_EMAIL', 'scipion@cnb.csic.es')
|
159
205
|
|
160
|
-
SCIPION_LOGO = _get('SCIPION_LOGO', 'scipion_logo.gif')
|
161
|
-
|
162
206
|
# Config variables
|
163
207
|
SCIPION_CONFIG = _get('SCIPION_CONFIG', 'scipion.conf')
|
164
208
|
"Path to the scipion configuration file where all this variables could be defined."
|
@@ -209,6 +253,15 @@ class Config:
|
|
209
253
|
WIZARD_MASK_COLOR = _get('WIZARD_MASK_COLOR', '[0.125, 0.909, 0.972]')
|
210
254
|
"Color to use in some wizards."
|
211
255
|
|
256
|
+
SCIPION_SPRITES_FILE = _get('SCIPION_SPRITES_FILE', _join(getResourcesPath(),'sprites.png'))
|
257
|
+
"File (png) with the icons in a collage. Default is found at pyworkflow/resources/sprites.png. And a GIMP file could be found at the same folder in the github repo."
|
258
|
+
|
259
|
+
SCIPION_SHOW_TEXT_IN_TOOLBAR = _get('SCIPION_SHOW_TEXT_IN_TOOLBAR', TRUE_STR) == TRUE_STR
|
260
|
+
"Define it to anything else except False to show the label of the icons. It will take more space."
|
261
|
+
|
262
|
+
SCIPION_ICON_ZOOM = int(_get('SCIPION_ICON_ZOOM', 50))
|
263
|
+
"Define it to anything else except False to show the label of the icons. It will take more space."
|
264
|
+
|
212
265
|
# Notification
|
213
266
|
SCIPION_NOTIFY = _get('SCIPION_NOTIFY', TRUE_STR) == TRUE_STR
|
214
267
|
"If set to False, Scipion developers will know almost nothing about Scipion usage and will have less information to improve it."
|
@@ -249,6 +302,12 @@ class Config:
|
|
249
302
|
SCIPION_USE_QUEUE = _get("SCIPION_USE_QUEUE", FALSE_STR) != FALSE_STR
|
250
303
|
"Default value for using the queue. By default is False. ANY value will be True except and empty value. \"False\" or \"0\" will be True too."
|
251
304
|
|
305
|
+
SCIPION_DEFAULT_EXECUTION_ACTION = int(_get('SCIPION_DEFAULT_EXECUTION_ACTION', DEFAULT_EXECUTION_ACTION_ASK))
|
306
|
+
"""Ask if you want to launch a single protocol or a sub-workflow. The default value is 1
|
307
|
+
1: Scipion always ask
|
308
|
+
2: Run a single protocol
|
309
|
+
3: Run a sub-workflow """
|
310
|
+
|
252
311
|
try:
|
253
312
|
VIEWERS = ast.literal_eval(_get('VIEWERS', "{}"))
|
254
313
|
except Exception as e:
|
@@ -300,7 +359,7 @@ class Config:
|
|
300
359
|
for name, value in vars(baseCls).items():
|
301
360
|
# Skip methods and internal attributes starting with __
|
302
361
|
# (e.g __doc__, __module__, etc)
|
303
|
-
if
|
362
|
+
if isinstance(value, (str, int, Variable)) and not name.startswith('__'):
|
304
363
|
configVars[name] = str(value)
|
305
364
|
return configVars
|
306
365
|
|
@@ -354,7 +413,8 @@ class Config:
|
|
354
413
|
|
355
414
|
@staticmethod
|
356
415
|
def debugSQLOn():
|
357
|
-
|
416
|
+
from .utils import envVarOn
|
417
|
+
return bool(envVarOn(SCIPION_DEBUG_SQLITE))
|
358
418
|
|
359
419
|
@staticmethod
|
360
420
|
def toggleDebugSQL():
|
@@ -42,7 +42,7 @@ VERSION_1 = '1.0.0'
|
|
42
42
|
VERSION_1_1 = '1.1.0'
|
43
43
|
VERSION_1_2 = '1.2.0'
|
44
44
|
VERSION_2_0 = '2.0.0'
|
45
|
-
VERSION_3_0 = '3.
|
45
|
+
VERSION_3_0 = '3.5.0'
|
46
46
|
|
47
47
|
# For a new release, define a new constant and assign it to LAST_VERSION
|
48
48
|
# The existing one has to be added to OLD_VERSIONS list.
|
@@ -198,3 +198,12 @@ class TK:
|
|
198
198
|
LEFT_DOUBLE_CLICK = '<Double-1>'
|
199
199
|
TREEVIEW_OPEN = '<<TreeviewOpen>>'
|
200
200
|
TREEVIEW_CLOSE = '<<TreeviewClose>>'
|
201
|
+
|
202
|
+
|
203
|
+
HELP_DURATION_FORMAT = "Duration format example: 1d 20h 30m 30s --> 1 day 20 hours 30 minutes and 30 seconds"
|
204
|
+
|
205
|
+
# Run protocol modes
|
206
|
+
DEFAULT_EXECUTION_ACTION_ASK = 1
|
207
|
+
DEFAULT_EXECUTION_ACTION_SINGLE = 2
|
208
|
+
DEFAULT_EXECUTION_ACTION_ALL = 3
|
209
|
+
|
@@ -34,6 +34,7 @@ import stat
|
|
34
34
|
import tkinter as tk
|
35
35
|
import time
|
36
36
|
import logging
|
37
|
+
|
37
38
|
logger = logging.getLogger(__name__)
|
38
39
|
|
39
40
|
import pyworkflow.utils as pwutils
|
@@ -124,7 +125,7 @@ class ObjectBrowser(tk.Frame):
|
|
124
125
|
img, desc = self.treeProvider.getObjectPreview(obj)
|
125
126
|
# Update image preview
|
126
127
|
if self.showPreviewTop:
|
127
|
-
if isinstance(img, str):
|
128
|
+
if isinstance(img, (str, pwutils.SpriteImage)):
|
128
129
|
img = self.getImage(img)
|
129
130
|
if img is None:
|
130
131
|
img = self.noImage
|
@@ -716,13 +717,4 @@ class FileBrowserWindow(BrowserWindow):
|
|
716
717
|
'.txt', '.log', '.out', '.err', '.stdout', '.stderr', '.emx',
|
717
718
|
'.json', '.xml', '.pam')
|
718
719
|
register(TextFileHandler(pwutils.Icon.PYTHON_FILE), '.py')
|
719
|
-
register(
|
720
|
-
register(SqlFileHandler(), '.sqlite', '.db')
|
721
|
-
# register(MdFileHandler(), '.xmd', '.star', '.pos', '.ctfparam', '.doc')
|
722
|
-
# register(ParticleFileHandler(),
|
723
|
-
# '.xmp', '.tif', '.tiff', '.spi', '.mrc', '.map', '.raw',
|
724
|
-
# '.inf', '.dm3', '.em', '.pif', '.psd', '.spe', '.ser', '.img',
|
725
|
-
# '.hed', *STANDARD_IMAGE_EXTENSIONS)
|
726
|
-
# register(VolFileHandler(), '.vol')
|
727
|
-
# register(StackHandler(), '.stk', '.mrcs', '.st', '.pif', '.dm4')
|
728
|
-
# register(ChimeraHandler(), '.bild')
|
720
|
+
register(SqlFileHandler(), '.sqlite', '.db')
|
@@ -34,7 +34,7 @@ from tkcolorpicker import askcolor as _askColor
|
|
34
34
|
from pyworkflow import Config
|
35
35
|
from pyworkflow.exceptions import PyworkflowException
|
36
36
|
from pyworkflow.utils import Message, Icon, Color
|
37
|
-
from . import gui, Window, widgets, configureWeigths, LIST_TREEVIEW, defineStyle
|
37
|
+
from . import gui, Window, widgets, configureWeigths, LIST_TREEVIEW, defineStyle, ToolTip
|
38
38
|
from .tree import BoundTree, Tree
|
39
39
|
from .text import Text, TaggedText
|
40
40
|
|
@@ -58,7 +58,7 @@ class Dialog(tk.Toplevel):
|
|
58
58
|
An image name can be passed to display left to the message.
|
59
59
|
"""
|
60
60
|
|
61
|
-
def __init__(self, parent, title, **kwargs):
|
61
|
+
def __init__(self, parent, title, lockGui=True, **kwargs):
|
62
62
|
"""Initialize a dialog.
|
63
63
|
Arguments:
|
64
64
|
parent -- a parent window (the application window)
|
@@ -82,7 +82,7 @@ class Dialog(tk.Toplevel):
|
|
82
82
|
# If the master is not viewable, don't
|
83
83
|
# make the child transient, or else it
|
84
84
|
# would be opened withdrawn
|
85
|
-
if parent.winfo_viewable():
|
85
|
+
if parent.winfo_viewable() and lockGui:
|
86
86
|
self.transient(parent)
|
87
87
|
|
88
88
|
if title:
|
@@ -102,7 +102,7 @@ class Dialog(tk.Toplevel):
|
|
102
102
|
# Frame for the info/message label
|
103
103
|
infoFrame = tk.Frame(self)
|
104
104
|
infoFrame.grid(row=1, column=0, sticky='sew',
|
105
|
-
|
105
|
+
padx=5, pady=(0, 5))
|
106
106
|
self.floatingMessage = tk.Label(infoFrame, text="", fg=Config.SCIPION_MAIN_COLOR)
|
107
107
|
self.floatingMessage.grid(row=0, column=0, sticky='news')
|
108
108
|
|
@@ -141,7 +141,8 @@ class Dialog(tk.Toplevel):
|
|
141
141
|
# window ".139897767953072.139897384058440" was deleted before its visibility changed
|
142
142
|
# wait for window to appear on screen before calling grab_set
|
143
143
|
self.wait_visibility()
|
144
|
-
|
144
|
+
if lockGui:
|
145
|
+
self.grab_set()
|
145
146
|
self.wait_window(self)
|
146
147
|
|
147
148
|
def destroy(self):
|
@@ -191,7 +192,8 @@ class Dialog(tk.Toplevel):
|
|
191
192
|
self.result = resultValue
|
192
193
|
noCancel = self.result != RESULT_CANCEL and self.result != RESULT_CLOSE
|
193
194
|
|
194
|
-
if noCancel
|
195
|
+
callBack = self.validate if noCancel else self.validateClose
|
196
|
+
if not callBack():
|
195
197
|
self.initial_focus.focus_set() # put focus back
|
196
198
|
return
|
197
199
|
|
@@ -227,6 +229,9 @@ class Dialog(tk.Toplevel):
|
|
227
229
|
"""
|
228
230
|
return 1 # override
|
229
231
|
|
232
|
+
def validateClose(self):
|
233
|
+
return True
|
234
|
+
|
230
235
|
def apply(self):
|
231
236
|
"""process the data
|
232
237
|
This method is called automatically to process the data, *after*
|
@@ -236,7 +241,7 @@ class Dialog(tk.Toplevel):
|
|
236
241
|
|
237
242
|
def getImage(self, imgName):
|
238
243
|
"""A shortcut to get an image from its name"""
|
239
|
-
return gui.getImage(imgName
|
244
|
+
return gui.getImage(imgName)
|
240
245
|
|
241
246
|
def getResult(self):
|
242
247
|
return self.result
|
@@ -328,7 +333,7 @@ class ExceptionDialog(MessageDialog):
|
|
328
333
|
detailsText = TaggedText(bodyFrame, bg=Config.SCIPION_BG_COLOR, bd=0, highlightthickness=0)
|
329
334
|
traceStr = traceback.format_exc()
|
330
335
|
fillMessageText(detailsText, traceStr)
|
331
|
-
detailsText.frame.grid(row=row+1, column=0, columnspan=2, sticky='news', padx=5, pady=5)
|
336
|
+
detailsText.frame.grid(row=row + 1, column=0, columnspan=2, sticky='news', padx=5, pady=5)
|
332
337
|
event.widget.grid_forget()
|
333
338
|
|
334
339
|
row = 1
|
@@ -337,7 +342,7 @@ class ExceptionDialog(MessageDialog):
|
|
337
342
|
if isinstance(self._exception, PyworkflowException):
|
338
343
|
helpUrl = self._exception.getUrl()
|
339
344
|
labelUrl = TaggedText(bodyFrame, bg=Config.SCIPION_BG_COLOR, bd=0, highlightthickness=0)
|
340
|
-
fillMessageText(labelUrl,"Please go here for more details: %s" % helpUrl)
|
345
|
+
fillMessageText(labelUrl, "Please go here for more details: %s" % helpUrl)
|
341
346
|
labelUrl.grid(row=row, column=0, columnspan=2, sticky='news')
|
342
347
|
row += 1
|
343
348
|
|
@@ -621,7 +626,7 @@ class ListDialog(Dialog):
|
|
621
626
|
|
622
627
|
def _createPreviewPanel(self, parent):
|
623
628
|
self.previewFrame = tk.Frame(parent)
|
624
|
-
self.previewFrame.grid(row=1,column=1)
|
629
|
+
self.previewFrame.grid(row=1, column=1)
|
625
630
|
|
626
631
|
def _createFilterBox(self, content):
|
627
632
|
""" Create the Frame with Filter widgets """
|
@@ -696,11 +701,12 @@ class ToolbarButton:
|
|
696
701
|
Store information about the buttons that will be added to the toolbar.
|
697
702
|
"""
|
698
703
|
|
699
|
-
def __init__(self, text, command, icon=None, tooltip=None):
|
704
|
+
def __init__(self, text, command, icon=None, tooltip=None, shortcut=None):
|
700
705
|
self.text = text
|
701
706
|
self.command = command
|
702
707
|
self.icon = icon
|
703
708
|
self.tooltip = tooltip
|
709
|
+
self.shortcut = shortcut
|
704
710
|
|
705
711
|
|
706
712
|
class ToolbarListDialog(ListDialog):
|
@@ -725,29 +731,36 @@ class ToolbarListDialog(ListDialog):
|
|
725
731
|
ListDialog.__init__(self, parent, title, provider, message, **kwargs)
|
726
732
|
|
727
733
|
def body(self, bodyFrame):
|
728
|
-
bodyFrame.config(bg=Config.SCIPION_BG_COLOR)
|
729
734
|
gui.configureWeigths(bodyFrame, 1, 0)
|
730
735
|
|
731
736
|
# Add an extra frame to insert the Toolbar
|
732
737
|
# and another one for the ListDialog's body
|
733
|
-
self.toolbarFrame = tk.Frame(bodyFrame
|
738
|
+
self.toolbarFrame = tk.Frame(bodyFrame)
|
734
739
|
self.toolbarFrame.grid(row=0, column=0, sticky='new')
|
735
|
-
if self.toolbarButtons:
|
736
|
-
for i, b in enumerate(self.toolbarButtons):
|
737
|
-
self._addButton(b, i)
|
738
740
|
|
739
741
|
subBody = tk.Frame(bodyFrame)
|
740
742
|
subBody.grid(row=1, column=0, sticky='news', padx=5, pady=5)
|
741
743
|
ListDialog.body(self, subBody)
|
744
|
+
|
745
|
+
if self.toolbarButtons:
|
746
|
+
for i, b in enumerate(self.toolbarButtons):
|
747
|
+
self._addButton(b, i)
|
748
|
+
|
742
749
|
if self._itemDoubleClick:
|
743
750
|
self.tree.itemDoubleClick = self._itemDoubleClick
|
744
751
|
|
745
752
|
def _addButton(self, button, col):
|
746
753
|
btn = tk.Label(self.toolbarFrame, text=button.text,
|
747
754
|
image=self.getImage(button.icon),
|
748
|
-
compound=tk.LEFT, cursor='hand2'
|
755
|
+
compound=tk.LEFT, cursor='hand2')
|
749
756
|
btn.grid(row=0, column=col, sticky='nw', padx=(5, 0), pady=(5, 0))
|
750
757
|
btn.bind('<Button-1>', button.command)
|
758
|
+
if button.tooltip:
|
759
|
+
tooltip = button.tooltip + ' (%s)' % button.shortcut if button.shortcut else button.tooltip
|
760
|
+
self.bind(button.shortcut, button.command)
|
761
|
+
ToolTip(btn, tooltip, delay=150)
|
762
|
+
if button.shortcut:
|
763
|
+
self.bind(button.shortcut, button.command)
|
751
764
|
|
752
765
|
|
753
766
|
class FlashMessage:
|
@@ -781,10 +794,9 @@ class FlashMessage:
|
|
781
794
|
class FloatingMessage:
|
782
795
|
def __init__(self, master, msg, xPos=None, yPos=None, textWidth=280,
|
783
796
|
font='Helvetica', size=12, bd=1, bg=Config.SCIPION_MAIN_COLOR, fg='white'):
|
784
|
-
|
785
797
|
if xPos is None:
|
786
|
-
xPos = (master.winfo_width()-textWidth)/2
|
787
|
-
yPos = master.winfo_height()/2
|
798
|
+
xPos = (master.winfo_width() - textWidth) / 2
|
799
|
+
yPos = master.winfo_height() / 2
|
788
800
|
|
789
801
|
self.floatingMessage = tk.Label(master, text=" %s " % msg,
|
790
802
|
bd=bd, bg=bg, fg=fg)
|
@@ -839,9 +851,6 @@ class FileBrowseDialog(Dialog):
|
|
839
851
|
return True
|
840
852
|
|
841
853
|
|
842
|
-
|
843
|
-
|
844
|
-
|
845
854
|
class SearchBaseWindow(Window):
|
846
855
|
""" Base window for searching in a list
|
847
856
|
You are going to implement several elements:
|
@@ -874,7 +883,7 @@ class SearchBaseWindow(Window):
|
|
874
883
|
|
875
884
|
def __init__(self, parentWindow, title="Search element", onClick=None, onDoubleClick=None, **kwargs):
|
876
885
|
super().__init__(title=title,
|
877
|
-
|
886
|
+
masterWindow=parentWindow)
|
878
887
|
|
879
888
|
self.onClick = self._click if onClick is None else onClick
|
880
889
|
self.onDoubleClick = self._double_click if onDoubleClick is None else onDoubleClick
|
@@ -905,8 +914,8 @@ class SearchBaseWindow(Window):
|
|
905
914
|
entry.focus_set()
|
906
915
|
entry.grid(row=0, column=1, sticky='nw')
|
907
916
|
btn = widgets.IconButton(frame, "Search",
|
908
|
-
|
909
|
-
|
917
|
+
imagePath=Icon.ACTION_SEARCH,
|
918
|
+
command=self._onSearchClick)
|
910
919
|
btn.grid(row=0, column=2, sticky='nw')
|
911
920
|
|
912
921
|
frame.grid(row=0, column=0, sticky='new', padx=5, pady=(10, 5))
|
@@ -947,7 +956,7 @@ class SearchBaseWindow(Window):
|
|
947
956
|
|
948
957
|
if searchtext in linelower[index]:
|
949
958
|
# prioritize findings in label
|
950
|
-
weight += column[self.WEIGHT_INDEX]*2
|
959
|
+
weight += column[self.WEIGHT_INDEX] * 2
|
951
960
|
|
952
961
|
elif " " in searchtext:
|
953
962
|
for word in searchtext.split():
|
@@ -464,105 +464,12 @@ class SubclassesTreeProvider(TreeProvider):
|
|
464
464
|
# Get the classes that are valid as input object in this Domain
|
465
465
|
domain = pw.Config.getDomain()
|
466
466
|
classes = [domain.findClass(c.strip()) for c in className.split(",")]
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
# already in the project. We will prefer to save time
|
471
|
-
# here than have the 'very last' version of the runs and objects
|
472
|
-
runs = project.getRuns(refresh=False)
|
473
|
-
|
474
|
-
for prot in runs:
|
475
|
-
# Make sure we don't include previous output of the same
|
476
|
-
# protocol, it will cause a recursive loop
|
477
|
-
if prot.getObjId() != self.protocol.getObjId():
|
478
|
-
# Check if the protocol itself is one of the desired classes
|
479
|
-
if any(issubclass(prot.getClass(), c) for c in classes):
|
480
|
-
p = pwobj.Pointer(prot)
|
481
|
-
objects.append(p)
|
482
|
-
|
483
|
-
try:
|
484
|
-
# paramName and attr must be set to None
|
485
|
-
# Otherwise, if a protocol has failed and the corresponding output object of type XX does not exist
|
486
|
-
# any other protocol that uses objects of type XX as input will not be able to choose then using
|
487
|
-
# the magnifier glass (object selector of type XX)
|
488
|
-
paramName = None
|
489
|
-
attr = None
|
490
|
-
for paramName, attr in prot.iterOutputAttributes(includePossible=True):
|
491
|
-
def _checkParam(paramName, attr):
|
492
|
-
# If attr is a sub-classes of any desired one, add it to the list
|
493
|
-
# we should also check if there is a condition, the object
|
494
|
-
# must comply with the condition
|
495
|
-
p = None
|
496
|
-
|
497
|
-
match = False
|
498
|
-
cancelConditionEval = False
|
499
|
-
possibleOutput = isinstance(attr, type)
|
500
|
-
|
501
|
-
# Go through all compatible Classes coming from in pointerClass string
|
502
|
-
for c in classes:
|
503
|
-
# If attr is instance
|
504
|
-
if isinstance(attr, c):
|
505
|
-
match = True
|
506
|
-
break
|
507
|
-
# If it is a class already: "possibleOutput" case. In this case attr is the class and not
|
508
|
-
# an instance of c. In this special case
|
509
|
-
elif possibleOutput and attr == c:
|
510
|
-
match = True
|
511
|
-
cancelConditionEval = True
|
512
|
-
|
513
|
-
# If attr matches the class
|
514
|
-
if match:
|
515
|
-
if cancelConditionEval or not condition or attr.evalCondition(condition):
|
516
|
-
p = pwobj.Pointer(prot, extended=paramName)
|
517
|
-
p._allowsSelection = True
|
518
|
-
objects.append(p)
|
519
|
-
return
|
520
|
-
|
521
|
-
# JMRT: For all sets, we don't want to include the
|
522
|
-
# subitems here for performance reasons (e.g SetOfParticles)
|
523
|
-
# Thus, a Set class can define EXPOSE_ITEMS = True
|
524
|
-
# to enable the inclusion of its items here
|
525
|
-
if getattr(attr, 'EXPOSE_ITEMS', False) and not possibleOutput:
|
526
|
-
# If the ITEM type match any of the desired classes
|
527
|
-
# we will add some elements from the set
|
528
|
-
if (attr.ITEM_TYPE is not None and
|
529
|
-
any(issubclass(attr.ITEM_TYPE, c) for c in classes)):
|
530
|
-
if p is None: # This means the set have not be added
|
531
|
-
p = pwobj.Pointer(prot, extended=paramName)
|
532
|
-
p._allowsSelection = False
|
533
|
-
objects.append(p)
|
534
|
-
# Add each item on the set to the list of objects
|
535
|
-
try:
|
536
|
-
for i, item in enumerate(attr):
|
537
|
-
if i == self.maxNum: # Only load up to NUM particles
|
538
|
-
break
|
539
|
-
pi = pwobj.Pointer(prot, extended=paramName)
|
540
|
-
pi.addExtended(item.getObjId())
|
541
|
-
pi._parentObject = p
|
542
|
-
objects.append(pi)
|
543
|
-
except Exception as ex:
|
544
|
-
print("Error loading items from:")
|
545
|
-
print(" protocol: %s, attribute: %s"
|
546
|
-
% (prot.getRunName(), paramName))
|
547
|
-
print(" dbfile: ",
|
548
|
-
os.path.join(project.getPath(),
|
549
|
-
attr.getFileName()))
|
550
|
-
print(ex)
|
551
|
-
|
552
|
-
_checkParam(paramName, attr)
|
553
|
-
# The following is a dirty fix for the RCT case where there
|
554
|
-
# are inner output, maybe we should consider extend this for
|
555
|
-
# in a more general manner
|
556
|
-
for subParam in ['_untilted', '_tilted']:
|
557
|
-
if hasattr(attr, subParam):
|
558
|
-
_checkParam('%s.%s' % (paramName, subParam),
|
559
|
-
getattr(attr, subParam))
|
560
|
-
except Exception as e:
|
561
|
-
print("Cannot read attributes for %s (%s)" % (prot.getClass(), e))
|
467
|
+
# Obtaining only the outputs of the protocols that do not violate the sense of processing,
|
468
|
+
# thus avoiding circular references between protocols
|
469
|
+
objects = project.getProtocolCompatibleOutputs(self.protocol, classes, condition)
|
562
470
|
|
563
471
|
# Sort objects before returning them
|
564
472
|
self._sortObjects(objects)
|
565
|
-
|
566
473
|
return objects
|
567
474
|
|
568
475
|
def _sortObjects(self, objects):
|
@@ -654,7 +561,7 @@ class SubclassesTreeProvider(TreeProvider):
|
|
654
561
|
viewers = domain.findViewers(obj.getClassName(), DESKTOP_TKINTER)
|
655
562
|
proj = self.protocol.getProject()
|
656
563
|
for v in viewers:
|
657
|
-
actions.append((
|
564
|
+
actions.append((v.getName(),
|
658
565
|
lambda: v(project=proj).visualize(obj)))
|
659
566
|
return actions
|
660
567
|
|
@@ -2242,6 +2149,11 @@ class FormWindow(Window):
|
|
2242
2149
|
errors, resultAction = ProtocolsView._launchSubWorkflow(self.protocol,
|
2243
2150
|
mode, self.root,
|
2244
2151
|
askSingleAll=True)
|
2152
|
+
|
2153
|
+
if errors:
|
2154
|
+
self.showInfo(errors)
|
2155
|
+
return
|
2156
|
+
|
2245
2157
|
if resultAction == RESULT_CANCEL:
|
2246
2158
|
return
|
2247
2159
|
elif resultAction == RESULT_RUN_ALL:
|
@@ -88,9 +88,10 @@ class LevelTreeLayout(GraphLayout):
|
|
88
88
|
# Setup empty layout for each node
|
89
89
|
for node in graph.getNodes():
|
90
90
|
node._layout = {}
|
91
|
-
|
91
|
+
|
92
|
+
visitDict = dict()
|
92
93
|
# Do some level initialization on each node
|
93
|
-
self._setLayoutLevel(rootNode, 1, None)
|
94
|
+
self._setLayoutLevel(rootNode, 1, None, visitDict)
|
94
95
|
self._computeNodeOffsets(rootNode, 1)
|
95
96
|
# Compute extreme left limit
|
96
97
|
m = 9999
|
@@ -106,36 +107,46 @@ class LevelTreeLayout(GraphLayout):
|
|
106
107
|
def _isNewNode(self, node):
|
107
108
|
return node.x == 0 or node.y == 0 or node.isRoot()
|
108
109
|
|
109
|
-
def _setLayoutLevel(self, node, level, parent):
|
110
|
+
def _setLayoutLevel(self, node, level, parent, visitDict=None, ancestors=[]):
|
110
111
|
""" Iterate over all nodes and set _layout dict.
|
111
112
|
Also set the node level, which is defined
|
112
113
|
as the max level of a parent + 1
|
113
114
|
"""
|
114
|
-
if
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
layout
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
115
|
+
if visitDict is None:
|
116
|
+
visitDict = {}
|
117
|
+
|
118
|
+
if node.getName() not in visitDict:
|
119
|
+
visitDict[node.getName()] = True
|
120
|
+
|
121
|
+
if level > self.maxLevel:
|
122
|
+
return
|
123
|
+
|
124
|
+
layout = node._layout
|
125
|
+
|
126
|
+
if level > layout.get('level', 0):
|
127
|
+
# Calculate the y-position depending on the level
|
128
|
+
# and the delta-Y (DY)
|
129
|
+
if not self.partial or self._isNewNode(node):
|
130
|
+
node.y = level * self.getY()
|
131
|
+
layout['level'] = level
|
132
|
+
layout['parent'] = parent
|
133
|
+
if hasattr(node, 'width'):
|
134
|
+
half = node.width / 2
|
135
|
+
else:
|
136
|
+
half = 50
|
137
|
+
layout['half'] = half
|
138
|
+
layout['hLimits'] = [[-half, half]]
|
139
|
+
layout['offset'] = 0
|
140
|
+
|
141
|
+
if self.__isNodeExpanded(node):
|
142
|
+
ancestors.append(node.getName())
|
143
|
+
for child in node.getChilds():
|
144
|
+
if child.getName() in ancestors:
|
145
|
+
logger.warning("WARNING: There might be a cyclic redundancy error in this protocol: %s (%s)" %(child.getLabel(),
|
146
|
+
child.getName()))
|
147
|
+
if Config.debugOn():
|
148
|
+
print("%s: Setting layout for child %s" % ("-" * level, child), flush=True)
|
149
|
+
self._setLayoutLevel(child, level+1, node, visitDict, ancestors.copy())
|
139
150
|
|
140
151
|
def __isNodeExpanded(self, node):
|
141
152
|
""" Check if the status of the node is expanded or collapsed. """
|