Commit 0b768ad2 authored by JosefBrandt's avatar JosefBrandt
Browse files

First phase of refactoring

parent 8fc15b1e
Loading
Loading
Loading
Loading
+93 −102
Original line number Diff line number Diff line
@@ -53,11 +53,12 @@ class ParticleAnalysis(QtWidgets.QMainWindow):
        self.setCentralWidget(self.widget)
        
        self.parent = parent
        
        self.dataset = dataset
        self.particleContainer = dataset.particleContainer
        self.datastats = DataStats(dataset)
        self.editor = ParticleEditor(self.datastats, self)
        
        self.additivePlot = None
#        self.additivePlot = None
        self.importWindow = None
        
        self.polymerCheckBoxes = []
@@ -67,8 +68,8 @@ class ParticleAnalysis(QtWidgets.QMainWindow):
        self.currentSpectrumIndex = 0
        self.lastSpectrumInFocus = None
        
        self.typeHistogram = ParticleTypeView(self)
        self.typeHistogram.indexClicked.connect(self.getAdditivePlot)
        self.typeHistogramPlot = ParticleTypeView(self)
#        self.typeHistogramPlot.indexClicked.connect(self.getAdditivePlot)
        self.sizeHistogramCanvas = FigureCanvas(Figure())
       
        sizeHistGroup = QtWidgets.QGroupBox()
@@ -106,7 +107,7 @@ class ParticleAnalysis(QtWidgets.QMainWindow):
        splitter1.addWidget(sizeHistGroup)
        splitter2 = QtWidgets.QSplitter(QtCore.Qt.Horizontal)
        splitter2.addWidget(splitter1)
        splitter2.addWidget(self.typeHistogram)
        splitter2.addWidget(self.typeHistogramPlot)
        splitter2.setSizes([300, 150])
       
        self.navigationGroup = QtWidgets.QGroupBox('Navigate through polymers')
@@ -164,32 +165,31 @@ class ParticleAnalysis(QtWidgets.QMainWindow):
        self.hqiSpinBox.setValue(75.0)
        self.hqiSpinBox.setDecimals(1)
        self.hqiSpinBox.setMinimum(0)
        self.hqiSpinBox.setMaximum(100)
        self.hqiSpinBox.setMaximumWidth(45)
        optionsLayout.addRow(QtWidgets.QLabel('min HQI:'), self.hqiSpinBox)
        
        self.compHqiSpinBox = QtWidgets.QDoubleSpinBox()
        self.compHqiSpinBox.setValue(30.0)
        self.compHqiSpinBox.setDecimals(1)
        self.compHqiSpinBox.setMinimum(0)
        self.compHqiSpinBox.setDisabled(True)
        optionsLayout.addRow(QtWidgets.QLabel('min component HQI'), self.compHqiSpinBox)
#        self.compHqiSpinBox = QtWidgets.QDoubleSpinBox()
#        self.compHqiSpinBox.setValue(30.0)
#        self.compHqiSpinBox.setDecimals(1)
#        self.compHqiSpinBox.setMinimum(0)
#        self.compHqiSpinBox.setDisabled(True)
#        optionsLayout.addRow(QtWidgets.QLabel('min component HQI'), self.compHqiSpinBox)
        
        self.dispResultSpinBox = QtWidgets.QSpinBox()
        self.dispResultSpinBox.setValue(20)
        self.dispResultSpinBox.setMinimum(1)
        self.dispResultSpinBox.valueChanged.connect(self.updateHistogram)
        self.dispResultSpinBox.valueChanged.connect(self.updateHistograms)
        optionsLayout.addRow(QtWidgets.QLabel('Max. items in display:'), self.dispResultSpinBox)
        
        for spinbox in [self.hqiSpinBox, self.compHqiSpinBox]:
            spinbox.setMaximum(100)
            spinbox.setMaximumWidth(45)
        
        self.updateBtn = QtWidgets.QPushButton('Update Results')
        self.updateBtn.setDisabled(True)
        self.updateBtn.clicked.connect(self.applyHQIThresholdToResults)
#        self.updateBtn.setDisabled(True)
        optionsLayout.addRow(self.updateBtn)
        
        self.optionsGroup.setLayout(optionsLayout)
        self.optionsGroup.setMinimumWidth(175)
        self.optionsGroup.setDisabled(True)
#        self.optionsGroup.setDisabled(True)
        
        self.resultScrollarea = QtWidgets.QScrollArea(self)
        self.resultScrollarea.setFixedWidth(250)
