Skip to content

Commit

Permalink
Merge pull request #559 from scipion-em/devel
Browse files Browse the repository at this point in the history
release 3.9
  • Loading branch information
JorMaister authored Sep 30, 2024
2 parents 10f0463 + d379d51 commit 725aca2
Show file tree
Hide file tree
Showing 32 changed files with 475 additions and 239 deletions.
18 changes: 18 additions & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,21 @@
V3.9.0
- Project can have a comment (tooltip over the project name and click will edit it). Will be populated with templates description.
- Project Color modes:
size color mode removed: Problematic in slow setups or huge projects.
labels color mode merged with status color mode.
- Manual subsets works when SCIPION_USE_QUEUE is active. For now this execution is not sent to the QUEUE: Might need to ask for the queue parameters.
- Step details show it step needs a GPU
- Folder size not showing in protocol's tooltip: poor performance in some setups
- Threads field and help improved: Distinguish between "Scipion threads" and "Threads" (program threads)
- create script accepts a comment (location optional as -)
- GPU "queue":
Basic GPU queue implemented for a more robust GPU specification in combination with threads. See threadmpigpu help page in the doc. Linked in the help.
Tests added
- Tolerate non exisiting SCIPION_SPRITES_FILE falling back to default value.
- Scroll and zoom gestures swap to more standard usage: Control + scroll = zoom, Shift + Scroll = Horizontal scroll.

developers:
- New constants for "id" and "_objId": ID_COLUMN='id', ID_ATTRIBUTE='_objId'
V3.8.0
users:
- Inform when a plugin does not import properly
Expand Down
10 changes: 8 additions & 2 deletions pyworkflow/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ def join(self, *path):

# Internal cached variables, use __ so they are not returned in getVars
__activeColor = None
__defaultSpritesFile = _join(getResourcesPath(),'sprites.png')

CONDA_ACTIVATION_CMD = _get(CONDA_ACTIVATION_CMD_VAR,'',
"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)\"")
Expand Down Expand Up @@ -299,7 +300,7 @@ def join(self, *path):
SCIPION_CONTRAST_COLOR = _get('SCIPION_CONTRAST_COLOR', 'cyan',
"Color used to highlight features over grayscaled images.", caster=validColor)

