From 48dddf1d34451981a82464cd46bbd49336f1faa3 Mon Sep 17 00:00:00 2001 From: Lars Bittrich Date: Mon, 29 Apr 2019 17:42:55 +0200 Subject: [PATCH] bugfixes in particle analysis --- analysis/analysisview.py | 9 +++++---- analysis/analysiswidgets.py | 2 +- analysis/datastats.py | 23 +++++++++++------------ analysis/particleeditor.py | 22 ++++++++++++++-------- analysis/sqlexport.py | 11 +++++++---- dataset.py | 14 +++++++++----- viewitems.py | 11 +---------- 7 files changed, 48 insertions(+), 44 deletions(-) diff --git a/analysis/analysisview.py b/analysis/analysisview.py index 03f2589..d04ba07 100644 --- a/analysis/analysisview.py +++ b/analysis/analysisview.py @@ -456,6 +456,7 @@ class ParticleAnalysis(QtWidgets.QMainWindow): #draw Sample Spectrum specIndex = self.currentSpectrumIndex spectra = self.datastats.spectra + particlestats = self.datastats.getParticleStats() self.spec_ax.axis("on") self.spec_ax.clear() self.spec_ax.plot(spectra[:, 0], spectra[:, specIndex+1]) @@ -463,7 +464,7 @@ class ParticleAnalysis(QtWidgets.QMainWindow): 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.datastats.particlestats[self.currentParticleIndex][2], 1))) + np.round(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)) @@ -498,8 +499,8 @@ class ParticleAnalysis(QtWidgets.QMainWindow): if uniquePolymers is not None: #the index is the contour index, find particle index: specIndex = self.datastats.particles2spectra[index][0] #select first spectrum of partoicle - self.datastats.currentParticleIndex = index - self.datastats.currentSpectrumIndex = specIndex + self.currentParticleIndex = index + self.currentSpectrumIndex = specIndex selectedPolymer = self.datastats.currentPolymers[specIndex] try: @@ -649,7 +650,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.datastats.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.getParticleStats()] #extract long size (if ellipse fit is nan -> box fit) sizehist = np.histogram(self.sizes, self.bins) self.totalhistx = [] for i in range(19): diff --git a/analysis/analysiswidgets.py b/analysis/analysiswidgets.py index 669a9c0..2108e96 100644 --- a/analysis/analysiswidgets.py +++ b/analysis/analysiswidgets.py @@ -36,7 +36,7 @@ class ExpExcelDialog(QtWidgets.QDialog): self.setGeometry(200,200, 300, 300) self.datastats = datastats - self.particles = self.datastats.particlestats + self.particles = self.datastats.getParticleStats() self.polymers = self.datastats.particleResults self.additives = self.datastats.currentAdditives self.hqis = self.datastats.hqis diff --git a/analysis/datastats.py b/analysis/datastats.py index 1d1c114..bc1a5ed 100644 --- a/analysis/datastats.py +++ b/analysis/datastats.py @@ -41,7 +41,6 @@ class DataStats(object): 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 @@ -113,15 +112,6 @@ class DataStats(object): return specs def loadParticleData(self): - self.particlestats = np.array(self.dataset.particlestats) - pixelscale = self.dataset.getPixelScale() - #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.dataset.particles2spectra sortindices = self.dataset.ramanscansortindex @@ -161,12 +151,21 @@ class DataStats(object): return None return self.uniquePolymers + def getParticleStats(self): + particlestats = np.array(self.dataset.particlestats) + pixelscale = self.dataset.getPixelScale() + #convert to mikrometer scale + particlestats[:,:5] *= pixelscale + particlestats[:,4] *= pixelscale #again for the area... + return particlestats + def createHistogramData(self): + particlestats = self.getParticleStats() self.uniquePolymers = np.unique(self.currentPolymers) - self.particleResults = [None]*len(self.particlestats) + self.particleResults = [None]*len(particlestats) self.typehistogram = {i: 0 for i in self.uniquePolymers} - if len(self.particles2spectra) != len(self.particlestats): + if len(self.particles2spectra) != len(particlestats): return False for particleID, specList in enumerate(self.particles2spectra): diff --git a/analysis/particleeditor.py b/analysis/particleeditor.py index 09529ec..1cdeab0 100644 --- a/analysis/particleeditor.py +++ b/analysis/particleeditor.py @@ -57,8 +57,6 @@ class ParticleEditor(object): return contourIndices = sorted(contourIndices) #we want to keep the contour with lowest index - print('merging contours:', contourIndices) - self.createSafetyBackup() #get contours: contours = [self.datastats.dataset.particlecontours[i] for i in contourIndices] cnt = np.vstack(tuple(contours)) #combine contous @@ -73,7 +71,7 @@ class ParticleEditor(object): img = np.zeros((rangey, rangex)) for i in contourIndices: - curCnt = self.datastats.dataset.particlecontours[i] + curCnt = self.datastats.dataset.particlecontours[i].copy() for i in range(len(curCnt)): curCnt[i][0][0] -= xmin-padding curCnt[i][0][1] -= ymin-padding @@ -88,6 +86,11 @@ class ParticleEditor(object): else: temp, contours, hierarchy = cv2.findContours(img, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_NONE) + if len(contours)>1: + QtWidgets.QMessageBox.critical(self.parent, 'ERROR!', + 'Particle contours are not connected and cannot be combined!') + return + newContour = contours[0] stats = self.characterizeParticle(newContour) @@ -95,6 +98,8 @@ class ParticleEditor(object): newContour[i][0][0] += xmin-padding newContour[i][0][1] += ymin-padding + print('merging contours:', contourIndices) + self.createSafetyBackup() #check, if dataset contains (already modified) particle2spectra, otherwise create new. if self.datastats.dataset.particles2spectra is None: #create default assignment @@ -134,6 +139,9 @@ class ParticleEditor(object): print('removing index from particles2spectra:', index) del self.datastats.dataset.particles2spectra[index] + #update contours in sampleview + self.parent.parent.contouritem.resetContours(self.datastats.dataset.particlecontours) + self.parent.loadParticleData() #save data minHQI = self.parent.hqiSpinBox.value() compHQI = self.parent.compHqiSpinBox.value() @@ -142,9 +150,6 @@ class ParticleEditor(object): 'Data inconsistency after saving!', QtWidgets.QMessageBox.Ok, QtWidgets.QMessageBox.Ok) - #update contours in sampleview - self.parent.parent.contouritem.resetContours(self.datastats.dataset.particlecontours) - self.parent.loadParticleData() def reassignParticles(self, contourindices, new_assignment): @@ -161,6 +166,9 @@ class ParticleEditor(object): self.datastats.spectraResults[specIndex] = new_assignment self.datastats.hqis[specIndex] = 100 + #update contours in sampleview + self.parent.parent.contouritem.resetContours(self.datastats.dataset.particlecontours) + self.parent.loadParticleData() #save data minHQI = self.parent.hqiSpinBox.value() compHQI = self.parent.compHqiSpinBox.value() @@ -168,8 +176,6 @@ class ParticleEditor(object): QtWidgets.QMessageBox.warning(self.parent, 'Error!', 'Data inconsistency after saving!', QtWidgets.QMessageBox.Ok, QtWidgets.QMessageBox.Ok) - - self.parent.loadParticleData() def deleteParticles(self): diff --git a/analysis/sqlexport.py b/analysis/sqlexport.py index 1f6cd3a..f364e4b 100755 --- a/analysis/sqlexport.py +++ b/analysis/sqlexport.py @@ -21,16 +21,16 @@ class SQLExport(QtWidgets.QDialog): self.datastats = datastats self.polymerList = self.datastats.particleResults - self.longSizes = np.round(np.array([i[0] if np.isnan(i[2]) else i[2] for i in self.datastats.particlestats]), 1) - self.shortSize = np.round(np.array([i[1] if np.isnan(i[3]) else i[3] for i in self.datastats.particlestats]), 1) + particlestats = self.datastats.getParticleStats() + self.longSizes = np.round(np.array([i[0] if np.isnan(i[2]) else i[2] for i in particlestats]), 1) + self.shortSize = np.round(np.array([i[1] if np.isnan(i[3]) else i[3] for i in particlestats]), 1) #spectra can be quite some data size, they are not copied here but referenced later on... self.particleImages = None self.log = [] - configfilename = os.path.join(os.path.dirname(os.path.split(__file__)[0]), - 'database_config.txt') + configfilename = os.path.join(os.path.split(__file__)[0], 'database_config.txt') if not os.path.exists(configfilename): QtWidgets.QMessageBox.warning(self, 'Warning!', @@ -338,6 +338,9 @@ class SQLExport(QtWidgets.QDialog): self.cnx = mysql.connector.connect(**self.config) #port: 3306 except mysql.connector.Error as err: print(err) + QtWidgets.QMessageBox.warning(self, 'Error!', + str(err), + QtWidgets.QMessageBox.Ok, QtWidgets.QMessageBox.Ok) self.cnx = None def getEntireTable(self, tablename): diff --git a/dataset.py b/dataset.py index be224d9..4cac3e3 100644 --- a/dataset.py +++ b/dataset.py @@ -54,11 +54,13 @@ def saveData(dataset, fname): dataset.zvalimg = zvalimg def arrayCompare(a1, a2): + if a1.shape!=a2.shape: + return False + if a1.dtype!=np.float32 and a1.dtype!=np.float64: + return np.all(a1==a2) ind = np.isnan(a1) if not np.any(ind): return np.all(a1==a2) - if a1.shape!=a2.shape: - return False return np.all(a1[~ind]==a2[~ind]) def listCompare(l1, l2): @@ -78,10 +80,11 @@ def listCompare(l1, l2): def recursiveDictCompare(d1, d2): for key in d1: if not key in d2: + print("key missing in d2:", key, flush=True) return False a = d1[key] b = d2[key] - print(key, type(a), type(b)) + print(key, type(a), type(b), flush=True) if isinstance(a, np.ndarray): if not isinstance(b, np.ndarray) or not arrayCompare(a, b): print("data is different!", a, b) @@ -97,8 +100,9 @@ def recursiveDictCompare(d1, d2): print("data is different!", a, b) return False elif a != b: - print("data is different!", a, b) - return False + if (a is not None) and (b is not None): + print("data is different!", a, b) + return False return True class DataSet(object): diff --git a/viewitems.py b/viewitems.py index e80652b..6dc18cc 100644 --- a/viewitems.py +++ b/viewitems.py @@ -145,25 +145,16 @@ class SegmentationContours(QtWidgets.QGraphicsItem): elif numParticles == 1: combineMenu.setDisabled(True) - action = contextMenu.exec_(event.screenPos()) if action == deleteAct: print('deleting') elif action in combineActs: newAssignment = action.text() -# if newAssignment == "other": -# QtWidgets.QMessageBox.about(self.parent, "Not yet implemented", "we are getting there...") -# return - self.parent.analysiswidget.editor.combineParticles(self.selectedContours, newAssignment) elif action in reassignActs: - newAssignment = action.text() -# if newAssignment == "other": -# QtWidgets.QMessageBox.about(self.parent, "Not yet implemented", "we are getting there...") -# return - + newAssignment = action.text() self.parent.analysiswidget.editor.reassignParticles(self.selectedContours, newAssignment) -- GitLab