"""
Abstract Factorization Class
Created on Mon Jul 25 10:44:03 2016
@author: chc
"""
import sys as _sys
import numpy as _np
import traceback as _traceback
from PyQt5 import QtWidgets as _QtWidgets
from PyQt5.QtWidgets import (QApplication as _QApplication,
QDialog as _QDialog,
QMessageBox as _QMsg)
import PyQt5.QtCore as _QtCore
# Import from Designer-based GUI
from crikit.ui.qt_Factorization import Ui_Dialog ### EDIT ###
# Generic imports for MPL-incorporation
import matplotlib as _mpl
from sciplot.ui.widget_mpl import MplCanvas as _MplCanvas
_mpl.use('Qt5Agg')
_mpl.rcParams['font.family'] = 'sans-serif'
_mpl.rcParams['font.size'] = 12
[docs]class DialogAbstractFactorization(_QDialog):
"""
SubUiSVD : SVD SubUI
"""
def __init__(self, parent=None):
super(DialogAbstractFactorization, self).__init__(parent=parent)
self._mpl_v1 = _mpl.__version__.split('.')[0] == 1
## def __init__(self, parent=None):
# raise NotImplementedError('This is an abstract class.')
## super(DialogAbstractFactorization, self).__init__(parent=parent) ### EDIT ###
## self.setup()
## self.setupData(img_shape=img_shape)
## self.ui_changes()
# pass
[docs] def ui_changes(self):
"""
Any changes to ui labels or otherwise for particular implementation
"""
pass
[docs] def setupData(self, img_shape):
self._img_shape = img_shape
self._img_size = int(_np.array(img_shape).prod())
self._img_shape2D = tuple(_np.array(img_shape)[0:2])
self._img_size2D = int(_np.array(img_shape)[0:2].prod())
self._n_y = img_shape[0]
self._n_x = img_shape[1]
self._n_spectra = img_shape[2]
self._n_factors = self.max_factors()
self.selected_factors = set()
self.cube_all = None
self.img_all = None
self.spect_all = None
[docs] def setup(self, parent = None):
# Generic load/init designer-based GUI
# super(DialogAbstractFactorization, self).__init__(parent) ### EDIT ###
self.ui = Ui_Dialog() ### EDIT ###
self.ui.setupUi(self) ### EDIT ###
self.ui.pushButtonNext.clicked.connect(self.advance)
self.ui.pushButtonPrev.clicked.connect(self.advance)
self.ui.pushButtonGoTo.clicked.connect(self.advance)
self.ui.pushButtonCancel.clicked.connect(self.reject)
self.ui.pushButtonOk.clicked.connect(self.accept)
self.ui.pushButtonClear.clicked.connect(self.clear)
self.ui.pushButtonApply.clicked.connect(self.applyCheckBoxes)
self.ui.pushButtonScript.clicked.connect(self.runScript)
self._first_factor_visible = 0
self._num_factor_visible = 6
self.ui.lcdSelectedFactors.display(0)
self.ui.lcdMaxFactors.display(self.max_factors())
self.factorWins = []
self.factorLabelCheckBoxes = [self.ui.checkBox,
self.ui.checkBox_2,
self.ui.checkBox_3,
self.ui.checkBox_4,
self.ui.checkBox_5,
self.ui.checkBox_6]
for count in range(self._num_factor_visible):
self.factorWins.append(_MplCanvas(subplot=211))
self.factorWins[count].ax[0].axis('Off')
if self._mpl_v1:
self.factorWins[count].ax[1].hold('Off')
self.ui.gridLayout.addWidget(self.factorWins[0],1,0)
self.ui.gridLayout.addWidget(self.factorWins[1],1,1)
self.ui.gridLayout.addWidget(self.factorWins[2],1,2)
self.ui.gridLayout.addWidget(self.factorWins[3],3,0)
self.ui.gridLayout.addWidget(self.factorWins[4],3,1)
self.ui.gridLayout.addWidget(self.factorWins[5],3,2)
self.reconCurrent = _MplCanvas(subplot=211)
self.reconCurrent.ax[0].axis('Off')
if self._mpl_v1:
self.reconCurrent.ax[1].hold('Off')
self.reconRemainder = _MplCanvas(subplot=211)
self.reconRemainder.ax[0].axis('Off')
if self._mpl_v1:
self.reconRemainder.ax[1].hold('Off')
self.ui.verticalLayout_3.insertWidget(1,self.reconCurrent)
self.ui.verticalLayout_3.insertWidget(-1,self.reconRemainder)
for count in range(self._num_factor_visible):
self.factorLabelCheckBoxes[count].setText('Keep: ' + str(count))
@property
def unselected_factors(self):
all_factors = set(_np.arange(self._n_factors))
return all_factors - self.selected_factors
[docs] def applyCheckBoxes(self):
"""
Add checked singular values (and remove un-checked SVs)
"""
for count, checkBox in enumerate(self.factorLabelCheckBoxes):
if checkBox.isChecked() == True:
self.selected_factors.add(self._first_factor_visible+count)
else:
try:
self.selected_factors.remove(self._first_factor_visible+count)
except:
pass
#print('Self.S: {}'.format(self.svddata.S[0:3]))
self.ui.lcdSelectedFactors.display(len(self.selected_factors))
self.updateCurrentRemainder()
[docs] def advance(self):
"""
View next set of SVs
"""
sender = self.sender().objectName()
if sender == 'pushButtonPrev':
self.updatePlots(startnum=self._first_factor_visible-self._num_factor_visible)
elif sender == 'pushButtonNext':
self.updatePlots(startnum=self._first_factor_visible+self._num_factor_visible)
elif sender == 'pushButtonGoTo':
self.updatePlots(startnum=self.ui.spinBoxGoTo.value())
else:
pass
[docs] def runScript(self):
"""
Run "script" of singular value selection
Example:
[1,2,3,5:7] = 1,2,3,5,6,7
"""
script = self.ui.lineEditSelections.text()
script = script.strip('[').strip(']')
script = script.split(',')
try:
for count in script:
if ':' in count:
temp = count.split(':')
if (int(temp[0]) >= self._n_factors) | (int(temp[1]) >= self._n_factors):
raise ValueError('{} value greater than maximum factor {}'.format(self.temp, self._n_factors))
self.selected_factors.update(set(_np.arange(int(temp[0]),int(temp[1])+1)))
elif count.strip() == '':
pass
else:
if int(count) >= self._n_factors:
raise ValueError('{} value greater than maximum factor {}'.format(int(count), self._n_factors))
self.selected_factors.add(int(count))
except Exception:
_traceback.print_exc(limit=1)
msg_box = _QMsg(_QMsg.Warning, 'Script Error', 'There was a problem with the script command: {}'.format(script), parent=self)
msg_box.exec()
self.updatePlots(startnum=self._first_factor_visible)
self.ui.lcdSelectedFactors.display(len(self.selected_factors))
self.updateCurrentRemainder()
[docs] def max_factors(self):
raise NotImplementedError('max_factors method not implemented')
[docs] def combiner(self, factors=None):
raise NotImplementedError('combiner method not implemented')
[docs] def mean_spatial(self, cube):
raise NotImplementedError('mean_spatial method not implemented')
[docs] def mean_spectral(self, cube):
raise NotImplementedError('mean_spectral method not implemented')
[docs] def get_spatial_slice(self, num):
raise NotImplementedError('get_spatial_slice method not implemented.')
[docs] def get_spectral_slice(self, num):
raise NotImplementedError('get_spectral_slice method not implemented.')
[docs] def updateCurrentRemainder(self):
"""
Update image reconstructed (mean over spectral vector) using remaining \
(unselected) singular values
"""
cube_select = self.combiner(self.selected_factors)
img_select = self.mean_spatial(cube_select)
spect_select = self.mean_spectral(cube_select)
# cube_nonselect = self.combiner(self.unselected_factors)
# cube_nonselect = self.cube_all - cube_select
# img_nonselect = self.mean_spatial(cube_nonselect)
# spect_nonselect = self.mean_spectral(cube_nonselect)
img_nonselect = self.img_all - img_select
print('Spect_select: {}'.format(spect_select))
print('Spect_select is None: {}'.format(spect_select is None))
spect_nonselect = self.spect_all - spect_select
self.reconCurrent.ax[0].cla()
self.reconCurrent.ax[1].cla()
# s_lim = _np.abs(img_select).max()
s_lim = _np.abs(img_select.mean() + 3*img_select.std())
self.reconCurrent.ax[0].imshow(img_select, interpolation='None',
cmap = 'bwr', origin='lower', vmin=0, vmax=s_lim)
self.reconCurrent.ax[1].plot(spect_select)
self.reconCurrent.draw()
self.reconRemainder.ax[0].cla()
self.reconRemainder.ax[1].cla()
# s_lim = _np.abs(img_nonselect).max()
s_lim = _np.abs(img_nonselect.mean() + 3*img_nonselect.std())
self.reconRemainder.ax[0].imshow(img_nonselect, interpolation='None',
cmap = 'bwr', origin='lower', vmin=-s_lim, vmax=s_lim)
self.reconRemainder.ax[1].plot(spect_nonselect)
self.reconRemainder.draw()
[docs] def updatePlots(self, startnum=0):
"""
Update images and spectra of set of singular values starting at SV \
number startnum
"""
if startnum <= 0:
startnum = 0
self.ui.pushButtonPrev.setEnabled(False)
self.ui.pushButtonNext.setEnabled(True)
elif startnum > self._n_factors - self._num_factor_visible:
startnum = self._n_factors - self._num_factor_visible
self.ui.pushButtonPrev.setEnabled(True)
self.ui.pushButtonNext.setEnabled(False)
else:
self.ui.pushButtonPrev.setEnabled(True)
self.ui.pushButtonNext.setEnabled(True)
self._first_factor_visible = startnum
for count in range(self._num_factor_visible):
self.factorWins[count].ax[0].clear()
sl = self.get_spatial_slice(count + self._first_factor_visible)
# sl_lim = _np.abs(sl).max()
sl_lim = _np.abs(sl.mean() + 3*sl.std())
self.factorWins[count].ax[0].imshow(sl, vmin=-sl_lim, vmax=sl_lim,
interpolation='none',
cmap = 'bwr' , origin='lower')
self.factorWins[count].ax[0].axis('Off')
self.factorWins[count].ax[1].clear()
self.factorWins[count].ax[1].plot(self.get_spectral_slice(count + self._first_factor_visible))
self.factorLabelCheckBoxes[count].setText('Keep: ' + str(startnum + count))
self.factorWins[count].draw()
if self._first_factor_visible + count in self.selected_factors:
self.factorLabelCheckBoxes[count].setChecked(True)
else:
self.factorLabelCheckBoxes[count].setChecked(False)
[docs] def clear(self):
"""
Clear selected singular values (i.e., none will be selected)
"""
self.selected_factors = set()
self.ui.lcdSelectedFactors.display(len(self.selected_factors))
self.updateCurrentRemainder()
self.updatePlots(startnum=self._first_factor_visible)
if __name__ == '__main__':
pass
# app = _QApplication(_sys.argv)
# app.setStyle('Cleanlooks')
# x = _np.linspace(100,200,50)
# y = _np.linspace(200,300,50)
# f = _np.linspace(500,3000,800)
# Ex = 30*_np.exp((-(f-1750)**2/(200**2)))
# Spectrum = _np.convolve(_np.flipud(Ex),Ex,mode='same')
# data = _np.zeros((y.size,x.size,f.size))
# for count in range(y.size):
# data[count,:,:] = y[count]*_np.random.poisson(_np.dot(x[:,None],Spectrum[None,:]))
# win = DialogAbstractFactorization.dialogAbstractFactorization(data, data.shape) ### EDIT ###
# print(win)
# _sys.exit(app.exec_())
# # _sys.exit()