SCIPION_SPRITES_FILE = _get('SCIPION_SPRITES_FILE', _join(getResourcesPath(),'sprites.png'),
SCIPION_SPRITES_FILE = _get('SCIPION_SPRITES_FILE', __defaultSpritesFile,
"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.")

SCIPION_SHOW_TEXT_IN_TOOLBAR = _get('SCIPION_SHOW_TEXT_IN_TOOLBAR', TRUE_STR,
Expand Down Expand Up @@ -544,7 +545,12 @@ def isCondaInstallation(cls):
condaExe = os.path.join(envFolder, "bin", "python")
return condaExe == getPython()


@classmethod
def getSpritesFile(cls):
if not os.path.exists(Config.SCIPION_SPRITES_FILE):
return cls.__defaultSpritesFile
else:
return Config.SCIPION_SPRITES_FILE


# Add bindings folder to sys.path
Expand Down
7 changes: 6 additions & 1 deletion pyworkflow/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
VERSION_1_1 = '1.1.0'
VERSION_1_2 = '1.2.0'
VERSION_2_0 = '2.0.0'
VERSION_3_0 = '3.8.0'
VERSION_3_0 = '3.9.0'

# For a new release, define a new constant and assign it to LAST_VERSION
# The existing one has to be added to OLD_VERSIONS list.
Expand Down Expand Up @@ -192,6 +192,7 @@ class DOCSITEURLS:
WAIT_FOR = GUI + '#waiting-for-other-protocols'
PLUGIN_MANAGER = USER + 'plugin-manager.html'
HOST_CONFIG = DOCS + "scipion-modes/host-configuration.html"
THREADS_MPIS_AND_GPUS = USER + 'threads-mpi-gpus.html'


# tkinter bind constants
Expand All @@ -211,3 +212,7 @@ class TK:
DEFAULT_EXECUTION_ACTION_SINGLE = 2
DEFAULT_EXECUTION_ACTION_ALL = 3

# Id field/attribute constants
ID_COLUMN='id'
ID_ATTRIBUTE='_objId'

12 changes: 6 additions & 6 deletions pyworkflow/gui/canvas.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ def __init__(self, parent, tooltipCallback=None, tooltipDelay=1500, **kwargs):
self.bind("<Control-1>", self.onControlClick)
# self.bind("<MouseWheel>", self.onScroll)
# Scroll bindings in Linux
self.bind("<Shift-Button-4>", self.zoomerP)
self.bind("<Shift-Button-5>", self.zoomerM)
self.bind("<Control-Button-4>", self.zoomerP)
self.bind("<Control-Button-5>", self.zoomerM)

self._tooltipId = None
self._tooltipOn = False # True if the tooltip is displayed
Expand Down Expand Up @@ -475,7 +475,7 @@ def _drawNodes(self, node, visitedDict={}):
self.addItem(item)

if getattr(node, 'expanded', True):
for child in node.getChilds():
for child in node.getChildren():
if self.nodeList is None:
self._drawNodes(child, visitedDict)
elif self.nodeList.getNode(child.run.getObjId()).isVisible():
Expand Down Expand Up @@ -512,7 +512,7 @@ def _visibleParents(self, node, parentlist):
"""
Return a list with the visible parents of the node's children
"""
for child in node.getChilds():
for child in node.getChildren():
parents = child.getParents()
for parent in parents:
parentNode = self.nodeList.getNode(parent.run.getObjId())
Expand All @@ -525,7 +525,7 @@ def _setupParentProperties(self, node, visitedDict):
the properties (width, height, x and y) is propagated
to the hidden childs.
"""
for child in node.getChilds():
for child in node.getChildren():
if child.getName() not in visitedDict:
child.width = node.width
child.height = node.height
Expand All @@ -544,7 +544,7 @@ def _updatePositions(self, node, visitedDict=None, createEdges=True):
item.moveTo(node.x, node.y)

if getattr(node, 'expanded', True):
for child in node.getChilds():
for child in node.getChildren():
if self.nodeList is None:
self.createEdge(item, child.item)
self._updatePositions(child, visitedDict, createEdges)
Expand Down
5 changes: 3 additions & 2 deletions pyworkflow/gui/dialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
from pyworkflow import Config
from pyworkflow.exceptions import PyworkflowException
from pyworkflow.utils import Message, Icon, Color
from . import gui, Window, widgets, configureWeigths, LIST_TREEVIEW, defineStyle, ToolTip
from . import gui, Window, widgets, configureWeigths, LIST_TREEVIEW, defineStyle, ToolTip, getDefaultFont
from .tree import BoundTree, Tree
from .text import Text, TaggedText

Expand Down Expand Up @@ -443,7 +443,8 @@ def body(self, bodyFrame):
label = tk.Label(bodyFrame, text=self.entryLabel, bg=Config.SCIPION_BG_COLOR, bd=0)
label.grid(row=row, column=0, sticky='nw', padx=(15, 10), pady=15)
self.entry = tk.Entry(bodyFrame, bg=gui.cfgEntryBgColor,
width=self.entryWidth, textvariable=self.tkvalue)
width=self.entryWidth, textvariable=self.tkvalue,
font=getDefaultFont())
self.entry.grid(row=row, column=1, sticky='new', padx=(0, 15), pady=15)
self.initial_focus = self.entry

Expand Down
14 changes: 12 additions & 2 deletions pyworkflow/gui/form.py
Original file line number Diff line number Diff line change
Expand Up @@ -1698,14 +1698,19 @@ def _createParallel(self, runFrame, r):
c2 = 0
sticky = 'e'

helpMessage = pwutils.Message.HELP_PARALLEL_HEADER

if mode == pwprot.STEPS_PARALLEL:
if allowThreads and numberOfThreads > 0:
prot.numberOfMpi.set(1)
self._createHeaderLabel(procFrame, pwutils.Message.LABEL_THREADS,
self._createHeaderLabel(procFrame, pwutils.Message.LABEL_SCIPION_THREADS,
sticky=sticky, row=r2, column=c2,
pady=0)
entry = self._createBoundEntry(procFrame,
pwutils.Message.VAR_THREADS)

helpMessage += pwutils.Message.HELP_SCIPION_THREADS

entry.grid(row=r2, column=c2 + 1, padx=(0, 5), sticky='w')
elif allowMpi and numberOfMpi > 1:
self.showError("MPI parameter is deprecated for protocols "
Expand All @@ -1728,6 +1733,8 @@ def _createParallel(self, runFrame, r):
# Modify values to be used in MPI entry
c2 += 2
sticky = 'w'

helpMessage += pwutils.Message.HELP_PARALLEL_THREADS
# ---- MPI ----
if allowMpi:
self._createHeaderLabel(procFrame, pwutils.Message.LABEL_MPI,
Expand All @@ -1736,11 +1743,14 @@ def _createParallel(self, runFrame, r):
entry = self._createBoundEntry(procFrame, pwutils.Message.VAR_MPI)
entry.grid(row=r2, column=c2 + 1, padx=(0, 5), sticky='w')

helpMessage += pwutils.Message.HELP_PARALLEL_MPI


btnHelp = IconButton(procFrame, pwutils.Message.TITLE_COMMENT,
pwutils.Icon.ACTION_HELP,
highlightthickness=0,
command=self._createHelpCommand(
pwutils.Message.HELP_MPI_THREADS))
helpMessage))
btnHelp.grid(row=0, column=4, padx=(5, 0), pady=2, sticky='e')

procFrame.columnconfigure(0, minsize=60)
Expand Down
12 changes: 6 additions & 6 deletions pyworkflow/gui/graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ def _setLevel(self, node, level, parent):
nextLevel = level + 1
if nextLevel > self.maxLevel:
return
for child in node.getChilds():
for child in node.getChildren():
if nextLevel > getattr(child, 'level', 0):
self._setLevel(child, nextLevel, node)

Expand All @@ -97,7 +97,7 @@ def _paintNodeWithChilds(self, node, level):
if level > self.maxLevel:
return

childs = [c for c in node.getChilds() if c.parent is node]
childs = [c for c in node.getChildren() if c.parent is node]
n = len(childs)

if n > 0:
Expand Down Expand Up @@ -174,7 +174,7 @@ def _getHLimits(self, node):
for each level of the tree
"""
node.hLimits = [[-node.half, node.half]]
childs = [c for c in node.getChilds() if c.parent is node]
childs = [c for c in node.getChildren() if c.parent is node]
for child in childs:
count = 1
if not hasattr(child, 'hLimits'):
Expand Down Expand Up @@ -221,7 +221,7 @@ def _createEdges(self, node, x):
if node.level == self.maxLevel:
return

for c in node.getChilds():
for c in node.getChildren():
if c.parent is node:
self._createEdges(c, nx)
self.createEdge(node.item, c.item)
Expand All @@ -230,7 +230,7 @@ def _paintNodeWithPosition(self, node):
""" Paint nodes using its position. """
self._paintNode(node, None)

for child in node.getChilds():
for child in node.getChildren():
# parent = None for nodes that have been not traversed
parent = getattr(child, 'parent', None)
if parent is None:
Expand All @@ -241,7 +241,7 @@ def _paintEdges(self, node):
""" Paint only the edges between nodes, assuming they are
already well positioned.
"""
for child in node.getChilds():
for child in node.getChildren():
if child.parent is node:
self._paintEdges(child)
self.createEdge(node.item, child.item)
4 changes: 2 additions & 2 deletions pyworkflow/gui/graph_layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ def _setLayoutLevel(self, node, level, parent, ancestors=[]):

if self.__isNodeExpanded(node):
ancestors.append(node.getName())
for child in node.getChilds():
for child in node.getChildren():
if child.getName() in ancestors:
logger.warning("WARNING: There might be a cyclic redundancy error in this protocol: %s (%s)" %(child.getLabel(),
child.getName()))
Expand All @@ -155,7 +155,7 @@ def __getNodeChilds(self, node):
visited by this node first (its 'parent')
"""
if self.__isNodeExpanded(node):
return [c for c in node.getChilds() if c._layout['parent'] is node]
return [c for c in node.getChildren() if c._layout['parent'] is node]
else:
return [] # treat collapsed nodes as if they have no childs

Expand Down
14 changes: 7 additions & 7 deletions pyworkflow/gui/project/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
import tkinter as tk

import pyworkflow as pw
from pyworkflow.gui import Window, Message, Color, getBigFont, defineStyle
from pyworkflow.gui import Window, Message, Color, getBigFont, defineStyle, ToolTip
from pyworkflow.gui.widgets import GradientFrame
from pyworkflow.utils.properties import Icon
from pyworkflow.gui.project.variables import VariablesDialog
Expand Down Expand Up @@ -98,18 +98,18 @@ def createHeaderFrame(self, parent):
bg=pw.Config.SCIPION_BG_COLOR)
versionLabel.grid(row=0, column=1, sticky='sw', pady=20)

# Create the Project Name label
projName = getattr(self, 'projName', '')
projLabel = tk.Label(header, text=projName, font=getBigFont(),
borderwidth=0, anchor='nw', bg=pw.Config.SCIPION_BG_COLOR,
fg=Color.ALT_COLOR_DARK)
projLabel.grid(row=0, column=2, sticky='sw', padx=(20, 5), pady=10)
self.customizeheader(header)

# Create gradient
GradientFrame(header, height=8, borderwidth=0).grid(row=1, column=0,
columnspan=3,
sticky='new')
return header

def customizeheader(self, headerFrame):
""" Implement in children classes to customize it: e.g.: Project name in project window"""
pass

def addViewList(self, header):
"""Create the view selection frame (Protocols|Data) in the header.
"""
Expand Down
Loading

0 comments on commit 725aca2

Please sign in to comment.