Commit 38d7b35f authored by Lars Bittrich's avatar Lars Bittrich

first step to move data operations to new datastats module

sqlexport (from Josed) added: credentials are imported via json file: here are still data operations
parent 6b9fc03c
......@@ -23,8 +23,6 @@ If not, see <https://www.gnu.org/licenses/>.
from PyQt5 import QtCore, QtGui, QtWidgets
import numpy as np
import sys
import operator
import os
import random
import colorsys
......@@ -34,8 +32,9 @@ from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as Navigatio
from .analysiswidgets import ExpExcelDialog, AdditiveViewer
from .loadresults import LoadWITecResults
from .editParticles import ParticleEditor
from .particleeditor import ParticleEditor
from .database import DataBaseWindow
from .datastats import DataStats
try:
from .sqlexport import SQLExport
sqlEnabled = True
......@@ -44,8 +43,8 @@ except:
class ParticleAnalysis(QtWidgets.QMainWindow):
def __init__(self, parent):
super(ParticleAnalysis, self).__init__()
def __init__(self, dataset, parent=None):
super(ParticleAnalysis, self).__init__(parent)
self.setGeometry(100, 100, 1680, 1050)
self.setWindowTitle('Results of polymer analysis')
self.layout = QtWidgets.QHBoxLayout()
......@@ -54,27 +53,13 @@ class ParticleAnalysis(QtWidgets.QMainWindow):
self.setCentralWidget(self.widget)
self.parent = parent
if self.parent is not None:
self.config = self.parent.dataset.resultParams
self.editor = ParticleEditor(self)
self.datastats = DataStats(dataset)
self.editor = ParticleEditor(self.datastats, self)
self.spectraResults = None #entire List of all spectra assignments
self.additiveResults = None #entire List of all additives
self.particlestats = None
self.particleResults = None #final assignment for each particle
self.currentPolymers = None #list of polymers after setting entries with low hqi to unknown
self.currentAdditives = None #same thing for the additives
self.uniquePolymers = None #list of present polymer types
self.spectra = None #acquired spectra
self.indices = None #assignment of what spectra-indices belong to what substance
self.additivePlot = None
self.importWindow = None
self.directory = None
self.particles2spectra = None
self.manualPolymers = {}
self.manualAdditives = {}
self.polymerCheckBoxes = []
self.lastSelectedCheckBoxNames = []
......@@ -235,11 +220,9 @@ class ParticleAnalysis(QtWidgets.QMainWindow):
self.layout.addLayout(self.menuLayout)
self.layout.addLayout(viewLayout)
# update config, if present:
if self.parent is not None:
if self.config['minHQI'] is not None:
self.hqiSpinBox.setValue(self.config['minHQI'])
self.compHqiSpinBox.setValue(self.config['compHQI'])
if self.datastats.config['minHQI'] is not None:
self.hqiSpinBox.setValue(self.datastats.config['minHQI'])
self.compHqiSpinBox.setValue(self.datastats.config['compHQI'])
self.createActions()
self.createMenus()
......@@ -327,97 +310,27 @@ class ParticleAnalysis(QtWidgets.QMainWindow):
self.refSelector.addItem('')
self.refSelector.addItems(self.dbWin.activeDatabase.spectraNames)
self.refSelector.setDisabled(False)
def loadSpectra(self, fname):
import time
t0 = time.time()
specfilename = self.parent.dataset.fname.split('.pkl')[0] + '_spectra.npy'
if os.path.exists(specfilename):
return np.load(specfilename)
else:
try:
specs = np.loadtxt(fname)
#if spectra are already in correct format (WITec, first column: wavenumbers, other columns, intensities),
#we take them, otherwise we have to convert from Renishaw export format...
if not len(np.unique(specs[:, 0])) == len(specs[:, 0]): #--> only unique numbers -> this is the wavenumber column, we have the witec format
#Renishaw Convert
#columns 0 and 1 are x and y coordinates. We dont need them...
startWavenumber = specs[0, 2]
startIndices = np.where(specs[:, 2] == startWavenumber)[0]
spectra = np.zeros((startIndices[1], len(startIndices)+1)) #create array with shape (numWavenumbers, numSpectra+1) (first column holds wavenumbers)
spectra[:, 0] = specs[startIndices[0]:startIndices[1], 2]
for i in range(len(startIndices)-1):
spectra[:, i+1] = specs[startIndices[i]:startIndices[i+1], 3]
#aaand the last spectrum:
spectra[:, -1] = specs[startIndices[-1]:, 3]
specs = np.flip(spectra, 0) #Renishaw goes from highest to lowest wavenumber, out of whatever reason...
#write spectra to binary file, that makes reloading them in future significantly faster
np.save(specfilename, specs)
print('loading specs:', time.time()-t0)
return specs
except:
return None
def updateData(self):
print('updating data from', self.parent.dataset.name)
self.spectraResults = self.parent.dataset.results['polymers']
self.additiveResults = self.parent.dataset.results['additives']
self.hqis = self.parent.dataset.results['hqis']
self.addhqis = self.parent.dataset.results['additive_hqis']
self.colorSeed = self.parent.dataset.colorSeed
if type(self.colorSeed) != str:
self.colorSeed = 'default'
#load Spectra
if self.parent.dataset.spectraPath is None:
fname = os.path.join(self.parent.dataset.path, self.parent.dataset.name + '_000_Spec.Data 1.txt')
else:
fname = self.parent.dataset.spectraPath
self.spectra = self.loadSpectra(fname)
if self.spectra is None:
fname = QtWidgets.QFileDialog.getOpenFileName(self, 'Select Spectra File', self.parent.dataset.path, 'text file (*.txt)')[0]
self.spectra = self.loadSpectra(fname)
if self.spectra is None:
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
self.parent.dataset.spectraPath = fname
self.specCanvas.draw()
self.loadParticleData()
def loadParticleData(self):
self.particlestats = np.array(self.parent.dataset.particlestats)
pixelscale = (self.parent.dataset.pixelscale_df if self.parent.dataset.imagescanMode == 'df' else self.parent.dataset.pixelscale_bf)
#convert to mikrometer scale
for index in range(len(self.particlestats)):
for subindex in range(5):
self.particlestats[index][subindex] = self.particlestats[index][subindex] * pixelscale #multiply by pixelscale
if subindex == 4:
self.particlestats[index][subindex] = self.particlestats[index][subindex] * pixelscale #again for the area...
self.particles2spectra = self.parent.dataset.particles2spectra
sortindices = self.parent.dataset.ramanscansortindex
if self.particles2spectra is None:
print('creating default particles2spectra list')
#no assignment found, so we assume one measurement per particle and use ramanscansortindex for assignment
self.particles2spectra = [[int(np.where(sortindices == i)[0])] for i in range(len(sortindices))]
#check, if dataset already contains results. Otherwise load them...
if self.spectraResults is None or (len(self.spectraResults) != len(sortindices)):
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.spectraResults = ['empty']*(self.spectra.shape[1]-1)
self.hqis = [100]*(self.spectra.shape[1]-1)
self.datastats.invalidateSpectra()
self.updateBtn.clicked.connect(self.formatResults)
self.formatResults()
else:
......@@ -425,79 +338,36 @@ class ParticleAnalysis(QtWidgets.QMainWindow):
self.formatResults()
def importTrueMatchResults(self):
self.importWindow = LoadWITecResults(self)
self.importWindow.show()
self.importWindow = LoadWITecResults(self.datastats, self)
self.importWindow.exec()
def getAdditivePlot(self, event):
clickedindex = int(np.round(event.xdata))
polymer = self.typehistogram[clickedindex][0] #get the polymer name, that was clicked on
polymer = self.datastats.typehistogram[clickedindex][0] #get the polymer name, that was clicked on
if len(self.sorted_additives[clickedindex]) > 0:
self.additivePlot = AdditiveViewer(polymer, self.sorted_additives[clickedindex])
if 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.spectraResults is not None:
if self.datastats.spectraResults is not None:
print('formatResults')
self.updateBtn.setDisabled(False)
self.optionsGroup.setDisabled(False)
del self.currentPolymers, self.currentAdditives
#convert to arrays (makes indexing easier...)
self.currentPolymers, self.hqis = np.array(self.spectraResults), np.array(self.hqis)
self.datastats.formatResults(self.hqiSpinBox.value(), self.compHqiSpinBox.value())
if self.additiveResults is not None:
self.currentAdditives, self.addhqis = np.array(self.additiveResults), np.array(self.addhqis)
if self.datastats.additiveResults is not None:
self.compHqiSpinBox.setDisabled(False)
else:
self.currentAdditives = None
#set poor HQI results to unknown
self.currentPolymers[self.hqis < self.hqiSpinBox.value()] = 'unknown'
if self.currentAdditives is not None:
self.currentAdditives[self.addhqis < self.compHqiSpinBox.value()] = 'unknown'
self.createHistogramData()
def createHistogramData(self):
self.uniquePolymers = np.unique(self.currentPolymers)
self.particleResults = [None]*len(self.particlestats)
self.typehistogram = {i: 0 for i in self.uniquePolymers}
if len(self.particles2spectra) != len(self.particlestats):
if not self.datastats.createHistogramData():
QtWidgets.QMessageBox.critical(self, 'Error', 'Inconsistent particle data. Please restore backup!')
return
for particleID, specList in enumerate(self.particles2spectra):
assignment = self.currentPolymers[specList[0]] #we take the first result as particle result. Hence, all spectra per particle have to have the same result
self.particleResults[particleID] = assignment
self.typehistogram[assignment] += 1
self.particleResults = np.array(self.particleResults)
##sort typehistogram, it will be converted into a list!!
self.typehistogram = sorted(self.typehistogram.items(), key = operator.itemgetter(1), reverse = True)
self.uniquePolymers = [i[0] for i in self.typehistogram]
self.indices = [] #what particles belong to which polymer type?
for polymer in self.uniquePolymers:
self.indices.append(list(np.where(self.particleResults == polymer)[0]))
###generate additive array for each type in typehistogram:
if self.currentAdditives is None:
self.sorted_additives = None
else:
self.sorted_additives = []
for polymer in self.typehistogram: #get additives of each polymer type
self.sorted_additives.append(self.currentAdditives[np.where(self.currentPolymers == polymer[0])])
for i in range(len(self.sorted_additives)): #sort out 'none' entries
nonentries = np.where(self.sorted_additives[i] == 'none')
self.sorted_additives[i] = np.delete(self.sorted_additives[i], nonentries)
###Handle Checkboxes for all polymers...
self.menuLayout.removeWidget(self.resultScrollarea)
for i in [self.resultCheckBoxes, self.resultCheckBoxesLayout, self.resultScrollarea, self.layout_SArea]:
......@@ -529,7 +399,7 @@ class ParticleAnalysis(QtWidgets.QMainWindow):
self.resultCheckBoxesLayout.addWidget(self.showTotalSelector)
#generate new checkboxes
self.polymerCheckBoxes = []
for index, polymer in enumerate(self.uniquePolymers):
for index, polymer in enumerate(self.datastats.uniquePolymers):
self.polymerCheckBoxes.append(QtWidgets.QCheckBox(self))
self.polymerCheckBoxes[index].setText(polymer)
self.resultCheckBoxesLayout.addWidget(self.polymerCheckBoxes[index])
......@@ -546,7 +416,7 @@ class ParticleAnalysis(QtWidgets.QMainWindow):
self.menuLayout.addWidget(self.resultScrollarea)
if self.currentAdditives is not None:
if self.datastats.currentAdditives is not None:
self.typeHistogramCanvas.setCursor(QtGui.QCursor(QtCore.Qt.WhatsThisCursor))
self.typeHistogramCanvas.mpl_connect('button_press_event', self.getAdditivePlot)
......@@ -557,7 +427,7 @@ class ParticleAnalysis(QtWidgets.QMainWindow):
self.navigationGroup.setEnabled(True)
self.polymerComboBox.currentIndexChanged.disconnect()
self.polymerComboBox.clear()
self.polymerComboBox.addItems(self.uniquePolymers)
self.polymerComboBox.addItems(self.datastats.uniquePolymers)
self.polymerComboBox.currentIndexChanged.connect(self.displayNewPolymerType)
self.polymerIndex = self.polymerComboBox.currentIndex()
......@@ -571,29 +441,31 @@ class ParticleAnalysis(QtWidgets.QMainWindow):
self.createPolymerOverlay()
def exportToExcel(self):
expWin = ExpExcelDialog(self)
expWin = ExpExcelDialog(self.datastats, self)
expWin.exec()
def exportToSQL(self):
sqlexp = SQLExport(self)
sqlexp = SQLExport(self.datastats, self)
sqlexp.exec()
def updateSpecPlot(self, centerOn=True, highlightContour=True):
#draw Sample Spectrum
specIndex = self.currentSpectrumIndex
spectra = self.datastats.spectra
self.spec_ax.axis("on")
self.spec_ax.clear()
self.spec_ax.plot(self.spectra[:, 0], self.spectra[:, specIndex+1])
self.spec_ax.plot(spectra[:, 0], spectra[:, specIndex+1])
self.spec_ax.tick_params(axis='both', which='both', labelsize=15)
self.spec_ax.set_xlabel('Wavenumber (cm-1)', fontsize = 15)
self.spec_ax.set_ylabel('Counts', fontsize = 15)
self.spec_ax.set_title('ScanPoint Number {}, Size = {} µm'.format(specIndex+1, np.round(self.particlestats[self.currentParticleIndex][2], 1)))
self.spec_ax.set_xbound(100, (3400 if self.spectra[-1, 0] > 3400 else self.spectra[-1, 0]))
wavenumber_diff = list(self.spectra[:, 0]-100)
self.spec_ax.set_title('ScanPoint Number {}, Size = {} µm'.format(specIndex+1,
np.round(self.datastats.particlestats[self.currentParticleIndex][2], 1)))
self.spec_ax.set_xbound(100, (3400 if spectra[-1, 0] > 3400 else spectra[-1, 0]))
wavenumber_diff = list(spectra[:, 0]-100)
y_start = wavenumber_diff.index(min(wavenumber_diff))
y_min = min(self.spectra[y_start:, specIndex+1])
y_max = max(self.spectra[y_start:, specIndex+1])
y_min = min(spectra[y_start:, specIndex+1])
y_max = max(spectra[y_start:, specIndex+1])
self.spec_ax.set_ybound(0.9*y_min, 1.1*y_max)
#draw Reference
......@@ -605,7 +477,7 @@ class ParticleAnalysis(QtWidgets.QMainWindow):
self.ref_ax.plot(ref[:, 0], ref[:, 1], color = 'r')
self.ref_ax.set_ylabel('Ref. Intensity', fontsize = 15, color = 'r')
self.ref_ax.tick_params('y', colors = 'r')
self.ref_ax.set_xbound(100, (3400 if self.spectra[-1, 0] > 3400 else self.spectra[-1, 0]))
self.ref_ax.set_xbound(100, (3400 if spectra[-1, 0] > 3400 else spectra[-1, 0]))
# wavenumber_diff = list(ref[:, 0]-100)
# y_start = wavenumber_diff.index(min(wavenumber_diff))
# y_min = min(ref[y_start:, specIndex+1])
......@@ -620,33 +492,33 @@ class ParticleAnalysis(QtWidgets.QMainWindow):
def displayNewPolymerType(self, resetCurrentIndex=True):
self.polymerIndex = self.polymerComboBox.currentIndex()
self.particleSelector.setMaximum(len(self.indices[self.polymerIndex]))
self.particleSelector.setMaximum(len(self.datastats.indices[self.polymerIndex]))
if resetCurrentIndex:
self.particleSelector.setValue(1)
self.spectrumSelector.setValue(1)
self.spectrumSelector.setMaximum(len(self.particles2spectra[self.currentParticleIndex]))
self.currentParticleIndex = self.indices[self.polymerIndex][self.particleSelector.value()-1]
self.currentSpectrumIndex = self.particles2spectra[self.currentParticleIndex][self.spectrumSelector.value()-1]
self.spectrumSelector.setMaximum(len(self.datastats.particles2spectra[self.currentParticleIndex]))
self.currentParticleIndex = self.datastats.indices[self.polymerIndex][self.particleSelector.value()-1]
self.currentSpectrumIndex = self.datastats.particles2spectra[self.currentParticleIndex][self.spectrumSelector.value()-1]
self.updateSpecPlot(centerOn=True)
else:
self.currentParticleIndex = self.indices[self.polymerIndex][self.particleSelector.value()-1]
self.currentSpectrumIndex = self.particles2spectra[self.currentParticleIndex][self.spectrumSelector.value()-1]
self.currentParticleIndex = self.datastats.indices[self.polymerIndex][self.particleSelector.value()-1]
self.currentSpectrumIndex = self.datastats.particles2spectra[self.currentParticleIndex][self.spectrumSelector.value()-1]
self.updateSpecPlot(centerOn=False)
def selectParticle(self, resetSpectrumCount=True):
if self.particles2spectra is not None:
self.currentParticleIndex = self.indices[self.polymerIndex][self.particleSelector.value()-1]
self.spectrumSelector.setMaximum(len(self.particles2spectra[self.currentParticleIndex]))
if self.datastats.particles2spectra is not None:
self.currentParticleIndex = self.datastats.indices[self.polymerIndex][self.particleSelector.value()-1]
self.spectrumSelector.setMaximum(len(self.datastats.particles2spectra[self.currentParticleIndex]))
if resetSpectrumCount:
self.spectrumSelector.setValue(1)
self.currentSpectrumIndex = self.particles2spectra[self.currentParticleIndex][self.spectrumSelector.value()-1]
self.currentSpectrumIndex = self.datastats.particles2spectra[self.currentParticleIndex][self.spectrumSelector.value()-1]
self.updateSpecPlot()
else:
print('no spectrum assignment found...')
def selectSpectrum(self):
if self.particles2spectra is not None:
self.currentSpectrumIndex = self.particles2spectra[self.currentParticleIndex][self.spectrumSelector.value()-1]
if self.datastats.particles2spectra is not None:
self.currentSpectrumIndex = self.datastats.particles2spectra[self.currentParticleIndex][self.spectrumSelector.value()-1]
self.updateSpecPlot()
def updateHistogram(self):
......@@ -662,13 +534,13 @@ class ParticleAnalysis(QtWidgets.QMainWindow):
abundancyList = []
for index, checkbox in enumerate(self.polymerCheckBoxes):
if checkbox.isChecked():
abundancyList.append(self.typehistogram[index][1])
curColor = self.getColorFromName(self.typehistogram[index][0], base255 = False)
abundancyList.append(self.datastats.typehistogram[index][1])
curColor = self.getColorFromName(self.datastats.typehistogram[index][0], base255 = False)
colorList.append(curColor)
else:
abundancyList = [i[1] for i in self.typehistogram]
for polymer in self.typehistogram:
abundancyList = [i[1] for i in self.datastats.typehistogram]
for polymer in self.datastats.typehistogram:
curColor = self.getColorFromName(polymer[0], base255 = False)
colorList.append(curColor)
......@@ -679,18 +551,18 @@ class ParticleAnalysis(QtWidgets.QMainWindow):
###add text labels
self.histPlotTextLabels = []
y_label_position = 0
for index, i in enumerate(self.typehistogram):
for index, i in enumerate(self.datastats.typehistogram):
if not self.selOverlayAct.isChecked() or self.polymerCheckBoxes[index].isChecked():
if self.sorted_additives is None:
if self.datastats.sorted_additives is None:
numads = ''
else:
numads = len(np.unique(self.sorted_additives[index]))
numads = len(np.unique(self.datastats.sorted_additives[index]))
if numads == 0:
numads = ''
else:
numads = '(' + str(numads) + ')'
numpolymers = i[1]
label = ('{} x ' + self.typehistogram[index][0] + ' {}').format(numpolymers, numads)
label = ('{} x ' + self.datastats.typehistogram[index][0] + ' {}').format(numpolymers, numads)
x_label_position = self.typeHist_ax.get_xlim()[1]*0.05
self.histPlotTextLabels.append(self.typeHist_ax.text(x_label_position, y_label_position, label, fontsize = 15, rotation = 0, verticalalignment = 'bottom'))
y_label_position += 1
......@@ -709,7 +581,7 @@ class ParticleAnalysis(QtWidgets.QMainWindow):
self.typeHist_ax.set_ylabel('Polymer Type', fontsize = 15)
self.typeHist_ax.set_xlabel('Number', fontsize = 15)
if len(self.typehistogram) > self.dispResultSpinBox.value():
if len(self.datastats.typehistogram) > self.dispResultSpinBox.value():
def wheelScroll(event):
step = -0.05*event.step*self.dispResultSpinBox.value()
......@@ -732,7 +604,7 @@ class ParticleAnalysis(QtWidgets.QMainWindow):
#general size histogram
self.bins = np.logspace(0.1, 3, 20)
self.sizes = [i[0] if np.isnan(i[2]) else i[2] for i in self.particlestats] #extract long size (if ellipse fit is nan -> box fit)
self.sizes = [i[0] if np.isnan(i[2]) else i[2] for i in self.datastats.particlestats] #extract long size (if ellipse fit is nan -> box fit)
sizehist = np.histogram(self.sizes, self.bins)
self.totalhistx = []
for i in range(19):
......@@ -755,7 +627,8 @@ class ParticleAnalysis(QtWidgets.QMainWindow):
selected.append(i.text())
for i in selected:
sizes = [self.sizes[index] for index in range(len(self.sizes)) if self.currentPolymers[index] == i]
sizes = [self.sizes[index] for index in range(len(self.sizes))
if self.datastats.currentPolymers[index] == i]
sizehist = np.histogram(sizes, self.bins)
self.sizeHist_ax.semilogx(self.totalhistx, sizehist[0], label = i, color = self.getColorFromName(i, base255 = False))
......@@ -780,19 +653,19 @@ class ParticleAnalysis(QtWidgets.QMainWindow):
self.parent.item.setOpacity(1)
def updateColorSeed(self):
text, ok = QtWidgets.QInputDialog.getText(self, 'Color Seed', 'Enter New Seed here', text=self.colorSeed)
text, ok = QtWidgets.QInputDialog.getText(self, 'Color Seed', 'Enter New Seed here', text=self.datastats.colorSeed)
if ok:
self.colorSeed = text
self.parent.dataset.colorSeed = text
self.datastats.colorSeed = text
self.datastats.dataset.colorSeed = text
self.updateHistogram()
self.createPolymerOverlay()
def getColorFromName(self, name, base255=True):
random.seed(self.colorSeed + name)
random.seed(self.datastats.colorSeed + name)
hue = random.random()
random.seed((self.colorSeed + name)*2)
random.seed((self.datastats.colorSeed + name)*2)
saturation = random.random()/4 + 0.75 #i.e., between 0.75 and 1
random.seed((self.colorSeed + name)*3)
random.seed((self.datastats.colorSeed + name)*3)
value = random.random()/5 + 0.8 #i.e., between 0.8 and 1
color = colorsys.hsv_to_rgb(hue, saturation, value)
if base255:
......@@ -803,19 +676,19 @@ class ParticleAnalysis(QtWidgets.QMainWindow):
return color
def createPolymerOverlay(self):
if not self.noOverlayAct.isChecked() and self.indices is not None:
if len(self.indices) > 0:
if not self.noOverlayAct.isChecked() and self.datastats.indices is not None:
if len(self.datastats.indices) > 0:
alpha = (128 if self.transpAct.isChecked() else 255)
#get colors for each polymer type
colorList = [QtGui.QColor(255, 255, 255, alpha=50)]*len(self.particleResults)
colorList = [QtGui.QColor(255, 255, 255, alpha=50)]*len(self.datastats.particleResults)
legendItems = []
for index, indexList in enumerate(self.indices):
for index, indexList in enumerate(self.datastats.indices):
if self.fullOverlayAct.isChecked() or (self.selOverlayAct.isChecked() and self.polymerCheckBoxes[index].isChecked()):
color = self.getColorFromName(self.uniquePolymers[index], base255=True)
color = self.getColorFromName(self.datastats.uniquePolymers[index], base255=True)
color = QtGui.QColor(color[0], color[1], color[2], alpha=alpha)
legendItems.append((self.uniquePolymers[index], color))
legendItems.append((self.datastats.uniquePolymers[index], color))
for i in indexList:
colorList[i] = color
......@@ -836,17 +709,6 @@ class ParticleAnalysis(QtWidgets.QMainWindow):
for scanIndicator in self.parent.ramanscanitems:
scanIndicator.hidden = hidden
scanIndicator.update()
def saveAnalysisResults(self):
self.parent.dataset.results = {'polymers': self.spectraResults,
'hqis': self.hqis,
'additives': self.additiveResults,
'additive_hqis': self.addhqis}
self.parent.dataset.resultParams = {'minHQI': self.hqiSpinBox.value(),
'compHQI': self.compHqiSpinBox.value()}
self.parent.dataset.save()
print('saved dataset')
def closeEvent(self, event):
......@@ -858,9 +720,10 @@ class ParticleAnalysis(QtWidgets.QMainWindow):
if __name__ == '__main__':
from ..dataset import DataSet
def run():
app = QtWidgets.QApplication(sys.argv)
meas = ParticleAnalysis(None)
meas = ParticleAnalysis(DataSet("dummydata"))
meas.showMaximized()
return app.exec_()
......
......@@ -30,16 +30,16 @@ from matplotlib.figure import Figure
class ExpExcelDialog(QtWidgets.QDialog):
def __init__(self, parent):
super(ExpExcelDialog, self).__init__()
def __init__(self, datastats, parent):
super(ExpExcelDialog, self).__init__(parent)
self.setWindowTitle('Export Options')
self.setGeometry(200,200, 300, 300)
self.parent = parent
self.particles = self.parent.particlestats
self.polymers = self.parent.particleResults
self.additives = self.parent.currentAdditives
self.hqis = self.parent.hqis
self.datastats = datastats
self.particles = self.datastats.particlestats
self.polymers = self.datastats.particleResults
self.additives = self.datastats.currentAdditives
self.hqis = self.datastats.hqis
self.layout = QtWidgets.QHBoxLayout()
self.setLayout(self.layout)
......@@ -51,7 +51,7 @@ class ExpExcelDialog(QtWidgets.QDialog):
self.exportOptions = ['Polymer Type (mandatory)', 'Additives', 'Long Size (µm)', 'Short Size (µm)', 'Area (µm²)', 'HQI', 'Size Classes']
self.checkBoxes = []
self.sizeClasses = [5, 10, 20, 50, 100, 1e6]
self.directory = self.parent.parent.dataset.path
self.directory = self.datastats.dataset.path
for index, option in enumerate(self.exportOptions):
self.checkBoxes.append(QtWidgets.QCheckBox(self))
......@@ -69,7 +69,7 @@ class ExpExcelDialog(QtWidgets.QDialog):
excelvbox.addWidget(self.checkBoxes[-1])
self.xlsFileName = QtWidgets.QLineEdit()
self.xlsFileName.setText('{}_Particle_List'.format(self.parent.parent.dataset.name))
self.xlsFileName.setText('{}_Particle_List'.format(self.datastats.dataset.name))
excelvbox.addWidget(QtWidgets.QLabel('Filename:'))
excelvbox.addWidget(self.xlsFileName)
......
# -*- coding: utf-8 -*-
"""
GEPARD - Gepard-Enabled PARticle Detection
Copyright (C) 2018 Lars Bittrich and Josef Brandt, Leibniz-Institut für
Polymerforschung Dresden e. V. <bittrich-lars@ipfdd.de>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program, see COPYING.
If not, see <https://www.gnu.org/licenses/>.
"""
import os
import numpy as np
import operator
class DataStats(object):
def __init__(self, dataset):
self.dataset = dataset
self.config = dataset.resultParams
self.spectraResults = None #entire List of all spectra assignments
self.additiveResults = None #entire List of all additives
self.particlestats = None
self.particleResults = None #final assignment for each particle
self.currentPolymers = None #list of polymers after setting entries with low hqi to unknown
self.currentAdditives = None #same thing for the additives
self.uniquePolymers = None #list of present polymer types
self.spectra = None #acquired spectra
self.indices = None #assignment of what spectra-indices belong to what substance
self.particles2spectra = None
self.manualPolymers = {}
self.manualAdditives = {}
def resetResults(self, spectraResults, additiveResults, hqis, addhqis):
self.spectraResults = spectraResults
self.additiveResults = additiveResults
self.hqis = hqis
self.addhqis = addhqis
def update(self):
print('updating data from', self.dataset.name)
self.spectraResults = self.dataset.results['polymers']
self.additiveResults = self.dataset.results['additives']
self.hqis = self.dataset.results['hqis']
self.addhqis = self.dataset.results['additive_hqis']
self.colorSeed = self.dataset.colorSeed
if type(self.colorSeed) != str:
self.colorSeed = 'default'
#load Spectra
if self.dataset.spectraPath is None:
fname = os.path.join(self.dataset.path, self.dataset.name + '_000_Spec.Data 1.txt')
else:
fname = self.dataset.spectraPath
return self.loadSpectra(fname)
def loadSpectra(self, fname):
import time
t0 = time.time()
specfilename = self.dataset.fname.split('.pkl')[0] + '_spectra.npy'
specs = None
if os.path.exists(specfilename):
specs = np.load(specfilename)
else:
try:
specs = np.loadtxt(fname)
#if spectra are already in correct format (WITec, first column: wavenumbers, other columns, intensities),
#we take them, otherwise we have to convert from Renishaw export format...
if not len(np.unique(specs[:, 0])) == len(specs[:, 0]): #--> only unique numbers -> this is the wavenumber column, we have the witec format
#Renishaw Convert
#columns 0 and 1 are x and y coordinates. We dont need them...
startWavenumber = specs[0, 2]
startIndices = np.where(specs[:, 2] == startWavenumber)[0]
spectra = np.zeros((startIndices[1], len(startIndices)+1)) #create array with shape (numWavenumbers, numSpectra+1) (first column holds wavenumbers)
spectra[:, 0] = specs[startIndices[0]:startIndices[1], 2]
for i in range(len(startIndices)-1):
spectra[:, i+1] = specs[startIndices[i]:startIndices[i+1], 3]
#aaand the last spectrum:
spectra[:, -1] = specs[startIndices[-1]:, 3]
specs = np.flip(spectra, 0) #Renishaw goes from highest to lowest wavenumber, out of whatever reason...
#write spectra to binary file, that makes reloading them in future significantly faster
np.save(specfilename, specs)
print('loading specs:', time.time()-t0)
self.dataset.spectraPath = fname
except:
pass
self.spectra = specs
return specs
def loadParticleData(self):
self.particlestats = np.array(self.dataset.particlestats)
pixelscale = (self.dataset.pixelscale_df if self.dataset.imagescanMode == 'df' else self.dataset.pixelscale_bf)
#convert to mikrometer scale