@@ -210,25 +210,24 @@ class ParticleAnalysis(QtWidgets.QMainWindow):
        self.resultCheckBoxes.setLayout(self.resultCheckBoxesLayout)

        self.layout_SArea.addWidget(self.resultCheckBoxes)
#        self.layout_SArea.addStretch(1)

#        self.menuLayout.addWidget(reloadGroup)
        self.menuLayout.addWidget(self.optionsGroup)
        self.menuLayout.addWidget(self.resultScrollarea)
        
        self.layout.addLayout(self.menuLayout)
        self.layout.addLayout(viewLayout)
        
        minHQI = self.datastats.dataset.resultParams['minHQI']
        compHQI = self.datastats.dataset.resultParams['compHQI']
        minHQI = self.dataset.resultParams['minHQI']
#        compHQI = self.dataset.resultParams['compHQI']
        if minHQI is not None:
            self.hqiSpinBox.setValue(minHQI)
            self.compHqiSpinBox.setValue(compHQI)
#            self.compHqiSpinBox.setValue(compHQI)
         
        self.createActions()
        self.createMenus()
        
        self.updateData()
        self.initializeSpectraPlot()
        self.applyHQIThresholdToResults()
    
    def createActions(self):
        self.loadTrueMatchAct = QtWidgets.QAction("Load &TrueMatch Results", self)
@@ -241,7 +240,7 @@ class ParticleAnalysis(QtWidgets.QMainWindow):
        self.selOverlayAct = QtWidgets.QAction("&Selected Overlay", self)
        self.fullOverlayAct = QtWidgets.QAction("&Full Overlay", self)
        
        self.transpAct = QtWidgets.QAction("&Transparent Overlay")
        self.transpAct = QtWidgets.QAction("&Transparent Overlay", self)
        self.transpAct.triggered.connect(self.createPolymerOverlay)
            
        self.hideLabelAct = QtWidgets.QAction('&Hide Polymer Numbers', self)
@@ -276,7 +275,7 @@ class ParticleAnalysis(QtWidgets.QMainWindow):
        self.overlayActGroup = QtWidgets.QActionGroup(self.dispMenu)
        self.overlayActGroup.setExclusive(True)
        self.overlayActGroup.triggered.connect(self.createPolymerOverlay)
        self.overlayActGroup.triggered.connect(self.updateHistogram)
        self.overlayActGroup.triggered.connect(self.updateHistograms)
        
        for act in [self.noOverlayAct, self.selOverlayAct, self.fullOverlayAct]:
            self.dispMenu.addAction(act)
@@ -312,63 +311,62 @@ class ParticleAnalysis(QtWidgets.QMainWindow):
            self.refSelector.addItems(self.dbWin.activeDatabase.spectraNames)
            self.refSelector.setDisabled(False)
            
    def updateData(self):
        spectra = self.datastats.update()
        if spectra is None:
            fname = QtWidgets.QFileDialog.getOpenFileName(self, 'Select Spectra File', self.datastats.dataset.path, 'text file (*.txt)')[0]
            spectra = self.datastats.loadSpectra(fname)
            if spectra is None:
                QtWidgets.QMessageBox.critical(self, 'ERROR!', 'spectra file could not be opened with np.loadtxt...')
                return
    def initializeSpectraPlot(self):  #formerly updateData(self)....
        self.particleContainer.loadSpectraFromDisk()
        self.specCanvas.draw()
        self.loadParticleData()
        
    def loadParticleData(self):
        #check, if dataset already contains results. Otherwise load them...
        if not self.datastats.loadParticleData():
            self.show()
            answer = QtWidgets.QMessageBox.question(self, 'Warning', 'No (or inconsistent) spectra results found, please run import dialog.\nPress OK to import or cancel to set to empty.', QtWidgets.QMessageBox.Ok | QtWidgets.QMessageBox.Cancel)
            if answer == QtWidgets.QMessageBox.Ok:
                self.importTrueMatchResults()
            elif answer == QtWidgets.QMessageBox.Cancel:
                self.datastats.invalidateSpectra()
                self.updateBtn.clicked.connect(self.formatResults)
                self.formatResults()
        else:
            self.updateBtn.clicked.connect(self.formatResults)
            self.formatResults()
#        self.loadParticleData()
        
#    def loadParticleData(self):
#        #check, if dataset already contains results. Otherwise load them...
#        if not self.datastats.loadParticleData():
#            self.show()
#            answer = QtWidgets.QMessageBox.question(self, 'Warning', 'No (or inconsistent) spectra results found, please run import dialog.\nPress OK to import or cancel to set to empty.', QtWidgets.QMessageBox.Ok | QtWidgets.QMessageBox.Cancel)
#            if answer == QtWidgets.QMessageBox.Ok:
#                self.importTrueMatchResults()
#            elif answer == QtWidgets.QMessageBox.Cancel:
#                self.datastats.invalidateSpectra()
#                self.updateBtn.clicked.connect(self.formatResults)
#                self.formatResults()
#        else:
#            self.updateBtn.clicked.connect(self.formatResults)
#            self.formatResults()
        
    def importTrueMatchResults(self):
        self.importWindow = LoadWITecResults(self.datastats, self)
        self.importWindow.exec()
    
    @QtCore.pyqtSlot(int)
    def getAdditivePlot(self, clickedindex):
        polymer = self.datastats.typehistogram[clickedindex][0]        #get the polymer name, that was clicked on
      
        if self.datastats.sorted_additives is not None and \
           len(self.datastats.sorted_additives[clickedindex]) > 0:            
            self.additivePlot = AdditiveViewer(polymer, self.datastats.sorted_additives[clickedindex])
            self.additivePlot.show()
#    @QtCore.pyqtSlot(int)
#    def getAdditivePlot(self, clickedindex):
#        polymer = self.datastats.typehistogram[clickedindex][0]        #get the polymer name, that was clicked on
#      
#        if self.datastats.sorted_additives is not None and \
#           len(self.datastats.sorted_additives[clickedindex]) > 0:            
#            self.additivePlot = AdditiveViewer(polymer, self.datastats.sorted_additives[clickedindex])
#            self.additivePlot.show()
    
    @QtCore.pyqtSlot()
    def formatResults(self):
        if self.datastats.spectraResults is not None:
            print('formatResults')
            self.updateBtn.setDisabled(False)
            self.optionsGroup.setDisabled(False)
    def applyHQIThresholdToResults(self):
        self.particleContainer.applyHQITresholdToParticles(self.hqiSpinBox.value())
        self.createHistogramData()
        
            self.datastats.formatResults(self.hqiSpinBox.value(), self.compHqiSpinBox.value())
#    def formatResults(self):
#        if self.datastats.spectraResults is not None:
#            print('formatResults')
#            self.updateBtn.setDisabled(False)
#            self.optionsGroup.setDisabled(False)
#            
#            self.datastats.formatResults(self.hqiSpinBox.value(), self.compHqiSpinBox.value())
#            
#            if self.datastats.additiveResults is not None:
#                self.compHqiSpinBox.setDisabled(False)
            
            if self.datastats.additiveResults is not None:
                self.compHqiSpinBox.setDisabled(False)
            
            self.createHistogramData()
            
    def createHistogramData(self):
        if not self.datastats.createHistogramData():
            QtWidgets.QMessageBox.critical(self, 'Error', 'Inconsistent particle data. Please restore backup!')
            return
#        if not self.datastats.createHistogramData():
#            QtWidgets.QMessageBox.critical(self, 'Error', 'Inconsistent particle data. Please restore backup!')
#            return
#        self.particleContainer.updateTypeHistogram()
        
        ###Handle Checkboxes for all polymers...
        self.menuLayout.removeWidget(self.resultScrollarea)
@@ -381,7 +379,7 @@ class ParticleAnalysis(QtWidgets.QMainWindow):
            del i
        self.showTotalSelector.setParent(None)
        self.showTotalSelector.setDisabled(False)
        self.showTotalSelector.stateChanged.connect(self.updateHistogram)
        self.showTotalSelector.stateChanged.connect(self.updateHistograms)
        
        del self.resultCheckBoxes
        del self.resultCheckBoxesLayout
@@ -391,17 +389,16 @@ class ParticleAnalysis(QtWidgets.QMainWindow):
        self.resultScrollarea = QtWidgets.QScrollArea(self)
        self.resultScrollarea.setFixedWidth(250)
        self.resultScrollarea.setWidgetResizable(True)

        widget = QtWidgets.QWidget()
        self.resultScrollarea.setWidget(widget)
        self.layout_SArea = QtWidgets.QVBoxLayout(widget)

        self.resultCheckBoxes = QtWidgets.QGroupBox('Show Polymer Types:')
        self.resultCheckBoxesLayout = QtWidgets.QVBoxLayout()
        self.resultCheckBoxesLayout.addWidget(self.showTotalSelector)
        
        #generate new checkboxes 
        self.polymerCheckBoxes = []
        uniquePolymers = self.datastats.getUniquePolymers()
        uniquePolymers = self.particleContainer.getUniquePolymers()
        for index, polymer in enumerate(uniquePolymers):
            self.polymerCheckBoxes.append(QtWidgets.QCheckBox(self))
            self.polymerCheckBoxes[index].setText(polymer)
