Commit 9b10245c authored by JosefBrandt's avatar JosefBrandt

Contours are working and can be selected
parent 9fdb42e2
This diff is collapsed.
......@@ -23,9 +23,22 @@ import numpy as np
import random
import colorsys
def getColorFromNameWithSeed(name, seed, base255=True):
random.seed(seed + name)
hue = random.random()
random.seed((seed + name)*2)
saturation = random.random()/4 + 0.75 #i.e., between 0.75 and 1
random.seed((seed + 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:
color = list(color)
for i in range(3):
color[i] = np.round(color[i]*255)
color = tuple(color)
return color
WX, WY = 1024, 200
class ColorLegend(QtWidgets.QMdiSubWindow):
def __init__(self, parent=None):
super().__init__(parent)
......@@ -42,7 +55,6 @@ class ColorLegend(QtWidgets.QMdiSubWindow):
def setTextColorItems(self, items):
for text, color in items:
print(text, color)
assert type(text)==str or type(text)==np.str_, "items must be tuples of text and QColor"
assert type(color)==QtGui.QColor or type(color)==QtCore.Qt.GlobalColor, "items must be tuples of text and QColor"
self.items = items
......@@ -111,25 +123,4 @@ class ColorLegend(QtWidgets.QMdiSubWindow):
y0 = index*(fontSize+spacer) + (fontSize - tileSize)/2 +spacer/2
qp.drawRect(x0, y0, tileSize, tileSize)
qp.end()
class ColorHandler(object):
def __init__(self):
pass
#We should implement another method of getting colors, rather than taking the random color generator
#presets and other stuff can be defined here
def getColorFromName(self, name, seed, base255=True):
random.seed(seed + name)
hue = random.random()
random.seed((seed + name)*2)
saturation = random.random()/4 + 0.75 #i.e., between 0.75 and 1
random.seed((seed + 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:
color = list(color)
for i in range(3):
color[i] = np.round(color[i]*255)
color = tuple(color)
return color
\ No newline at end of file
qp.end()
\ No newline at end of file
......@@ -23,9 +23,9 @@ If not, see <https://www.gnu.org/licenses/>.
import numpy as np
from PyQt5 import QtWidgets
class LoadWITecResults(QtWidgets.QDialog):
class LoadTrueMatchResults(QtWidgets.QDialog):
def __init__(self, particleContainer, parent):
super(LoadWITecResults, self).__init__()
super(LoadTrueMatchResults, self).__init__()
self.setGeometry(400, 400, 200, 300)
self.setWindowTitle('Get Truematch Results')
self.layout = QtWidgets.QGridLayout()
......
......@@ -59,6 +59,20 @@ class ParticleContainer(object):
particle.shortSize_ellipse = float(particlestats[index][3])
particle.area = float(particlestats[index][4])
def testForInconsistentParticles(self): #i.e., particles that have multiple measurements with different assignments
self.inconsistentParticles = []
for particle in self.particles:
if not particle.measurementsHaveSameOrigAssignment():
self.inconsistentParticles.append(particle)
if len(self.inconsistentParticles) > 0:
print('Warning, inconsistent particles found!')
for particle in self.inconsistentParticles:
print(f'Particle with index {particle.index} has the following assignments:')
for assignment in particle.getOrigMeasurementAssignments():
print(assignment)
else:
print('All particles have consistent spectra assignments')
def applyPixelScaleToParticleStats(self, pixelscale):
for index, particle in enumerate(self.particles):
particle.longSize_box *= pixelscale
......@@ -110,6 +124,10 @@ class ParticleContainer(object):
contours.append(particle.contour)
return contours
def getParticleAssignmentByIndex(self, partIndex):
particle = self.getParticleOfIndex(partIndex)
return particle.getParticleAssignment()
def getMeasurementPixelCoords(self):
coords = []
for particle in self.particles:
......@@ -148,20 +166,6 @@ class ParticleContainer(object):
for particle in self.particles:
if specIndex in particle.getMeasurementIndices():
return particle.getHQIOfMeasurementIndex(specIndex)
def testForInconsistentParticles(self): #i.e., particles that have multiple measurements with different assignments
self.inconsistentParticles = []
for particle in self.particles:
if not particle.measurementsHaveSameOrigAssignment():
self.inconsistentParticles.append(particle)
if len(self.inconsistentParticles) > 0:
print('Warning, inconsistent particles found!')
for particle in self.inconsistentParticles:
print(f'Particle with index {particle.index} has the following assignments:')
for assignment in particle.getOrigMeasurementAssignments():
print(assignment)
else:
print('All particles have consistent spectra assignments')
def getSizesOfAllParticles(self):
particleSizes = []
......@@ -340,199 +344,4 @@ class Measurement(object):
return self.assignment_orig
def getScanIndex(self):
return self.ramanScanIndex
#def readDataStats(fname):
# ds = loadData(fname)
# datastats = DataStats(ds)
# datastats.update()
# datastats.loadParticleData()
# minHQI = datastats.dataset.resultParams['minHQI']
# compHQI = datastats.dataset.resultParams['compHQI']
# datastats.formatResults(minHQI, compHQI)
# datastats.createHistogramData()
# return datastats
#
#class DataStats(object):
# def __init__(self, dataset):
# self.dataset = dataset
#
# self.spectraResults = None #entire List of all spectra assignments
# self.additiveResults = None #entire List of all additives
# 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.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.particles2spectra = self.dataset.particles2spectra
#
# sortindices = self.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...
# return not (self.spectraResults is None or (len(self.spectraResults) != len(sortindices)))
# def invalidateSpectra(self):
# self.spectraResults = ['empty']*(self.spectra.shape[1]-1)
# self.hqis = [100]*(self.spectra.shape[1]-1)
# def formatResults(self, hqi, compHqi):
# if self.spectraResults is not None:
# del self.currentPolymers, self.currentAdditives
#
# #convert to arrays (makes indexing easier...)
# self.currentPolymers, self.hqis = np.array(self.spectraResults), np.array(self.hqis)
#
# if self.additiveResults is not None:
# self.currentAdditives, self.addhqis = np.array(self.additiveResults), np.array(self.addhqis)
# self.compHqiSpinBox.setDisabled(False)
# else:
# self.currentAdditives = None
#
# #set poor HQI results to unknown
# self.currentPolymers[self.hqis < hqi] = 'unknown'
#
# if self.currentAdditives is not None:
# self.currentAdditives[self.addhqis < compHqi] = 'unknown'
# def getUniquePolymers(self):
# if self.currentPolymers is None:
# 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(particlestats)
# self.typehistogram = {i: 0 for i in self.uniquePolymers}
#
# if len(self.particles2spectra) != len(particlestats):
# return False
#
# 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)
# return True
#
# def saveAnalysisResults(self, minHQI, compHQI):
# self.dataset.results = {'polymers': self.spectraResults,
# 'hqis': self.hqis,
# 'additives': self.additiveResults,
# 'additive_hqis': self.addhqis}
#
# self.dataset.resultParams = {'minHQI': minHQI,
# 'compHQI': compHQI}
# self.dataset.save()
# testresult = self.testRead()
# print('saved dataset; Valid:', testresult)
# return testresult
#
#
# def testRead(self):
# statsread = readDataStats(self.dataset.fname)
# return recursiveDictCompare(self.__dict__, statsread.__dict__)
\ No newline at end of file
return self.ramanScanIndex
\ No newline at end of file
......@@ -675,7 +675,7 @@ class ParticleDetectionView(QtWidgets.QWidget):
curParticle.addEmptyMeasurement()
curParticle.setMeasurementPixelCoords(index, point.x, point.y)
# self.dataset.ramanpoints = measurementpoints
self.dataset.ramanpoints = measurementPoints #consider moving that to particleContainer
# self.dataset.particlecontours = contours
# self.dataset.particlestats = particlestats
# self.dataset.ramanscansortindex = []
......
......@@ -27,7 +27,6 @@ from analysis.colorlegend import ColorLegend
import os
class GEPARDMainWindow(QtWidgets.QMainWindow):
def __init__(self, logpath):
super(GEPARDMainWindow, self).__init__()
......
......@@ -29,6 +29,7 @@ from detectionview import ParticleDetectionView
from analysis.analysisview import ParticleAnalysis
from zeissimporter import ZeissImporter
from viewitems import FitPosIndicator, Node, Edge, ScanIndicator, RamanScanIndicator, SegmentationContour
from analysis.colorlegend import getColorFromNameWithSeed
from helperfunctions import polygoncovering, cv2imread_fix
import cv2
from ramancom.configRaman import RamanConfigWin
......@@ -77,8 +78,8 @@ class SampleView(QtWidgets.QGraphicsView):
self.imgdata = None
self.isblocked = False
self.contourItems = []
# self.contouritem = SegmentationContours(self)
# scene.addItem(self.contouritem)
self.selectedContours = []
self.detectionwidget = None
self.ramanwidget = RamanScanUI(self.ramanctrl, None, self.logpath, self)
self.ramanwidget.imageUpdate.connect(self.loadPixmap)
......@@ -89,7 +90,10 @@ class SampleView(QtWidgets.QGraphicsView):
self.setMinimumSize(600, 600)
self.darkenPixmap = False
self.microscopeMode = None
self.coordTestMode = False
# self.coordTestMode = False
def takeScreenshot(self):
#TODO:
......@@ -489,10 +493,10 @@ class SampleView(QtWidgets.QGraphicsView):
self.boundaryitems = edges, nodes
self.resetScanPositions()
@QtCore.pyqtSlot(int, bool)
def selectContour(self, index, centerOn=True):
if self.analysiswidget is not None:
self.analysiswidget.selectContour(index, centerOn)
# @QtCore.pyqtSlot(int, bool)
# def selectContour(self, index, centerOn=True):
# if self.analysiswidget is not None:
# self.analysiswidget.selectContour(index, centerOn)
def prepareAnalysis(self):
self.clearItems()
......@@ -511,12 +515,25 @@ class SampleView(QtWidgets.QGraphicsView):
self.scene().removeItem(cnt)
self.contourItems = []
if self.dataset is not None:
for contour in self.dataset.particleContainer.getParticleContours():
for particleIndex, contour in enumerate(self.dataset.particleContainer.getParticleContours()):
newCnt = SegmentationContour(self, contour)
newCnt.setIndex(particleIndex)
assignment = self.dataset.particleContainer.getParticleAssignmentByIndex(particleIndex)
color = getColorFromNameWithSeed(assignment, self.dataset.colorSeed)
newCnt.setColor(QtGui.QColor(color[0], color[1], color[2], 255))
if self.analysiswidget is not None:
newCnt.connectContourSelectedSignalTo(self.analysiswidget.selectParticleIndex)
# newCnt.contourSelected.connect(self.analysiswidget.selectContour)
self.contourItems.append(newCnt)
self.scene().addItem(newCnt)
def updateLegend(self, legendItems):
self.imparent.legend.setTextColorItems(legendItems)
def highLightRamanIndex(self, index):
if index < len(self.ramanscanitems):
for item in self.ramanscanitems:
......@@ -526,12 +543,6 @@ class SampleView(QtWidgets.QGraphicsView):
def centerOnRamanIndex(self, index, centerOn=True, highlightContour=True):
if centerOn:
self.centerOn(self.ramanscanitems[index])
# if highlightContour:
# self.contouritem.selectedContours = []
# else:
# self.ensureVisible(self.ramanscanitems[index])
def clearItems(self):
for item in self.fititems:
......
......@@ -21,20 +21,34 @@ If not, see <https://www.gnu.org/licenses/>.
import numpy as np
from PyQt5 import QtCore, QtWidgets, QtGui
class ContourSignalEmitter(QtCore.QObject):
contourSelected = QtCore.pyqtSignal(int)
def __init__(self):
super(ContourSignalEmitter, self).__init__()
class SegmentationContour(QtWidgets.QGraphicsItem):
def __init__(self, parent, contourData, pos=(0,0)):
super().__init__()
self.parent = parent
self.signalEmitter = ContourSignalEmitter()
self.setPos(pos[0], pos[1])
self.setFlag(QtWidgets.QGraphicsItem.ItemIsSelectable)
self.setAcceptedMouseButtons(QtCore.Qt.AllButtons)
self.brect = QtCore.QRectF(0,0,1,1)
self.contourData = contourData
self.polygon = None
self.color = QtCore.Qt.green
self.hidden = False
self.color = QtGui.QColor(50, 255, 50, 200)
self.particleIndex = None
self.isSelected = False
self.getBrectAndPolygon()
def connectContourSelectedSignalTo(self, targetMethod):
self.signalEmitter.contourSelected.connect(targetMethod)
def getBrectAndPolygon(self):
polygon = QtGui.QPolygonF()
x0 = self.contourData[:,0,0].min()
......@@ -50,24 +64,34 @@ class SegmentationContour(QtWidgets.QGraphicsItem):
def boundingRect(self):
return self.brect
def setIndex(self, index):
self.particleIndex = index
def setColor(self, color):
self.color = color
def setHidden(self, hidden):
self.hidden = hidden
def mousePressEvent(self, event):
if event.button()==QtCore.Qt.LeftButton:
print('selected particle index', self.particleIndex)
self.isSelected = True
self.signalEmitter.contourSelected.emit(self.particleIndex)
def paint(self, painter, option, widget):
if self.polygon is not None:
if self.polygon is not None and not self.hidden:
painter.setPen(QtCore.Qt.green)
if self.parent.analysiswidget is not None:
nonePaintMode = self.parent.analysiswidget.noOverlayAct.isChecked()
else:
nonePaintMode = False
if self.isSelected:
painter.setPen(QtGui.QColor(int(self.color.red()*0.7), int(self.color.green()*0.7), int(self.color.blue()*0.7), self.color.alpha()))
if not nonePaintMode:
painter.setBrush(self.color)
else:
alpha = 200
if not nonePaintMode:
if not self.hidden:
painter.setBrush(QtGui.QColor(200, 200, 200, alpha))
painter.setPen(QtCore.Qt.white)
else:
painter.setPen(QtGui.QColor(int(self.color.red()*0.7), int(self.color.green()*0.7), int(self.color.blue()*0.7), self.color.alpha()))
if not self.hidden:
painter.setBrush(self.color)
painter.drawPolygon(self.polygon)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment