scipion-pyworkflow 3.10.6__py3-none-any.whl → 3.11.1__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/config.py +131 -67
- pyworkflow/constants.py +2 -1
- pyworkflow/gui/browser.py +39 -5
- pyworkflow/gui/dialog.py +2 -0
- pyworkflow/gui/form.py +141 -52
- pyworkflow/gui/gui.py +8 -8
- pyworkflow/gui/project/project.py +6 -7
- pyworkflow/gui/project/searchprotocol.py +91 -7
- pyworkflow/gui/project/viewdata.py +1 -1
- pyworkflow/gui/project/viewprotocols.py +45 -22
- pyworkflow/gui/project/viewprotocols_extra.py +9 -6
- pyworkflow/gui/widgets.py +2 -2
- pyworkflow/mapper/sqlite.py +4 -4
- pyworkflow/plugin.py +93 -44
- pyworkflow/project/project.py +158 -70
- pyworkflow/project/usage.py +165 -0
- pyworkflow/protocol/executor.py +30 -18
- pyworkflow/protocol/hosts.py +9 -6
- pyworkflow/protocol/launch.py +15 -8
- pyworkflow/protocol/params.py +59 -19
- pyworkflow/protocol/protocol.py +124 -58
- pyworkflow/resources/showj/arrowDown.png +0 -0
- pyworkflow/resources/showj/arrowUp.png +0 -0
- pyworkflow/resources/showj/background_section.png +0 -0
- pyworkflow/resources/showj/colRowModeOff.png +0 -0
- pyworkflow/resources/showj/colRowModeOn.png +0 -0
- pyworkflow/resources/showj/delete.png +0 -0
- pyworkflow/resources/showj/doc_icon.png +0 -0
- pyworkflow/resources/showj/download_icon.png +0 -0
- pyworkflow/resources/showj/enabled_gallery.png +0 -0
- pyworkflow/resources/showj/galleryViewOff.png +0 -0
- pyworkflow/resources/showj/galleryViewOn.png +0 -0
- pyworkflow/resources/showj/goto.png +0 -0
- pyworkflow/resources/showj/menu.png +0 -0
- pyworkflow/resources/showj/separator.png +0 -0
- pyworkflow/resources/showj/tableViewOff.png +0 -0
- pyworkflow/resources/showj/tableViewOn.png +0 -0
- pyworkflow/resources/showj/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
- pyworkflow/resources/showj/ui-bg_glass_95_fef1ec_1x400.png +0 -0
- pyworkflow/resources/showj/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
- pyworkflow/resources/showj/volumeOff.png +0 -0
- pyworkflow/resources/showj/volumeOn.png +0 -0
- pyworkflow/utils/log.py +15 -6
- pyworkflow/utils/properties.py +78 -92
- pyworkflow/utils/utils.py +3 -2
- pyworkflow/viewer.py +23 -1
- pyworkflow/webservices/config.py +0 -3
- pyworkflow/webservices/notifier.py +24 -34
- pyworkflowtests/protocols.py +1 -3
- pyworkflowtests/tests/test_protocol_execution.py +4 -0
- {scipion_pyworkflow-3.10.6.dist-info → scipion_pyworkflow-3.11.1.dist-info}/METADATA +13 -27
- {scipion_pyworkflow-3.10.6.dist-info → scipion_pyworkflow-3.11.1.dist-info}/RECORD +56 -35
- {scipion_pyworkflow-3.10.6.dist-info → scipion_pyworkflow-3.11.1.dist-info}/WHEEL +1 -1
- scipion_pyworkflow-3.10.6.dist-info/dependency_links.txt +0 -1
- {scipion_pyworkflow-3.10.6.dist-info → scipion_pyworkflow-3.11.1.dist-info}/entry_points.txt +0 -0
- {scipion_pyworkflow-3.10.6.dist-info → scipion_pyworkflow-3.11.1.dist-info}/licenses/LICENSE.txt +0 -0
- {scipion_pyworkflow-3.10.6.dist-info → scipion_pyworkflow-3.11.1.dist-info}/top_level.txt +0 -0
pyworkflow/config.py
CHANGED
@@ -97,12 +97,15 @@ class Variable:
|
|
97
97
|
self.value = new_value
|
98
98
|
self.isDefault= self._isValueDefault()
|
99
99
|
def _isValueDefault(self):
|
100
|
-
return self.value==self.default
|
100
|
+
return self.value == self.default
|
101
|
+
|
102
|
+
|
101
103
|
class VariablesRegistry:
|
102
|
-
_variables={}
|
104
|
+
_variables = {}
|
103
105
|
|
104
106
|
def __init__(self):
|
105
107
|
raise RuntimeError("Variables class doesn't need to be instantiated.")
|
108
|
+
|
106
109
|
@classmethod
|
107
110
|
def register(cls, variable: Variable):
|
108
111
|
cls._variables[variable.name] = variable
|
@@ -146,7 +149,7 @@ class Config:
|
|
146
149
|
|
147
150
|
if key in os.environ:
|
148
151
|
value = os.environ.get(key)
|
149
|
-
isDefault = (value==default)
|
152
|
+
isDefault = (value == default)
|
150
153
|
else:
|
151
154
|
isDefault = True
|
152
155
|
value = default
|
@@ -154,10 +157,10 @@ class Config:
|
|
154
157
|
# If the caster is passed do the casting, if fails go back to default
|
155
158
|
if caster:
|
156
159
|
try:
|
157
|
-
value=caster(value)
|
160
|
+
value = caster(value)
|
158
161
|
except:
|
159
162
|
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))
|
163
|
+
(key, value, caster, default))
|
161
164
|
value = default
|
162
165
|
# If empty use default value
|
163
166
|
if value == "" != default:
|
@@ -168,10 +171,23 @@ class Config:
|
|
168
171
|
if isinstance(value, str):
|
169
172
|
value = os.path.expandvars(os.path.expanduser(value))
|
170
173
|
|
171
|
-
# Register the variable
|
174
|
+
# Register the variable. Boolean variables are converted to booleans after this call. May not be accurate.
|
175
|
+
# 1 turns into False in the Config
|
172
176
|
VariablesRegistry.register(Variable(key,description, source, value, default, var_type=var_type, isDefault=isDefault))
|
173
177
|
return value
|
174
178
|
|
179
|
+
@staticmethod
|
180
|
+
def __notFalse(value):
|
181
|
+
return value != FALSE_STR
|
182
|
+
|
183
|
+
@staticmethod
|
184
|
+
def __notTrue(value):
|
185
|
+
return value != TRUE_STR
|
186
|
+
|
187
|
+
@staticmethod
|
188
|
+
def __bool(value):
|
189
|
+
return value.lower() in TRUE_YES_ON_
|
190
|
+
|
175
191
|
class Root:
|
176
192
|
""" Simple helper to return path from a root. """
|
177
193
|
|
@@ -185,13 +201,17 @@ class Config:
|
|
185
201
|
# join will not join if expanded is absolute
|
186
202
|
return os.path.join(self._root, expanded)
|
187
203
|
|
188
|
-
# Home for scipion
|
189
204
|
_get = __get.__func__
|
190
|
-
|
191
|
-
|
205
|
+
_notFalse = __notFalse.__func__
|
206
|
+
__bool = __bool.__func__
|
207
|
+
|
208
|
+
# Home for scipion
|
209
|
+
_home_var = _get(SCIPION_HOME_VAR, '',
|
210
|
+
"Path where Scipion is installed. Other paths are based on this like SCIPION_SOFTWARE, SCIPION_TESTS,... unless specified")
|
211
|
+
SCIPION_HOME = os.path.abspath(_home_var)
|
192
212
|
|
193
213
|
# False if SCIPION_HOME is not found in the environment. To distinguish API documentation generation execution.
|
194
|
-
SCIPION_HOME_DEFINED =
|
214
|
+
SCIPION_HOME_DEFINED = _home_var != ''
|
195
215
|
|
196
216
|
_root = Root(str(SCIPION_HOME))
|
197
217
|
_join = _root.join
|
@@ -201,68 +221,75 @@ class Config:
|
|
201
221
|
__defaultSpritesFile = _join(getResourcesPath(),'sprites.png')
|
202
222
|
|
203
223
|
CONDA_ACTIVATION_CMD = _get(CONDA_ACTIVATION_CMD_VAR,'',
|
204
|
-
|
224
|
+
"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)\"")
|
205
225
|
|
206
226
|
# SCIPION PATHS
|
207
227
|
SCIPION_SOFTWARE = _get('SCIPION_SOFTWARE', _join('software'),
|
208
|
-
|
228
|
+
"Path where Scipion will install the software. Defaults to SCIPION_HOME/software.", var_type=VarTypes.FOLDER)
|
209
229
|
|
210
230
|
SCIPION_TESTS = _get('SCIPION_TESTS', _join('data', 'tests'),
|
211
|
-
|
231
|
+
"Path where to find/download test data. Defaults to SCIPION_HOME/data/tests.", var_type=VarTypes.FOLDER)
|
212
232
|
|
213
233
|
# User dependent paths
|
214
234
|
SCIPION_USER_DATA = _get('SCIPION_USER_DATA', '~/ScipionUserData',
|
215
|
-
|
235
|
+
"Path where Scipion projects are or will be created. Defaults to ~/ScipionUserData", var_type=VarTypes.FOLDER)
|
216
236
|
|
217
237
|
# LOGGING variables
|
218
238
|
SCIPION_LOGS = _get('SCIPION_LOGS', _join(SCIPION_USER_DATA, 'logs'),
|
219
|
-
|
239
|
+
"Folder for Scipion logs used by the GUI. Defaults to SCIPION_USER_DATA/logs.", var_type=VarTypes.FOLDER)
|
220
240
|
|
221
241
|
SCIPION_LOG_CONFIG = _get('SCIPION_LOG_CONFIG', None,
|
222
|
-
|
242
|
+
"Optional. Path to a python logging configuration file to fine tune the logging.", var_type=VarTypes.PATH)
|
223
243
|
|
224
244
|
SCIPION_LOG = _get('SCIPION_LOG', _join(SCIPION_LOGS, 'scipion.log'),
|
225
|
-
|
245
|
+
"Path to the file where scipion will write GUI logging messages. Defaults to SCIPION_LOGS/scipion.log", var_type=VarTypes.PATH)
|
226
246
|
|
227
247
|
SCIPION_LOG_FORMAT = _get('SCIPION_LOG_FORMAT', "%(message)s",
|
228
|
-
|
248
|
+
"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")
|
229
249
|
|
230
250
|
SCIPION_LOG_LEVEL = _get(SCIPION_LOG_LEVEL, 'INFO',
|
231
|
-
|
251
|
+
"Default logging level. String among CRITICAL, ERROR, WARNING, INFO, DEBUG, NOTSET. Default value is INFO.")
|
232
252
|
|
233
253
|
NO_COLOR = _get('NO_COLOR', '',
|
234
|
-
|
254
|
+
"str: Comply with https://no-color.org/ initiative. Set it to something different than '' to deactivate colors in the output.")
|
235
255
|
|
236
256
|
SCIPION_SCRATCH = _get(SCIPION_SCRATCH, None,
|
237
|
-
|
257
|
+
"Optional. Path to a location mounted in a scratch drive (SSD,...)")
|
238
258
|
|
239
259
|
SCIPION_TESTS_OUTPUT = _get('SCIPION_TESTS_OUTPUT', _join(SCIPION_USER_DATA, 'Tests'),
|
240
|
-
|
260
|
+
"Path to a folder where the output of the tests will be written. Defaults to SCIPION_USER_DATA/Tests.", var_type=VarTypes.FOLDER)
|
241
261
|
|
242
262
|
SCIPION_TEST_NOSYNC = _get('SCIPION_TEST_NOSYNC', FALSE_STR,
|
243
|
-
|
263
|
+
"Set it to any value except False to cancel test dataset synchronization."
|
264
|
+
" Needed when updating files in a dataset.", caster=_notFalse)
|
244
265
|
|
245
266
|
SCIPION_SUPPORT_EMAIL = 'scipion@cnb.csic.es'
|
246
267
|
|
247
268
|
# Config variables
|
248
269
|
SCIPION_CONFIG = _get('SCIPION_CONFIG', _join('config','scipion.conf'),
|
249
|
-
|
270
|
+
"Path to the scipion configuration file where all this variables could be defined.", var_type=VarTypes.PATH)
|
250
271
|
|
251
272
|
SCIPION_LOCAL_CONFIG = _get('SCIPION_LOCAL_CONFIG', SCIPION_CONFIG,
|
252
|
-
|
273
|
+
"Path to an optional/extra/user configuration file meant to overwrite default variables.", var_type=VarTypes.PATH)
|
253
274
|
|
254
275
|
SCIPION_HOSTS = _get('SCIPION_HOSTS', _join('config','hosts.conf'),
|
255
|
-
|
276
|
+
"Path to the host.cof file to allow scipion to use queue engines and run in HPC environments.")
|
256
277
|
|
257
278
|
SCIPION_PROTOCOLS = _get('SCIPION_PROTOCOLS', _join('config','protocols.conf'),
|
258
|
-
|
279
|
+
"Custom conf file to extend the protocols tree view panel (panel on the left)")
|
259
280
|
|
260
281
|
SCIPION_PLUGIN_JSON = _get('SCIPION_PLUGIN_JSON', None,
|
261
|
-
|
282
|
+
"Optional. Path to get the json file with all the plugins available for Scipion.")
|
283
|
+
|
284
|
+
SCIPION_SITE = _get('SCIPION_SITE', 'https://scipion.i2pc.es',
|
285
|
+
"Scipion site URL.")
|
286
|
+
SCIPION_SITE_API = SCIPION_SITE + '/report_protocols/api/v2'
|
287
|
+
SCIPION_STATS_WORKFLOW_APP = SCIPION_SITE_API + '/workflow/'
|
288
|
+
SCIPION_STATS_SUGGESTION = SCIPION_SITE_API + '/nextprotocol/suggestion/%s'
|
262
289
|
|
263
290
|
SCIPION_PLUGIN_REPO_URL = _get('SCIPION_PLUGIN_REPO_URL',
|
264
|
-
'
|
265
|
-
|
291
|
+
SCIPION_SITE + '/getplugins/',
|
292
|
+
"Url from where to get the list of plugins.")
|
266
293
|
|
267
294
|
# REMOTE Section
|
268
295
|
SCIPION_URL = 'https://scipion.cnb.csic.es/downloads/scipion'
|
@@ -271,65 +298,69 @@ class Config:
|
|
271
298
|
|
272
299
|
# Scipion Notes
|
273
300
|
SCIPION_NOTES_FILE = _get(SCIPION_NOTES_FILE, 'notes.txt',
|
274
|
-
|
301
|
+
"Name of the file where to write per project notes.")
|
275
302
|
|
276
303
|
SCIPION_NOTES_PROGRAM = _get(SCIPION_NOTES_PROGRAM, None,
|
277
|
-
|
304
|
+
"Command or program to use to open the notes file. Otherwise system will extension association will take place.")
|
278
305
|
|
279
306
|
SCIPION_NOTES_ARGS = _get(SCIPION_NOTES_ARGS, None)
|
280
307
|
|
281
308
|
# External text editor:
|
282
309
|
SCIPION_TEXT_EDITOR = _get(SCIPION_TEXT_EDITOR, '',
|
283
|
-
|
310
|
+
"Preferred text editor executable.", caster=str)
|
284
311
|
|
285
312
|
# Aspect
|
286
313
|
SCIPION_FONT_NAME = _get('SCIPION_FONT_NAME', "Helvetica",
|
287
|
-
|
314
|
+
"Name of the font to use in Scipion GUI. Defaults to Helvetica.")
|
288
315
|
|
289
|
-
SCIPION_FONT_SIZE = _get('SCIPION_FONT_SIZE', SCIPION_DEFAULT_FONT_SIZE,
|
290
|
-
|
316
|
+
SCIPION_FONT_SIZE = _get('SCIPION_FONT_SIZE', str(SCIPION_DEFAULT_FONT_SIZE),
|
317
|
+
"Size of the 'normal' font to be used in Scipion GUI. "
|
318
|
+
"Defaults to 10.", caster=int)
|
291
319
|
|
292
320
|
SCIPION_MAIN_COLOR = _get('SCIPION_MAIN_COLOR', Color.MAIN_COLOR,
|
293
|
-
|
321
|
+
"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",
|
294
322
|
caster=validColor)
|
295
323
|
|
296
324
|
SCIPION_BG_COLOR = _get('SCIPION_BG_COLOR', Color.BG_COLOR,
|
297
|
-
|
325
|
+
"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",
|
298
326
|
validColor)
|
299
327
|
|
300
|
-
SCIPION_CONTRAST_COLOR = _get('SCIPION_CONTRAST_COLOR', 'cyan',
|
301
|
-
|
328
|
+
SCIPION_CONTRAST_COLOR = _get('SCIPION_CONTRAST_COLOR', 'cyan', "Color used to highlight features over "
|
329
|
+
"gray-scaled images.", caster=validColor)
|
302
330
|
|
303
331
|
SCIPION_SPRITES_FILE = _get('SCIPION_SPRITES_FILE', __defaultSpritesFile,
|
304
|
-
|
332
|
+
"File (png) with the icons in a collage. Default is found at "
|
333
|
+
"pyworkflow/resources/sprites.png. And a GIMP file could be found at the same "
|
334
|
+
"folder in the github repo.")
|
305
335
|
|
306
|
-
SCIPION_SHOW_TEXT_IN_TOOLBAR = _get('SCIPION_SHOW_TEXT_IN_TOOLBAR', TRUE_STR,
|
307
|
-
|
336
|
+
SCIPION_SHOW_TEXT_IN_TOOLBAR = _get('SCIPION_SHOW_TEXT_IN_TOOLBAR', TRUE_STR, "Define it to anything else except "
|
337
|
+
"%s to hide labels. It will take less space." % TRUE_YES_ON_, caster=__bool)
|
308
338
|
|
309
|
-
SCIPION_ICON_ZOOM = _get('SCIPION_ICON_ZOOM', 50,
|
310
|
-
|
339
|
+
SCIPION_ICON_ZOOM = _get('SCIPION_ICON_ZOOM', "50",
|
340
|
+
"Define it to any integer value(percentage) to increase/decrease the size of the icons.",
|
341
|
+
var_type=VarTypes.INTEGER, caster=int)
|
311
342
|
|
312
343
|
# Notification
|
313
|
-
SCIPION_NOTIFY = _get('SCIPION_NOTIFY', TRUE_STR,
|
314
|
-
|
344
|
+
SCIPION_NOTIFY = _get('SCIPION_NOTIFY', TRUE_STR, "If set to anything except %s Scipion developers will know "
|
345
|
+
"nothing abut Scipion usage and will have less information to improve it." % TRUE_YES_ON_,
|
346
|
+
caster=__bool)
|
315
347
|
|
316
348
|
# *** Execution variables ***
|
317
|
-
SCIPION_CWD = _get('SCIPION_CWD', os.path.abspath(os.getcwd()),
|
318
|
-
"Directory when scipion was launched")
|
349
|
+
SCIPION_CWD = _get('SCIPION_CWD', os.path.abspath(os.getcwd()), "Directory when scipion was launched")
|
319
350
|
|
320
351
|
SCIPION_GUI_REFRESH_IN_THREAD = _get('SCIPION_GUI_REFRESH_IN_THREAD', FALSE_STR,
|
321
|
-
|
352
|
+
"True to refresh the runs graph with a thread. Unstable.") != FALSE_STR
|
322
353
|
|
323
354
|
SCIPION_GUI_REFRESH_INITIAL_WAIT = _get("SCIPION_GUI_REFRESH_INITIAL_WAIT", 5,
|
324
|
-
|
355
|
+
"Seconds to wait after a manual refresh", caster=int)
|
325
356
|
|
326
357
|
SCIPION_GUI_CANCEL_AUTO_REFRESH = _get("SCIPION_GUI_CANCEL_AUTO_REFRESH",FALSE_STR,
|
327
|
-
|
358
|
+
"Set it to True to cancel automatic refresh of the runs.") != FALSE_STR
|
328
359
|
|
329
360
|
# Cancel shutil fast copy. In GPFS, shutil.copy does fail when trying a fastcopy and does not
|
330
361
|
# fall back on the slow copy. For legacy reasons None is also False.
|
331
362
|
SCIPION_CANCEL_FASTCOPY = _get('SCIPION_CANCEL_FASTCOPY', FALSE_STR,
|
332
|
-
|
363
|
+
"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."
|
333
364
|
) not in [NONE_STR, FALSE_STR]
|
334
365
|
|
335
366
|
# Priority package list: This variable is used in the view protocols in
|
@@ -339,26 +370,40 @@ class Config:
|
|
339
370
|
SCIPION_PRIORITY_PACKAGE_LIST = _get('SCIPION_PRIORITY_PACKAGE_LIST', EMPTY_STR)
|
340
371
|
|
341
372
|
SCIPION_STEPS_CHECK_SEC = _get('SCIPION_STEPS_CHECK_SEC', 5,
|
342
|
-
|
373
|
+
"Number of seconds to wait before checking if new input is available in "
|
374
|
+
"streamified protocols.", caster=int)
|
343
375
|
|
344
376
|
SCIPION_UPDATE_SET_ATTEMPTS = _get('SCIPION_UPDATE_SET_ATTEMPTS', 3,
|
345
|
-
|
377
|
+
"Number of attempts to modify the protocol output before failing. "
|
378
|
+
"The default value is 3", caster=int)
|
346
379
|
|
347
380
|
SCIPION_UPDATE_SET_ATTEMPT_WAIT = _get('SCIPION_UPDATE_SET_ATTEMPT_WAIT', 2,
|
348
|
-
|
381
|
+
"Time in seconds to wait until the next attempt when checking new outputs. "
|
382
|
+
"The default value is 2 seconds", caster=int)
|
383
|
+
|
384
|
+
SCIPION_UNLOAD_FORM_ON_SAVE = _get('SCIPION_UNLOAD_FORM_ON_SAVE', TRUE_STR,
|
385
|
+
"When a protocol is saved it is unloaded if all goes fine. Set it to false "
|
386
|
+
"otherwise to rescue old behaviour.", caster=__bool)
|
349
387
|
|
350
388
|
SCIPION_USE_QUEUE = _get("SCIPION_USE_QUEUE", FALSE_STR,
|
351
|
-
|
389
|
+
"Default value for using the queue. By default is False. "
|
390
|
+
"ANY value will be True except and empty value. \"False\" or \"0\" "
|
391
|
+
"will be True too.") != FALSE_STR
|
352
392
|
|
353
393
|
SCIPION_DEFAULT_EXECUTION_ACTION = _get('SCIPION_DEFAULT_EXECUTION_ACTION', DEFAULT_EXECUTION_ACTION_ASK,
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
394
|
+
"""Ask if you want to launch a single protocol or a sub-workflow. The default value is 1
|
395
|
+
1: Scipion always ask
|
396
|
+
2: Run a single protocol
|
397
|
+
3: Run a sub-workflow """, caster=int)
|
358
398
|
|
359
399
|
SCIPION_MAPPER_USE_TEMPLATE = _get('SCIPION_MAPPER_USE_TEMPLATE', TRUE_STR,
|
360
|
-
|
361
|
-
|
400
|
+
"Set it to False to force instantiation for each item during sets iterations. Experimental. This penalize the iteration but avoids"
|
401
|
+
"the use of .clone() ot the items.") == TRUE_STR
|
402
|
+
|
403
|
+
CUDA_DEVICE_ORDER = _get('CUDA_DEVICE_ORDER', 'PCI_BUS_ID',
|
404
|
+
"To make GPU ID match what you see in nvidia-smi, that is the PCI ID."
|
405
|
+
" Use FASTEST_FIRST for default behaviour but this may not match what is returned by nvidia-smi."
|
406
|
+
" See https://docs.nvidia.com/cuda/cuda-c-programming-guide/#:~:text=in%20device%20memory.-,CUDA_DEVICE_ORDER,-FASTEST_FIRST%2C%20PCI_BUS_ID%2C%20(default ")
|
362
407
|
|
363
408
|
try:
|
364
409
|
VIEWERS = ast.literal_eval(_get('VIEWERS', "{}", "Json string to define which viewer are the default ones per output type."))
|
@@ -377,7 +422,8 @@ class Config:
|
|
377
422
|
:return: Folder where libraries must be placed in case a binding needs them
|
378
423
|
"""
|
379
424
|
lib = cls._join(cls.SCIPION_SOFTWARE, 'lib')
|
380
|
-
|
425
|
+
if cls.SCIPION_HOME_DEFINED:
|
426
|
+
os.makedirs(lib, exist_ok=True)
|
381
427
|
return lib
|
382
428
|
|
383
429
|
@classmethod
|
@@ -388,7 +434,8 @@ class Config:
|
|
388
434
|
:return: The bindings folder
|
389
435
|
"""
|
390
436
|
bindings = cls._join(cls.SCIPION_SOFTWARE, 'bindings')
|
391
|
-
|
437
|
+
if cls.SCIPION_HOME_DEFINED:
|
438
|
+
os.makedirs(bindings, exist_ok=True)
|
392
439
|
return bindings
|
393
440
|
|
394
441
|
@classmethod
|
@@ -397,7 +444,8 @@ class Config:
|
|
397
444
|
Folder where scipion logs must be placed. The folder is created
|
398
445
|
"""
|
399
446
|
logsFolder = cls.SCIPION_LOGS
|
400
|
-
|
447
|
+
if cls.SCIPION_HOME_DEFINED:
|
448
|
+
os.makedirs(logsFolder, exist_ok=True)
|
401
449
|
return logsFolder
|
402
450
|
|
403
451
|
@classmethod
|
@@ -455,8 +503,13 @@ class Config:
|
|
455
503
|
debugOn = not Config.debugOn()
|
456
504
|
os.environ[SCIPION_DEBUG] = str(debugOn)
|
457
505
|
os.environ[SCIPION_DEBUG_NOCLEAN] = str(debugOn)
|
458
|
-
os.environ[SCIPION_LOG_LEVEL] = "INFO" if not debugOn else "DEBUG"
|
459
506
|
|
507
|
+
newLevel = "DEBUG" if debugOn else "INFO"
|
508
|
+
os.environ[SCIPION_LOG_LEVEL] = newLevel
|
509
|
+
|
510
|
+
from pyworkflow.utils import changeLogLevel
|
511
|
+
changeLogLevel(newLevel)
|
512
|
+
logger.info("Log level set to %s" % newLevel)
|
460
513
|
@staticmethod
|
461
514
|
def debugSQLOn():
|
462
515
|
from .utils import envVarOn
|
@@ -545,6 +598,17 @@ class Config:
|
|
545
598
|
condaExe = os.path.join(envFolder, "bin", "python")
|
546
599
|
return condaExe == getPython()
|
547
600
|
|
601
|
+
@classmethod
|
602
|
+
def getEnvName(cls):
|
603
|
+
""" Returns Scipion's environment name(conda or venv)"""
|
604
|
+
if cls.isCondaInstallation():
|
605
|
+
envPath = os.environ['CONDA_PREFIX']
|
606
|
+
else: # Virtualenv
|
607
|
+
envPath = os.environ['VIRTUAL_ENV']
|
608
|
+
|
609
|
+
return os.path.basename(envPath)
|
610
|
+
|
611
|
+
|
548
612
|
@classmethod
|
549
613
|
def getSpritesFile(cls):
|
550
614
|
if not os.path.exists(Config.SCIPION_SPRITES_FILE):
|
pyworkflow/constants.py
CHANGED
@@ -43,7 +43,7 @@ VERSION_1 = '1.0.0'
|
|
43
43
|
VERSION_1_1 = '1.1.0'
|
44
44
|
VERSION_1_2 = '1.2.0'
|
45
45
|
VERSION_2_0 = '2.0.0'
|
46
|
-
VERSION_3_0 = '3.
|
46
|
+
VERSION_3_0 = '3.11.1'
|
47
47
|
|
48
48
|
# For a new release, define a new constant and assign it to LAST_VERSION
|
49
49
|
# The existing one has to be added to OLD_VERSIONS list.
|
@@ -141,6 +141,7 @@ PROJECT_SETTINGS = 'settings.sqlite'
|
|
141
141
|
FALSE_STR = str(False)
|
142
142
|
TRUE_STR = str(True)
|
143
143
|
NONE_STR = str(None)
|
144
|
+
TRUE_YES_ON_ = ['true', 'yes', 'on', '1']
|
144
145
|
EMPTY_STR = ""
|
145
146
|
|
146
147
|
# GUI colors
|
pyworkflow/gui/browser.py
CHANGED
@@ -217,6 +217,33 @@ class FileHandler(object):
|
|
217
217
|
return []
|
218
218
|
|
219
219
|
|
220
|
+
class FSFileHandler(FileHandler):
|
221
|
+
|
222
|
+
def __init__(self):
|
223
|
+
self._refresh_callback = None
|
224
|
+
|
225
|
+
def setRefresh(self, refresh_callback):
|
226
|
+
self._refresh_callback = refresh_callback
|
227
|
+
|
228
|
+
def copyToClipboard(self, file):
|
229
|
+
import pyperclip
|
230
|
+
pyperclip.copy(file)
|
231
|
+
logger.info(f'{file} copy to clipboard')
|
232
|
+
|
233
|
+
def deleteFile(self, file):
|
234
|
+
pwutils.cleanPath(file)
|
235
|
+
|
236
|
+
if self._refresh_callback:
|
237
|
+
self._refresh_callback(None)
|
238
|
+
def getFileActions(self, objFile):
|
239
|
+
""" Return basic os actions like delete or copy to clipboard
|
240
|
+
"""
|
241
|
+
fn = objFile.getPath()
|
242
|
+
return [('Copy path', lambda: self.copyToClipboard(fn), pwutils.Icon.ACTION_COPY),
|
243
|
+
('Delete', lambda: self.deleteFile(fn), pwutils.Icon.DELETE_OPERATION)
|
244
|
+
]
|
245
|
+
|
246
|
+
|
220
247
|
class TextFileHandler(FileHandler):
|
221
248
|
def __init__(self, textIcon):
|
222
249
|
FileHandler.__init__(self)
|
@@ -235,7 +262,7 @@ class FileTreeProvider(TreeProvider):
|
|
235
262
|
""" Populate a tree with files and folders of a given path """
|
236
263
|
|
237
264
|
_FILE_HANDLERS = {}
|
238
|
-
|
265
|
+
_FS_HANDLER = FSFileHandler()
|
239
266
|
FILE_COLUMN = 'File'
|
240
267
|
SIZE_COLUMN = 'Size'
|
241
268
|
|
@@ -252,18 +279,23 @@ class FileTreeProvider(TreeProvider):
|
|
252
279
|
handlersList.append(fileHandler)
|
253
280
|
cls._FILE_HANDLERS[fileExt] = handlersList
|
254
281
|
|
255
|
-
def __init__(self, currentDir
|
282
|
+
def __init__(self, currentDir, showHidden, onlyFolders, browser):
|
256
283
|
TreeProvider.__init__(self, sortingColumnName=self.FILE_COLUMN)
|
257
284
|
self._currentDir = os.path.abspath(currentDir)
|
258
285
|
self._showHidden = showHidden
|
259
286
|
self._onlyFolders = onlyFolders
|
287
|
+
self._browser = browser
|
260
288
|
self.getColumns = lambda: [(self.FILE_COLUMN, 300),
|
261
289
|
(self.SIZE_COLUMN, 70), ('Time', 150)]
|
262
290
|
|
263
291
|
def getFileHandlers(self, obj):
|
264
292
|
filename = obj.getFileName()
|
265
293
|
fileExt = pwutils.getExt(filename)
|
266
|
-
|
294
|
+
fhs = self._FILE_HANDLERS.get(fileExt,[])
|
295
|
+
# add basic options: delete, copy. They do not depend on the extension.
|
296
|
+
if self._FS_HANDLER not in fhs:
|
297
|
+
fhs.append(self._FS_HANDLER)
|
298
|
+
return fhs
|
267
299
|
|
268
300
|
def getObjectInfo(self, obj):
|
269
301
|
filename = obj.getFileName()
|
@@ -299,11 +331,13 @@ class FileTreeProvider(TreeProvider):
|
|
299
331
|
fileHandlers = self.getFileHandlers(obj)
|
300
332
|
actions = []
|
301
333
|
for fileHandler in fileHandlers:
|
334
|
+
if fileHandler == self._FS_HANDLER:
|
335
|
+
fileHandler.setRefresh(self._browser._actionRefresh)
|
302
336
|
actions += fileHandler.getFileActions(obj)
|
303
337
|
# Always allow the option to open as text
|
304
338
|
# specially useful for unknown formats
|
305
339
|
fn = obj.getPath()
|
306
|
-
actions.append(("Open external
|
340
|
+
actions.append(("Open external program",
|
307
341
|
lambda: openTextFileEditor(fn), pwutils.Icon.ACTION_REFERENCES))
|
308
342
|
|
309
343
|
return actions
|
@@ -404,7 +438,7 @@ class FileBrowser(ObjectBrowser):
|
|
404
438
|
self.previousSearch = None
|
405
439
|
self.previousSearchTS = None
|
406
440
|
self.shortCuts = shortCuts
|
407
|
-
self._provider = FileTreeProvider(initialDir, showHidden, onlyFolders)
|
441
|
+
self._provider = FileTreeProvider(initialDir, showHidden, onlyFolders, self)
|
408
442
|
self.selectButton = selectButton
|
409
443
|
self.entryLabel = entryLabel
|
410
444
|
self.entryVar = tk.StringVar()
|
pyworkflow/gui/dialog.py
CHANGED
@@ -917,6 +917,8 @@ class SearchBaseWindow(Window):
|
|
917
917
|
|
918
918
|
frame.grid(row=0, column=0, sticky='new', padx=5, pady=(10, 5))
|
919
919
|
|
920
|
+
return frame
|
921
|
+
|
920
922
|
def _createResultsBox(self, content):
|
921
923
|
frame = tk.Frame(content, bg=Color.ALT_COLOR, padx=5, pady=5)
|
922
924
|
configureWeigths(frame)
|