@@ -409,14 +406,12 @@ class ParticleAnalysis(QtWidgets.QMainWindow):
            if polymer in self.lastSelectedCheckBoxNames:
                self.polymerCheckBoxes[index].setChecked(True)
            
            self.polymerCheckBoxes[index].stateChanged.connect(self.updateHistogram)
            self.polymerCheckBoxes[index].stateChanged.connect(self.updateHistograms)
            self.polymerCheckBoxes[index].stateChanged.connect(self.createPolymerOverlay)

        self.resultCheckBoxesLayout.addStretch()
        self.resultCheckBoxes.setLayout(self.resultCheckBoxesLayout)
        
        self.layout_SArea.addWidget(self.resultCheckBoxes)
        
        self.menuLayout.addWidget(self.resultScrollarea)
        
        self.expExcelAct.setDisabled(False)
@@ -436,7 +431,7 @@ class ParticleAnalysis(QtWidgets.QMainWindow):
        else:
            self.displayNewPolymerType()
            
        self.updateHistogram()
        self.updateHistograms()
        self.createPolymerOverlay()
    
    def exportToExcel(self):
@@ -451,7 +446,7 @@ class ParticleAnalysis(QtWidgets.QMainWindow):
    def updateSpecPlot(self, centerOn=True, highlightContour=True):
        #draw Sample Spectrum
        specIndex = self.currentSpectrumIndex
        spectra = self.datastats.spectra
        spectra = self.particleContainer.spectra
        particlestats = self.datastats.getParticleStats()
        self.spec_ax.axis("on")
        self.spec_ax.clear()
@@ -563,33 +558,29 @@ class ParticleAnalysis(QtWidgets.QMainWindow):
            self.currentSpectrumIndex = self.datastats.particles2spectra[self.currentParticleIndex][self.spectrumSelector.value()-1]
            self.updateSpecPlot()
    
    def updateHistogram(self):  
    def updateHistograms(self):  
        self.updateTypeHistogram()
        self.updateSizeHistogram()
        
        
    def updateTypeHistogram(self):
        #draw the general histogram
        colorList = []
        abundancyList = []
        labelList = []
        for index, i in enumerate(self.datastats.typehistogram):
        typeHistogram = self.particleContainer.getTypeHistogram()
        for index, polymType in enumerate(typeHistogram):
            if not self.selOverlayAct.isChecked() or self.polymerCheckBoxes[index].isChecked():
                abundancyList.append(self.datastats.typehistogram[index][1])
                curColor = self.getColorFromName(self.datastats.typehistogram[index][0])
                abundancyList.append(typeHistogram[polymType])
                curColor = self.getColorFromName(polymType)
                colorList.append(QtGui.QColor(*curColor))
                if self.datastats.sorted_additives is None:
                    numads = ''
                else:
                    numads = len(np.unique(self.datastats.sorted_additives[index]))    
                    if numads == 0: 
                        numads = ''
                    else:
                        numads = '(' + str(numads) + ')'
                numpolymers = i[1]
                label = ('{} x ' + self.datastats.typehistogram[index][0] + ' {}').format(numpolymers, numads) 
                labelList.append(label)
            
        print("abundancyList:", abundancyList)
        print("labelList:", labelList)
        print("colorList:", colorList)
        self.typeHistogram.updateTypes(list(zip(abundancyList, labelList, colorList)))
#        print("abundancyList:", abundancyList)
#        print("labelList:", labelList)
#        print("colorList:", colorList)
        self.typeHistogramPlot.updateTypeHistogram(list(zip(abundancyList, labelList, colorList)))
    
    def updateSizeHistogram(self):
        #general size histogram
        self.sizeHist_ax.clear()
        self.sizeHist_ax.axis('on')
@@ -648,7 +639,7 @@ class ParticleAnalysis(QtWidgets.QMainWindow):
        if ok:
            self.datastats.colorSeed = text
            self.datastats.dataset.colorSeed = text
            self.updateHistogram()
            self.updateHistograms()
            self.createPolymerOverlay()

    def getColorFromName(self, name, base255=True):
@@ -673,7 +664,7 @@ class ParticleAnalysis(QtWidgets.QMainWindow):
                
                alpha = (128 if self.transpAct.isChecked() else 255)
                #get colors for each polymer type
                colorList = [QtGui.QColor(255, 255, 255, alpha=50)]*len(self.datastats.particleResults)
                colorList = [QtGui.QColor(255, 255, 255, alpha=50)]*len(self.datastats.particleContainer)
                legendItems = []
                    
                for index, indexList in enumerate(self.datastats.indices):
