"""
Classes to handle drawing of symbols and symbol labelling to the openGL window
Currently this is peaks and multiplets
"""
#=========================================================================================
# 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: Geerten Vuister $"
__dateModified__ = "$dateModified: 2021-12-23 13:15:21 +0000 (Thu, December 23, 2021) $"
__version__ = "$Revision: 3.0.4 $"
#=========================================================================================
# Created
#=========================================================================================
__author__ = "$Author: Ed Brooksbank $"
__date__ = "$Date: 2018-12-20 13:28:13 +0000 (Thu, December 20, 2018) $"
#=========================================================================================
# Start of code
#=========================================================================================
import sys
import math
import numpy as np
from PyQt5 import QtWidgets
from ccpn.core.lib.Notifiers import Notifier
from ccpn.util.Colour import getAutoColourRgbRatio
from ccpn.util.AttrDict import AttrDict
from ccpn.util.Logging import getLogger
from ccpn.ui.gui.guiSettings import CCPNGLWIDGET_FOREGROUND, getColours
from ccpn.ui.gui.lib.OpenGL.CcpnOpenGLFonts import GLString
from ccpn.ui.gui.lib.OpenGL.CcpnOpenGLArrays import GLRENDERMODE_DRAW, GLRENDERMODE_RESCALE, GLRENDERMODE_REBUILD, \
GLREFRESHMODE_NEVER, GLREFRESHMODE_REBUILD, GLSymbolArray, GLLabelArray
import ccpn.ui.gui.lib.OpenGL.CcpnOpenGLDefs as GLDefs
from ccpn.ui.gui.lib.OpenGL.CcpnOpenGLGlobal import getAliasSetting
# NOTE:ED - remember these for later, may create larger vertex arrays for symbols, but should be quicker
# --
# x = np.array([1, 2, 3, -1, 5, 0, 3, 4, 4, 7, 3, 5, 9, 0, 5, 4, 3], dtype=np.uint32)
# seems to be the fastest way of getting masked values
# SKIPINDEX = np.uint32(-1) = 4294967295
# i.e. max index number, use as fill
# timeit.timeit('import numpy as np; x = np.array([1, 2, 3, -1, 5, 0, 3, 4, 4, 7, 3, 5, 9, 0, 5, 4, 3], dtype=np.uint32); x[np.where(x != 3)]', number=200000)
# fastest way to create filled arrays
# *** timeit.timeit('import numpy as np; x = np.array([1, 2, 3, -1, 5, 0, 3, 4, 4, 7, 3, 5, 9, 0, 5, 4, 3], dtype=np.uint32); a = x[x != SKIPINDEX]', number=200000)
# timeit.timeit('import numpy as np; x = np.array([1, 2, 3, -1, 5, 0, 3, 4, 4, 7, 3, 5, 9, 0, 5, 4, 3], dtype=np.uint32); mx = np.full(200000, SKIPINDEX, dtype=np.uint32)', number=20000)
# --
# np.take(x, np.where(x != 3))
# mx = np.ma.masked_values(x, 3)
# a = x[np.where(x != 3)]
# *** a = x[x != SKIPINDEX]
from ccpn.ui.gui.lib.OpenGL import GL, GLU, GLUT
OBJ_ISINPLANE = 0
OBJ_ISINFLANKINGPLANE = 1
OBJ_LINEWIDTHS = 2
OBJ_SPECTRALFREQUENCIES = 3
OBJ_OTHER = 4
OBJ_STORELEN = 5
_totalTime = 0.0
_timeCount = 0
_numTimes = 12
DEFAULTLINECOLOUR = '#7f7f7f'
[docs]class GLLabelling():
"""Base class to handle symbol and symbol labelling
"""
LENSQ = GLDefs.LENSQ
LENSQ2 = GLDefs.LENSQ2
LENSQ4 = GLDefs.LENSQ4
POINTCOLOURS = GLDefs.POINTCOLOURS
def __init__(self, parent=None, strip=None, name=None, enableResize=False):
"""Initialise the class
"""
self._GLParent = parent
self.strip = strip
self.name = name
self._resizeEnabled = enableResize
self._threads = {}
self._threadupdate = False
self.current = self.strip.current if self.strip else None
self._objectStore = {}
self._GLSymbols = {}
self._GLLabels = {}
self._ordering = ()
self._visibleOrdering = ()
self._listViews = ()
self._visibleListViews = ()
self._objIsInVisiblePlanesCache = {}
self.autoColour = self._GLParent.SPECTRUMPOSCOLOUR
[docs] def enableResize(self, value):
"""enable resizing for labelling
"""
if not isinstance(value, bool):
raise TypeError('enableResize must be a bool')
self._resizeEnabled = value
[docs] def rescale(self):
if self._resizeEnabled:
for pp in self._GLSymbols.values():
pp.renderMode = GLRENDERMODE_RESCALE
for pp in self._GLLabels.values():
pp.renderMode = GLRENDERMODE_RESCALE
[docs] def setListViews(self, spectrumViews):
"""Return a list of tuples containing the visible lists and the containing spectrumView
"""
self._listViews = [(lv, specView) for specView in spectrumViews
for lv in self.listViews(specView)
if not lv.isDeleted]
self._visibleListViews = [(lv, specView) for lv, specView in self._listViews
if lv.isDisplayed
and specView.isDisplayed]
# and lv in self._GLSymbols.keys()]
self._ordering = spectrumViews
def _handleNotifier(self, triggers, obj):
if Notifier.DELETE in triggers:
self._deleteSymbol(obj)
self._deleteLabel(obj)
if Notifier.CREATE in triggers:
self._createSymbol(obj)
self._createLabel(obj)
if Notifier.CHANGE in triggers:
self._changeSymbol(obj)
self._changeLabel(obj)
def _processNotifier(self, data):
"""Process notifiers
"""
triggers = data[Notifier.TRIGGER]
obj = data[Notifier.OBJECT]
# update the multiplet labelling
if Notifier.DELETE in triggers:
self._deleteSymbol(obj)
self._deleteLabel(obj)
if Notifier.CREATE in triggers:
self._createSymbol(obj)
self._createLabel(obj)
if Notifier.CHANGE in triggers:
self._changeSymbol(obj)
self._changeLabel(obj)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Handle notifiers
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def _deleteSymbol(self, obj):
pls = self.objectList(obj)
if pls:
spectrum = pls.spectrum
for objListView in self.listViews(pls):
if objListView in self._GLSymbols.keys():
for spectrumView in spectrum.spectrumViews:
if spectrumView in self._ordering: # strip.spectrumViews:
if spectrumView.isDeleted:
continue
self._removeSymbol(spectrumView, objListView, obj)
# self._updateHighlightedSymbols(spectrumView, objListView)
self._GLSymbols[objListView].updateAliasedIndexVBO()
break
# from ccpn.util.decorators import profile
# @profile
def _createSymbol(self, obj):
pls = self.objectList(obj)
if pls:
spectrum = pls.spectrum
for objListView in self.listViews(pls):
if objListView in self._GLSymbols.keys():
for spectrumView in spectrum.spectrumViews:
if spectrumView in self._ordering: # strip.spectrumViews:
if spectrumView.isDeleted:
continue
self._appendSymbol(spectrumView, objListView, obj)
# self._updateHighlightedSymbols(spectrumView, objListView)
self._GLSymbols[objListView].updateAliasedIndexVBO()
break
def _changeSymbol(self, obj):
pls = self.objectList(obj)
if pls:
spectrum = pls.spectrum
for objListView in self.listViews(pls):
if objListView in self._GLSymbols.keys():
for spectrumView in spectrum.spectrumViews:
if spectrumView in self._ordering: # strip.spectrumViews:
if spectrumView.isDeleted:
continue
self._removeSymbol(spectrumView, objListView, obj)
self._appendSymbol(spectrumView, objListView, obj)
# self._updateHighlightedSymbols(spectrumView, objListView)
self._GLSymbols[objListView].updateAliasedIndexVBO()
break
def _deleteLabel(self, obj):
for pll in self._GLLabels.keys():
drawList = self._GLLabels[pll]
for drawStr in drawList.stringList:
if drawStr.stringObject == obj:
drawList.stringList.remove(drawStr)
break
def _changeLabel(self, obj):
# NOTE:ED - not the nicest way of changing a label - needs work
self._deleteLabel(obj)
self._createLabel(obj)
def _createLabel(self, obj):
pls = self.objectList(obj)
if pls:
spectrum = pls.spectrum
for objListView in self.listViews(pls):
if objListView in self._GLLabels.keys():
for spectrumView in spectrum.spectrumViews:
if spectrumView in self._ordering: # strip.spectrumViews:
if spectrumView.isDeleted:
continue
drawList = self._GLLabels[objListView]
self._appendLabel(spectrumView, objListView, drawList.stringList, obj)
self._rescaleLabels(spectrumView, objListView, drawList)
def _getSymbolWidths(self, spectrumView):
"""return the required r, w, symbolWidth for the current screen scaling.
"""
symbolType = self.strip.symbolType
symbolWidth = self.strip.symbolSize / 2.0
pIndex = self._spectrumSettings[spectrumView][GLDefs.SPECTRUM_POINTINDEX]
vPP = spectrumView.spectrum.ppmPerPoints
try:
r = self._GLParent.symbolX * np.sign(self._GLParent.pixelX)
pr = abs(r / vPP[pIndex[0]])
except:
pr = r
try:
w = self._GLParent.symbolY * np.sign(self._GLParent.pixelY)
pw = abs(w / vPP[pIndex[1]])
except:
pw = w
return r, w, symbolType, symbolWidth, pr, pw
def _appendLabel(self, spectrumView, objListView, stringList, obj):
"""Append a new label to the end of the list
"""
if obj.isDeleted:
return
objPos = obj.pointPositions
if not objPos:
return
objLineWidths = obj.pointLineWidths
spectrum = spectrumView.spectrum
spectrumFrequency = spectrum.spectrometerFrequencies
# pls = peakListView.peakList
pls = self.objectList(objListView)
pIndex = self._spectrumSettings[spectrumView][GLDefs.SPECTRUM_POINTINDEX]
try:
p0 = (objPos[pIndex[0]] - 1, objPos[pIndex[1]] - 1)
except Exception as es:
raise
pointLineWidths = (objLineWidths[pIndex[0]], objLineWidths[pIndex[1]])
frequency = (spectrumFrequency[pIndex[0]], spectrumFrequency[pIndex[1]])
_alias = obj.aliasing
alias = getAliasSetting(_alias[pIndex[0]], _alias[pIndex[1]])
if None in p0:
getLogger().warning('Object %s contains undefined position %s' % (str(obj.pid), str(p0)))
return
_, _, symbolType, symbolWidth, r, w = self._getSymbolWidths(spectrumView)
stringOffset = None
if symbolType in (1, 2):
# put to the top-right corner of the lineWidth
if pointLineWidths[0] and pointLineWidths[1]:
r = GLDefs.STRINGSCALE * 0.5 * pointLineWidths[0] #/ frequency[0]
w = GLDefs.STRINGSCALE * 0.5 * pointLineWidths[1] #/ frequency[1]
stringOffset = (r, w)
else:
r = GLDefs.STRINGSCALE * r
w = GLDefs.STRINGSCALE * w
if pIndex:
# get visible/plane status
_isInPlane, _isInFlankingPlane, planeIndex, fade = self.objIsInVisiblePlanes(spectrumView, obj)
# skip if not visible
if not _isInPlane and not _isInFlankingPlane:
return
if self._isSelected(obj):
listCol = self._GLParent.highlightColour[:3]
else:
if objListView.meritEnabled and obj.figureOfMerit < objListView.meritThreshold:
objCol = objListView.meritColour or GLDefs.DEFAULTCOLOUR
else:
objCol = objListView.textColour or GLDefs.DEFAULTCOLOUR
listCol = getAutoColourRgbRatio(objCol, pls.spectrum,
self.autoColour,
getColours()[CCPNGLWIDGET_FOREGROUND])
text = self.getLabelling(obj, self._GLParent._symbolLabelling)
newString = GLString(text=text,
font=self._GLParent.getSmallFont(),
x=p0[0], y=p0[1],
ox=r, oy=w,
colour=(*listCol, fade),
GLContext=self._GLParent,
obj=obj, clearArrays=False,
alias=alias)
newString.stringOffset = stringOffset
stringList.append(newString)
def _fillLabels(self, spectrumView, objListView, pls, objectList):
"""Append all labels to the new list
"""
spectrum = spectrumView.spectrum
spectrumFrequency = spectrum.spectrometerFrequencies
# use the first object for referencing
obj = objectList(pls)[0]
objPos = obj.pointPositions
if not objPos:
return
objLineWidths = obj.pointLineWidths
pIndex = self._spectrumSettings[spectrumView][GLDefs.SPECTRUM_POINTINDEX]
p0 = (objPos[pIndex[0]] - 1, objPos[pIndex[1]] - 1)
pointLineWidths = (objLineWidths[pIndex[0]], objLineWidths[pIndex[1]])
frequency = (spectrumFrequency[pIndex[0]], spectrumFrequency[pIndex[1]])
_alias = obj.aliasing
alias = getAliasSetting(_alias[pIndex[0]], _alias[pIndex[1]])
if None in p0:
getLogger().warning('Object %s contains undefined position %s' % (str(obj.pid), str(p0)))
return
_, _, symbolType, symbolWidth, r, w = self._getSymbolWidths(spectrumView)
stringOffset = None
if symbolType in (1, 2):
if pointLineWidths[0] and pointLineWidths[1]:
r = - GLDefs.STRINGSCALE * 0.5 * pointLineWidths[0] #/ frequency[0]
w = - GLDefs.STRINGSCALE * 0.5 * pointLineWidths[1] #/ frequency[1]
stringOffset = (r, w)
else:
r = GLDefs.STRINGSCALE * r
w = GLDefs.STRINGSCALE * w
if pIndex:
# get visible/plane status
_isInPlane, _isInFlankingPlane, planeIndex, fade = self.objIsInVisiblePlanes(spectrumView, obj)
# skip if not visible
if not _isInPlane and not _isInFlankingPlane:
return
if self._isSelected(obj):
listCol = self._GLParent.highlightColour[:3]
else:
if objListView.meritEnabled and obj.figureOfMerit < objListView.meritThreshold:
objCol = objListView.meritColour or GLDefs.DEFAULTCOLOUR
else:
objCol = objListView.textColour or GLDefs.DEFAULTCOLOUR
listCol = getAutoColourRgbRatio(objCol, pls.spectrum,
self.autoColour,
getColours()[CCPNGLWIDGET_FOREGROUND])
text = self.getLabelling(obj, self._GLParent._symbolLabelling)
outString = GLString(text=text,
font=self._GLParent.getSmallFont(),
x=p0[0], y=p0[1],
ox=r, oy=w,
colour=(*listCol, fade),
GLContext=self._GLParent,
obj=obj, clearArrays=False,
alias=alias)
outString.stringOffset = stringOffset
return outString
def _removeSymbol(self, spectrumView, objListView, delObj):
"""Remove a symbol from the list
"""
symbolType = self.strip.symbolType
drawList = self._GLSymbols[objListView]
self.objIsInVisiblePlanesRemove(spectrumView, delObj) # probably only needed in create/change
indexOffset = 0
numPoints = 0
pp = 0
while (pp < len(drawList.pids)):
# check whether the peaks still exists
obj = drawList.pids[pp]
if obj == delObj:
offset = drawList.pids[pp + 1]
numPoints = drawList.pids[pp + 2]
if symbolType != 0 and symbolType != 3: # not a cross/plus
numPoints = 2 * numPoints + 5
# _isInPlane = drawList.pids[pp + 3]
# _isInFlankingPlane = drawList.pids[pp + 4]
# _selected = drawList.pids[pp + 5]
indexStart = drawList.pids[pp + 6]
indexEnd = drawList.pids[pp + 7]
indexOffset = indexEnd - indexStart
drawList.indices = np.delete(drawList.indices, np.s_[indexStart:indexEnd])
drawList.vertices = np.delete(drawList.vertices, np.s_[2 * offset:2 * (offset + numPoints)])
drawList.attribs = np.delete(drawList.attribs, np.s_[offset:offset + numPoints])
drawList.offsets = np.delete(drawList.offsets, np.s_[2 * offset:2 * (offset + numPoints)])
drawList.colors = np.delete(drawList.colors, np.s_[4 * offset:4 * (offset + numPoints)])
drawList.pids = np.delete(drawList.pids, np.s_[pp:pp + GLDefs.LENPID])
drawList.numVertices -= numPoints
# subtract the offset from all the higher indices to account for the removed points
drawList.indices[np.where(drawList.indices >= offset)] -= numPoints
break
else:
pp += GLDefs.LENPID
# clean up the rest of the list
while (pp < len(drawList.pids)):
drawList.pids[pp + 1] -= numPoints
drawList.pids[pp + 6] -= indexOffset
drawList.pids[pp + 7] -= indexOffset
pp += GLDefs.LENPID
_squareSymbol = ((np.array((0, 1, 2, 3), dtype=np.uint32), np.array((0, 1, 2, 3, 0, 2, 2, 1, 0, 3, 3, 1), dtype=np.uint32)),
(np.array((0, 4, 4, 3, 3, 0), dtype=np.uint32), np.array((0, 4, 4, 3, 3, 0, 0, 2, 2, 1, 3, 1), dtype=np.uint32)),
(np.array((2, 4, 4, 1, 1, 2), dtype=np.uint32), np.array((2, 4, 4, 1, 1, 2, 0, 2, 0, 3, 3, 1), dtype=np.uint32)))
_squareSymbolLen = tuple(tuple(len(sq) for sq in squareList) for squareList in _squareSymbol)
def _getSquareSymbolCount(self, planeIndex, obj):
"""returns the number of indices required for the symbol based on the planeIndex
type of planeIndex - currently 0/1/2 indicating whether normal, infront or behind
currently visible planes
"""
return self._squareSymbolLen[planeIndex % 3][self._isSelected(obj)]
def _makeSquareSymbol(self, drawList, indexEnd, vertexStart, planeIndex, obj):
"""Make a new square symbol based on the planeIndex type.
"""
_selected = self._isSelected(obj)
_indices = self._squareSymbol[planeIndex % 3][_selected] + vertexStart
iCount = len(_indices)
drawList.indices[indexEnd:indexEnd + iCount] = _indices
return iCount, _selected
def _appendSquareSymbol(self, drawList, vertexStart, planeIndex, obj):
"""Append a new square symbol based on the planeIndex type.
"""
_selected = self._isSelected(obj)
_indices = self._squareSymbol[planeIndex % 3][_selected] + vertexStart
iCount = len(_indices)
drawList.indices = np.append(drawList.indices, _indices)
return iCount, _selected
_plusSymbol = ((np.array((5, 6, 7, 8), dtype=np.uint32), np.array((5, 6, 7, 8, 0, 2, 2, 1, 0, 3, 3, 1), dtype=np.uint32)),
(np.array((6, 4, 4, 5, 4, 8), dtype=np.uint32), np.array((6, 4, 4, 5, 4, 8, 0, 2, 2, 1, 3, 1, 0, 3), dtype=np.uint32)),
(np.array((6, 4, 4, 5, 4, 7), dtype=np.uint32), np.array((6, 4, 4, 5, 4, 7, 0, 2, 2, 1, 3, 1, 0, 3), dtype=np.uint32)))
_plusSymbolLen = tuple(tuple(len(sq) for sq in squareList) for squareList in _plusSymbol)
def _getPlusSymbolCount(self, planeIndex, obj):
"""returns the number of indices required for the symbol based on the planeIndex
type of planeIndex - currently 0/1/2 indicating whether normal, infront or behind
currently visible planes
"""
return self._plusSymbolLen[planeIndex % 3][self._isSelected(obj)]
def _makePlusSymbol(self, drawList, indexEnd, vertexStart, planeIndex, obj):
"""Make a new plus symbol based on the planeIndex type.
"""
_selected = self._isSelected(obj)
_indices = self._plusSymbol[planeIndex % 3][_selected] + vertexStart
iCount = len(_indices)
drawList.indices[indexEnd:indexEnd + iCount] = _indices
return iCount, _selected
def _appendPlusSymbol(self, drawList, vertexStart, planeIndex, obj):
"""Append a new plus symbol based on the planeIndex type.
"""
_selected = self._isSelected(obj)
_indices = self._plusSymbol[planeIndex % 3][_selected] + vertexStart
iCount = len(_indices)
drawList.indices = np.append(drawList.indices, _indices)
return iCount, _selected
def _insertSymbolItem(self, strip, obj, listCol, indexing, r, w,
spectrumFrequency, symbolType, drawList, spectrumView, tCount):
"""insert a single symbol to the end of the symbol list
"""
# indexStart = indexing.start
indexEnd = indexing.end
objNum = indexing.objNum
vertexPtr = indexing.vertexPtr
vertexStart = indexing.vertexStart
# get visible/plane status
_isInPlane, _isInFlankingPlane, planeIndex, fade = self.objIsInVisiblePlanes(spectrumView, obj)
# skip if not visible
if not _isInPlane and not _isInFlankingPlane:
return
if self._isSelected(obj):
cols = self._GLParent.highlightColour[:3]
else:
cols = listCol
pIndex = self._spectrumSettings[spectrumView][GLDefs.SPECTRUM_POINTINDEX]
objPos = obj.pointPositions
objLineWidths = obj.pointLineWidths
p0 = (objPos[pIndex[0]] - 1, objPos[pIndex[1]] - 1)
pointLineWidths = (objLineWidths[pIndex[0]], objLineWidths[pIndex[1]])
frequency = (spectrumFrequency[pIndex[0]], spectrumFrequency[pIndex[1]])
_alias = obj.aliasing
# alias = 1024 * _alias[pIndex[0]] + _alias[pIndex[1]]
alias = getAliasSetting(_alias[pIndex[0]], _alias[pIndex[1]])
if None in p0:
getLogger().warning('Object %s contains undefined position %s' % (str(obj.pid), str(p0)))
return
if not pIndex:
# if axisCount != 2:
getLogger().debug('Bad axisCodes: %s - %s' % (obj.pid, obj.axisCodes))
else:
if symbolType == 0 or symbolType == 3:
# draw a cross
# keep the cross square at 0.1ppm
_selected = False
iCount = 0
# unselected
if _isInPlane or _isInFlankingPlane:
if symbolType == 0: # cross
iCount, _selected = self._makeSquareSymbol(drawList, indexEnd, vertexStart, planeIndex, obj)
else:
iCount, _selected = self._makePlusSymbol(drawList, indexEnd, vertexStart, planeIndex, obj)
# add extra indices
self._insertSymbolItemVertices(_isInFlankingPlane, _isInPlane, _selected, cols, drawList, fade, iCount, indexing, obj,
objNum, p0, pIndex, planeIndex, r, vertexPtr, w, alias)
elif symbolType == 1: # draw an ellipse at lineWidth
if pointLineWidths[0] and pointLineWidths[1]:
# draw 24 connected segments
r = 0.5 * pointLineWidths[0]
w = 0.5 * pointLineWidths[1]
numPoints = 24
angPlus = 2.0 * np.pi
skip = 1
else:
# draw 12 disconnected segments (dotted)
# r = symbolWidth
# w = symbolWidth
numPoints = 12
angPlus = np.pi
skip = 2
np2 = 2 * numPoints
ang = list(range(numPoints))
_selected = False
# # need to subclass the different point types a lot better :|
# _numPoints = 24
# _angPlus = 2.0 * np.pi
# _skip = 1
# _ang = list(range(numPoints))
# _indicesLineWidth = np.array(tuple(val for an in _ang for val in ((2 * an), (2 * an) + 1)), dtype=np.uint32)
# _np1 = len(_indicesLineWidth)
# _indicesLineWidthSelect = _indicesLineWidth + np.array((_np1, _np1 + 2,
# _np1 + 2, _np1 + 1,
# _np1, _np1 + 3,
# _np1 + 3, _np1 + 1), dtype=np.uint32)
# _np2 = len(_indicesLineWidthSelect)
#
# _vertexLineWidth = np.array(tuple(val for an in _ang
# for val in (- r * math.sin(_skip * an * _angPlus / _numPoints),
# - w * math.cos(_skip * an * _angPlus / _numPoints),
# - r * math.sin((_skip * an + 1) * _angPlus / _numPoints),
# - w * math.cos((_skip * an + 1) * _angPlus / _numPoints))), dtype=np.float32) + \
# np.array((- r, - w, + r, + w, + r, - w, - r, + w, 0, 0), dtype=np.float32)
# _vp1 = len(_vertexLineWidth)
# _vp2 = _vp1 // 2
#
# if self._isSelected(obj):
# iCount = _np1
# drawList.indices[indexEnd:indexEnd + _np1] = _indicesLineWidth + indexStart
# else:
# iCount = _np2
# drawList.indices[indexEnd:indexEnd + _np2] = _indicesLineWidthSelect + indexStart
#
# _pos = (p0[0], p0[1]) * _vp2
# drawList.vertices[vertexPtr:vertexPtr + _vp1] = _vertexLineWidth + _pos
_vertexStart = indexing.vertexStart
if _isInPlane or _isInFlankingPlane:
drawList.indices[indexEnd:indexEnd + np2] = tuple(val for an in ang
for val in (_vertexStart + (2 * an), _vertexStart + (2 * an) + 1))
iCount = np2
if self._isSelected(obj):
_selected = True
drawList.indices[indexEnd + np2:indexEnd + np2 + 8] = (_vertexStart + np2, _vertexStart + np2 + 2,
_vertexStart + np2 + 2, _vertexStart + np2 + 1,
_vertexStart + np2, _vertexStart + np2 + 3,
_vertexStart + np2 + 3, _vertexStart + np2 + 1)
iCount += 8
# add extra indices
extraIndices = 0 #self.appendExtraIndices(drawList, indexStart + np2, obj)
# draw an ellipse at lineWidth
drawList.vertices[vertexPtr:vertexPtr + 2 * np2] = tuple(val for an in ang
for val in (p0[0] - r * math.sin(skip * an * angPlus / numPoints),
p0[1] - w * math.cos(skip * an * angPlus / numPoints),
p0[0] - r * math.sin((skip * an + 1) * angPlus / numPoints),
p0[1] - w * math.cos((skip * an + 1) * angPlus / numPoints)))
drawList.vertices[vertexPtr + 2 * np2:vertexPtr + 2 * np2 + 10] = (p0[0] - r, p0[1] - w,
p0[0] + r, p0[1] + w,
p0[0] + r, p0[1] - w,
p0[0] - r, p0[1] + w,
p0[0], p0[1])
drawList.colors[2 * vertexPtr:2 * vertexPtr + 4 * np2 + 20] = (*cols, fade) * (np2 + 5)
drawList.attribs[vertexPtr // 2:(vertexPtr // 2) + np2 + 5] = (alias,) * (np2 + 5)
drawList.offsets[vertexPtr:vertexPtr + 2 * np2 + 10] = (p0[0], p0[1]) * (np2 + 5)
# add extra vertices
extraVertices = 0 #self.appendExtraVertices(drawList, obj, p0, [*cols, fade], fade)
# keep a pointer to the obj
drawList.pids[objNum:objNum + GLDefs.LENPID] = (obj, drawList.numVertices, (numPoints + extraVertices),
_isInPlane, _isInFlankingPlane, _selected,
indexEnd, indexEnd + iCount + extraIndices,
planeIndex, 0, 0, 0)
indexing.start += ((np2 + 5) + extraIndices)
indexing.end += (iCount + extraIndices) # len(drawList.indices)
drawList.numVertices += ((np2 + 5) + extraVertices)
indexing.objNum += GLDefs.LENPID
indexing.vertexPtr += (2 * ((np2 + 5) + extraVertices))
indexing.vertexStart += ((np2 + 5) + extraVertices)
elif symbolType == 2: # draw a filled ellipse at lineWidth
if pointLineWidths[0] and pointLineWidths[1]:
# draw 24 connected segments
r = 0.5 * pointLineWidths[0] # / frequency[0]
w = 0.5 * pointLineWidths[1] # / frequency[1]
numPoints = 24
angPlus = 2 * np.pi
skip = 1
else:
# draw 12 disconnected segments (dotted)
# r = symbolWidth
# w = symbolWidth
numPoints = 12
angPlus = 1.0 * np.pi
skip = 2
np2 = 2 * numPoints
ang = list(range(numPoints))
_selected = False
_vertexStart = indexing.vertexStart
if _isInPlane or _isInFlankingPlane:
drawList.indices[indexEnd:indexEnd + 3 * numPoints] = tuple(val for an in ang
for val in (_vertexStart + (2 * an), _vertexStart + (2 * an) + 1, _vertexStart + np2 + 4))
iCount = 3 * numPoints
# add extra indices
extraIndices = 0 #self.appendExtraIndices(drawList, indexStart + np2 + 4, obj)
# draw an ellipse at lineWidth
drawList.vertices[vertexPtr:vertexPtr + 2 * np2] = tuple(val for an in ang
for val in (p0[0] - r * math.sin(skip * an * angPlus / numPoints),
p0[1] - w * math.cos(skip * an * angPlus / numPoints),
p0[0] - r * math.sin((skip * an + 1) * angPlus / numPoints),
p0[1] - w * math.cos((skip * an + 1) * angPlus / numPoints)))
drawList.vertices[vertexPtr + 2 * np2:vertexPtr + 2 * np2 + 10] = (p0[0] - r, p0[1] - w,
p0[0] + r, p0[1] + w,
p0[0] + r, p0[1] - w,
p0[0] - r, p0[1] + w,
p0[0], p0[1])
drawList.colors[2 * vertexPtr:2 * vertexPtr + 4 * np2 + 20] = (*cols, fade) * (np2 + 5)
drawList.attribs[vertexPtr // 2:(vertexPtr // 2) + np2 + 5] = (alias,) * (np2 + 5)
drawList.offsets[vertexPtr:vertexPtr + 2 * np2 + 10] = (p0[0], p0[1]) * (np2 + 5)
# add extra vertices for the multiplet
extraVertices = 0 #self.appendExtraVertices(drawList, obj, p0, [*cols, fade], fade)
# keep a pointer to the obj
drawList.pids[objNum:objNum + GLDefs.LENPID] = (obj, drawList.numVertices, (numPoints + extraVertices),
_isInPlane, _isInFlankingPlane, _selected,
indexEnd, indexEnd + iCount + extraIndices,
planeIndex, 0, 0, 0)
indexing.start += ((np2 + 5) + extraIndices)
indexing.end += (iCount + extraIndices) # len(drawList.indices)
drawList.numVertices += ((np2 + 5) + extraVertices)
indexing.objNum += GLDefs.LENPID
indexing.vertexPtr += (2 * ((np2 + 5) + extraVertices))
indexing.vertexStart += ((np2 + 5) + extraVertices)
else:
raise ValueError('GL Error: bad symbol type')
def _insertSymbolItemVertices(self, _isInFlankingPlane, _isInPlane, _selected, cols, drawList, fade, iCount, indexing, obj,
objNum, p0, pIndex, planeIndex, r, vertexPtr, w, alias):
drawList.vertices[vertexPtr:vertexPtr + self.LENSQ2] = (p0[0] - r, p0[1] - w,
p0[0] + r, p0[1] + w,
p0[0] + r, p0[1] - w,
p0[0] - r, p0[1] + w,
p0[0], p0[1],
p0[0], p0[1] - w,
p0[0], p0[1] + w,
p0[0] + r, p0[1],
p0[0] - r, p0[1]
)
drawList.colors[2 * vertexPtr:2 * vertexPtr + self.LENSQ4] = (*cols, fade) * self.LENSQ
drawList.attribs[vertexPtr // 2:(vertexPtr // 2) + self.LENSQ] = (alias,) * self.LENSQ
drawList.offsets[vertexPtr:vertexPtr + self.LENSQ2] = (p0[0], p0[1]) * self.LENSQ
# add extra indices
extraIndices, extraIndexCount = self.insertExtraIndices(drawList, indexing.end + iCount, indexing.start + self.LENSQ, obj)
# add extra vertices for the multiplet
extraVertices = self.insertExtraVertices(drawList, vertexPtr + self.LENSQ2, pIndex, obj, p0, (*cols, fade), fade)
# keep a pointer to the obj
drawList.pids[objNum:objNum + GLDefs.LENPID] = (obj, drawList.numVertices, (self.LENSQ + extraVertices),
_isInPlane, _isInFlankingPlane, _selected,
indexing.end, indexing.end + iCount + extraIndices,
planeIndex, 0, 0, 0)
indexing.start += (self.LENSQ + extraIndexCount)
indexing.end += (iCount + extraIndices) # len(drawList.indices)
drawList.numVertices += (self.LENSQ + extraVertices)
indexing.objNum += GLDefs.LENPID
indexing.vertexPtr += (2 * (self.LENSQ + extraVertices))
indexing.vertexStart += (self.LENSQ + extraVertices)
# NOTE:ED - new pre-defined indices/vertex lists
# # indices for lineWidth symbols, not selected/selected in different number of points
# _lineWidthIndices = {numPoints: ((np.append(np.array(tuple(val for an in range(numPoints) for val in ((2 * an), (2 * an) + 1)), dtype=np.uint32),
# np.array((0, 1, 2, 3), dtype=np.uint32)),
# np.append(np.array(tuple(val for an in range(numPoints) for val in ((2 * an), (2 * an) + 1)), dtype=np.uint32),
# np.array((0, 1, 2, 3, 0, 2, 2, 1, 0, 3, 3, 1), dtype=np.uint32))))
# for numPoints in (12, 18, 24, 36)}
#
# # vertices for lineWidth symbols
# _lineWidthVertices = {numPoints: np.append(np.array(tuple(val for an in range(numPoints)
# for val in (- math.sin(skip * an * angPlus / numPoints),
# - math.cos(skip * an * angPlus / numPoints),
# - math.sin((skip * an + 1) * angPlus / numPoints),
# - math.cos((skip * an + 1) * angPlus / numPoints)))),
# np.array((-1, -1, 1, 1, 1, -1, -1, 1, 0, 0), dtype=np.float32))
# for numPoints, skip, angPlus in ((12),
# (18),
# (24),
# (36))}
def _appendSymbolItem(self, strip, obj, listCol, indexing, r, w,
spectrumFrequency, symbolType, drawList, spectrumView):
"""append a single symbol to the end of the symbol list
"""
# indexStart, indexEnd are indexes into the drawList.indices for the indices for this symbol
# indexStart = indexing.start # indexList[0]
indexEnd = indexing.end #indexList[1]
vertexStart = indexing.vertexStart
# get visible/plane status
_isInPlane, _isInFlankingPlane, planeIndex, fade = self.objIsInVisiblePlanes(spectrumView, obj)
# skip if not visible
if not _isInPlane and not _isInFlankingPlane:
return
if self._isSelected(obj):
cols = self._GLParent.highlightColour[:3]
else:
cols = listCol
pIndex = self._spectrumSettings[spectrumView][GLDefs.SPECTRUM_POINTINDEX]
objPos = obj.pointPositions
objLineWidths = obj.pointLineWidths
if not objPos or not objLineWidths:
getLogger().debug('Object %s contains undefined position' % str(obj.pid))
return
p0 = (objPos[pIndex[0]] - 1, objPos[pIndex[1]] - 1)
pointLineWidths = (objLineWidths[pIndex[0]], objLineWidths[pIndex[1]])
frequency = (spectrumFrequency[pIndex[0]], spectrumFrequency[pIndex[1]])
_alias = obj.aliasing
# alias = 1024 * _alias[pIndex[0]] + _alias[pIndex[1]]
alias = getAliasSetting(_alias[pIndex[0]], _alias[pIndex[1]])
if None in p0:
getLogger().debug('Object %s contains undefined position %s' % (str(obj.pid), str(p0)))
return
if not pIndex:
# if axisCount != 2:
getLogger().debug('Bad axisCodes: %s - %s' % (obj.pid, obj.axisCodes))
else:
if symbolType == 0 or symbolType == 3:
# draw a cross
# keep the cross square at 0.1ppm
_selected = False
iCount = 0
if _isInPlane or _isInFlankingPlane:
if symbolType == 0: # cross
iCount, _selected = self._appendSquareSymbol(drawList, vertexStart, planeIndex, obj)
else: # plus
iCount, _selected = self._appendPlusSymbol(drawList, vertexStart, planeIndex, obj)
self._appendSymbolItemVertices(_isInFlankingPlane, _isInPlane, _selected, cols, drawList, fade, iCount, indexing,
obj, p0, pIndex, planeIndex, r, w, alias)
elif symbolType == 1: # draw an ellipse at lineWidth
if pointLineWidths[0] and pointLineWidths[1]:
# draw 24 connected segments
r = 0.5 * pointLineWidths[0] # / frequency[0]
w = 0.5 * pointLineWidths[1] # / frequency[1]
numPoints = 24
angPlus = 2.0 * np.pi
skip = 1
else:
# draw 12 disconnected segments (dotted)
# r = symbolWidth
# w = symbolWidth
numPoints = 12
angPlus = np.pi
skip = 2
np2 = 2 * numPoints
ang = list(range(numPoints))
_selected = False
iCount = 0
_vertexStart = indexing.vertexStart
if _isInPlane or _isInFlankingPlane:
drawList.indices = np.append(drawList.indices, np.array(tuple(val for an in ang
for val in ((2 * an), (2 * an) + 1)), dtype=np.uint32) + _vertexStart)
iCount = np2
if self._isSelected(obj):
_selected = True
drawList.indices = np.append(drawList.indices, np.array((0, 2, 2, 1, 0, 3, 3, 1), dtype=np.uint32) + (_vertexStart + np2))
iCount += 8
# add extra indices for the multiplet
extraIndices = 0 #self.appendExtraIndices(drawList, indexStart + np2, obj)
# draw an ellipse at lineWidth
drawList.vertices = np.append(drawList.vertices, np.array(tuple(val for an in ang
for val in (p0[0] - r * math.sin(skip * an * angPlus / numPoints),
p0[1] - w * math.cos(skip * an * angPlus / numPoints),
p0[0] - r * math.sin((skip * an + 1) * angPlus / numPoints),
p0[1] - w * math.cos((skip * an + 1) * angPlus / numPoints))),
dtype=np.float32))
drawList.vertices = np.append(drawList.vertices, np.array((p0[0] - r, p0[1] - w,
p0[0] + r, p0[1] + w,
p0[0] + r, p0[1] - w,
p0[0] - r, p0[1] + w,
p0[0], p0[1]), dtype=np.float32))
drawList.colors = np.append(drawList.colors, np.array((*cols, fade) * (np2 + 5), dtype=np.float32))
drawList.attribs = np.append(drawList.attribs, np.array((alias,) * (np2 + 5), dtype=np.float32))
drawList.offsets = np.append(drawList.offsets, np.array((p0[0], p0[1]) * (np2 + 5), dtype=np.float32))
# add extra vertices for the multiplet
extraVertices = 0 #self.appendExtraVertices(drawList, obj, p0, [*cols, fade], fade)
# keep a pointer to the obj
drawList.pids = np.append(drawList.pids, (obj, drawList.numVertices, (numPoints + extraVertices),
_isInPlane, _isInFlankingPlane, _selected,
indexEnd, indexEnd + iCount + extraIndices,
planeIndex, 0, 0, 0))
# indexEnd = len(drawList.indices)
# indexList[0] += ((np2 + 5) + extraIndices)
# indexList[1] = len(drawList.indices)
indexing.start += ((np2 + 5) + extraIndices)
indexing.end += (iCount + extraIndices) # len(drawList.indices)
drawList.numVertices += ((np2 + 5) + extraVertices)
indexing.vertexStart += ((np2 + 5) + extraVertices)
elif symbolType == 2: # draw a filled ellipse at lineWidth
if pointLineWidths[0] and pointLineWidths[1]:
# draw 24 connected segments
r = 0.5 * pointLineWidths[0] # / frequency[0]
w = 0.5 * pointLineWidths[1] # / frequency[1]
numPoints = 24
angPlus = 2 * np.pi
skip = 1
else:
# draw 12 disconnected segments (dotted)
# r = symbolWidth
# w = symbolWidth
numPoints = 12
angPlus = 1.0 * np.pi
skip = 2
np2 = 2 * numPoints
ang = list(range(numPoints))
_selected = False
iCount = 0
_vertexStart = indexing.vertexStart
if _isInPlane or _isInFlankingPlane:
drawList.indices = np.append(drawList.indices,
np.array(tuple(val for an in ang
for val in ((2 * an), (2 * an) + 1, np2 + 4)), dtype=np.uint32) + _vertexStart)
iCount = 3 * numPoints
# add extra indices for the multiplet
extraIndices = 0 #self.appendExtraIndices(drawList, indexStart + np2 + 4, obj)
# draw an ellipse at lineWidth
drawList.vertices = np.append(drawList.vertices, np.array(tuple(val for an in ang
for val in (p0[0] - r * math.sin(skip * an * angPlus / numPoints),
p0[1] - w * math.cos(skip * an * angPlus / numPoints),
p0[0] - r * math.sin((skip * an + 1) * angPlus / numPoints),
p0[1] - w * math.cos((skip * an + 1) * angPlus / numPoints))),
dtype=np.float32))
drawList.vertices = np.append(drawList.vertices, np.array((p0[0] - r, p0[1] - w,
p0[0] + r, p0[1] + w,
p0[0] + r, p0[1] - w,
p0[0] - r, p0[1] + w,
p0[0], p0[1]), dtype=np.float32))
drawList.colors = np.append(drawList.colors, np.array((*cols, fade) * (np2 + 5), dtype=np.float32))
drawList.attribs = np.append(drawList.attribs, np.array((alias,) * (np2 + 5), dtype=np.float32))
drawList.offsets = np.append(drawList.offsets, np.array((p0[0], p0[1]) * (np2 + 5), dtype=np.float32))
# add extra vertices for the multiplet
extraVertices = 0 #self.appendExtraVertices(drawList, obj, p0, [*cols, fade], fade)
# keep a pointer to the obj
drawList.pids = np.append(drawList.pids, (obj, drawList.numVertices, (numPoints + extraVertices),
_isInPlane, _isInFlankingPlane, _selected,
indexEnd, indexEnd + iCount + extraIndices,
planeIndex, 0, 0, 0))
indexing.start += ((np2 + 5) + extraIndices)
indexing.end += (iCount + extraIndices)
drawList.numVertices += ((np2 + 5) + extraVertices)
indexing.vertexStart += ((np2 + 5) + extraVertices)
else:
raise ValueError('GL Error: bad symbol type')
def _appendSymbolItemVertices(self, _isInFlankingPlane, _isInPlane, _selected, cols, drawList, fade, iCount, indexing, obj, p0, pIndex,
planeIndex, r, w, alias):
drawList.vertices = np.append(drawList.vertices, np.array((p0[0] - r, p0[1] - w,
p0[0] + r, p0[1] + w,
p0[0] + r, p0[1] - w,
p0[0] - r, p0[1] + w,
p0[0], p0[1],
p0[0], p0[1] - w,
p0[0], p0[1] + w,
p0[0] + r, p0[1],
p0[0] - r, p0[1]
), dtype=np.float32))
drawList.colors = np.append(drawList.colors, np.array((*cols, fade) * self.LENSQ, dtype=np.float32))
drawList.attribs = np.append(drawList.attribs, np.array((alias,) * self.LENSQ, dtype=np.float32))
drawList.offsets = np.append(drawList.offsets, np.array((p0[0], p0[1]) * self.LENSQ, dtype=np.float32))
# called extraIndices, extraIndexCount above
# add extra indices
_indexCount, extraIndices = self.appendExtraIndices(drawList, indexing.vertexStart + self.LENSQ, obj)
# add extra vertices for the multiplet
extraVertices = self.appendExtraVertices(drawList, pIndex, obj, p0, (*cols, fade), fade)
# keep a pointer to the obj
drawList.pids = np.append(drawList.pids, (obj, drawList.numVertices, (self.LENSQ + extraVertices),
_isInPlane, _isInFlankingPlane, _selected,
indexing.end, indexing.end + iCount + _indexCount, planeIndex, 0, 0, 0))
indexing.start += (self.LENSQ + extraIndices)
indexing.end += (iCount + _indexCount)
drawList.numVertices += (self.LENSQ + extraVertices)
indexing.vertexStart += (self.LENSQ + extraVertices)
def _appendSymbol(self, spectrumView, objListView, obj):
"""Append a new symbol to the end of the list
"""
spectrum = spectrumView.spectrum
drawList = self._GLSymbols[objListView]
self.objIsInVisiblePlanesRemove(spectrumView, obj)
# find the correct scale to draw square pixels
# don't forget to change when the axes change
_, _, symbolType, symbolWidth, r, w = self._getSymbolWidths(spectrumView)
if symbolType == 0 or symbolType == 3: # a cross/plus
# change the ratio on resize
drawList.refreshMode = GLREFRESHMODE_REBUILD
drawList.drawMode = GL.GL_LINES
drawList.fillMode = None
elif symbolType == 1: # draw an ellipse at lineWidth
# fix the size to the axes
drawList.refreshMode = GLREFRESHMODE_NEVER
drawList.drawMode = GL.GL_LINES
drawList.fillMode = None
elif symbolType == 2: # draw a filled ellipse at lineWidth
# fix the size to the axes
drawList.refreshMode = GLREFRESHMODE_NEVER
drawList.drawMode = GL.GL_TRIANGLES
drawList.fillMode = GL.GL_FILL
else:
raise ValueError('GL Error: bad symbol type')
# build the peaks VBO
indexing = AttrDict()
indexing.start = len(drawList.indices)
indexing.end = len(drawList.indices)
indexing.vertexStart = drawList.numVertices
pls = self.objectList(objListView)
if objListView.meritEnabled and obj.figureOfMerit < objListView.meritThreshold:
objCol = objListView.meritColour or GLDefs.DEFAULTCOLOUR
else:
objCol = objListView.symbolColour or GLDefs.DEFAULTCOLOUR
listCol = getAutoColourRgbRatio(objCol, pls.spectrum,
self.autoColour,
getColours()[CCPNGLWIDGET_FOREGROUND])
spectrumFrequency = spectrum.spectrometerFrequencies
strip = spectrumView.strip
self._appendSymbolItem(strip, obj, listCol, indexing, r, w,
spectrumFrequency, symbolType, drawList, spectrumView)
def _updateHighlightedLabels(self, spectrumView, objListView):
if objListView not in self._GLLabels:
return
drawList = self._GLLabels[objListView]
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:
# get visible/plane status
_isInPlane, _isInFlankingPlane, planeIndex, fade = self.objIsInVisiblePlanes(spectrumView, obj)
if _isInPlane or _isInFlankingPlane:
if self._isSelected(obj):
drawStr.setStringColour((*self._GLParent.highlightColour[:3], fade))
else:
if meritEnabled and obj.figureOfMerit < meritThreshold:
cols = meritCol
else:
cols = listCol
drawStr.setStringColour((*cols, fade))
drawStr.updateTextArrayVBOColour()
[docs] def updateHighlightSymbols(self):
"""Respond to an update highlight notifier and update the highlighted symbols/labels
"""
for spectrumView in self._ordering:
if spectrumView.isDeleted:
continue
for objListView in self.listViews(spectrumView):
if objListView in self._GLSymbols.keys():
self._updateHighlightedSymbols(spectrumView, objListView)
self._updateHighlightedLabels(spectrumView, objListView)
[docs] def updateAllSymbols(self):
"""Respond to update all notifier
"""
for spectrumView in self._ordering:
if spectrumView.isDeleted:
continue
for objListView in self.listViews(spectrumView):
if objListView in self._GLSymbols.keys():
objListView.buildSymbols = True
objListView.buildLabels = True
def _updateHighlightedSymbols(self, spectrumView, objListView):
"""update the highlighted symbols
"""
strip = self.strip
symbolType = strip.symbolType
drawList = self._GLSymbols[objListView]
drawList.indices = np.empty(0, dtype=np.uint32)
indexStart = 0
indexEnd = 0
vertexStart = 0
pls = self.objectList(objListView)
listCol = getAutoColourRgbRatio(objListView.symbolColour 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 symbolType == 0 or symbolType == 3:
for pp in range(0, len(drawList.pids), GLDefs.LENPID):
# check whether the peaks still exists
obj = drawList.pids[pp]
offset = drawList.pids[pp + 1]
numPoints = drawList.pids[pp + 2]
if not obj.isDeleted:
_selected = False
iCount = 0
_indexCount = 0
# get visible/plane status
_isInPlane, _isInFlankingPlane, planeIndex, fade = self.objIsInVisiblePlanes(spectrumView, obj)
if _isInPlane or _isInFlankingPlane:
if symbolType == 0: # cross
iCount, _selected = self._appendSquareSymbol(drawList, vertexStart, planeIndex, obj)
else: # plus
iCount, _selected = self._appendPlusSymbol(drawList, vertexStart, planeIndex, obj)
if _selected:
cols = self._GLParent.highlightColour[:3]
else:
if meritEnabled and obj.figureOfMerit < meritThreshold:
cols = meritCol
else:
cols = listCol
# make sure that links for the multiplets are added
_indexCount, extraIndices = self.appendExtraIndices(drawList, indexStart + self.LENSQ, obj)
drawList.colors[offset * 4:(offset + self.POINTCOLOURS) * 4] = (*cols, fade) * self.POINTCOLOURS #numPoints
# list MAY contain out of plane peaks
drawList.pids[pp + 3:pp + 9] = (_isInPlane, _isInFlankingPlane, _selected,
indexEnd, indexEnd + iCount + _indexCount, planeIndex)
indexEnd += (iCount + _indexCount)
indexStart += numPoints
vertexStart += numPoints
elif symbolType == 1:
for pp in range(0, len(drawList.pids), GLDefs.LENPID):
# check whether the peaks still exists
obj = drawList.pids[pp]
offset = drawList.pids[pp + 1]
numPoints = drawList.pids[pp + 2]
np2 = 2 * numPoints
if not obj.isDeleted:
ang = list(range(numPoints))
_selected = False
# get visible/plane status
_isInPlane, _isInFlankingPlane, planeIndex, fade = self.objIsInVisiblePlanes(spectrumView, obj)
if _isInPlane or _isInFlankingPlane:
drawList.indices = np.append(drawList.indices, np.array(tuple(val for an in ang
for val in (indexStart + (2 * an), indexStart + (2 * an) + 1)), dtype=np.uint32))
if self._isSelected(obj):
_selected = True
cols = self._GLParent.highlightColour[:3]
drawList.indices = np.append(drawList.indices, np.array((indexStart + np2, indexStart + np2 + 2,
indexStart + np2 + 2, indexStart + np2 + 1,
indexStart + np2, indexStart + np2 + 3,
indexStart + np2 + 3, indexStart + np2 + 1), dtype=np.uint32))
else:
if objListView.meritEnabled and obj.figureOfMerit < objListView.meritThreshold:
cols = meritCol
else:
cols = listCol
drawList.colors[offset * 4:(offset + np2 + 5) * 4] = (*cols, fade) * (np2 + 5)
drawList.pids[pp + 3:pp + 9] = (_isInPlane, _isInFlankingPlane, _selected,
indexEnd, len(drawList.indices), planeIndex)
indexEnd = len(drawList.indices)
indexStart += np2 + 5
elif symbolType == 2:
for pp in range(0, len(drawList.pids), GLDefs.LENPID):
# check whether the peaks still exists
obj = drawList.pids[pp]
offset = drawList.pids[pp + 1]
numPoints = drawList.pids[pp + 2]
np2 = 2 * numPoints
if not obj.isDeleted:
ang = list(range(numPoints))
_selected = False
# get visible/plane status
_isInPlane, _isInFlankingPlane, planeIndex, fade = self.objIsInVisiblePlanes(spectrumView, obj)
if _isInPlane or _isInFlankingPlane:
drawList.indices = np.append(drawList.indices, np.array(tuple(val for an in ang
for val in (2 * an, (2 * an) + 1, np2 + 4)),
dtype=np.uint32) + indexStart)
if self._isSelected(obj):
_selected = True
cols = self._GLParent.highlightColour[:3]
else:
if objListView.meritEnabled and obj.figureOfMerit < objListView.meritThreshold:
cols = meritCol
else:
cols = listCol
drawList.colors[offset * 4:(offset + np2 + 5) * 4] = (*cols, fade) * (np2 + 5)
drawList.pids[pp + 3:pp + 9] = (_isInPlane, _isInFlankingPlane, _selected,
indexEnd, len(drawList.indices), planeIndex)
indexEnd = len(drawList.indices)
indexStart += np2 + 5
else:
raise ValueError('GL Error: bad symbol type')
drawList.updateIndexVBOIndices()
drawList.updateTextArrayVBOColour()
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Rescaling
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def _rescaleSymbolOffsets(self, r, w):
return np.array([-r, -w, +r, +w, +r, -w, -r, +w, 0, 0, 0, -w, 0, +w, +r, 0, -r, 0], np.float32), self.LENSQ2
def _rescaleSymbols(self, spectrumView, objListView):
"""rescale symbols when the screen dimensions change
"""
drawList = self._GLSymbols[objListView]
if not drawList.numVertices:
return
# if drawList.refreshMode == GLREFRESHMODE_REBUILD:
_, _, symbolType, symbolWidth, r, w = self._getSymbolWidths(spectrumView)
if symbolType == 0 or symbolType == 3: # a cross/plus
offsets, offsetsLENSQ2 = self._rescaleSymbolOffsets(r, w)
for pp in range(0, len(drawList.pids), GLDefs.LENPID):
indexStart = 2 * drawList.pids[pp + 1]
try:
drawList.vertices[indexStart:indexStart + offsetsLENSQ2] = drawList.offsets[indexStart:indexStart + offsetsLENSQ2] + offsets
except:
raise RuntimeError('Error _rescaleSymbols')
pass
elif symbolType == 1: # an ellipse
numPoints = 12
angPlus = 1.0 * np.pi
skip = 2
np2 = 2 * numPoints
ang = list(range(numPoints))
offsets = np.empty(56)
for an in ang:
offsets[4 * an:4 * an + 4] = [- r * math.sin(skip * an * angPlus / numPoints),
- w * math.cos(skip * an * angPlus / numPoints),
- r * math.sin((skip * an + 1) * angPlus / numPoints),
- w * math.cos((skip * an + 1) * angPlus / numPoints)]
offsets[48:56] = [-r, -w, +r, +w, +r, -w, -r, +w]
for pp in range(0, len(drawList.pids), GLDefs.LENPID):
if drawList.pids[pp + 2] == 12:
indexStart = 2 * drawList.pids[pp + 1]
drawList.vertices[indexStart:indexStart + 56] = drawList.offsets[indexStart:indexStart + 56] + offsets
elif symbolType == 2: # filled ellipse
numPoints = 12
angPlus = 1.0 * np.pi
skip = 2
np2 = 2 * numPoints
ang = list(range(numPoints))
offsets = np.empty(48)
for an in ang:
offsets[4 * an:4 * an + 4] = [- r * math.sin(skip * an * angPlus / numPoints),
- w * math.cos(skip * an * angPlus / numPoints),
- r * math.sin((skip * an + 1) * angPlus / numPoints),
- w * math.cos((skip * an + 1) * angPlus / numPoints)]
for pp in range(0, len(drawList.pids), GLDefs.LENPID):
if drawList.pids[pp + 2] == 12:
indexStart = 2 * drawList.pids[pp + 1]
drawList.vertices[indexStart:indexStart + 48] = drawList.offsets[indexStart:indexStart + 48] + offsets
else:
raise ValueError('GL Error: bad symbol type')
def _rescaleLabels(self, spectrumView=None, objListView=None, drawList=None):
"""Rescale all labels to the new dimensions of the screen
"""
_, _, symbolType, symbolWidth, r, w = self._getSymbolWidths(spectrumView)
# NOTE:ED - could add in the peakItem offset at this point
if symbolType == 0 or symbolType == 3: # a cross/plus
for drawStr in drawList.stringList:
drawStr.setStringOffset((r, w))
drawStr.updateTextArrayVBOAttribs()
elif symbolType == 1:
for drawStr in drawList.stringList:
if drawStr.stringOffset:
lr, lw = drawStr.stringOffset
drawStr.setStringOffset((lr, lw))
else:
drawStr.setStringOffset((GLDefs.STRINGSCALE * r, GLDefs.STRINGSCALE * w))
drawStr.updateTextArrayVBOAttribs()
elif symbolType == 2:
for drawStr in drawList.stringList:
if drawStr.stringOffset:
lr, lw = drawStr.stringOffset
drawStr.setStringOffset((lr, lw))
else:
drawStr.setStringOffset((GLDefs.STRINGSCALE * r, GLDefs.STRINGSCALE * w))
drawStr.updateTextArrayVBOAttribs()
else:
raise ValueError('GL Error: bad symbol type')
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Building
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def _buildSymbolsCountItem(self, strip, spectrumView, obj, symbolType, tCount):
"""return the number of indices and vertices for the object
"""
# get visible/plane status
_isInPlane, _isInFlankingPlane, planeIndex, fade = self.objIsInVisiblePlanes(spectrumView, obj)
# skip if not visible
if not _isInPlane and not _isInFlankingPlane:
return 0, 0
if symbolType == 0: # draw a cross symbol
ind = self._getSquareSymbolCount(planeIndex, obj)
ind += self.extraIndicesCount(obj)
extraVertices = self.extraVerticesCount(obj)
vert = (self.LENSQ + extraVertices)
return ind, vert
elif symbolType == 3: # draw a plus symbol
ind = self._getPlusSymbolCount(planeIndex, obj)
ind += self.extraIndicesCount(obj)
extraVertices = self.extraVerticesCount(obj)
vert = (self.LENSQ + extraVertices)
return ind, vert
elif symbolType == 1: # draw an ellipse at lineWidth
if obj.pointLineWidths[0] and obj.pointLineWidths[1]:
numPoints = 24
else:
numPoints = 12
np2 = 2 * numPoints
ind = np2
if self._isSelected(obj):
ind += 8
vert = (np2 + 5)
return ind, vert
elif symbolType == 2: # draw a filled ellipse at lineWidth
if obj.pointLineWidths[0] and obj.pointLineWidths[1]:
numPoints = 24
else:
numPoints = 12
ind = 3 * numPoints
vert = ((2 * numPoints) + 5)
return ind, vert
else:
raise ValueError('GL Error: bad symbol type')
def _buildSymbolsCount(self, spectrumView, objListView, drawList):
"""count the number of indices and vertices for the label list
"""
pls = self.objectList(objListView)
# reset the object pointers
self._objectStore = {}
indCount = 0
vertCount = 0
objCount = 0
for tCount, obj in enumerate(self.objects(pls)):
ind, vert = self._buildSymbolsCountItem(self.strip, spectrumView, obj, self.strip.symbolType, tCount)
indCount += ind
vertCount += vert
if ind:
objCount += 1
# set up arrays
drawList.indices = np.empty(indCount, dtype=np.uint32)
drawList.vertices = np.empty(vertCount * 2, dtype=np.float32)
drawList.colors = np.empty(vertCount * 4, dtype=np.float32)
drawList.attribs = np.empty(vertCount, dtype=np.float32)
drawList.offsets = np.empty(vertCount * 2, dtype=np.float32)
drawList.pids = np.empty(objCount * GLDefs.LENPID, dtype=np.object_)
drawList.numVertices = 0
return indCount, vertCount
def _buildObjIsInVisiblePlanesList(self, spectrumView, objListView):
"""Build the dict of all object is visible values
"""
objList = self.objectList(objListView)
# clear the old list for this spectrumView
if spectrumView in self._objIsInVisiblePlanesCache:
del self._objIsInVisiblePlanesCache[spectrumView]
for obj in self.objects(objList):
self.objIsInVisiblePlanes(spectrumView, obj)
# from ccpn.util.decorators import profile
# @profile
def _buildSymbols(self, spectrumView, objListView):
spectrum = spectrumView.spectrum
if objListView not in self._GLSymbols:
self._GLSymbols[objListView] = GLSymbolArray(GLContext=self,
spectrumView=spectrumView,
objListView=objListView)
drawList = self._GLSymbols[objListView]
if drawList.renderMode == GLRENDERMODE_RESCALE:
drawList.renderMode = GLRENDERMODE_DRAW # back to draw mode
self._rescaleSymbols(spectrumView=spectrumView, objListView=objListView)
# self._rescaleLabels(spectrumView=spectrumView,
# objListView=objListView,
# drawList=self._GLLabels[objListView])
drawList.defineAliasedIndexVBO()
elif drawList.renderMode == GLRENDERMODE_REBUILD:
drawList.renderMode = GLRENDERMODE_DRAW # back to draw mode
# find the correct scale to draw square pixels
# don't forget to change when the axes change
_, _, symbolType, symbolWidth, r, w = self._getSymbolWidths(spectrumView)
if symbolType == 0 or symbolType == 3: # a cross/plus
# change the ratio on resize
drawList.refreshMode = GLREFRESHMODE_REBUILD
drawList.drawMode = GL.GL_LINES
drawList.fillMode = None
elif symbolType == 1: # draw an ellipse at lineWidth
# fix the size to the axes
drawList.refreshMode = GLREFRESHMODE_NEVER
drawList.drawMode = GL.GL_LINES
drawList.fillMode = None
elif symbolType == 2: # draw a filled ellipse at lineWidth
# fix the size to the axes
drawList.refreshMode = GLREFRESHMODE_NEVER
drawList.drawMode = GL.GL_TRIANGLES
drawList.fillMode = GL.GL_FILL
else:
raise ValueError('GL Error: bad symbol type')
# build the peaks VBO
indexing = AttrDict()
indexing.start = 0
indexing.end = 0
indexing.vertexPtr = 0
indexing.vertexStart = 0
indexing.objNum = 0
pls = self.objectList(objListView)
listCol = getAutoColourRgbRatio(objListView.symbolColour 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
spectrumFrequency = spectrum.spectrometerFrequencies
strip = spectrumView.strip
ind, vert = self._buildSymbolsCount(spectrumView, objListView, drawList)
if ind:
for tCount, obj in enumerate(self.objects(pls)):
if meritEnabled and obj.figureOfMerit < meritThreshold:
cols = meritCol
else:
cols = listCol
self._insertSymbolItem(strip, obj, cols, indexing, r, w,
spectrumFrequency, symbolType, drawList,
spectrumView, tCount)
drawList.defineAliasedIndexVBO()
[docs] def buildSymbols(self):
if self.strip.isDeleted:
return
# list through the valid peakListViews attached to the strip - including undeleted
for spectrumView in self._ordering: # strip.spectrumViews:
if spectrumView.isDeleted:
continue
# for peakListView in spectrumView.peakListViews:
for objListView in self.listViews(spectrumView): # spectrumView.peakListViews:
if objListView.isDeleted or objListView._flaggedForDelete:
if objListView in self._objIsInVisiblePlanesCache:
del self._objIsInVisiblePlanesCache[objListView]
continue
if objListView in self._GLSymbols:
if self._GLSymbols[objListView].renderMode == GLRENDERMODE_RESCALE:
self._buildSymbols(spectrumView, objListView)
if objListView.buildSymbols:
objListView.buildSymbols = False
# generate the planeVisibility list here - need to integrate with labels
self._buildObjIsInVisiblePlanesList(spectrumView, objListView)
# set the interior flags for rebuilding the GLdisplay
if objListView in self._GLSymbols:
self._GLSymbols[objListView].renderMode = GLRENDERMODE_REBUILD
self._buildSymbols(spectrumView, objListView)
[docs] def buildLabels(self):
if self.strip.isDeleted:
return
_buildList = []
for spectrumView in self._ordering: # strip.spectrumViews:
if spectrumView.isDeleted:
continue
# for peakListView in spectrumView.peakListViews:
for objListView in self.listViews(spectrumView):
if objListView.isDeleted:
continue
if objListView in self._GLLabels.keys():
if self._GLLabels[objListView].renderMode == GLRENDERMODE_RESCALE:
self._rescaleLabels(spectrumView, objListView, self._GLLabels[objListView])
self._GLLabels[objListView].renderMode = GLRENDERMODE_DRAW
continue
if objListView.buildLabels:
objListView.buildLabels = False
if objListView in self._GLLabels.keys():
self._GLLabels[objListView].renderMode = GLRENDERMODE_REBUILD
# self._buildPeakListLabels(spectrumView, peakListView)
_buildList.append([spectrumView, objListView])
if _buildList:
self._buildAllLabels(_buildList)
# self._rescalePeakListLabels(spectrumView, peakListView, self._GLPeakListLabels[peakListView])
def _buildAllLabels(self, viewList):
for ii, view in enumerate(viewList):
spectrumView = view[0]
objListView = view[1]
if objListView not in self._GLLabels.keys():
self._GLLabels[objListView] = GLLabelArray(GLContext=self,
spectrumView=spectrumView,
objListView=objListView)
drawList = self._GLLabels[objListView]
drawList.stringList = []
buildQueue = (viewList, self._GLParent, self._GLLabels)
# not calling as a thread because it's not multiprocessing AND its slower
self._threadBuildAllLabels(*buildQueue)
# buildPeaks = Thread(name=str(self.strip.pid),
# target=self._threadBuildAllLabels,
# args=buildQueue)
# buildPeaks.start()
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Threads
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def _threadBuildLabels(self, spectrumView, objListView, drawList, glStrip):
global _totalTime
global _timeCount
global _numTimes
tempList = []
pls = self.objectList(objListView)
# append all labels separately
for obj in self.objects(pls):
self._appendLabel(spectrumView, objListView, tempList, obj)
# # # append all labels in one go
# # self._fillLabels(spectrumView, objListView, tempList, pls, self.objects)
# print(f'>>> building {len(tempList)} labels')
# try:
# self._tempMax = max(self._tempMax, len(tempList))
# print(f'>>> building {len(tempList)} labels - {self._tempMax}')
# except:
# self._tempMax = len(tempList)
# print(f'>>> building {len(tempList)} labels - {self._tempMax}')
drawList.stringList = tempList
# drawList.renderMode = GLRENDERMODE_RESCALE
def _threadBuildAllLabels(self, viewList, glStrip, _outList):
# def _threadBuildAllPeakListLabels(self, threadQueue):#viewList, glStrip, _outList):
# print ([obj for obj in threadQueue])
# viewList = threadQueue[0]
# glStrip = threadQueue[1]
# _outList = threadQueue[2]
# stringList = threadQueue[3]
for ii, view in enumerate(viewList):
spectrumView = view[0]
objListView = view[1]
self._threadBuildLabels(spectrumView, objListView,
_outList[objListView],
glStrip)
glStrip.GLSignals.emitPaintEvent(source=glStrip)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Drawing
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[docs] def drawSymbols(self, spectrumView):
"""Draw the symbols to the screen
"""
if self.strip.isDeleted:
return
for objListView, specView in self._visibleListViews:
if specView == spectrumView and not objListView.isDeleted and objListView in self._GLSymbols.keys():
self._GLSymbols[objListView].drawAliasedIndexVBO()
[docs] def drawLabels(self, spectrumView):
"""Draw the labelling to the screen
"""
if self.strip.isDeleted:
return
# self._spectrumSettings = spectrumSettings
# self.buildLabels()
# # loop through the attached peakListViews to the strip
# for spectrumView in self._GLParent._ordering: #self._parent.spectrumViews:
# if spectrumView.isDeleted:
# continue
# # for peakListView in spectrumView.peakListViews:
# for objListView in self.listViews(spectrumView):
# if spectrumView.isVisible() and objListView.isVisible():
for objListView, specView in self._visibleListViews:
if specView == spectrumView and not objListView.isDeleted and objListView in self._GLLabels.keys():
for drawString in self._GLLabels[objListView].stringList:
# if shader and stackingMode:
# # use the stacking matrix to offset the 1D spectra
# shader.setStackOffset(spectrumSettings[specView][GLDefs.SPECTRUM_STACKEDMATRIXOFFSET])
# draw text
drawString.drawTextArrayVBO()
[docs] def objIsInVisiblePlanesReset(self):
"""Reset the object visibility cache
"""
self._objIsInVisiblePlanesCache = {}
[docs] def objIsInVisiblePlanesClear(self):
"""clear the object visibility cache for each peak in the spectrumViews
"""
for specView in self._objIsInVisiblePlanesCache:
self._objIsInVisiblePlanesCache[specView] = {}
[docs] def objIsInVisiblePlanesRemove(self, spectrumView, obj):
"""Remove a single object from the cache
"""
try:
# try to remove from the nested dict
del self._objIsInVisiblePlanesCache[spectrumView][obj]
except:
# nothing needed here
pass
[docs]class GL1dLabelling():
"""Class to handle symbol and symbol labelling for generic 1d displays
"""
def _updateHighlightedSymbols(self, spectrumView, objListView):
"""update the highlighted symbols
"""
strip = self.strip
symbolType = strip.symbolType
drawList = self._GLSymbols[objListView]
drawList.indices = np.array([], dtype=np.uint32)
indexStart = 0
indexEnd = 0
vertexStart = 0
if symbolType == 0 or symbolType == 3:
listView = self.objectList(objListView)
listCol = getAutoColourRgbRatio(objListView.symbolColour or GLDefs.DEFAULTCOLOUR, listView.spectrum,
self.autoColour,
getColours()[CCPNGLWIDGET_FOREGROUND])
meritCol = getAutoColourRgbRatio(objListView.meritColour or GLDefs.DEFAULTCOLOUR, listView.spectrum,
self.autoColour,
getColours()[CCPNGLWIDGET_FOREGROUND])
meritEnabled = objListView.meritEnabled
meritThreshold = objListView.meritThreshold
for pp in range(0, len(drawList.pids), GLDefs.LENPID):
# check whether the peaks still exists
obj = drawList.pids[pp]
offset = drawList.pids[pp + 1]
numPoints = drawList.pids[pp + 2]
if not obj.isDeleted:
if symbolType == 0: # cross
iCount, _selected = self._appendSquareSymbol(drawList, vertexStart, 0, obj)
else: # plus
iCount, _selected = self._appendPlusSymbol(drawList, vertexStart, 0, obj)
if _selected:
cols = self._GLParent.highlightColour[:3]
else:
if meritEnabled and obj.figureOfMerit < meritThreshold:
cols = meritCol
else:
cols = listCol
# called extraIndices, extraIndexCount above
# make sure that links for the multiplets are added
_indexCount, extraIndices = self.appendExtraIndices(drawList, indexStart + self.LENSQ, obj)
drawList.colors[offset * 4:(offset + self.POINTCOLOURS) * 4] = (*cols, 1.0) * self.POINTCOLOURS # numPoints
drawList.pids[pp + 3:pp + 9] = (True, True, _selected,
indexEnd, indexEnd + iCount + _indexCount, 0) # don't need to change planeIndex, but keep space for it
indexEnd += (iCount + _indexCount)
indexStart += numPoints
vertexStart += numPoints
drawList.updateIndexVBOIndices()
drawList.updateTextArrayVBOColour()
elif symbolType == 1 or symbolType == 2:
pass
else:
raise ValueError('GL Error: bad symbol type')
def _insertSymbolItem(self, strip, obj, listCol, indexing, r, w,
spectrumFrequency, symbolType, drawList, spectrumView):
"""insert a single symbol to the end of the symbol list
"""
# indexStart = indexing.start
indexEnd = indexing.end
objNum = indexing.objNum
vertexPtr = indexing.vertexPtr
vertexStart = indexing.vertexStart
if not obj:
return
objPos = obj.pointPositions
if not objPos:
getLogger().warning(f'Object contains undefined position {obj}')
p0 = (0.0, 0.0)
else:
p0 = (objPos[0] - 1, obj.height)
if None in p0:
getLogger().warning(f'Object {str(obj)} contains undefined position {str(p0)}')
return
_alias = obj.aliasing
alias = getAliasSetting(_alias[0], 0)
if self._isSelected(obj):
cols = self._GLParent.highlightColour[:3]
else:
cols = listCol
if symbolType == 0: # cross
iCount, _selected = self._makeSquareSymbol(drawList, indexEnd, vertexStart, 0, obj)
else:
iCount, _selected = self._makePlusSymbol(drawList, indexEnd, vertexStart, 0, obj)
self._insertSymbolItemVertices(True, True, _selected, cols, drawList, 1.0, iCount,
indexing, obj, objNum, p0, 0, 0, r, vertexPtr, w, alias)
def _buildSymbols(self, spectrumView, objListView):
spectrum = spectrumView.spectrum
if objListView not in self._GLSymbols:
self._GLSymbols[objListView] = GLSymbolArray(GLContext=self,
spectrumView=spectrumView,
objListView=objListView)
drawList = self._GLSymbols[objListView]
if drawList.renderMode == GLRENDERMODE_RESCALE:
drawList.renderMode = GLRENDERMODE_DRAW # back to draw mode
self._rescaleSymbols(spectrumView=spectrumView, objListView=objListView)
# self._rescaleLabels(spectrumView=spectrumView,
# objListView=objListView,
# drawList=self._GLLabels[objListView])
drawList.defineAliasedIndexVBO()
elif drawList.renderMode == GLRENDERMODE_REBUILD:
drawList.renderMode = GLRENDERMODE_DRAW # back to draw mode
# drawList.refreshMode = GLRENDERMODE_DRAW
# find the correct scale to draw square pixels
# don't forget to change when the axes change
_, _, symbolType, symbolWidth, r, w = self._getSymbolWidths(spectrumView)
# change the ratio on resize
drawList.refreshMode = GLREFRESHMODE_REBUILD
drawList.drawMode = GL.GL_LINES
drawList.fillMode = None
# build the peaks VBO
indexing = AttrDict()
indexing.start = 0
indexing.end = 0
indexing.objNum = 0
indexing.vertexPtr = 0
indexing.vertexStart = 0
pls = self.objectList(objListView)
if not pls:
return
listCol = getAutoColourRgbRatio(objListView.symbolColour 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
spectrumFrequency = spectrum.spectrometerFrequencies
strip = spectrumView.strip
ind, vert = self._buildSymbolsCount(spectrumView, objListView, drawList)
if ind:
for tcount, obj in enumerate(self.objects(pls)):
if meritEnabled and obj.figureOfMerit < meritThreshold:
cols = meritCol
else:
cols = listCol
self._insertSymbolItem(strip, obj, cols, indexing, r, w,
spectrumFrequency, symbolType, drawList,
spectrumView)
drawList.defineAliasedIndexVBO()
def _rescaleSymbols(self, spectrumView, objListView):
"""rescale symbols when the screen dimensions change
"""
drawList = self._GLSymbols[objListView]
if not drawList.numVertices:
return
# if drawList.refreshMode == GLREFRESHMODE_REBUILD:
_, _, symbolType, symbolWidth, r, w = self._getSymbolWidths(spectrumView)
if symbolType == 0 or symbolType == 3: # a cross/plus
offsets, offsetsLENSQ2 = self._rescaleSymbolOffsets(r, w)
for pp in range(0, len(drawList.pids), GLDefs.LENPID):
indexStart = 2 * drawList.pids[pp + 1]
try:
drawList.vertices[indexStart:indexStart + offsetsLENSQ2] = drawList.offsets[indexStart:indexStart + offsetsLENSQ2] + offsets
except Exception as es:
pass
elif symbolType == 1 or symbolType == 2:
pass
else:
raise ValueError('GL Error: bad symbol type')
def _appendSymbol(self, spectrumView, objListView, obj):
"""Append a new symbol to the end of the list
"""
drawList = self._GLSymbols[objListView]
# find the correct scale to draw square pixels
# don't forget to change when the axes change
_, _, symbolType, symbolWidth, r, w = self._getSymbolWidths(spectrumView)
if symbolType == 0 or symbolType == 3: # a cross/plus
# change the ratio on resize
drawList.refreshMode = GLREFRESHMODE_REBUILD
drawList.drawMode = GL.GL_LINES
drawList.fillMode = None
# build the peaks VBO
indexing = AttrDict()
indexing.start = len(drawList.indices)
indexing.end = len(drawList.indices)
indexing.vertexStart = drawList.numVertices
# NOTE:ED - SEEMS TO BE A BUG HERE WITH THE INDEXING BEFORE HIGHLIGHTING!
# OTHERWISE 1d and Nd SHOULD BE THE SAME _appendSymbolVertices...
# CHECK - but I think solved
pls = self.objectList(objListView)
listCol = getAutoColourRgbRatio(objListView.symbolColour 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 self._isSelected(obj):
cols = self._GLParent.highlightColour[:3]
else:
if meritEnabled and obj.figureOfMerit < meritThreshold:
cols = meritCol
else:
cols = listCol
pIndex = self._spectrumSettings[spectrumView][GLDefs.SPECTRUM_POINTINDEX]
if not obj.pointPositions:
return
p0 = (obj.pointPositions[pIndex[0]] - 1, obj.height)
_alias = obj.aliasing
alias = getAliasSetting(_alias[0], 0)
if None in p0:
getLogger().warning('Object %s contains undefined position %s' % (str(obj.pid), str(p0)))
return
if symbolType == 0 or symbolType == 3: # a cross/plus
if symbolType == 0: # cross
iCount, _selected = self._appendSquareSymbol(drawList, indexing.vertexStart, 0, obj)
else: # plus
iCount, _selected = self._appendPlusSymbol(drawList, indexing.vertexStart, 0, obj)
self._appendSymbolItemVertices(True, True, _selected, cols, drawList, 1.0, iCount, indexing, obj, p0, pIndex,
0, r, w, alias)
def _removeSymbol(self, spectrumView, objListView, delObj):
"""Remove a symbol from the list
"""
drawList = self._GLSymbols[objListView]
indexOffset = 0
numPoints = 0
pp = 0
while (pp < len(drawList.pids)):
# check whether the peaks still exists
obj = drawList.pids[pp]
if obj == delObj:
offset = drawList.pids[pp + 1]
numPoints = drawList.pids[pp + 2]
indexStart = drawList.pids[pp + 6]
indexEnd = drawList.pids[pp + 7]
indexOffset = indexEnd - indexStart
drawList.indices = np.delete(drawList.indices, np.s_[indexStart:indexEnd])
drawList.vertices = np.delete(drawList.vertices, np.s_[2 * offset:2 * (offset + numPoints)])
drawList.attribs = np.delete(drawList.attribs, np.s_[offset:offset + numPoints])
drawList.offsets = np.delete(drawList.offsets, np.s_[2 * offset:2 * (offset + numPoints)])
drawList.colors = np.delete(drawList.colors, np.s_[4 * offset:4 * (offset + numPoints)])
drawList.pids = np.delete(drawList.pids, np.s_[pp:pp + GLDefs.LENPID])
drawList.numVertices -= numPoints
# subtract the offset from all the higher indices to account for the removed points
drawList.indices[np.where(drawList.indices >= offset)] -= numPoints
break
else:
pp += GLDefs.LENPID
# clean up the rest of the list
while (pp < len(drawList.pids)):
drawList.pids[pp + 1] -= numPoints
drawList.pids[pp + 6] -= indexOffset
drawList.pids[pp + 7] -= indexOffset
pp += GLDefs.LENPID
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)
_, _, symbolType, symbolWidth, r, w = self._getSymbolWidths(spectrumView)
pIndex = self._spectrumSettings[spectrumView][GLDefs.SPECTRUM_POINTINDEX]
if not obj.pointPositions:
return
p0 = (obj.pointPositions[pIndex[0]] - 1, obj.height)
if None in p0:
getLogger().warning('Object %s contains undefined position %s' % (str(obj.pid), str(p0)))
return
_alias = obj.aliasing
alias = getAliasSetting(_alias[0], 0)
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)
newString = GLString(text=text,
font=self._GLParent.getSmallFont(),
x=p0[0], y=p0[1],
ox=r, oy=w,
# ox=symbolWidth, oy=symbolWidth,
# x=self._screenZero[0], y=self._screenZero[1]
colour=(*cols, 1.0),
GLContext=self._GLParent,
obj=obj,
alias=alias)
newString.stringOffset = None
stringList.append(newString)
def _rescaleLabels(self, spectrumView=None, objListView=None, drawList=None):
"""Rescale all labels to the new dimensions of the screen
"""
symbolType = self.strip.symbolType
if symbolType == 0 or symbolType == 3: # a cross/plus
_, _, symbolType, symbolWidth, r, w = self._getSymbolWidths(spectrumView)
for drawStr in drawList.stringList:
drawStr.setStringOffset((r, w))
drawStr.updateTextArrayVBOAttribs()
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Drawing
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~