Source code for ccpn.ui.gui.popups.SetPeakAliasing
"""
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: Geerten Vuister $"
__dateModified__ = "$dateModified: 2021-12-23 11:27:18 +0000 (Thu, December 23, 2021) $"
__version__ = "$Revision: 3.0.4 $"
#=========================================================================================
# Created
#=========================================================================================
__author__ = "$Author: Ed Brooksbank $"
__date__ = "$Date: 2020-12-03 18:38:18 +0000 (Thu, December 03, 2020) $"
#=========================================================================================
# Start of code
#=========================================================================================
from PyQt5 import QtGui
from collections import OrderedDict
from functools import partial
from ccpn.ui.gui.widgets.MessageDialog import showYesNo
from ccpn.ui.gui.widgets.Label import Label
from ccpn.ui.gui.widgets.Frame import Frame
from ccpn.ui.gui.widgets.PulldownList import PulldownList
from ccpn.ui.gui.widgets.HLine import HLine
from ccpn.ui.gui.widgets.CompoundWidgets import CheckBoxCompoundWidget
from ccpn.ui.gui.guiSettings import getColours, DIVIDER
from ccpn.ui.gui.popups.Dialog import CcpnDialogMainWidget, handleDialogApply
from ccpn.ui.gui.lib.OpenGL.CcpnOpenGL import GLNotifier
from ccpn.ui.gui.lib.SpectrumDisplay import navigateToCurrentPeakPosition
from ccpn.core.lib.SpectrumLib import MAXALIASINGRANGE
DEFAULTALIASING = MAXALIASINGRANGE
COLWIDTH = 140
[docs]class SetPeakAliasingPopup(CcpnDialogMainWidget):
"""
Open a small popup to allow setting aliasing value of selected 'current' items
"""
FIXEDWIDTH = True
FIXEDHEIGHT = True
# internal namespace
_NAVIGATETO = '_navigateTo'
storeStateOnReject = True
def __init__(self, parent=None, mainWindow=None, title='Set Aliasing', peaks=None, **kwds):
"""
Initialise the widget
"""
super().__init__(parent, setLayout=True, windowTitle=title, **kwds)
self.mainWindow = mainWindow
self.application = mainWindow.application
self.project = mainWindow.application.project
self.current = mainWindow.application.current
self.spectra = OrderedDict()
self.spectraPulldowns = OrderedDict()
self.spectraCheckBoxes = OrderedDict()
self.spectraPos = OrderedDict()
self.peaks = peaks or []
# max to min to match the spectrum properties popup
self._aliasRange = [rr for rr in range(MAXALIASINGRANGE, -MAXALIASINGRANGE - 1, -1)]
# setup the widgets
self._setWidgets()
# set up the required buttons for the dialog
self.setCloseButton(callback=self.reject, enabled=True, text='Close', tipText='Close Dialog')
self.setOkButton(callback=self._okButton, enabled=True, text='Set Aliasing', tipText='Set Aliasing and Close')
self.setDefaultButton(self.CLOSEBUTTON)
# populate the widgets
self._populate()
# set the links to the buttons
self.__postInit__()
self._okButton = self.dialogButtons.button(self.OKBUTTON)
self._closeButton = self.dialogButtons.button(self.CLOSEBUTTON)
self.GLSignals = GLNotifier(parent=self)
def _setWidgets(self):
"""Setup the widgets for the dialog
"""
row = 0
Label(self.mainWidget, text='Set aliasing for currently selected peaks', grid=(row, 0), gridSpan=(1, 2))
row += 1
spectrumFrame = Frame(self.mainWidget, setLayout=True, showBorder=False, grid=(row, 0), gridSpan=(1, 2))
row += 1
specRow = 0
for peak in self.peaks:
if peak.peakList.spectrum not in self.spectra:
spectrum = peak.peakList.spectrum
self.spectra[spectrum] = set()
self.spectraPos[spectrum] = None
dims = spectrum.dimensionCount
if specRow > 0:
# add divider
HLine(spectrumFrame, grid=(specRow, 0), gridSpan=(1, dims + 2), colour=getColours()[DIVIDER], height=15)
specRow += 1
# add pulldown widget
Label(spectrumFrame, text='Spectrum: %s' % str(spectrum.pid), grid=(specRow, 0), bold=True)
Label(spectrumFrame, text=' axisCodes:', grid=(specRow, 1))
for dim in range(dims):
Label(spectrumFrame, text=spectrum.axisCodes[dim], grid=(specRow, dim + 2))
specRow += 1
self.spectraPulldowns[spectrum] = []
Label(spectrumFrame, text=' aliasing:', grid=(specRow, 1))
for dim in range(dims):
self.spectraPulldowns[spectrum].append(PulldownList(spectrumFrame, # texts=aliasText,
grid=(specRow, dim + 2),
callback=partial(self._pulldownCallback, spectrum, dim)))
# may cause a problem if the peak dimension does not correspond to a visible XY axis
# peaks could disappear from all views
specRow += 1
self.spectraPos[peak.spectrum] = tuple(peak.spectrum.point2ppm(pp, dimension=ind + 1) for ind, pp in enumerate(peak.pointPositions))
self.spectra[peak.peakList.spectrum].add(peak)
self.navigateToPeaks = CheckBoxCompoundWidget(
self.mainWidget,
grid=(row, 0), gridSpan=(1, 2), hAlign='left',
orientation='left',
labelText='Navigate to new peak position',
checked=False
)
def _populate(self):
"""Populate the widgets
"""
with self.blockWidgetSignals():
for spectrum in self.spectra.keys():
if self.spectra[spectrum]:
dims = spectrum.dimensionCount
_specWidths = spectrum.spectralWidths
aliasInds = spectrum.aliasingIndexes
_pos = self.spectraPos[spectrum]
# initialise the counters
aliasCount = []
dimAlias = []
for dim in range(dims):
dimAlias.append(set())
aliasCount.append({})
# keep a count of how many times the alias values appear
for peak in self.spectra[spectrum]:
pa = peak.aliasing
for dim in range(dims):
dimAlias[dim].add(pa[dim])
if pa[dim] not in aliasCount[dim]:
aliasCount[dim][pa[dim]] = 0
aliasCount[dim][pa[dim]] += 1
for dim in range(dims):
# make the pulldown texts from the alias values and the pointPosition of the first peak in each list
# may not be the most clear for selection crossing multiple alias regions
aliasText = [f'{aa} ({_pos[dim] + (aa * _specWidths[dim]):.3f})' for aa in self._aliasRange]
self.spectraPulldowns[spectrum][dim].setData(texts=aliasText)
spectrumAliasRange = list(range(aliasInds[dim][1], aliasInds[dim][0] - 1, -1))
if len(dimAlias[dim]) == 1:
# set the index for the found alias
self.spectraPulldowns[spectrum][dim].setIndex(self._aliasRange.index(dimAlias[dim].pop()))
elif len(dimAlias[dim]) > 1:
# set the index to the most common aliasing
maxAlias = max(aliasCount[dim].values())
maxKey = [k for k, v in aliasCount[dim].items() if v == maxAlias]
if maxKey:
self.spectraPulldowns[spectrum][dim].setIndex(self._aliasRange.index(maxKey[0]))
else:
# just set to 0 alias element - middle element if full range
self.spectraPulldowns[spectrum][dim].setIndex(self._aliasRange.index(0))
# add some colour to show the alias value that are not in the spectrum range
combo = self.spectraPulldowns[spectrum][dim]
combo._validSelection = True
combo._validRange = spectrumAliasRange
model = combo.model()
for ind, rr in enumerate(self._aliasRange):
if rr not in spectrumAliasRange:
color = QtGui.QColor('red')
model.item(ind).setForeground(color)
self._setPulldownTextColour(combo)
def _pulldownCallback(self, spectrum, dim, value):
"""Update selection colour of pulldown
"""
combo = self.spectraPulldowns[spectrum][dim]
self._setPulldownTextColour(combo)
def _setPulldownTextColour(self, combo):
"""Set the colour of the pulldown text
"""
# NOTE:ED - should move this the the pulldown widget
ind = combo.currentIndex()
model = combo.model()
item = model.item(ind)
if item is not None:
color = item.foreground().color()
# use the palette to change the colour of the selection text - may not match for other themes
palette = combo.palette()
palette.setColor(QtGui.QPalette.Active, QtGui.QPalette.Text, color)
combo.setPalette(palette)
# update the selection flag
combo._validSelection = (True if (self._aliasRange[ind]) in combo._validRange else False)
def _okButton(self):
"""
When ok button pressed: update and exit
"""
with handleDialogApply(self):
_spectrumWarning = 'Spectra containing out-of-range aliasing ranges:\n\n'
_updateSpectra = []
# verify that there are no out-of-range spectra
for spectrum in self.spectra.keys():
for dim in range(spectrum.dimensionCount):
combo = self.spectraPulldowns[spectrum][dim]
if not combo._validSelection:
_spectrumWarning += f' {spectrum.pid}\n'
_updateSpectra.append(spectrum)
break
if _updateSpectra:
if len(_updateSpectra) == 1:
_msg = '\nSelecting Yes will update the aliasingLimits for the spectrum\n' \
'Do you want to Continue?'
else:
_msg = '\nSelecting Yes will update the aliasingLimits for the spectra\n' \
'Do you want to Continue?'
ok = showYesNo('Warning', _spectrumWarning + _msg)
if not ok:
return
for spectrum in self.spectra.keys():
# set the aliasing for the peaks from the pulldown indexes
# newAlias = tuple(spectrumAliasRange[ind][pullDown.getSelectedIndex()] for ind, pullDown in enumerate(self.spectraPulldowns[spectrum]))
newAlias = tuple(self._aliasRange[pullDown.getSelectedIndex()] for ind, pullDown in enumerate(self.spectraPulldowns[spectrum]))
spectrum.setPeakAliasing(list(self.spectra[spectrum]), newAlias, (spectrum in _updateSpectra))
if self.navigateToPeaks.isChecked():
navigateToCurrentPeakPosition(self.application, selectFirstPeak=True)
self.accept()
[docs] def storeWidgetState(self):
"""Store the state of the checkBoxes between popups
"""
nav = self.navigateToPeaks.isChecked()
SetPeakAliasingPopup._storedState[self._NAVIGATETO] = nav
[docs] def restoreWidgetState(self):
"""Restore the state of the checkBoxes
"""
self.navigateToPeaks.set(SetPeakAliasingPopup._storedState.get(self._NAVIGATETO, False))