+4 −4
Original line number Diff line number Diff line
@@ -37,7 +37,7 @@ class ExpExcelDialog(QtWidgets.QDialog):
        
        self.datastats = datastats
        self.particles = self.datastats.getParticleStats()
        self.polymers = self.datastats.particleResults
        self.polymers = self.datastats.particleContainer
        self.additives = self.datastats.currentAdditives
        self.hqis = self.datastats.hqis
        
@@ -262,8 +262,8 @@ class ParticleTypeView(QtWidgets.QScrollArea):
        self.setAlignment(QtCore.Qt.AlignHCenter)
        self.widgets = []
        
    def updateTypes(self, types):
        print("Updating polymer type view", flush=True)
    def updateTypeHistogram(self, types):
#        print("Updating polymer type view", flush=True)
        for pi in self.widgets:
            self.indicatorbox.removeWidget(pi)
            pi.setParent(None)
@@ -277,7 +277,7 @@ class ParticleTypeView(QtWidgets.QScrollArea):
        
        for index, entry in enumerate(types):
            num, text, color = entry
            print("num, text, color:", num, text, color, flush=True)
#            print("num, text, color:", num, text, color, flush=True)
            pi = ParticleIndicator(num, numtotal, color, text)
            self.indicatorbox.addWidget(pi)
            pi.clicked.connect(getIndexFunction(index))
+5 −2
Original line number Diff line number Diff line
@@ -35,13 +35,16 @@ from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as Navigatio
from matplotlib.figure import Figure
import functools
from scipy.linalg import solveh_banded
from pathlib import Path

class DataBaseWindow(QtWidgets.QMainWindow):
    def __init__(self, parent):
        super(DataBaseWindow, self).__init__()
        self.parent = parent
        self.path = os.path.join(Path.home(), 'gepard', 'databases')
        
        logpath = QtCore.QStandardPaths.writableLocation(
              QtCore.QStandardPaths.AppLocalDataLocation)
        
        self.path = os.path.join(logpath, 'databases')
        self.importPath = self.path
        if not os.path.exists(self.path):
            os.mkdir(self.path)
+284 −107

File changed.

Preview size limit exceeded, changes collapsed.

+68 −0
Original line number Diff line number Diff line
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Tue May 28 20:33:14 2019

@author: brandt
"""
import numpy as np

'''Return Spectra array (First column: Wavenumbers, all other columns, intensities)
and names for all in file contained spectra'''


#TODO: Include sanity checks for correct file format?

def importWITecSpectra(fname):
    def firstColumnOnlyHasUniqueNumbers(data):
        #this is the case for WITec Spectra sets, but not for Renishaw
        if len(np.unique(data[:, 0])) == len(data[:, 0]):
            return True
        else:
            return False
        
    data = np.loadtxt(fname)
    names = [f'Spectrum {i+1}' for i in range(data.shape[1]-1)]
    
    if firstColumnOnlyHasUniqueNumbers(data):
        return data, names
    else:
        raise ImportError
    
def importRenishawSpectra(fname):
    data = np.loadtxt(fname)
    rawSpectra = data[:, 2:4]
    spectraIndices = np.where(rawSpectra[:, 0] == rawSpectra[0, 0])[0]
    positions = np.zeros((len(spectraIndices), 2))
    spectra = []
    names = []
    
    spectra = np.zeros((spectraIndices[1], len(spectraIndices)+1))
    spectra[:, 0] = rawSpectra[0:spectraIndices[1], 0]
    for i in range(len(spectraIndices)):
        names.append(f'Spectrum {i+1}')
        positions[i, :] = [data[spectraIndices[i], 0], data[spectraIndices[i], 1]]
        if i < len(spectraIndices)-1:
            spectra[:, i+1] = rawSpectra[spectraIndices[i]:spectraIndices[i+1], 1]
        else:
            spectra[:, i+1] = rawSpectra[spectraIndices[i]:, 1]
    
    spectra = np.flipud(spectra)
    wavenumbers = spectra[:, 0]
    spectra = spectra[:, 1:]
    
    return np.transpose(np.vstack((wavenumbers, spectra))), names

def importPerkinElmerSpectra(fname):
    names = []
    spectra = []
    with open(fname) as fp:
        for index, line in enumerate(fp.readlines()):
            if index == 0:
                for name in line.split(';'):
                    names.append(name.split('.sp')[0])
                    
            elif index > 1:
                spectra.append(line.split(';'))
    
    return np.array(spectra, dtype=np.float), names[1:]
Loading