scipion-pyworkflow 3.7.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyworkflow/__init__.py +33 -0
- pyworkflow/apps/__init__.py +29 -0
- pyworkflow/apps/pw_manager.py +37 -0
- pyworkflow/apps/pw_plot.py +51 -0
- pyworkflow/apps/pw_project.py +113 -0
- pyworkflow/apps/pw_protocol_list.py +143 -0
- pyworkflow/apps/pw_protocol_run.py +51 -0
- pyworkflow/apps/pw_run_tests.py +267 -0
- pyworkflow/apps/pw_schedule_run.py +322 -0
- pyworkflow/apps/pw_sleep.py +37 -0
- pyworkflow/apps/pw_sync_data.py +439 -0
- pyworkflow/apps/pw_viewer.py +78 -0
- pyworkflow/config.py +536 -0
- pyworkflow/constants.py +212 -0
- pyworkflow/exceptions.py +18 -0
- pyworkflow/gui/__init__.py +36 -0
- pyworkflow/gui/browser.py +726 -0
- pyworkflow/gui/canvas.py +1190 -0
- pyworkflow/gui/dialog.py +976 -0
- pyworkflow/gui/form.py +2627 -0
- pyworkflow/gui/graph.py +247 -0
- pyworkflow/gui/graph_layout.py +271 -0
- pyworkflow/gui/gui.py +566 -0
- pyworkflow/gui/matplotlib_image.py +233 -0
- pyworkflow/gui/plotter.py +247 -0
- pyworkflow/gui/project/__init__.py +25 -0
- pyworkflow/gui/project/base.py +192 -0
- pyworkflow/gui/project/constants.py +139 -0
- pyworkflow/gui/project/labels.py +205 -0
- pyworkflow/gui/project/project.py +484 -0
- pyworkflow/gui/project/searchprotocol.py +154 -0
- pyworkflow/gui/project/searchrun.py +181 -0
- pyworkflow/gui/project/steps.py +166 -0
- pyworkflow/gui/project/utils.py +332 -0
- pyworkflow/gui/project/variables.py +179 -0
- pyworkflow/gui/project/viewdata.py +472 -0
- pyworkflow/gui/project/viewprojects.py +510 -0
- pyworkflow/gui/project/viewprotocols.py +2093 -0
- pyworkflow/gui/project/viewprotocols_extra.py +560 -0
- pyworkflow/gui/text.py +771 -0
- pyworkflow/gui/tooltip.py +185 -0
- pyworkflow/gui/tree.py +684 -0
- pyworkflow/gui/widgets.py +307 -0
- pyworkflow/mapper/__init__.py +26 -0
- pyworkflow/mapper/mapper.py +222 -0
- pyworkflow/mapper/sqlite.py +1578 -0
- pyworkflow/mapper/sqlite_db.py +145 -0
- pyworkflow/object.py +1512 -0
- pyworkflow/plugin.py +712 -0
- pyworkflow/project/__init__.py +31 -0
- pyworkflow/project/config.py +451 -0
- pyworkflow/project/manager.py +179 -0
- pyworkflow/project/project.py +1990 -0
- pyworkflow/project/scripts/clean_projects.py +77 -0
- pyworkflow/project/scripts/config.py +92 -0
- pyworkflow/project/scripts/create.py +77 -0
- pyworkflow/project/scripts/edit_workflow.py +90 -0
- pyworkflow/project/scripts/fix_links.py +39 -0
- pyworkflow/project/scripts/load.py +87 -0
- pyworkflow/project/scripts/refresh.py +83 -0
- pyworkflow/project/scripts/schedule.py +111 -0
- pyworkflow/project/scripts/stack2volume.py +41 -0
- pyworkflow/project/scripts/stop.py +81 -0
- pyworkflow/protocol/__init__.py +38 -0
- pyworkflow/protocol/bibtex.py +48 -0
- pyworkflow/protocol/constants.py +86 -0
- pyworkflow/protocol/executor.py +334 -0
- pyworkflow/protocol/hosts.py +313 -0
- pyworkflow/protocol/launch.py +270 -0
- pyworkflow/protocol/package.py +42 -0
- pyworkflow/protocol/params.py +744 -0
- pyworkflow/protocol/protocol.py +2554 -0
- pyworkflow/resources/Imagej.png +0 -0
- pyworkflow/resources/chimera.png +0 -0
- pyworkflow/resources/fa-exclamation-triangle_alert.png +0 -0
- pyworkflow/resources/fa-info-circle_alert.png +0 -0
- pyworkflow/resources/fa-search.png +0 -0
- pyworkflow/resources/fa-times-circle_alert.png +0 -0
- pyworkflow/resources/file_vol.png +0 -0
- pyworkflow/resources/loading.gif +0 -0
- pyworkflow/resources/no-image128.png +0 -0
- pyworkflow/resources/scipion_bn.png +0 -0
- pyworkflow/resources/scipion_icon.png +0 -0
- pyworkflow/resources/scipion_icon.svg +397 -0
- pyworkflow/resources/scipion_icon_proj.png +0 -0
- pyworkflow/resources/scipion_icon_projs.png +0 -0
- pyworkflow/resources/scipion_icon_prot.png +0 -0
- pyworkflow/resources/scipion_logo.png +0 -0
- pyworkflow/resources/scipion_logo_normal.png +0 -0
- pyworkflow/resources/scipion_logo_small.png +0 -0
- pyworkflow/resources/sprites.png +0 -0
- pyworkflow/resources/sprites.xcf +0 -0
- pyworkflow/resources/wait.gif +0 -0
- pyworkflow/template.py +322 -0
- pyworkflow/tests/__init__.py +29 -0
- pyworkflow/tests/test_utils.py +25 -0
- pyworkflow/tests/tests.py +341 -0
- pyworkflow/utils/__init__.py +38 -0
- pyworkflow/utils/dataset.py +414 -0
- pyworkflow/utils/echo.py +104 -0
- pyworkflow/utils/graph.py +196 -0
- pyworkflow/utils/log.py +284 -0
- pyworkflow/utils/path.py +527 -0
- pyworkflow/utils/process.py +132 -0
- pyworkflow/utils/profiler.py +92 -0
- pyworkflow/utils/progressbar.py +154 -0
- pyworkflow/utils/properties.py +627 -0
- pyworkflow/utils/reflection.py +129 -0
- pyworkflow/utils/utils.py +877 -0
- pyworkflow/utils/which.py +229 -0
- pyworkflow/viewer.py +328 -0
- pyworkflow/webservices/__init__.py +8 -0
- pyworkflow/webservices/config.py +11 -0
- pyworkflow/webservices/notifier.py +162 -0
- pyworkflow/webservices/repository.py +59 -0
- pyworkflow/webservices/workflowhub.py +74 -0
- pyworkflow/wizard.py +64 -0
- pyworkflowtests/__init__.py +51 -0
- pyworkflowtests/bibtex.py +51 -0
- pyworkflowtests/objects.py +830 -0
- pyworkflowtests/protocols.py +154 -0
- pyworkflowtests/tests/__init__.py +0 -0
- pyworkflowtests/tests/test_canvas.py +72 -0
- pyworkflowtests/tests/test_domain.py +45 -0
- pyworkflowtests/tests/test_logs.py +74 -0
- pyworkflowtests/tests/test_mappers.py +392 -0
- pyworkflowtests/tests/test_object.py +507 -0
- pyworkflowtests/tests/test_project.py +42 -0
- pyworkflowtests/tests/test_protocol_execution.py +72 -0
- pyworkflowtests/tests/test_protocol_export.py +78 -0
- pyworkflowtests/tests/test_protocol_output.py +158 -0
- pyworkflowtests/tests/test_streaming.py +47 -0
- pyworkflowtests/tests/test_utils.py +210 -0
- scipion_pyworkflow-3.7.0.dist-info/LICENSE.txt +674 -0
- scipion_pyworkflow-3.7.0.dist-info/METADATA +107 -0
- scipion_pyworkflow-3.7.0.dist-info/RECORD +140 -0
- scipion_pyworkflow-3.7.0.dist-info/WHEEL +5 -0
- scipion_pyworkflow-3.7.0.dist-info/dependency_links.txt +1 -0
- scipion_pyworkflow-3.7.0.dist-info/entry_points.txt +5 -0
- scipion_pyworkflow-3.7.0.dist-info/top_level.txt +2 -0
@@ -0,0 +1,229 @@
|
|
1
|
+
|
2
|
+
# Copyright (c) 2002-2005 ActiveState Corp.
|
3
|
+
# See LICENSE.txt for license details.
|
4
|
+
# Author:
|
5
|
+
# Trent Mick (TrentM@ActiveState.com)
|
6
|
+
# Home:
|
7
|
+
# http://trentm.com/projects/which/
|
8
|
+
|
9
|
+
"""Find the full path to commands.
|
10
|
+
|
11
|
+
which(command, path=None, verbose=0, exts=None)
|
12
|
+
Return the full path to the first match of the given command on the
|
13
|
+
path.
|
14
|
+
|
15
|
+
whichall(command, path=None, verbose=0, exts=None)
|
16
|
+
Return a list of full paths to all matches of the given command on
|
17
|
+
the path.
|
18
|
+
|
19
|
+
whichgen(command, path=None, verbose=0, exts=None)
|
20
|
+
Return a generator which will yield full paths to all matches of the
|
21
|
+
given command on the path.
|
22
|
+
|
23
|
+
"""
|
24
|
+
|
25
|
+
import os
|
26
|
+
import sys
|
27
|
+
import stat
|
28
|
+
# ---- exceptions
|
29
|
+
|
30
|
+
|
31
|
+
class WhichError(Exception):
|
32
|
+
pass
|
33
|
+
|
34
|
+
# ---- internal support stuff
|
35
|
+
|
36
|
+
|
37
|
+
def _getRegisteredExecutable(exeName):
|
38
|
+
"""Windows allow application paths to be registered in the registry."""
|
39
|
+
registered = None
|
40
|
+
if sys.platform.startswith('win'):
|
41
|
+
if os.path.splitext(exeName)[1].lower() != '.exe':
|
42
|
+
exeName += '.exe'
|
43
|
+
import winreg
|
44
|
+
try:
|
45
|
+
key = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\" +\
|
46
|
+
exeName
|
47
|
+
value = winreg.QueryValue(winreg.HKEY_LOCAL_MACHINE, key)
|
48
|
+
registered = (value, "from HKLM\\"+key)
|
49
|
+
except winreg.error:
|
50
|
+
pass
|
51
|
+
if registered and not os.path.exists(registered[0]):
|
52
|
+
registered = None
|
53
|
+
return registered
|
54
|
+
|
55
|
+
|
56
|
+
def _samefile(fname1, fname2):
|
57
|
+
if sys.platform.startswith('win'):
|
58
|
+
return (os.path.normpath(os.path.normcase(fname1)) ==
|
59
|
+
os.path.normpath(os.path.normcase(fname2)))
|
60
|
+
else:
|
61
|
+
return os.path.samefile(fname1, fname2)
|
62
|
+
|
63
|
+
|
64
|
+
def _cull(potential, matches, verbose=0):
|
65
|
+
"""Cull inappropriate matches. Possible reasons:
|
66
|
+
- a duplicate of a previous match
|
67
|
+
- not a disk file
|
68
|
+
- not executable (non-Windows)
|
69
|
+
If 'potential' is approved it is returned and added to 'matches'.
|
70
|
+
Otherwise, None is returned.
|
71
|
+
"""
|
72
|
+
for match in matches: # don't yield duplicates
|
73
|
+
if _samefile(potential[0], match[0]):
|
74
|
+
if verbose:
|
75
|
+
sys.stderr.write("duplicate: %s (%s)\n" % potential)
|
76
|
+
return None
|
77
|
+
else:
|
78
|
+
if not stat.S_ISREG(os.stat(potential[0]).st_mode):
|
79
|
+
if verbose:
|
80
|
+
sys.stderr.write("not a regular file: %s (%s)\n" % potential)
|
81
|
+
elif not os.access(potential[0], os.X_OK):
|
82
|
+
if verbose:
|
83
|
+
sys.stderr.write("no executable access: %s (%s)\n"
|
84
|
+
% potential)
|
85
|
+
else:
|
86
|
+
matches.append(potential)
|
87
|
+
return potential
|
88
|
+
|
89
|
+
|
90
|
+
# ---- module API
|
91
|
+
|
92
|
+
def whichgen(command, path=None, verbose=0, exts=None):
|
93
|
+
"""Return a generator of full paths to the given command.
|
94
|
+
|
95
|
+
:param command: is a the name of the executable to search for.
|
96
|
+
:param path: is an optional alternate path list to search. The default it
|
97
|
+
to use the PATH environment variable.
|
98
|
+
:param verbose: if true, will cause a 2-tuple to be returned for each
|
99
|
+
match. The second element is a textual description of where the
|
100
|
+
match was found.
|
101
|
+
:param exts: optionally allows one to specify a list of extensions to use
|
102
|
+
instead of the standard list for this system. This can
|
103
|
+
effectively be used as an optimization to, for example, avoid
|
104
|
+
stat's of "foo.vbs" when searching for "foo" and you know it is
|
105
|
+
not a VisualBasic script but ".vbs" is on PATHEXT. This option
|
106
|
+
is only supported on Windows.
|
107
|
+
|
108
|
+
:return: This method returns a generator which yields either full paths to
|
109
|
+
the given command or, if verbose, tuples of the form (<path to
|
110
|
+
command>, <where path found>).
|
111
|
+
|
112
|
+
"""
|
113
|
+
matches = []
|
114
|
+
if path is None:
|
115
|
+
usingGivenPath = 0
|
116
|
+
path = os.environ.get("PATH", "").split(os.pathsep)
|
117
|
+
if sys.platform.startswith("win"):
|
118
|
+
path.insert(0, os.curdir) # implied by Windows shell
|
119
|
+
else:
|
120
|
+
usingGivenPath = 1
|
121
|
+
|
122
|
+
# Windows has the concept of a list of extensions (PATHEXT env var).
|
123
|
+
if sys.platform.startswith("win"):
|
124
|
+
if exts is None:
|
125
|
+
exts = os.environ.get("PATHEXT", "").split(os.pathsep)
|
126
|
+
# If '.exe' is not in exts then obviously this is Win9x and
|
127
|
+
# or a bogus PATHEXT, then use a reasonable default.
|
128
|
+
for ext in exts:
|
129
|
+
if ext.lower() == ".exe":
|
130
|
+
break
|
131
|
+
else:
|
132
|
+
exts = ['.COM', '.EXE', '.BAT']
|
133
|
+
elif not isinstance(exts, list):
|
134
|
+
raise TypeError("'exts' argument must be a list or None")
|
135
|
+
else:
|
136
|
+
if exts is not None:
|
137
|
+
raise WhichError("'exts' argument is not supported on "
|
138
|
+
"platform '%s'" % sys.platform)
|
139
|
+
exts = []
|
140
|
+
|
141
|
+
# File name cannot have path separators because PATH lookup does not
|
142
|
+
# work that way.
|
143
|
+
if os.sep in command or os.altsep and os.altsep in command:
|
144
|
+
pass
|
145
|
+
else:
|
146
|
+
for i in range(len(path)):
|
147
|
+
dirName = path[i]
|
148
|
+
# On windows the dirName *could* be quoted, drop the quotes
|
149
|
+
if sys.platform.startswith("win") and len(dirName) >= 2\
|
150
|
+
and dirName[0] == '"' and dirName[-1] == '"':
|
151
|
+
dirName = dirName[1:-1]
|
152
|
+
for ext in ['']+exts:
|
153
|
+
absName = os.path.abspath(
|
154
|
+
os.path.normpath(os.path.join(dirName, command+ext)))
|
155
|
+
if os.path.isfile(absName):
|
156
|
+
if usingGivenPath:
|
157
|
+
fromWhere = "from given path element %d" % i
|
158
|
+
elif not sys.platform.startswith("win"):
|
159
|
+
fromWhere = "from PATH element %d" % i
|
160
|
+
elif i == 0:
|
161
|
+
fromWhere = "from current directory"
|
162
|
+
else:
|
163
|
+
fromWhere = "from PATH element %d" % (i-1)
|
164
|
+
match = _cull((absName, fromWhere), matches, verbose)
|
165
|
+
if match:
|
166
|
+
if verbose:
|
167
|
+
yield match
|
168
|
+
else:
|
169
|
+
yield match[0]
|
170
|
+
match = _getRegisteredExecutable(command)
|
171
|
+
if match is not None:
|
172
|
+
match = _cull(match, matches, verbose)
|
173
|
+
if match:
|
174
|
+
if verbose:
|
175
|
+
yield match
|
176
|
+
else:
|
177
|
+
yield match[0]
|
178
|
+
|
179
|
+
|
180
|
+
def which(command, path=None, verbose=0, exts=None):
|
181
|
+
"""Return the full path to the first match of the given command on
|
182
|
+
the path.
|
183
|
+
|
184
|
+
:param command: is a the name of the executable to search for.
|
185
|
+
:param path: is an optional alternate path list to search.
|
186
|
+
The default is to use the PATH environment variable.
|
187
|
+
:param verbose: if true, will cause a 2-tuple to be returned.
|
188
|
+
The second element is a textual description of where the match was found.
|
189
|
+
:param exts: optionally allows one to specify a list of extensions to use
|
190
|
+
instead of the standard list for this system. This can
|
191
|
+
effectively be used as an optimization to, for example, avoid
|
192
|
+
stat's of "foo.vbs" when searching for "foo" and you know it is
|
193
|
+
not a VisualBasic script but ".vbs" is on PATHEXT. This option
|
194
|
+
is only supported on Windows.
|
195
|
+
|
196
|
+
:return If no match is found for the command, an empty string is returned.
|
197
|
+
|
198
|
+
"""
|
199
|
+
try:
|
200
|
+
match = next(whichgen(command, path, verbose, exts))
|
201
|
+
except StopIteration:
|
202
|
+
return ''
|
203
|
+
return match
|
204
|
+
|
205
|
+
|
206
|
+
def commandExists(command):
|
207
|
+
path = which(command)
|
208
|
+
return path != ''
|
209
|
+
|
210
|
+
|
211
|
+
def whichall(command, path=None, verbose=0, exts=None):
|
212
|
+
"""Return a list of full paths to all matches of the given command
|
213
|
+
on the path.
|
214
|
+
|
215
|
+
:param command: is a the name of the executable to search for.
|
216
|
+
:param path: is an optional alternate path list to search. The default it
|
217
|
+
to use the PATH environment variable.
|
218
|
+
:param verbose: if true, will cause a 2-tuple to be returned for each
|
219
|
+
match. The second element is a textual description of where the
|
220
|
+
match was found.
|
221
|
+
:param exts: optionally allows one to specify a list of extensions to use
|
222
|
+
instead of the standard list for this system. This can
|
223
|
+
effectively be used as an optimization to, for example, avoid
|
224
|
+
stat's of "foo.vbs" when searching for "foo" and you know it is
|
225
|
+
not a VisualBasic script but ".vbs" is on PATHEXT. This option
|
226
|
+
is only supported on Windows.
|
227
|
+
|
228
|
+
"""
|
229
|
+
return list(whichgen(command, path, verbose, exts))
|
pyworkflow/viewer.py
ADDED
@@ -0,0 +1,328 @@
|
|
1
|
+
# **************************************************************************
|
2
|
+
# *
|
3
|
+
# * Authors: J.M. De la Rosa Trevin (delarosatrevin@scilifelab.se) [1]
|
4
|
+
# *
|
5
|
+
# * [1] SciLifeLab, Stockholm University
|
6
|
+
# *
|
7
|
+
# * This program is free software: you can redistribute it and/or modify
|
8
|
+
# * it under the terms of the GNU General Public License as published by
|
9
|
+
# * the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# * (at your option) any later version.
|
11
|
+
# *
|
12
|
+
# * This program is distributed in the hope that it will be useful,
|
13
|
+
# * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# * GNU General Public License for more details.
|
16
|
+
# *
|
17
|
+
# * You should have received a copy of the GNU General Public License
|
18
|
+
# * along with this program. If not, see <https://www.gnu.org/licenses/>.
|
19
|
+
# *
|
20
|
+
# * All comments concerning this program package may be sent to the
|
21
|
+
# * e-mail address 'scipion@cnb.csic.es'
|
22
|
+
# *
|
23
|
+
# **************************************************************************
|
24
|
+
|
25
|
+
|
26
|
+
import os
|
27
|
+
|
28
|
+
import pyworkflow.protocol as pwprot
|
29
|
+
from pyworkflow.utils import KEYSYM
|
30
|
+
from subprocess import call
|
31
|
+
|
32
|
+
DESKTOP_TKINTER = 'tkinter'
|
33
|
+
WEB_DJANGO = 'django'
|
34
|
+
|
35
|
+
|
36
|
+
class View(object):
|
37
|
+
""" Represents a visualization result for some object or file.
|
38
|
+
Views can be plots, table views, chimera scripts, commands or messages.
|
39
|
+
"""
|
40
|
+
def show(self):
|
41
|
+
""" This method should be overwritten to implement how
|
42
|
+
this particular view will be displayed in desktop.
|
43
|
+
"""
|
44
|
+
pass
|
45
|
+
|
46
|
+
def toUrl(self):
|
47
|
+
""" If the view have web implementation, this method
|
48
|
+
should be implemented to build the url with parameters
|
49
|
+
that will be used to respond.
|
50
|
+
"""
|
51
|
+
pass
|
52
|
+
|
53
|
+
|
54
|
+
class CommandView(View):
|
55
|
+
""" View for calling an external command. """
|
56
|
+
def __init__(self, cmd, **kwargs):
|
57
|
+
View.__init__(self)
|
58
|
+
self._cmd = cmd
|
59
|
+
self._env = kwargs.get('env', None)
|
60
|
+
self._cwd = kwargs.get('cwd', None)
|
61
|
+
|
62
|
+
def show(self):
|
63
|
+
call(self._cmd, shell=True, env=self._env, cwd=self._cwd)
|
64
|
+
|
65
|
+
|
66
|
+
MSG_INFO = 0
|
67
|
+
MSG_WARN = 1
|
68
|
+
MSG_ERROR = 2
|
69
|
+
|
70
|
+
MSG_DICT = {MSG_INFO: 'showInfo',
|
71
|
+
MSG_WARN: 'showWarning',
|
72
|
+
MSG_ERROR: 'showError'}
|
73
|
+
|
74
|
+
|
75
|
+
class MessageView(View):
|
76
|
+
""" View for some message. """
|
77
|
+
def __init__(self, msg, title='', msgType=MSG_INFO, tkParent=None,
|
78
|
+
**kwargs):
|
79
|
+
View.__init__(self)
|
80
|
+
self._msg = msg
|
81
|
+
self._title = title
|
82
|
+
self._msgType = msgType
|
83
|
+
self._tkParent = tkParent
|
84
|
+
|
85
|
+
def show(self):
|
86
|
+
import pyworkflow.gui.dialog as dialog
|
87
|
+
func = getattr(dialog, MSG_DICT[self._msgType])
|
88
|
+
func(self._title, self._msg, self._tkParent)
|
89
|
+
|
90
|
+
def getMessage(self):
|
91
|
+
return self._msg
|
92
|
+
|
93
|
+
|
94
|
+
class TextView(View):
|
95
|
+
""" View for display some text file. """
|
96
|
+
def __init__(self, filelist, title='', tkParent=None, **kwargs):
|
97
|
+
View.__init__(self)
|
98
|
+
self._filelist = filelist
|
99
|
+
if title:
|
100
|
+
self._title = title
|
101
|
+
else:
|
102
|
+
self._title = filelist[0]
|
103
|
+
self._tkParent = tkParent
|
104
|
+
|
105
|
+
def getFileList(self):
|
106
|
+
return self._filelist
|
107
|
+
|
108
|
+
def show(self):
|
109
|
+
from pyworkflow.gui.text import showTextFileViewer
|
110
|
+
showTextFileViewer(self._title, self._filelist, self._tkParent)
|
111
|
+
|
112
|
+
|
113
|
+
# ---------------- Viewers ----------------------------------------
|
114
|
+
class Viewer(object):
|
115
|
+
""" A Viewer will provide several Views to visualize
|
116
|
+
the data associated to data objects or protocol.
|
117
|
+
|
118
|
+
The _targets class property should contain a list of string
|
119
|
+
with the class names that this viewer is able to visualize.
|
120
|
+
For example: _targets = ['Image', 'SetOfImages']
|
121
|
+
"""
|
122
|
+
_targets = []
|
123
|
+
_environments = [DESKTOP_TKINTER]
|
124
|
+
_name = None
|
125
|
+
|
126
|
+
def __init__(self, tmpPath='./Tmp', **args):
|
127
|
+
self._tmpPath = tmpPath
|
128
|
+
self._project = args.get('project')
|
129
|
+
if self._project is None:
|
130
|
+
raise Exception('Can not initialize a Viewer with None project.')
|
131
|
+
self.protocol = args.get('protocol', None)
|
132
|
+
self.formWindow = args.get('parent', None)
|
133
|
+
self._keyPressed = args.get('keyPressed', None)
|
134
|
+
self._tkRoot = self.formWindow.root if self.formWindow else None
|
135
|
+
|
136
|
+
def getKeyPressed(self):
|
137
|
+
return self._keyPressed
|
138
|
+
|
139
|
+
def shiftPressed(self):
|
140
|
+
return self._keyPressed==KEYSYM.SHIFT
|
141
|
+
|
142
|
+
def controlPressed(self):
|
143
|
+
return self._keyPressed == KEYSYM.CONTROL
|
144
|
+
|
145
|
+
def getTkRoot(self):
|
146
|
+
return self._tkRoot
|
147
|
+
|
148
|
+
def _getTmpPath(self, *paths):
|
149
|
+
return os.path.join(self._tmpPath, *paths)
|
150
|
+
|
151
|
+
def visualize(self, obj, **kwargs):
|
152
|
+
""" Display each of the views, by default
|
153
|
+
the implementation is for desktop.
|
154
|
+
"""
|
155
|
+
for view in self._visualize(obj, **kwargs):
|
156
|
+
view.show()
|
157
|
+
|
158
|
+
def _visualize(self, obj, **kwargs):
|
159
|
+
""" This method should make the necessary conversions
|
160
|
+
and return the list of Views that will be used to
|
161
|
+
visualize the object
|
162
|
+
"""
|
163
|
+
return []
|
164
|
+
|
165
|
+
# FIXME: REMOVE THIS METHOD AFTER RE-FACTORING
|
166
|
+
def getView(self):
|
167
|
+
""" This method should return the string value of the view in web
|
168
|
+
that will respond to this viewer. This method only should be implemented
|
169
|
+
in those viewers that have WEB_DJANGO environment defined.
|
170
|
+
"""
|
171
|
+
return None
|
172
|
+
|
173
|
+
def getProject(self):
|
174
|
+
return self._project
|
175
|
+
|
176
|
+
def setProject(self, project):
|
177
|
+
self._project = project
|
178
|
+
|
179
|
+
def getParent(self):
|
180
|
+
""" Get the Tk parent widget. """
|
181
|
+
return self.formWindow
|
182
|
+
|
183
|
+
def infoMessage(self, msg, title='',):
|
184
|
+
""" Build a message View of type INFO. """
|
185
|
+
return MessageView(msg, title, msgType=MSG_INFO, tkParent=self._tkRoot)
|
186
|
+
|
187
|
+
def errorMessage(self, msg, title=''):
|
188
|
+
""" Build a message View of type INFO. """
|
189
|
+
return MessageView(msg, title, msgType=MSG_ERROR, tkParent=self._tkRoot)
|
190
|
+
|
191
|
+
def errorList(self, errors, views, title='Visualization errors'):
|
192
|
+
""" Convert an error list in a single Error message. """
|
193
|
+
if errors:
|
194
|
+
views.append(self.errorMessage('\n'.join(errors), title))
|
195
|
+
|
196
|
+
def warnMessage(self, msg, title=''):
|
197
|
+
""" Build a message View of type INFO. """
|
198
|
+
return MessageView(msg, title, msgType=MSG_WARN, tkParent=self._tkRoot)
|
199
|
+
|
200
|
+
def textView(self, filelist, title=''):
|
201
|
+
return TextView(filelist, title, tkParent=self.formWindow)
|
202
|
+
|
203
|
+
def tkWindow(self, windowClass, **kwargs):
|
204
|
+
kwargs['masterWindow'] = self.formWindow
|
205
|
+
return windowClass(**kwargs)
|
206
|
+
|
207
|
+
def getProtocolId(self):
|
208
|
+
if not hasattr(self, 'protocol'):
|
209
|
+
raise Exception("self.protocol is not defined for this Viewer.")
|
210
|
+
return self.protocol.strId()
|
211
|
+
|
212
|
+
@classmethod
|
213
|
+
def getName(cls):
|
214
|
+
if cls._name is None:
|
215
|
+
return cls.__name__
|
216
|
+
return cls._name
|
217
|
+
|
218
|
+
|
219
|
+
class ProtocolViewer(Viewer, pwprot.Protocol):
|
220
|
+
""" Special kind of viewer that have a Form to organize better
|
221
|
+
complex visualization associated with protocol results.
|
222
|
+
If should provide a mapping between form params and the corresponding
|
223
|
+
functions that will return the corresponding Views.
|
224
|
+
"""
|
225
|
+
def __init__(self, **kwargs):
|
226
|
+
# Here we are going to intercept the original _defineParams function
|
227
|
+
# and replace by an empty one, this is to postpone the definition of
|
228
|
+
# params until the protocol is set and then self.protocol can be used
|
229
|
+
# for a more dynamic definition
|
230
|
+
object.__setattr__(self, '_defineParamsBackup', self._defineParams)
|
231
|
+
object.__setattr__(self, '_defineParams', self._defineParamsEmpty)
|
232
|
+
|
233
|
+
pwprot.Protocol.__init__(self, **kwargs)
|
234
|
+
Viewer.__init__(self, **kwargs)
|
235
|
+
self.allowHeader.set(False)
|
236
|
+
# This flag will be used to display a plot or return the plotter
|
237
|
+
self.showPlot = True
|
238
|
+
self._tkRoot = None
|
239
|
+
self.formWindow = None
|
240
|
+
self.setWorkingDir(self.getProject().getTmpPath())
|
241
|
+
|
242
|
+
def getWindow(self):
|
243
|
+
return self.formWindow
|
244
|
+
|
245
|
+
def getTkRoot(self):
|
246
|
+
return self._tkRoot
|
247
|
+
|
248
|
+
def _defineParamsEmpty(self, form):
|
249
|
+
""" Just do nothing and postpone the real definition. """
|
250
|
+
pass
|
251
|
+
|
252
|
+
def setProtocol(self, protocol):
|
253
|
+
""" Set the protocol instance to the viewer and
|
254
|
+
call the definition of the parameters.
|
255
|
+
"""
|
256
|
+
self.protocol = protocol
|
257
|
+
self._defineParamsBackup(self._definition)
|
258
|
+
self._createVarsFromDefinition()
|
259
|
+
|
260
|
+
def visualize(self, obj, **args):
|
261
|
+
"""Open the Protocol GUI Form given a Protocol instance"""
|
262
|
+
from pyworkflow.gui.form import FormWindow
|
263
|
+
self.setProtocol(obj)
|
264
|
+
self.windows = args.get('windows', None)
|
265
|
+
self.formWindow = FormWindow("Protocol Viewer: " + self.getClassName(),
|
266
|
+
self, self._viewAll, self.windows,
|
267
|
+
visualizeDict=self.__getVisualizeWrapperDict(),
|
268
|
+
visualizeMode=True)
|
269
|
+
self.formWindow.visualizeMode = True
|
270
|
+
self.showInfo = self.formWindow.showInfo
|
271
|
+
self.showError = self.formWindow.showError
|
272
|
+
self._tkRoot = self.formWindow.root
|
273
|
+
self.formWindow.show(center=True)
|
274
|
+
|
275
|
+
def _visualizeParam(self, paramName=None):
|
276
|
+
""" Call handler to get viewers and visualize each one. """
|
277
|
+
errors = self.validate()
|
278
|
+
if errors:
|
279
|
+
errorMsg = '\n'.join(errors)
|
280
|
+
self.showError(errorMsg, "Validation errors")
|
281
|
+
else:
|
282
|
+
views = self._getVisualizeDict()[paramName](paramName)
|
283
|
+
if views:
|
284
|
+
for v in views:
|
285
|
+
v.show()
|
286
|
+
|
287
|
+
def __getVisualizeWrapperDict(self):
|
288
|
+
""" Replace the True attributes handler by the generic one. """
|
289
|
+
d = {}
|
290
|
+
for k in self._getVisualizeDict():
|
291
|
+
d[k] = self._visualizeParam
|
292
|
+
|
293
|
+
return d
|
294
|
+
|
295
|
+
def _getVisualizeDict(self):
|
296
|
+
""" Create the visualization dict for view individual params. """
|
297
|
+
return {}
|
298
|
+
|
299
|
+
def _viewAll(self, *args):
|
300
|
+
""" Visualize all data give the parameters. """
|
301
|
+
for k, v in self._getVisualizeDict().items():
|
302
|
+
if self.getAttributeValue(k, False):
|
303
|
+
v(k)
|
304
|
+
|
305
|
+
def _citations(self):
|
306
|
+
return self.protocol._citations()
|
307
|
+
|
308
|
+
def validateInstallation(self):
|
309
|
+
return
|
310
|
+
|
311
|
+
# TODO deprecate this method, it's duplicate of one from pwutils.utils
|
312
|
+
def _getListFromRangeString(self, rangeStr):
|
313
|
+
""" Create a list of integer from a string with range definitions
|
314
|
+
Examples:
|
315
|
+
"1,5-8,10" -> [1,5,6,7,8,10]
|
316
|
+
"2,6,9-11" -> [2,6,9,10,11]
|
317
|
+
"2 5, 6-8" -> [2,5,6,7,8]
|
318
|
+
"""
|
319
|
+
elements = rangeStr.split(',')
|
320
|
+
values = []
|
321
|
+
for e in elements:
|
322
|
+
if '-' in e:
|
323
|
+
limits = e.split('-')
|
324
|
+
values += range(int(limits[0]), int(limits[1])+1)
|
325
|
+
else:
|
326
|
+
# If values are separated by comma also split
|
327
|
+
values += map(int, e.split())
|
328
|
+
return values
|
@@ -0,0 +1,8 @@
|
|
1
|
+
|
2
|
+
# Export all configuration variables in case they will be needed outside this module
|
3
|
+
# Nonetheless, the recommend way is to import the classes or functions provided
|
4
|
+
# by the module
|
5
|
+
from .config import *
|
6
|
+
|
7
|
+
from .notifier import ProjectWorkflowNotifier
|
8
|
+
from .repository import WorkflowRepository
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# Variable related to the online services (workflow stats and repository) that Scipion reports to or communicate.
|
2
|
+
# These variables may change between Scipion versions but do not depend on the user or system
|
3
|
+
|
4
|
+
# Web that gathers protocol usage
|
5
|
+
SCIPION_STATS_SERVER = 'https://scipion.i2pc.es'
|
6
|
+
SCIPION_STATS_WORKFLOW_APP = SCIPION_STATS_SERVER + '/report_protocols/api/workflow/workflow/'
|
7
|
+
|
8
|
+
# Web that handles workflows
|
9
|
+
WORKFLOW_REPOSITORY_SERVER = 'https://workflows.scipion.i2pc.es/'
|
10
|
+
WORKFLOW_PROG_STEP1 = 'workflowProgStep1_add/'
|
11
|
+
WORKFLOW_PROG_STEP2 = 'workflowProgStep2_add/'
|