Source code for ccpn.ui.gui.lib.OpenGL.CcpnOpenGLSimpleLabels

"""
Module Documentation here
"""
#=========================================================================================
# Licence, Reference and Credits
#=========================================================================================
__copyright__ = "Copyright (C) CCPN project (http://www.ccpn.ac.uk) 2014 - 2021"
__credits__ = ("Ed Brooksbank, Joanna Fox, Victoria A Higman, Luca Mureddu, Eliza Płoskoń",
               "Timothy J Ragan, Brian O Smith, Gary S Thompson & Geerten W Vuister")
__licence__ = ("CCPN licence. See http://www.ccpn.ac.uk/v3-software/downloads/license")
__reference__ = ("Skinner, S.P., Fogh, R.H., Boucher, W., Ragan, T.J., Mureddu, L.G., & Vuister, G.W.",
                 "CcpNmr AnalysisAssign: a flexible platform for integrated NMR analysis",
                 "J.Biomol.Nmr (2016), 66, 111-124, http://doi.org/10.1007/s10858-016-0060-y")
#=========================================================================================
# Last code modification
#=========================================================================================
__modifiedBy__ = "$modifiedBy: Ed Brooksbank $"
__dateModified__ = "$dateModified: 2021-06-28 19:12:27 +0100 (Mon, June 28, 2021) $"
__version__ = "$Revision: 3.0.4 $"
#=========================================================================================
# Created
#=========================================================================================
__author__ = "$Author: Ed Brooksbank $"
__date__ = "$Date: 2020-01-23 15:34:14 +0000 (Thu, January 23, 2020) $"

#=========================================================================================
# Start of code
#=========================================================================================

import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from ccpn.util.Colour import hexToRgbRatio, colorSchemeTable, ERRORCOLOUR
from ccpn.util.Logging import getLogger

from . import GL

from ccpn.ui.gui.lib.OpenGL.CcpnOpenGLFonts import GLString
import ccpn.ui.gui.lib.OpenGL.CcpnOpenGLDefs as GLDefs
from ccpn.core.lib.AxisCodeLib import getAxisCodeMatchIndices


