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

"""
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-10-12 18:07:10 +0100 (Tue, October 12, 2021) $"
__version__ = "$Revision: 3.0.4 $"
#=========================================================================================
# Created
#=========================================================================================
__author__ = "$Author: Ed Brooksbank $"
__date__ = "$Date: 2020-12-11 17:47:59 +0000 (Fri, December 11, 2020) $"
#=========================================================================================
# Start of code
#=========================================================================================

from ccpn.util.Colour import getAutoColourRgbRatio
from ccpn.util.Logging import getLogger
from ccpn.ui.gui.guiSettings import getColours, CCPNGLWIDGET_FOREGROUND, CCPNGLWIDGET_INTEGRALSHADE
from ccpn.ui.gui.lib.OpenGL import CcpnOpenGLDefs as GLDefs
from ccpn.ui.gui.lib.OpenGL.CcpnOpenGLArrays import GLRENDERMODE_REBUILD, GLRENDERMODE_DRAW, GLRENDERMODE_RESCALE
from ccpn.ui.gui.lib.OpenGL.CcpnOpenGLFonts import GLString
from ccpn.ui.gui.lib.OpenGL.CcpnOpenGLLabelling import GL1dLabelling, GLLabelling
from ccpn.ui.gui.lib.OpenGL.CcpnOpenGLWidgets import GLIntegralRegion


[docs]class GLintegralListMethods(): """Class of methods common to 1d and Nd integrals This is added to the Integral Classes below and doesn't require an __init__ """ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # List handlers # The routines that have to be changed when accessing different named # lists. #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ def _isSelected(self, integral): """return True if the obj in the defined object list """ if self.current.integrals: return integral in self.current.integrals return False
[docs] def objects(self, obj): """return the integrals attached to the object """ return obj.integrals
[docs] def objectList(self, obj): """return the integralList attached to the integral """ return obj.integralList
[docs] def listViews(self, integralList): """Return the integralListViews attached to the integralList """ return integralList.integralListViews
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # List specific routines #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[docs] def getLabelling(self, obj, labelType): """get the object label based on the current labelling method """ return obj.id + '\n' + str(obj.value)
[docs] def extraIndicesCount(self, integral): """Calculate how many indices to add """ return 0
[docs] def appendExtraIndices(self, *args): """Add extra indices to the index list """ return 0, 0
[docs] def extraVerticesCount(self, integral): """Calculate how many vertices to add """ return 0
[docs] def appendExtraVertices(self, *args): """Add extra vertices to the vertex list """ return 0
[docs] def insertExtraIndices(self, *args): """Insert extra indices into the vertex list """ return 0, 0
[docs] def insertExtraVertices(self, *args): """Insert extra vertices into the vertex list """ return 0
[docs] def rescaleIntegralLists(self): for il in self._GLSymbols.values(): il._rescale()
[docs]class GLintegralNdLabelling(GL1dLabelling, GLintegralListMethods, GLLabelling): #, GLpeakNdLabelling): """Class to handle symbol and symbol labelling for Nd displays """ # def __init__(self, parent=None, strip=None, name=None, resizeGL=False): # """Initialise the class # """ # super(GLintegralNdLabelling, self).__init__(parent=parent, strip=strip, name=name, resizeGL=resizeGL) def _updateHighlightedSymbols(self, spectrumView, integralListView): drawList = self._GLSymbols[integralListView] drawList._rebuild() drawList.updateTextArrayVBOColour() def _updateHighlightedLabels(self, spectrumView, objListView): if objListView not in self._GLLabels: return drawList = self._GLLabels[objListView] strip = self.strip # pls = peakListView.peakList pls = self.objectList(objListView) listCol = getAutoColourRgbRatio(objListView.textColour or GLDefs.DEFAULTCOLOUR, pls.spectrum, self.autoColour, getColours()[CCPNGLWIDGET_FOREGROUND]) meritCol = getAutoColourRgbRatio(objListView.meritColour or GLDefs.DEFAULTCOLOUR, pls.spectrum, self.autoColour, getColours()[CCPNGLWIDGET_FOREGROUND]) meritEnabled = objListView.meritEnabled meritThreshold = objListView.meritThreshold for drawStr in drawList.stringList: obj = drawStr.stringObject if obj and not obj.isDeleted: if self._isSelected(obj): drawStr.setStringColour((*self._GLParent.highlightColour[:3], GLDefs.INPLANEFADE)) else: if meritEnabled and obj.figureOfMerit < meritThreshold: cols = meritCol else: cols = listCol drawStr.setStringColour((*cols, GLDefs.INPLANEFADE)) drawStr.updateTextArrayVBOColour()
[docs] def drawSymbols(self, spectrumSettings, shader=None, stackingMode=True): if self.strip.isDeleted: return self._spectrumSettings = spectrumSettings self.buildSymbols() # why is this not initialising? self._GLParent.globalGL._shaderProgram1.setMVMatrix(self._GLParent._IMatrix) for integralListView, specView in self._visibleListViews: if not integralListView.isDeleted and integralListView in self._GLSymbols.keys(): # draw the integralAreas if they exist for integralArea in self._GLSymbols[integralListView]._regions: if hasattr(integralArea, '_integralArea'): if self._GLParent._stackingMode: # use the stacking matrix to offset the 1D spectra # - not sure that they are actually drawn in stacking mode self._GLParent.globalGL._shaderProgram1.setMVMatrix(self._GLParent._spectrumSettings[ specView][ GLDefs.SPECTRUM_STACKEDMATRIX]) # draw the actual integral areas integralArea._integralArea.drawVertexColorVBO() self._GLParent.globalGL._shaderProgram1.setMVMatrix(self._GLParent._IMatrix)
[docs] def drawSymbolRegions(self, spectrumSettings): if self.strip.isDeleted: return self._spectrumSettings = spectrumSettings self.buildSymbols() for integralListView, specView in self._visibleListViews: if not integralListView.isDeleted and integralListView in self._GLSymbols.keys(): # draw the boxes around the highlighted integral areas - multisampling not required here self._GLSymbols[integralListView].drawIndexVBO() self._GLParent.globalGL._shaderProgram1.setMVMatrix(self._GLParent._IMatrix)
def _rescaleLabels(self, spectrumView=None, objListView=None, drawList=None): """Rescale all labels to the new dimensions of the screen """ for drawStr in drawList.stringList: vertices = drawStr.numVertices if vertices: if drawStr.axisIndex == 0: _font = drawStr.font offsets = [drawStr.axisPosition + (3.0 * self._GLParent.pixelX), self._GLParent.axisT - (2 * _font.charHeight * self._GLParent.pixelY), 0.0] else: offsets = [self._GLParent.axisL + (3.0 * self._GLParent.pixelX), drawStr.axisPosition + (3.0 * self._GLParent.pixelY), 0.0] drawStr.attribs[:] = offsets * vertices drawStr.updateTextArrayVBOAttribs() def _buildSymbols(self, spectrumView, integralListView): if integralListView not in self._GLSymbols: self._GLSymbols[integralListView] = GLIntegralRegion(project=self.strip.project, GLContext=self._GLParent, spectrumView=spectrumView, integralListView=integralListView) drawList = self._GLSymbols[integralListView] if drawList.renderMode == GLRENDERMODE_REBUILD: drawList.renderMode = GLRENDERMODE_DRAW # back to draw mode drawList.clearArrays() drawList._clearRegions() ils = integralListView.integralList listCol = getAutoColourRgbRatio(integralListView.symbolColour or GLDefs.DEFAULTCOLOUR, ils.spectrum, self.autoColour, getColours()[CCPNGLWIDGET_FOREGROUND]) meritCol = getAutoColourRgbRatio(integralListView.meritColour or GLDefs.DEFAULTCOLOUR, ils.spectrum, self.autoColour, getColours()[CCPNGLWIDGET_FOREGROUND]) meritEnabled = integralListView.meritEnabled meritThreshold = integralListView.meritThreshold for integral in ils.integrals: if meritEnabled and integral.figureOfMerit < meritThreshold: cols = meritCol else: cols = listCol drawList.addIntegral(integral, integralListView, colour=None, brush=(*cols, CCPNGLWIDGET_INTEGRALSHADE)) drawList.defineIndexVBO() elif drawList.renderMode == GLRENDERMODE_RESCALE: drawList.renderMode = GLRENDERMODE_DRAW # back to draw mode drawList._rebuildIntegralAreas() drawList.defineIndexVBO() def _deleteSymbol(self, integral): for ils in self._GLSymbols.values(): # confusing as peakList and integralList share the same list :) if not ils.integralListView.isDeleted and integral.integralList == ils.integralListView.integralList: for reg in ils._regions: if reg._object == integral: ils._regions.remove(reg) ils._rebuild() return def _createSymbol(self, integral): for ils in self._GLSymbols.values(): if not ils.integralListView.isDeleted and integral.integralList == ils.integralListView.integralList: ilv = ils.integralListView listCol = getAutoColourRgbRatio(ilv.symbolColour or GLDefs.DEFAULTCOLOUR, ilv.integralList.spectrum, self._GLParent.SPECTRUMPOSCOLOUR, getColours()[CCPNGLWIDGET_FOREGROUND]) meritCol = getAutoColourRgbRatio(ilv.meritColour or GLDefs.DEFAULTCOLOUR, ilv.integralList.spectrum, self._GLParent.SPECTRUMPOSCOLOUR, getColours()[CCPNGLWIDGET_FOREGROUND]) meritEnabled = ilv.meritEnabled meritThreshold = ilv.meritThreshold if meritEnabled and integral.figureOfMerit < meritThreshold: cols = meritCol else: cols = listCol ils.addIntegral(integral, ilv, colour=None, brush=(*cols, CCPNGLWIDGET_INTEGRALSHADE)) return def _changeSymbol(self, integral): """update the vertex list attached to the integral """ for ils in self._GLSymbols.values(): for reg in ils._regions: if reg._object == integral: if hasattr(reg, '_integralArea'): # set the rebuild flag for this region reg._integralArea.renderMode = GLRENDERMODE_REBUILD ils._rebuildIntegralAreas() return def _appendLabel(self, spectrumView, objListView, stringList, obj): """Append a new label to the end of the list """ spectrum = spectrumView.spectrum spectrumFrequency = spectrum.spectrometerFrequencies # pls = peakListView.peakList pls = self.objectList(objListView) # symbolWidth = self.strip.symbolSize / 2.0 # get the correct coordinates based on the axisCodes p0 = [0.0] * 2 # len(self.axisOrder) lims = obj.limits[0] if obj.limits else (0.0, 0.0) for ps, psCode in enumerate(self._GLParent.axisOrder[0:2]): for pp, ppCode in enumerate(obj.axisCodes): if self._GLParent._preferences.matchAxisCode == 0: # default - match atom type if ppCode[0] == psCode[0]: # need to put the position in here if self._GLParent.INVERTXAXIS: p0[ps] = pos = max(lims) # obj.position[pp] else: p0[ps] = pos = min(lims) # obj.position[pp] else: p0[ps] = 0.0 #obj.height elif self._GLParent._preferences.matchAxisCode == 1: # match full code if ppCode == psCode: if self._GLParent.INVERTXAXIS: p0[ps] = pos = max(lims) # obj.position[pp] else: p0[ps] = pos = min(lims) # obj.position[pp] else: p0[ps] = 0.0 #obj.height if None in p0: getLogger().warning('Object %s contains undefined position %s' % (str(obj.pid), str(p0))) return if self._isSelected(obj): cols = self._GLParent.highlightColour[:3] else: listCol = getAutoColourRgbRatio(objListView.textColour or GLDefs.DEFAULTCOLOUR, pls.spectrum, self.autoColour, getColours()[CCPNGLWIDGET_FOREGROUND]) meritCol = getAutoColourRgbRatio(objListView.meritColour or GLDefs.DEFAULTCOLOUR, pls.spectrum, self.autoColour, getColours()[CCPNGLWIDGET_FOREGROUND]) meritEnabled = objListView.meritEnabled meritThreshold = objListView.meritThreshold if meritEnabled and obj.figureOfMerit < meritThreshold: cols = meritCol else: cols = listCol text = self.getLabelling(obj, self._GLParent._symbolLabelling) smallFont = self._GLParent.getSmallFont() textX = pos or 0.0 + (3.0 * self._GLParent.pixelX) textY = self._GLParent.axisT - (2 * smallFont.charHeight * self._GLParent.pixelY) newString = GLString(text=text, font=smallFont, # x=p0[0], y=p0[1], x=textX, y=textY, # ox=symbolWidth, oy=symbolWidth, # x=self._screenZero[0], y=self._screenZero[1] colour=(*cols, 1.0), GLContext=self._GLParent, obj=obj) # this is in the attribs newString.axisIndex = 0 newString.axisPosition = pos or 0.0 stringList.append(newString) # # this is in the attribs # stringList[-1].axisIndex = 0 # stringList[-1].axisPosition = pos or 0.0
[docs] def objIsInVisiblePlanes(self, spectrumView, obj): """Get the current object is in visible planes settings """ return True, False, 0, 1.0
[docs]class GLintegral1dLabelling(GLintegralNdLabelling): """Class to handle symbol and symbol labelling for 1d displays """ # 20190607:ED Note, this is not quite correct, but there are no Nd regions yet pass # def __init__(self, parent=None, strip=None, name=None, resizeGL=False): # """Initialise the class # """ # super(GLintegral1dLabelling, self).__init__(parent=parent, strip=strip, name=name, resizeGL=resizeGL)
[docs] def objIsInVisiblePlanes(self, spectrumView, obj): """Get the current object is in visible planes settings """ return True, False, 0, 1.0