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
pyworkflow/config.py ADDED
@@ -0,0 +1,536 @@
1
+ import logging
2
+
3
+ logger = logging.getLogger(__file__)
4
+ import ast
5
+ import importlib
6
+ import inspect
7
+ import os
8
+ import shutil
9
+ import sys
10
+ import types
11
+ from .constants import *
12
+
13
+ HOME = os.path.abspath(os.path.dirname(__file__))
14
+ PYTHON = os.environ.get(SCIPION_PYTHON, SCIPION_PYTHON_DEFAULT)
15
+
16
+
17
+ def join(*paths):
18
+ """ join paths from HOME . """
19
+ return os.path.join(HOME, *paths)
20
+
21
+
22
+ __resourcesPath = join('resources')
23
+
24
+ def getResourcesPath(file=None):
25
+
26
+ return __resourcesPath if file is None else os.path.join(__resourcesPath, file)
27
+
28
+ def findResource(filename):
29
+ from .utils.path import findFile
30
+ return findFile(filename, *[__resourcesPath])
31
+
32
+
33
+ def genNotesHeading():
34
+ return SCIPION_NOTES_HEADING_MSG
35
+
36
+
37
+ def getAppsPath(*paths):
38
+ return join(APPS, *paths)
39
+
40
+
41
+ def getSyncDataScript():
42
+ return getAppsPath(PW_SYNC_DATA)
43
+
44
+
45
+ def getScheduleScript():
46
+ return getAppsPath(PW_SCHEDULE_RUN)
47
+
48
+
49
+ def getTestsScript():
50
+ return getAppsPath(PW_RUN_TESTS)
51
+
52
+
53
+ def getViewerScript():
54
+ return getAppsPath(PW_VIEWER)
55
+
56
+
57
+ def getPyworkflowPath():
58
+ """ Returns the path where pyworkflow is"""
59
+ return os.path.dirname(__file__)
60
+
61
+
62
+ def getModuleFolder(moduleName):
63
+ """ Returns the path of a module without importing it"""
64
+ spec = importlib.util.find_spec(moduleName)
65
+ return os.path.dirname(spec.origin)
66
+
67
+
68
+ def validColor(colorname):
69
+ """ If it can be converted to rgb is a valid color"""
70
+ from matplotlib.colors import to_rgb
71
+ to_rgb(colorname)
72
+ return colorname
73
+
74
+ class VarTypes(Enum):
75
+ STRING = 0
76
+ BOOLEAN = 1
77
+ PATH = 2 # Any Path: Folder or file
78
+ INTEGER = 3
79
+ DECIMAL = 4
80
+ FILENAME = 5 # Just the base name of a file
81
+ FOLDER = 6 # A folder
82
+
83
+ class Variable:
84
+ def __init__(self, name, description, source, value, default, var_type: VarTypes = VarTypes.STRING, isDefault=None):
85
+ self.name = name
86
+ self.description = description
87
+ self.source = source
88
+ self.value = value
89
+ self.default = default
90
+ self.isDefault = isDefault if isDefault is not None else self._isValueDefault()
91
+ self.var_type = var_type
92
+ def setToDefault(self):
93
+ self.isDefault=True
94
+ self.value=self.default
95
+
96
+ def setValue(self, new_value):
97
+ self.value = new_value
98
+ self.isDefault= self._isValueDefault()
99
+ def _isValueDefault(self):
100
+ return self.value==self.default
101
+ class VariablesRegistry:
102
+ _variables={}
103
+
104
+ def __init__(self):
105
+ raise RuntimeError("Variables class doesn't need to be instantiated.")
106
+ @classmethod
107
+ def register(cls, variable: Variable):
108
+ cls._variables[variable.name] = variable
109
+
110
+ @classmethod
111
+ def variables(cls):
112
+ return cls._variables
113
+
114
+ @classmethod
115
+ def __iter__(cls):
116
+ """ Iterate alphabetically"""
117
+ for key in sorted(cls._variables):
118
+ yield cls._variables[key]
119
+
120
+ @classmethod
121
+ def save(cls, path):
122
+ """ Saves the variables in the path specified """
123
+ from pyworkflow.utils import backup
124
+ backup(path)
125
+
126
+ with open(path,"w") as fh:
127
+ # Save the section as in any python config file format.
128
+ fh.write("[PYWORKFLOW]\n")
129
+ for var in cls.__iter__():
130
+ if var.source == "pyworkflow" and not var.isDefault:
131
+ fh.write("%s=%s\n" % (var.name, var.value))
132
+
133
+ fh.write("\n[PLUGINS]\n")
134
+ for var in cls._variables.values():
135
+ if var.source != "pyworkflow" and not var.isDefault:
136
+ fh.write("%s=%s\n" % (var.name, var.value))
137
+
138
+
139
+ class Config:
140
+ """ Main Config for pyworkflow. It contains the main Scipion configuration variables
141
+ providing default values or, if present, taking them from the environment.
142
+ Necessary value is SCIPION_HOME and has to be present in the environment"""
143
+
144
+ @staticmethod
145
+ def __get(key, default, description=None, caster=None, var_type:VarTypes=VarTypes.STRING, source="pyworkflow"):
146
+
147
+ if key in os.environ:
148
+ value = os.environ.get(key)
149
+ isDefault = (value==default)
150
+ else:
151
+ isDefault = True
152
+ value = default
153
+
154
+ # If the caster is passed do the casting, if fails go back to default
155
+ if caster:
156
+ try:
157
+ value=caster(value)
158
+ except:
159
+ logger.warning("Variable %s has this value %s that can't be casted to the right type (%s). Using %s (default value)" %
160
+ (key,value, caster, default))
161
+ value = default
162
+ # If empty use default value
163
+ if value == "" != default:
164
+ logger.warning("%s variable is empty, falling back to default value (%s)" % (key, default))
165
+ value = default
166
+
167
+ # Expand user and variables if string value
168
+ if isinstance(value, str):
169
+ value = os.path.expandvars(os.path.expanduser(value))
170
+
171
+ # Register the variable
172
+ VariablesRegistry.register(Variable(key,description, source, value, default, var_type=var_type, isDefault=isDefault))
173
+ return value
174
+
175
+ class Root:
176
+ """ Simple helper to return path from a root. """
177
+
178
+ def __init__(self, root):
179
+ self._root = root
180
+
181
+ def join(self, *path):
182
+ # We need to consider variable in the config with ~
183
+ expanded = os.path.expanduser(os.path.join(*path))
184
+
185
+ # join will not join if expanded is absolute
186
+ return os.path.join(self._root, expanded)
187
+
188
+ # Home for scipion
189
+ _get = __get.__func__
190
+ SCIPION_HOME = os.path.abspath(_get(SCIPION_HOME_VAR, '',
191
+ "Path where Scipion is installed. Other paths are based on this like SCIPION_SOFTWARE, SCIPION_TESTS,... unless specified"))
192
+
193
+ # False if SCIPION_HOME is not found in the environment. To distinguish API documentation generation execution.
194
+ SCIPION_HOME_DEFINED = SCIPION_HOME != ''
195
+
196
+ _root = Root(str(SCIPION_HOME))
197
+ _join = _root.join
198
+
199
+ # Internal cached variables, use __ so they are not returned in getVars
200
+ __activeColor = None
201
+
202
+ CONDA_ACTIVATION_CMD = _get(CONDA_ACTIVATION_CMD_VAR,'',
203
+ "str: Command to activate/initialize conda itself. Do not confuse it with 'conda activate'. It should be defined at installation time. It looks like this: eval \"$(/extra/miniconda3/bin/conda shell.bash hook)\"")
204
+
205
+ # SCIPION PATHS
206
+ SCIPION_SOFTWARE = _get('SCIPION_SOFTWARE', _join('software'),
207
+ "Path where Scipion will install the software. Defaults to SCIPION_HOME/software.", var_type=VarTypes.FOLDER)
208
+
209
+ SCIPION_TESTS = _get('SCIPION_TESTS', _join('data', 'tests'),
210
+ "Path where to find/download test data. Defaults to SCIPION_HOME/data/tests.", var_type=VarTypes.FOLDER)
211
+
212
+ # User dependent paths
213
+ SCIPION_USER_DATA = _get('SCIPION_USER_DATA', '~/ScipionUserData',
214
+ "Path where Scipion projects are or will be created. Defaults to ~/ScipionUserData", var_type=VarTypes.FOLDER)
215
+
216
+ # LOGGING variables
217
+ SCIPION_LOGS = _get('SCIPION_LOGS', _join(SCIPION_USER_DATA, 'logs'),
218
+ "Folder for Scipion logs used by the GUI. Defaults to SCIPION_USER_DATA/logs.", var_type=VarTypes.FOLDER)
219
+
220
+ SCIPION_LOG_CONFIG = _get('SCIPION_LOG_CONFIG', None,
221
+ "Optional. Path to a python logging configuration file to fine tune the logging.", var_type=VarTypes.PATH)
222
+
223
+ SCIPION_LOG = _get('SCIPION_LOG', _join(SCIPION_LOGS, 'scipion.log'),
224
+ "Path to the file where scipion will write GUI logging messages. Defaults to SCIPION_LOGS/scipion.log", var_type=VarTypes.PATH)
225
+
226
+ SCIPION_LOG_FORMAT = _get('SCIPION_LOG_FORMAT', "%(message)s",
227
+ "str: Format for all the log lines, defaults to %(message)s. To compose the format see https://docs.python.org/3/library/logging.html#logrecord-attributes")
228
+
229
+ SCIPION_LOG_LEVEL = _get(SCIPION_LOG_LEVEL, 'INFO',
230
+ "Default logging level. String among CRITICAL, ERROR, WARNING, INFO, DEBUG, NOTSET. Default value is INFO.")
231
+
232
+ NO_COLOR = _get('NO_COLOR', '',
233
+ "str: Comply with https://no-color.org/ initiative. Set it to something different than '' to deactivate colors in the output.")
234
+
235
+ SCIPION_SCRATCH = _get(SCIPION_SCRATCH, None,
236
+ "Optional. Path to a location mounted in a scratch drive (SSD,...)")
237
+
238
+ SCIPION_TESTS_OUTPUT = _get('SCIPION_TESTS_OUTPUT', _join(SCIPION_USER_DATA, 'Tests'),
239
+ "Path to a folder where the output of the tests will be written. Defaults to SCIPION_USER_DATA/Tests.", var_type=VarTypes.FOLDER)
240
+
241
+ SCIPION_TEST_NOSYNC = _get('SCIPION_TEST_NOSYNC', FALSE_STR,
242
+ "Set it to 1, True, Yes or y to cancel test dataset synchronization. Needed when updating files in a dataset.") != FALSE_STR
243
+
244
+ SCIPION_SUPPORT_EMAIL = 'scipion@cnb.csic.es'
245
+
246
+ # Config variables
247
+ SCIPION_CONFIG = _get('SCIPION_CONFIG', _join('config','scipion.conf'),
248
+ "Path to the scipion configuration file where all this variables could be defined.", var_type=VarTypes.PATH)
249
+
250
+ SCIPION_LOCAL_CONFIG = _get('SCIPION_LOCAL_CONFIG', SCIPION_CONFIG,
251
+ "Path to an optional/extra/user configuration file meant to overwrite default variables.", var_type=VarTypes.PATH)
252
+
253
+ SCIPION_HOSTS = _get('SCIPION_HOSTS', _join('config','hosts.conf'),
254
+ "Path to the host.cof file to allow scipion to use queue engines and run in HPC environments.")
255
+
256
+ SCIPION_PROTOCOLS = _get('SCIPION_PROTOCOLS', _join('config','protocols.conf'),
257
+ "Custom conf file to extend the protocols tree view panel (panel on the left)")
258
+
259
+ SCIPION_PLUGIN_JSON = _get('SCIPION_PLUGIN_JSON', None,
260
+ "Optional. Path to get the json file with all the plugins available for Scipion.")
261
+
262
+ SCIPION_PLUGIN_REPO_URL = _get('SCIPION_PLUGIN_REPO_URL',
263
+ 'https://scipion.i2pc.es/getplugins/',
264
+ "Url from where to get the list of plugins.")
265
+
266
+ # REMOTE Section
267
+ SCIPION_URL = 'https://scipion.cnb.csic.es/downloads/scipion'
268
+ SCIPION_URL_SOFTWARE = SCIPION_URL + '/software'
269
+ SCIPION_URL_TESTDATA = SCIPION_URL + '/data/tests'
270
+
271
+ # Scipion Notes
272
+ SCIPION_NOTES_FILE = _get(SCIPION_NOTES_FILE, 'notes.txt',
273
+ "Name of the file where to write per project notes.")
274
+
275
+ SCIPION_NOTES_PROGRAM = _get(SCIPION_NOTES_PROGRAM, None,
276
+ "Command or program to use to open the notes file. Otherwise system will extension association will take place.")
277
+
278
+ SCIPION_NOTES_ARGS = _get(SCIPION_NOTES_ARGS, None)
279
+
280
+ # External text editor:
281
+ SCIPION_TEXT_EDITOR = _get(SCIPION_TEXT_EDITOR, '',
282
+ "Preferred text editor executable.", caster=str)
283
+
284
+ # Aspect
285
+ SCIPION_FONT_NAME = _get('SCIPION_FONT_NAME', "Helvetica",
286
+ "Name of the font to use in Scipion GUI. Defaults to Helvetica.")
287
+
288
+ SCIPION_FONT_SIZE = _get('SCIPION_FONT_SIZE', SCIPION_DEFAULT_FONT_SIZE,
289
+ "Size of the 'normal' font to be used in Scipion GUI. Defaults to 10.", caster=int)
290
+
291
+ SCIPION_MAIN_COLOR = _get('SCIPION_MAIN_COLOR', Color.MAIN_COLOR,
292
+ "str: Main color of the GUI. Background will be white, so for better contrast choose a dark color. Probably any name here will work: https://matplotlib.org/stable/gallery/color/named_colors.html",
293
+ caster=validColor)
294
+
295
+ SCIPION_BG_COLOR = _get('SCIPION_BG_COLOR', Color.BG_COLOR,
296
+ "str: Main background color of the GUI. Default is white, chose a light one. Probably any name here will work: https://matplotlib.org/stable/gallery/color/named_colors.html",
297
+ validColor)
298
+
299
+ SCIPION_CONTRAST_COLOR = _get('SCIPION_CONTRAST_COLOR', 'cyan',
300
+ "Color used to highlight features over grayscaled images.", caster=validColor)
301
+
302
+ SCIPION_SPRITES_FILE = _get('SCIPION_SPRITES_FILE', _join(getResourcesPath(),'sprites.png'),
303
+ "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.")
304
+
305
+ SCIPION_SHOW_TEXT_IN_TOOLBAR = _get('SCIPION_SHOW_TEXT_IN_TOOLBAR', TRUE_STR,
306
+ "Define it to anything else except False to show the label of the icons. It will take more space.") == TRUE_STR
307
+
308
+ SCIPION_ICON_ZOOM = _get('SCIPION_ICON_ZOOM', 50,
309
+ "Define it to anything else except False to show the label of the icons. It will take more space.", var_type=VarTypes.INTEGER, caster=int)
310
+
311
+ # Notification
312
+ SCIPION_NOTIFY = _get('SCIPION_NOTIFY', TRUE_STR,
313
+ "If set to False, Scipion developers will know almost nothing about Scipion usage and will have less information to improve it.") == TRUE_STR
314
+
315
+ # *** Execution variables ***
316
+ SCIPION_CWD = _get('SCIPION_CWD', os.path.abspath(os.getcwd()),
317
+ "Directory when scipion was launched")
318
+
319
+ SCIPION_GUI_REFRESH_IN_THREAD = _get('SCIPION_GUI_REFRESH_IN_THREAD', FALSE_STR,
320
+ "True to refresh the runs graph with a thread. Unstable.") != FALSE_STR
321
+
322
+ SCIPION_GUI_REFRESH_INITIAL_WAIT = _get("SCIPION_GUI_REFRESH_INITIAL_WAIT", 5,
323
+ "Seconds to wait after a manual refresh", caster=int)
324
+
325
+ SCIPION_GUI_CANCEL_AUTO_REFRESH = _get("SCIPION_GUI_CANCEL_AUTO_REFRESH",FALSE_STR,
326
+ "Set it to True to cancel automatic refresh of the runs.") != FALSE_STR
327
+
328
+ # Cancel shutil fast copy. In GPFS, shutil.copy does fail when trying a fastcopy and does not
329
+ # fall back on the slow copy. For legacy reasons None is also False.
330
+ SCIPION_CANCEL_FASTCOPY = _get('SCIPION_CANCEL_FASTCOPY', FALSE_STR,
331
+ "Cancel fast copy done by shutil (copying files) when it fails. Has happened in GPFS environments. Defaults to False. None is also False otherwise fastcopy is cancelled."
332
+ ) not in [NONE_STR, FALSE_STR]
333
+
334
+ # Priority package list: This variable is used in the view protocols in
335
+ # order to load first the plugins that contains the main protocols.conf
336
+ # sections, so other plugins can define only their sections avoiding
337
+ # duplicating all the sections in all plugins. Scipion app is currently defining it for em tomo and chem
338
+ SCIPION_PRIORITY_PACKAGE_LIST = _get('SCIPION_PRIORITY_PACKAGE_LIST', EMPTY_STR)
339
+
340
+ SCIPION_STEPS_CHECK_SEC = _get('SCIPION_STEPS_CHECK_SEC', 5,
341
+ "Number of seconds to wait before checking if new input is available in streamified protocols.", caster=int)
342
+
343
+ SCIPION_UPDATE_SET_ATTEMPTS = _get('SCIPION_UPDATE_SET_ATTEMPTS', 3,
344
+ "Number of attempts to modify the protocol output before failing. The default value is 3", caster=int)
345
+
346
+ SCIPION_UPDATE_SET_ATTEMPT_WAIT = _get('SCIPION_UPDATE_SET_ATTEMPT_WAIT', 2,
347
+ "Time in seconds to wait until the next attempt when checking new outputs. The default value is 2 seconds", caster=int)
348
+
349
+ SCIPION_USE_QUEUE = _get("SCIPION_USE_QUEUE", FALSE_STR,
350
+ "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.")!= FALSE_STR
351
+
352
+ SCIPION_DEFAULT_EXECUTION_ACTION = _get('SCIPION_DEFAULT_EXECUTION_ACTION', DEFAULT_EXECUTION_ACTION_ASK,
353
+ """Ask if you want to launch a single protocol or a sub-workflow. The default value is 1
354
+ 1: Scipion always ask
355
+ 2: Run a single protocol
356
+ 3: Run a sub-workflow """, caster=int)
357
+
358
+ SCIPION_MAPPER_USE_TEMPLATE = _get('SCIPION_MAPPER_USE_TEMPLATE', TRUE_STR,
359
+ "Set it to False to force instantiation for each item during sets iterations. Experimental. This penalize the iteration but avoids"
360
+ "the use of .clone() ot the items.") == TRUE_STR
361
+
362
+ try:
363
+ VIEWERS = ast.literal_eval(_get('VIEWERS', "{}", "Json string to define which viewer are the default ones per output type."))
364
+ except Exception as e:
365
+ VIEWERS = {}
366
+ logger.error("ERROR loading preferred viewers, VIEWERS variable will be ignored", exc_info=e)
367
+
368
+ SCIPION_DOMAIN = _get(SCIPION_DOMAIN, None, "Domain base class. Ignore.")
369
+ SCIPION_TESTS_CMD = _get(SCIPION_TESTS_CMD, getTestsScript(), "Command to run tests")
370
+
371
+ # ---- Getters ---- #
372
+ # Getters are alternatives to offer a variable, but preventing it to be stored in the config
373
+ @classmethod
374
+ def getLibFolder(cls):
375
+ """
376
+ :return: Folder where libraries must be placed in case a binding needs them
377
+ """
378
+ lib = cls._join(cls.SCIPION_SOFTWARE, 'lib')
379
+ os.makedirs(lib, exist_ok=True)
380
+ return lib
381
+
382
+ @classmethod
383
+ def getBindingsFolder(cls):
384
+ """
385
+ Folder where bindings must be placed. This folder is added to sys.path at launching time.
386
+ If the binding depends on a dynamic libraries, those must be placed at cls.getLibFolder()
387
+ :return: The bindings folder
388
+ """
389
+ bindings = cls._join(cls.SCIPION_SOFTWARE, 'bindings')
390
+ os.makedirs(bindings, exist_ok=True)
391
+ return bindings
392
+
393
+ @classmethod
394
+ def getLogsFolder(cls):
395
+ """
396
+ Folder where scipion logs must be placed. The folder is created
397
+ """
398
+ logsFolder = cls.SCIPION_LOGS
399
+ os.makedirs(logsFolder, exist_ok=True)
400
+ return logsFolder
401
+
402
+ @classmethod
403
+ def getVars(cls):
404
+ """ Return a dictionary with all variables defined
405
+ in this Config.
406
+ """
407
+ configVars = dict()
408
+ # For each variable, also in base classes
409
+ for baseCls in inspect.getmro(cls):
410
+ for name, value in vars(baseCls).items():
411
+ # Skip methods and internal attributes starting with __
412
+ # (e.g __doc__, __module__, etc)
413
+ if isinstance(value, (str, int)) and not name.startswith('__'):
414
+ configVars[name] = str(value)
415
+ return configVars
416
+
417
+ @classmethod
418
+ def getDomain(cls):
419
+ """ Import domain module from path or name defined in SCIPION_DOMAIN.
420
+ """
421
+ value = cls.SCIPION_DOMAIN
422
+
423
+ if not value:
424
+ return None
425
+
426
+ if os.path.isdir(value):
427
+ dirname, value = os.path.split(value)
428
+ sys.path.append(dirname)
429
+
430
+ return importlib.import_module(value).Domain
431
+
432
+ @classmethod
433
+ def setDomain(cls, moduleOrNameOrPath):
434
+ if isinstance(moduleOrNameOrPath, types.ModuleType):
435
+ value = os.path.abspath(moduleOrNameOrPath.__path__[0])
436
+ else:
437
+ value = moduleOrNameOrPath
438
+ cls.SCIPION_DOMAIN = value
439
+ os.environ[SCIPION_DOMAIN] = value
440
+
441
+ @staticmethod
442
+ def getPythonLibFolder():
443
+ from sysconfig import get_paths
444
+ return os.path.join(get_paths()['data'], "lib")
445
+
446
+ @staticmethod
447
+ def debugOn():
448
+ """ Returns a True if debug mode (SCIPION_DEBUG variable) is active """
449
+ from .utils import envVarOn
450
+ return bool(envVarOn(SCIPION_DEBUG))
451
+
452
+ @staticmethod
453
+ def toggleDebug():
454
+ debugOn = not Config.debugOn()
455
+ os.environ[SCIPION_DEBUG] = str(debugOn)
456
+ os.environ[SCIPION_DEBUG_NOCLEAN] = str(debugOn)
457
+ os.environ[SCIPION_LOG_LEVEL] = "INFO" if not debugOn else "DEBUG"
458
+
459
+ @staticmethod
460
+ def debugSQLOn():
461
+ from .utils import envVarOn
462
+ return bool(envVarOn(SCIPION_DEBUG_SQLITE))
463
+
464
+ @staticmethod
465
+ def toggleDebugSQL():
466
+ newValue = not Config.debugSQLOn()
467
+ os.environ[SCIPION_DEBUG_SQLITE] = str(newValue)
468
+
469
+ @classmethod
470
+ def refreshInThreads(cls):
471
+ return cls.SCIPION_GUI_REFRESH_IN_THREAD
472
+
473
+ @classmethod
474
+ def getExternalJsonTemplates(cls):
475
+ return os.path.dirname(cls.SCIPION_CONFIG)
476
+
477
+ @classmethod
478
+ def getWizardMaskColor(cls):
479
+ """ Color is a name"""
480
+ from matplotlib.colors import to_rgb
481
+ return list(to_rgb(cls.SCIPION_CONTRAST_COLOR))
482
+
483
+ @classmethod
484
+ def getPriorityPackageList(cls):
485
+ if cls.SCIPION_PRIORITY_PACKAGE_LIST != EMPTY_STR:
486
+ return cls.SCIPION_PRIORITY_PACKAGE_LIST.split(" ")
487
+ else:
488
+ return []
489
+
490
+ @classmethod
491
+ def getStepsCheckSeconds(cls):
492
+ return cls.SCIPION_STEPS_CHECK_SEC
493
+
494
+ @classmethod
495
+ def getUpdateSetAttempts(cls):
496
+ return cls.SCIPION_UPDATE_SET_ATTEMPTS
497
+
498
+ @classmethod
499
+ def getUpdateSetAttemptsWait(cls):
500
+ return cls.SCIPION_UPDATE_SET_ATTEMPT_WAIT
501
+
502
+ @classmethod
503
+ def colorsInTerminal(cls):
504
+ """ Returns true if colors are allowed. Based on NO_COLOR variable. Undefined or '' colors are enabled"""
505
+ return cls.NO_COLOR == ''
506
+
507
+
508
+ @classmethod
509
+ def getActiveColor(cls):
510
+ """ Returns a color lighter than the SCIPION_MAIN_COLOR"""
511
+
512
+ if cls.__activeColor is None:
513
+ from pyworkflow.utils import lighter, rgb_to_hex
514
+ from matplotlib.colors import to_rgb
515
+ rgb_main = to_rgb(cls.SCIPION_MAIN_COLOR)
516
+ rgb_main = (rgb_main[0] * 255, rgb_main[1] * 255, rgb_main[2] * 255)
517
+ rgb_active = lighter(rgb_main, 0.3)
518
+ cls.__activeColor = rgb_to_hex(rgb_active)
519
+
520
+ return cls.__activeColor
521
+
522
+ @classmethod
523
+ def isScipionRunning(cls):
524
+ """ Returns true if this execution is understood to be running Scipion.
525
+ In some case, documentation inspection by sphynx or when packaging a plugin using setup.py
526
+ this code could be reached but is not an actual execution. This is useful for cancelling some actions
527
+ like registering FileHandlers or other stuff not needed when just importing modules."""
528
+ return cls.SCIPION_HOME_DEFINED != False
529
+
530
+
531
+ # Add bindings folder to sys.path
532
+ sys.path.append(Config.getBindingsFolder())
533
+
534
+ # Cancel fast copy
535
+ if Config.SCIPION_CANCEL_FASTCOPY:
536
+ shutil._USE_CP_SENDFILE = False