[docs]class GLSimpleStrings(): """ Class to handle grouped labels with an optional infinite line if required Labels can be locked to screen co-ordinates or top/bottom, left/right justified """ def __init__(self, parent=None, strip=None, name=None, resizeGL=False, blendMode=False, drawMode=GL.GL_LINES, dimension=2): """Initialise the class """ self._GLParent = parent self.strip = strip self.name = name self.resizeGL = resizeGL self.axisCodes = self.strip.axisCodes self.current = self.strip.current if self.strip else None self.strings = {}
[docs] def buildStrings(self): for spectrumView in self._GLParent._ordering: # strip.spectrumViews: if spectrumView.isDeleted: continue if spectrumView not in self.strings: _posColours = (ERRORCOLOUR,) _posCol = spectrumView.spectrum.sliceColour if _posCol and _posCol.startswith('#'): _posColours = (_posCol,) elif _posCol in colorSchemeTable: _posColours = colorSchemeTable[_posCol] self.addString(spectrumView, (0, 0), colour=_posColours[0], alpha=1.0, lock=GLDefs.LOCKAXIS | GLDefs.LOCKLEFT | GLDefs.LOCKBOTTOM, axisCodes=('intensity',))
[docs] def drawStrings(self): if self.strip.isDeleted: return self.buildStrings() # iterate over and draw all strings for visible spectrumViews for specView, string in self.strings.items(): if specView in self._GLParent._visibleOrdering and string.stringObject and not string.stringObject.isDeleted: string.drawTextArrayVBO()
[docs] def objectText(self, obj): """return the string to be used for the label To be subclassed as required """ return str(obj.spectrum.id)
[docs] def objectInstance(self, obj): """return the object instance to insert into the string To be subclassed as required """ return obj.spectrum
[docs] def objectSettings(self, string, obj): """Set up class specific settings for the new string To be subclassed as required """ string.spectrumView = obj if string.axisCodes: string.axisIndices = getAxisCodeMatchIndices(string.axisCodes, self.axisCodes)
[docs] def addString(self, obj, position=(0, 0), axisCodes=None, colour="#FF0000", alpha=1.0, lock=GLDefs.LOCKNONE, serial=0): """Add a new string to the list """ GLp = self._GLParent col = hexToRgbRatio(colour) # NOTE:ED check axis units - assume 'ppm' for the minute # fixed ppm position - rescale will do the rest textX = position[0] textY = position[1] # create new label, should be ready to draw newLabel = GLString(text=self.objectText(obj), font=GLp.getSmallFont(), #.globalGL.glSmallFont, x=textX, y=textY, colour=(*col, alpha), GLContext=GLp, obj=self.objectInstance(obj), serial=serial) newLabel.position = position newLabel.axisCodes = axisCodes newLabel.lock = lock # set up class specific settings, to be subclassed as required self.objectSettings(newLabel, obj) # shouldn't be necessary but here for completeness self._rescaleString(newLabel) # assume objects are only used once, will replace a previous object self.strings[obj] = newLabel # return the new created GLstring return newLabel
[docs] def renameString(self, obj): """Rename a string in the list, if it exists """ strings = [(specView, string) for specView, string in self.strings.items() if string.stringObject is obj] for specView, string in strings: string.text = self.objectText(specView) string.buildString() self._rescaleString(string)
[docs] def removeString(self, obj): """Remove a string from the list, if it exists """ if obj in self.strings: del self.strings[obj]
def _rescaleString(self, obj): vertices = obj.numVertices if vertices: # check the lock type to determine how to rescale lock = obj.lock GLp = self._GLParent position = list(obj.position) # move the axes to account for the stacking if self._GLParent._stackingMode: if obj.spectrumView not in GLp._spectrumSettings: return _, position[1] = GLp._spectrumSettings[obj.spectrumView][GLDefs.SPECTRUM_STACKEDMATRIXOFFSET] if lock == GLDefs.LOCKNONE: # lock to the correct axisCodes if exist - not tested yet if obj.axisIndices[0] and obj.axisIndices[1]: offsets = [position[obj.axisIndices[0]], position[obj.axisIndices[1]], 0.0] else: offsets = [position[0], position[1], 0.0] elif lock == GLDefs.LOCKSCREEN: # fixed screen co-ordinates offsets = [GLp.axisL + position[0] * GLp.pixelX, GLp.axisB + position[1] * GLp.pixelY, 0.0] # not locking to an axisCode elif lock == GLDefs.LOCKLEFT: # lock to the left margin offsets = [GLp.axisL + 3.0 * GLp.pixelX, position[1], 0.0] elif lock == GLDefs.LOCKRIGHT: # lock to the right margin offsets = [GLp.axisR - (3.0 + obj.width) * GLp.pixelX, position[1], 0.0] elif lock == GLDefs.LOCKBOTTOM: # lock to the bottom margin - updated in resize offsets = [position[0], GLp.axisB + 3.0 * GLp.pixelY, 0.0] elif lock == GLDefs.LOCKTOP: # lock to the top margin - updated in resize offsets = [position[0], GLp.axisT - (3.0 + obj.height) * GLp.pixelY, 0.0] elif lock & GLDefs.LOCKAXIS: # locking to a named axisCodes if len(obj.axisIndices) == 1: # match to a single axisCode if obj.axisIndices[0] == 1: if lock & GLDefs.LOCKRIGHT: # lock to the right margin offsets = [GLp.axisR - (3.0 + obj.width) * GLp.pixelX, position[1], 0.0] else: # lock to the left margin offsets = [GLp.axisL + 3.0 * GLp.pixelX, position[1], 0.0] elif obj.axisIndices[0] == 0: if lock & GLDefs.LOCKTOP: # lock to the top margin - updated in resize offsets = [position[0], GLp.axisT - (3.0 + obj.height) * GLp.pixelY, 0.0] else: # lock to the bottom margin - updated in resize offsets = [position[0], GLp.axisB + 3.0 * GLp.pixelY, 0.0] else: # can't match more than 1 return else: return # for pp in range(0, 2 * vertices, 2): # obj.attribs[pp:pp + 2] = offsets obj.attribs[:] = offsets * vertices # redefine the string's position VBOs obj.updateTextArrayVBOAttribs() try: _posColours = (ERRORCOLOUR,) _posCol = obj.spectrumView.spectrum.sliceColour if _posCol and _posCol.startswith('#'): _posColours = (_posCol,) elif _posCol in colorSchemeTable: _posColours = colorSchemeTable[_posCol] # reset the colour, may have changed due to spectrum colour change, but not caught anywhere else yet obj.setStringHexColour(_posColours[0], alpha=1.0) # redefine the string's colour VBOs obj.updateTextArrayVBOColour() except Exception as es: getLogger().warning('error setting string colour')
[docs] def rescale(self): """rescale the objects """ for string in self.strings.values(): self._rescaleString(string)
[docs]class GLSimpleLegend(GLSimpleStrings): """ Class to handle drawing the legend to the screen """
[docs] def buildStrings(self): for spectrumView in self._GLParent._ordering: # strip.spectrumViews: if spectrumView.isDeleted: continue if spectrumView not in self.strings: _posColours = (ERRORCOLOUR,) _posCol = spectrumView.spectrum.sliceColour if _posCol and _posCol.startswith('#'): _posColours = (_posCol,) elif _posCol in colorSchemeTable: _posColours = colorSchemeTable[_posCol] self.addString(spectrumView, (0, 0), colour=_posColours[0], alpha=1.0)
[docs] def drawStrings(self): if self.strip.isDeleted: return self.buildStrings() # iterate over and draw all strings for visible spectrumViews for specView, string in self.strings.items(): if specView in self._GLParent._visibleOrdering and string.stringObject and not string.stringObject.isDeleted: string.drawTextArrayVBO()
[docs] def objectText(self, obj): """return the string to be used for the label To be subclassed as required """ return str(obj.id)
[docs] def objectInstance(self, obj): """return the object instance to insert into the string To be subclassed as required """ return obj
[docs] def objectSettings(self, string, obj): """Set up class specific settings for the new string To be subclassed as required """ string.spectrum = obj
[docs] def addString(self, obj, position=(0, 0), axisCodes=None, colour="#FF0000", alpha=1.0, lock=GLDefs.LOCKNONE, serial=0): """Add a new string to the list """ GLp = self._GLParent col = hexToRgbRatio(colour) # fixed ppm position - rescale will do the rest textX = position[0] textY = position[1] # create new label, should be ready to draw newLabel = GLString(text=self.objectText(obj), font=GLp.getSmallFont(), #.globalGL.glSmallFont, x=textX, y=textY, colour=(*col, alpha), GLContext=GLp, obj=self.objectInstance(obj), serial=serial) newLabel.position = position newLabel.axisCodes = axisCodes newLabel.lock = lock # set up class specific settings, to be subclassed as required self.objectSettings(newLabel, obj) # shouldn't be necessary but here for completeness self._rescaleString(newLabel) # assume objects are only used once, will replace a previous object self.strings[obj] = newLabel # return the new created GLstring return newLabel
def _rescaleString(self, stringObj): vertices = stringObj.numVertices if vertices: GLp = self._GLParent position = list(stringObj.position) # fixed screen co-ordinates from top-left offsets = [GLp.axisL + position[0] * GLp.pixelX, GLp.axisB + position[1] * GLp.pixelY, 0.0] # for pp in range(0, 2 * vertices, 2): # stringObj.attribs[pp:pp + 2] = offsets stringObj.attribs[:] = offsets * vertices # redefine the string's position VBOs stringObj.updateTextArrayVBOAttribs() try: _posColours = (ERRORCOLOUR,) _posCol = stringObj.stringObject.sliceColour if _posCol and _posCol.startswith('#'): _posColours = (_posCol,) elif _posCol in colorSchemeTable: _posColours = colorSchemeTable[_posCol] # reset the colour, may have changed due to spectrum colour change, but not caught anywhere else yet stringObj.setStringHexColour(_posColours[0], alpha=1.0) # redefine the string's colour VBOs stringObj.updateTextArrayVBOColour() except Exception as es: getLogger().warning('error setting legend string colour')
[docs] def rescale(self): """rescale the objects """ for string in self.strings.values(): self._rescaleString(string)