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.
Files changed (140) hide show
  1. pyworkflow/__init__.py +33 -0
  2. pyworkflow/apps/__init__.py +29 -0
  3. pyworkflow/apps/pw_manager.py +37 -0
  4. pyworkflow/apps/pw_plot.py +51 -0
  5. pyworkflow/apps/pw_project.py +113 -0
  6. pyworkflow/apps/pw_protocol_list.py +143 -0
  7. pyworkflow/apps/pw_protocol_run.py +51 -0
  8. pyworkflow/apps/pw_run_tests.py +267 -0
  9. pyworkflow/apps/pw_schedule_run.py +322 -0
  10. pyworkflow/apps/pw_sleep.py +37 -0
  11. pyworkflow/apps/pw_sync_data.py +439 -0
  12. pyworkflow/apps/pw_viewer.py +78 -0
  13. pyworkflow/config.py +536 -0
  14. pyworkflow/constants.py +212 -0
  15. pyworkflow/exceptions.py +18 -0
  16. pyworkflow/gui/__init__.py +36 -0
  17. pyworkflow/gui/browser.py +726 -0
  18. pyworkflow/gui/canvas.py +1190 -0
  19. pyworkflow/gui/dialog.py +976 -0
  20. pyworkflow/gui/form.py +2627 -0
  21. pyworkflow/gui/graph.py +247 -0
  22. pyworkflow/gui/graph_layout.py +271 -0
  23. pyworkflow/gui/gui.py +566 -0
  24. pyworkflow/gui/matplotlib_image.py +233 -0
  25. pyworkflow/gui/plotter.py +247 -0
  26. pyworkflow/gui/project/__init__.py +25 -0
  27. pyworkflow/gui/project/base.py +192 -0
  28. pyworkflow/gui/project/constants.py +139 -0
  29. pyworkflow/gui/project/labels.py +205 -0
  30. pyworkflow/gui/project/project.py +484 -0
  31. pyworkflow/gui/project/searchprotocol.py +154 -0
  32. pyworkflow/gui/project/searchrun.py +181 -0
  33. pyworkflow/gui/project/steps.py +166 -0
  34. pyworkflow/gui/project/utils.py +332 -0
  35. pyworkflow/gui/project/variables.py +179 -0
  36. pyworkflow/gui/project/viewdata.py +472 -0
  37. pyworkflow/gui/project/viewprojects.py +510 -0
  38. pyworkflow/gui/project/viewprotocols.py +2093 -0
  39. pyworkflow/gui/project/viewprotocols_extra.py +560 -0
  40. pyworkflow/gui/text.py +771 -0
  41. pyworkflow/gui/tooltip.py +185 -0
  42. pyworkflow/gui/tree.py +684 -0
  43. pyworkflow/gui/widgets.py +307 -0
  44. pyworkflow/mapper/__init__.py +26 -0
  45. pyworkflow/mapper/mapper.py +222 -0
  46. pyworkflow/mapper/sqlite.py +1578 -0
  47. pyworkflow/mapper/sqlite_db.py +145 -0
  48. pyworkflow/object.py +1512 -0
  49. pyworkflow/plugin.py +712 -0
  50. pyworkflow/project/__init__.py +31 -0
  51. pyworkflow/project/config.py +451 -0
  52. pyworkflow/project/manager.py +179 -0
  53. pyworkflow/project/project.py +1990 -0
  54. pyworkflow/project/scripts/clean_projects.py +77 -0
  55. pyworkflow/project/scripts/config.py +92 -0
  56. pyworkflow/project/scripts/create.py +77 -0
  57. pyworkflow/project/scripts/edit_workflow.py +90 -0
  58. pyworkflow/project/scripts/fix_links.py +39 -0
  59. pyworkflow/project/scripts/load.py +87 -0
  60. pyworkflow/project/scripts/refresh.py +83 -0
  61. pyworkflow/project/scripts/schedule.py +111 -0
  62. pyworkflow/project/scripts/stack2volume.py +41 -0
  63. pyworkflow/project/scripts/stop.py +81 -0
  64. pyworkflow/protocol/__init__.py +38 -0
  65. pyworkflow/protocol/bibtex.py +48 -0
  66. pyworkflow/protocol/constants.py +86 -0
  67. pyworkflow/protocol/executor.py +334 -0
  68. pyworkflow/protocol/hosts.py +313 -0
  69. pyworkflow/protocol/launch.py +270 -0
  70. pyworkflow/protocol/package.py +42 -0
  71. pyworkflow/protocol/params.py +744 -0
  72. pyworkflow/protocol/protocol.py +2554 -0
  73. pyworkflow/resources/Imagej.png +0 -0
  74. pyworkflow/resources/chimera.png +0 -0
  75. pyworkflow/resources/fa-exclamation-triangle_alert.png +0 -0
  76. pyworkflow/resources/fa-info-circle_alert.png +0 -0
  77. pyworkflow/resources/fa-search.png +0 -0
  78. pyworkflow/resources/fa-times-circle_alert.png +0 -0
  79. pyworkflow/resources/file_vol.png +0 -0
  80. pyworkflow/resources/loading.gif +0 -0
  81. pyworkflow/resources/no-image128.png +0 -0
  82. pyworkflow/resources/scipion_bn.png +0 -0
  83. pyworkflow/resources/scipion_icon.png +0 -0
  84. pyworkflow/resources/scipion_icon.svg +397 -0
  85. pyworkflow/resources/scipion_icon_proj.png +0 -0
  86. pyworkflow/resources/scipion_icon_projs.png +0 -0
  87. pyworkflow/resources/scipion_icon_prot.png +0 -0
  88. pyworkflow/resources/scipion_logo.png +0 -0
  89. pyworkflow/resources/scipion_logo_normal.png +0 -0
  90. pyworkflow/resources/scipion_logo_small.png +0 -0
  91. pyworkflow/resources/sprites.png +0 -0
  92. pyworkflow/resources/sprites.xcf +0 -0
  93. pyworkflow/resources/wait.gif +0 -0
  94. pyworkflow/template.py +322 -0
  95. pyworkflow/tests/__init__.py +29 -0
  96. pyworkflow/tests/test_utils.py +25 -0
  97. pyworkflow/tests/tests.py +341 -0
  98. pyworkflow/utils/__init__.py +38 -0
  99. pyworkflow/utils/dataset.py +414 -0
  100. pyworkflow/utils/echo.py +104 -0
  101. pyworkflow/utils/graph.py +196 -0
  102. pyworkflow/utils/log.py +284 -0
  103. pyworkflow/utils/path.py +527 -0
  104. pyworkflow/utils/process.py +132 -0
  105. pyworkflow/utils/profiler.py +92 -0
  106. pyworkflow/utils/progressbar.py +154 -0
  107. pyworkflow/utils/properties.py +627 -0
  108. pyworkflow/utils/reflection.py +129 -0
  109. pyworkflow/utils/utils.py +877 -0
  110. pyworkflow/utils/which.py +229 -0
  111. pyworkflow/viewer.py +328 -0
  112. pyworkflow/webservices/__init__.py +8 -0
  113. pyworkflow/webservices/config.py +11 -0
  114. pyworkflow/webservices/notifier.py +162 -0
  115. pyworkflow/webservices/repository.py +59 -0
  116. pyworkflow/webservices/workflowhub.py +74 -0
  117. pyworkflow/wizard.py +64 -0
  118. pyworkflowtests/__init__.py +51 -0
  119. pyworkflowtests/bibtex.py +51 -0
  120. pyworkflowtests/objects.py +830 -0
  121. pyworkflowtests/protocols.py +154 -0
  122. pyworkflowtests/tests/__init__.py +0 -0
  123. pyworkflowtests/tests/test_canvas.py +72 -0
  124. pyworkflowtests/tests/test_domain.py +45 -0
  125. pyworkflowtests/tests/test_logs.py +74 -0
  126. pyworkflowtests/tests/test_mappers.py +392 -0
  127. pyworkflowtests/tests/test_object.py +507 -0
  128. pyworkflowtests/tests/test_project.py +42 -0
  129. pyworkflowtests/tests/test_protocol_execution.py +72 -0
  130. pyworkflowtests/tests/test_protocol_export.py +78 -0
  131. pyworkflowtests/tests/test_protocol_output.py +158 -0
  132. pyworkflowtests/tests/test_streaming.py +47 -0
  133. pyworkflowtests/tests/test_utils.py +210 -0
  134. scipion_pyworkflow-3.7.0.dist-info/LICENSE.txt +674 -0
  135. scipion_pyworkflow-3.7.0.dist-info/METADATA +107 -0
  136. scipion_pyworkflow-3.7.0.dist-info/RECORD +140 -0
  137. scipion_pyworkflow-3.7.0.dist-info/WHEEL +5 -0
  138. scipion_pyworkflow-3.7.0.dist-info/dependency_links.txt +1 -0
  139. scipion_pyworkflow-3.7.0.dist-info/entry_points.txt +5 -0
  140. 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/'