Commit c438bcca authored by Hackmet's avatar Hackmet

Peparation for RenishawCom, inclusion of analysis module

parent bddc18b2
...@@ -21,7 +21,7 @@ Requirements: ...@@ -21,7 +21,7 @@ Requirements:
for 64bit as many use cases require a lot of memory (16 GB better 32 GB for 64bit as many use cases require a lot of memory (16 GB better 32 GB
recommended) recommended)
* the tsp module in externalmodules can be built with * the tsp module in external can be built with
python setuptsp.py python setuptsp.py
please note: for this step a valid compiler needs to be installed in the please note: for this step a valid compiler needs to be installed in the
system; Otherwise use the precompiled tsp-module system; Otherwise use the precompiled tsp-module
......
# -*- 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/>.
"""
from PyQt5 import QtCore, QtWidgets, QtGui
from PIL import ImageFont
import numpy as np
WX, WY = 1024, 200
class Legend(QtWidgets.QMdiSubWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint|QtCore.Qt.FramelessWindowHint)
self.setFixedSize(200, 800)
self.wscale = 1
self.drag = None
self.items = [] #list of items to display (text, color)
self.tileSize = 12
self.fontSize = 15
self.spacer = 10
def mousePressEvent(self, event):
if event.button()==QtCore.Qt.LeftButton:
self.drag = event.pos()
def mouseMoveEvent(self, event):
if self.drag is not None:
p0 = event.pos()
self.move(self.mapToParent(p0-self.drag))
self.parentWidget().update()
else:
super().mouseMoveEvent(event)
def mouseReleaseEvent(self, event):
self.drag = None
super().mouseReleaseEvent(event)
def paintEvent(self, event):
numEntries = len(self.items)
if numEntries > 0:
def getSize(fontsize, text, tileSize, spacer):
# font = ImageFont.truetype('arial.ttf', fontsize)
# size = font.getsize(text)
size = 5*len(text), fontsize+2
width, height = size[0]*1.5 + tileSize + spacer, numEntries * (tileSize+1*spacer) + 2*spacer
return width, height
fontSize, tileSize, spacer = self.fontSize, self.tileSize, self.spacer
longestEntry = max([i[0] for i in self.items], key=len)
width, height = getSize(fontSize, longestEntry, tileSize, spacer)
#scale smaller, if necessary
if height > 1024:
factor = 1024/height
#prevent text getting tooo small:
factor = np.clip(factor, 0.6, 1) #0.6*15 would be fontSize 9
height, tileSize, fontSize, spacer = height*factor, tileSize*factor, int(fontSize*factor), spacer*factor
width, height = getSize(fontSize, longestEntry, tileSize, spacer)
self.setFixedSize(width, height)
qp = QtGui.QPainter()
qp.begin(self)
font = QtGui.QFont()
font.setPixelSize(fontSize)
qp.setFont(font)
for index, item in enumerate(self.items):
#draw Text
x0 = tileSize+2*spacer
y0 = index*(fontSize+spacer)
rect= QtCore.QRectF(x0, y0, width, float(fontSize+spacer))
qp.drawText(rect, QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter, item[0])
#draw colored Box
qp.setBrush(item[1])
x0 = spacer
y0 = index*(fontSize+spacer) + (fontSize - tileSize)/2 +spacer/2
qp.drawRect(x0, y0, tileSize, tileSize)
qp.end()
\ No newline at end of file
This diff is collapsed.
# -*- coding: utf-8 -*-
"""
Created on Wed Jan 16 12:43:00 2019
@author: brandt
"""
"""
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 numpy as np
import cv2
#import matplotlib.pyplot as plt
class ParticleEditor(object):
def __init__(self, parent):
self.parent = parent #the assigned analysis widget
def createSafetyBackup(self):
self.parent.parent.dataset.saveBackup()
def combineParticles(self, contourIndices, new_assignment):
contourIndices = sorted(contourIndices) #we want to keep the contour with lowest index
print('selected contours:', contourIndices)
self.createSafetyBackup()
#get contours:
contours = [self.parent.parent.dataset.particlecontours[i] for i in contourIndices]
cnt = np.vstack(tuple(contours)) #combine contous
#draw contours
xmin, xmax = cnt[:,0,:][:, 0].min(), cnt[:,0,:][:, 0].max()
ymin, ymax = cnt[:,0,:][:, 1].min(), cnt[:,0,:][:, 1].max()
padding = 2 #pixel in each direction
rangex = int(np.round((xmax-xmin)+2*padding))
rangey = int(np.round((ymax-ymin)+2*padding))
for i in range(len(cnt)):
cnt[i][0][0] -= xmin-padding
cnt[i][0][1] -= ymin-padding
img = np.zeros((rangey, rangex))
cv2.drawContours(img, [cnt], 0, 1, -1)
cv2.drawContours(img, [cnt], 0, 1, 1)
img = np.uint8(cv2.morphologyEx(img, cv2.MORPH_CLOSE, np.ones((3, 3))))
temp, contours, hierarchy = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
newContour = contours[0]
stats = self.characterizeParticle(newContour)
for i in range(len(newContour)):
newContour[i][0][0] += xmin-padding
newContour[i][0][1] += ymin-padding
#check, if dataset contains (already modified) particle2spectra, otherwise create new.
if self.parent.parent.dataset.particles2spectra is None: #create default assignment
print('recreating particles2spectra from within edit particles...')
sortindices = self.parent.parent.dataset.ramanscansortindex
self.parent.parent.dataset.particles2spectra = [[int(np.where(sortindices == i)[0])] for i in range(len(sortindices))]
#Contour indices are the same as the original particlestats, which are contained in the dataset.
#We have to modify that and reload in the analysisview
#first, overwrite first index with new particlestats
self.parent.parent.dataset.particlestats[contourIndices[0]] = stats
#now, delete the rest...
self.parent.parent.dataset.particlestats = [i for ind, i in enumerate(self.parent.parent.dataset.particlestats) if ind not in contourIndices[1:]]
#same with the contours
self.parent.parent.dataset.particlecontours[contourIndices[0]] = newContour
self.parent.parent.dataset.particlecontours = [i for ind, i in enumerate(self.parent.parent.dataset.particlecontours) if ind not in contourIndices[1:]]
#update particle2spectra_list
#what is the current particle index??
specIndices = []
#other spectra indices:
for index in contourIndices:
specIndices.append(self.parent.particles2spectra[index])
#flatten index list (in case, that a nested list was created...)
specIndices = list(np.unique(np.array(specIndices)))
for i in specIndices:
self.parent.spectraResults[i] = new_assignment
self.parent.hqis[i] = 100 #avoid sorting them out again by hqi-filter...
print(f'spectrum {i} of particle{contourIndices[0]} is now {new_assignment}')
#modify particles2spectra..
self.parent.parent.dataset.particles2spectra[contourIndices[0]] = specIndices
for index in reversed(contourIndices[1:]):
print('removing index from particles2spectra:', index)
del self.parent.parent.dataset.particles2spectra[index]
#save dataset
self.parent.parent.dataset.save()
#update contours in sampleview
self.parent.parent.contouritem.resetContours(self.parent.parent.dataset.particlecontours)
self.parent.loadParticleData()
def reassignParticles(self, contourindices, new_assignment):
self.createSafetyBackup()
for partIndex in contourindices:
for specIndex in self.parent.particles2spectra[partIndex]:
self.parent.currentPolymers[specIndex] = new_assignment
self.parent.spectraResults[specIndex] = new_assignment
self.parent.hqis[specIndex] = 100
self.parent.createHistogramData()
def deleteParticles(self):
self.createSafetyBackup()
pass
def splitParticles(self):
self.createSafetyBackup()
pass
def characterizeParticle(self, contours):
##characterize particle
longellipse, shortellipse = np.nan, np.nan
cnt = contours
if cnt.shape[0] >= 5: ##at least 5 points required for ellipse fitting...
ellipse = cv2.fitEllipse(cnt)
shortellipse, longellipse = ellipse[1]
rect = cv2.minAreaRect(cnt)
long, short = rect[1]
if short>long:
long, short = short, long
return long, short, longellipse, shortellipse, cv2.contourArea(cnt)
#if __name__ == '__main__':
# import
\ No newline at end of file
This diff is collapsed.
...@@ -25,7 +25,7 @@ import cv2 ...@@ -25,7 +25,7 @@ import cv2
from helperfunctions import cv2imread_fix, cv2imwrite_fix from helperfunctions import cv2imread_fix, cv2imwrite_fix
from copy import copy from copy import copy
currentversion = 1 currentversion = 2
def loadData(fname): def loadData(fname):
retds = None retds = None
...@@ -60,8 +60,11 @@ class DataSet(object): ...@@ -60,8 +60,11 @@ class DataSet(object):
self.version = currentversion self.version = currentversion
self.lastpos = None self.lastpos = None
self.maxdim = None self.maxdim = None
self.pixelscale = None # µm / pixel self.pixelscale_df = None # µm / pixel --> scale of DARK FIELD camera (used for image stitching)
self.imagedim = None # width, height, angle self.pixelscale_bf = None # µm / pixel of DARK FIELD camera (set to same as bright field, if both use the same camera)
self.imagedim_bf = None # width, height, angle of BRIGHT FIELD camera
self.imagedim_df = None # width, height, angle of DARK FIELD camera (set to same as bright field, if both use the same camera)
self.imagescanMode = 'df' #was the fullimage acquired in dark- or brightfield?
self.fitpoints = [] # manually adjusted positions aquired to define the specimen geometry self.fitpoints = [] # manually adjusted positions aquired to define the specimen geometry
self.fitindices = [] # which of the five positions in the ui are already known self.fitindices = [] # which of the five positions in the ui are already known
self.boundary = [] # scan boundary computed by a circle around the fitpoints + manual adjustments self.boundary = [] # scan boundary computed by a circle around the fitpoints + manual adjustments
...@@ -92,6 +95,18 @@ class DataSet(object): ...@@ -92,6 +95,18 @@ class DataSet(object):
self.ramanscansortindex = None self.ramanscansortindex = None
self.ramanscandone = False self.ramanscandone = False
self.results = {'polymers': None,
'hqis': None,
'additives': None,
'additive_hqis': None}
self.resultParams = {'minHQI': None,
'compHQI': None}
self.particles2spectra = None #links idParticle to corresponding idSpectra (i.e., first measured particle (ID=0) is linked to spectra indices 0 and 1)
self.colorSeed = 'default'
self.resultsUploadedToSQL = []
self.readin = True # a value that is always set to True at loadData self.readin = True # a value that is always set to True at loadData
# and mark that the coordinate system might be changed in the meantime # and mark that the coordinate system might be changed in the meantime
self.mode = "prepare" self.mode = "prepare"
...@@ -136,7 +151,7 @@ class DataSet(object): ...@@ -136,7 +151,7 @@ class DataSet(object):
zvalimg = None zvalimg = None
Ngrid = len(self.grid) Ngrid = len(self.grid)
width, height, rotationvalue = self.imagedim width, height, rotationvalue = self.imagedim_df
p0, p1 = self.maxdim[:2], self.maxdim[2:] p0, p1 = self.maxdim[:2], self.maxdim[2:]
for i in range(Ngrid): for i in range(Ngrid):
print(f"Processing image {i+1} of {Ngrid}") print(f"Processing image {i+1} of {Ngrid}")
...@@ -154,6 +169,23 @@ class DataSet(object): ...@@ -154,6 +169,23 @@ class DataSet(object):
del self.particleimgs del self.particleimgs
self.version = 1 self.version = 1
if self.version == 1:
print("Converting legacy version 1 to 2")
if hasattr(self, 'pixelscale'):
print('pixelscale was', self.pixelscale)
self.pixelscale_bf = self.pixelscale
self.pixelscale_df = self.pixelscale
# del self.pixelscale
if hasattr(self, 'imagedim'):
self.imagedim_bf = self.imagedim
self.imagedim_df = self.imagedim
# del self.imagedim
self.version = 2
# add later conversion for higher version numbers here # add later conversion for higher version numbers here
def getSubImage(self, img, index, draw=True): def getSubImage(self, img, index, draw=True):
...@@ -176,24 +208,42 @@ class DataSet(object): ...@@ -176,24 +208,42 @@ class DataSet(object):
assert self.heightmap is not None assert self.heightmap is not None
return self.heightmap[0]*x + self.heightmap[1]*y + self.heightmap[2] return self.heightmap[0]*x + self.heightmap[1]*y + self.heightmap[2]
def mapToPixel(self, p, force=False): def mapToPixel(self, p, mode='df', force=False):
if not force: if not force:
assert not self.readin assert not self.readin
p0 = copy(self.lastpos) p0 = copy(self.lastpos)
p0[0] -= self.imagedim[0]/2
p0[1] += self.imagedim[1]/2 if mode == 'df':
return (p[0] - p0[0])/self.pixelscale, (p0[1] - p[1])/self.pixelscale p0[0] -= self.imagedim_df[0]/2
p0[1] += self.imagedim_df[1]/2
return (p[0] - p0[0])/self.pixelscale_df, (p0[1] - p[1])/self.pixelscale_df
elif mode == 'bf':
p0[0] -= self.imagedim_bf[0]/2
p0[1] += self.imagedim_bf[1]/2
return (p[0] - p0[0])/self.pixelscale_bf, (p0[1] - p[1])/self.pixelscale_bf
else:
print('mapToPixelMode not understood')
return
def mapToLength(self, pixelpos, force=False): def mapToLength(self, pixelpos, mode='df', force=False):
if not force: if not force:
assert not self.readin assert not self.readin
p0 = copy(self.lastpos) p0 = copy(self.lastpos)
p0[0] -= self.imagedim[0]/2 if mode == 'df':
p0[1] += self.imagedim[1]/2 p0[0] -= self.imagedim_df[0]/2
return (pixelpos[0]*self.pixelscale + p0[0]), (p0[1] - pixelpos[1]*self.pixelscale) p0[1] += self.imagedim_df[1]/2
return (pixelpos[0]*self.pixelscale_df + p0[0]), (p0[1] - pixelpos[1]*self.pixelscale_df)
elif mode == 'bf':
p0[0] -= self.imagedim_bf[0]/2
p0[1] += self.imagedim_bf[1]/2
return (pixelpos[0]*self.pixelscale_bf + p0[0]), (p0[1] - pixelpos[1]*self.pixelscale_bf)
else:
print('mapToRamanMode not understood')
return
def mapToLengthRaman(self, pixelpos, noz=False): def mapToLengthRaman(self, pixelpos, microscopeMode='df', noz=False):
p0x, p0y = self.mapToLength(pixelpos) p0x, p0y = self.mapToLength(pixelpos, mode = microscopeMode)
x, y = p0x + self.pshift[0], p0y + self.pshift[1] x, y = p0x + self.pshift[0], p0y + self.pshift[1]
z = None z = None
if not noz: if not noz:
...@@ -223,8 +273,8 @@ class DataSet(object): ...@@ -223,8 +273,8 @@ class DataSet(object):
self.name = os.path.splitext(os.path.basename(self.fname))[0] self.name = os.path.splitext(os.path.basename(self.fname))[0]
def getImageName(self): def getImageName(self):
return os.path.join(self.path, "fullimage.tif") return os.path.join(self.path, 'fullimage.tif')
def getZvalImageName(self): def getZvalImageName(self):
return os.path.join(self.path, "zvalues.tif") return os.path.join(self.path, "zvalues.tif")
...@@ -241,20 +291,38 @@ class DataSet(object): ...@@ -241,20 +291,38 @@ class DataSet(object):
return os.path.join(self.path, "tmp.bmp") return os.path.join(self.path, "tmp.bmp")
def saveParticleData(self): def saveParticleData(self):
if len(self.ramanscansortindex)>0: print('not saving ParticleData into text file..\nThe current output format might be wrong, if multiple spectra per particle are present...')
data = [] # if len(self.ramanscansortindex)>0:
for i in self.ramanscansortindex: # data = []
data.append(list(self.ramanpoints[i])+list(self.particlestats[i])) # pixelscale = (self.pixelscale_df if self.imagescanMode == 'df' else self.pixelscale_bf)
data = np.array(data) # for i in self.ramanscansortindex:
data[:,0], data[:,1], z = self.mapToLengthRaman((data[:,0], data[:,1]), noz=True) # data.append(list(self.ramanpoints[i])+list(self.particlestats[i]))
data[:,2:7] *= self.pixelscale # data = np.array(data)
header = "x [µm], y [µm], length [µm], height [µm], length_ellipse [µm], height_ellipse [µm]" # data[:,0], data[:,1], z = self.mapToLengthRaman((data[:,0], data[:,1]), microscopeMode=self.imagescanMode, noz=True)
if data.shape[1]>6: # data[:,2:7] *= pixelscale
header = header + ", area [µm^2]" # header = "x [µm], y [µm], length [µm], height [µm], length_ellipse [µm], height_ellipse [µm]"
data[:,6] *= self.pixelscale # if data.shape[1]>6:
np.savetxt(os.path.join(self.path, "particledata.txt"), data, # header = header + ", area [µm^2]"
header=header) # data[:,6] *= pixelscale
# np.savetxt(os.path.join(self.path, "particledata.txt"), data,
# header=header)
def save(self): def save(self):
saveData(self, self.fname) saveData(self, self.fname)
\ No newline at end of file def saveBackup(self):
backupNameNotFound = True
inc = 0
while backupNameNotFound:
directory = os.path.dirname(self.fname)
filename = self.name + '_backup_' + str(inc) + '.pkl'
path = os.path.join(directory, filename)
if os.path.exists(path):
inc += 1
else:
saveData(self, path)
backupNameNotFound = False
if __name__ == '__main__':
dset = loadData(r'D:\Projekte\Mikroplastik\Microcatch_BALT\Sampling Kampagne 1\MCI_2\MCI_2_all_kleiner500\MCI_2_ds1+2_all_kleiner500_10_1\MCI_2_ds1+2_all_kleiner500_10_1.pkl')
...@@ -267,7 +267,7 @@ class ImageView(QtWidgets.QLabel): ...@@ -267,7 +267,7 @@ class ImageView(QtWidgets.QLabel):
painter.drawEllipse(p[0]-p[2], p[1]-p[2], 2*p[2], 2*p[2]) painter.drawEllipse(p[0]-p[2], p[1]-p[2], 2*p[2], 2*p[2])
class ParticleDetectionView(QtWidgets.QWidget): class ParticleDetectionView(QtWidgets.QWidget):
imageUpdate = QtCore.pyqtSignal(name='imageUpdate') imageUpdate = QtCore.pyqtSignal(str, name='imageUpdate') #str = 'df' (= darkfield) or 'bf' (=bright field)
detectionFinished = QtCore.pyqtSignal(name='detectionFinished') detectionFinished = QtCore.pyqtSignal(name='detectionFinished')
def __init__(self, img, dataset, parent=None): def __init__(self, img, dataset, parent=None):
...@@ -277,6 +277,7 @@ class ParticleDetectionView(QtWidgets.QWidget): ...@@ -277,6 +277,7 @@ class ParticleDetectionView(QtWidgets.QWidget):
self.imgclip = 0,0,0,0 self.imgclip = 0,0,0,0
self.seg = Segmentation(self.dataset) self.seg = Segmentation(self.dataset)
self.thread = None self.thread = None
self.view = parent
vbox = QtWidgets.QVBoxLayout() vbox = QtWidgets.QVBoxLayout()
hbox = QtWidgets.QHBoxLayout() hbox = QtWidgets.QHBoxLayout()
...@@ -462,7 +463,7 @@ class ParticleDetectionView(QtWidgets.QWidget): ...@@ -462,7 +463,7 @@ class ParticleDetectionView(QtWidgets.QWidget):
def closeEvent(self, event): def closeEvent(self, event):
self.detectionFinished.emit() self.detectionFinished.emit()
self.destroy() # self.destroy()
def mousePressEvent(self, event): def mousePressEvent(self, event):
if event.button()==QtCore.Qt.RightButton: if event.button()==QtCore.Qt.RightButton:
...@@ -561,7 +562,7 @@ class ParticleDetectionView(QtWidgets.QWidget): ...@@ -561,7 +562,7 @@ class ParticleDetectionView(QtWidgets.QWidget):
self.dataset.ramanscandone = False self.dataset.ramanscandone = False
self.dataset.mode = "opticalscan" self.dataset.mode = "opticalscan"
self.dataset.save() self.dataset.save()
self.imageUpdate.emit() self.imageUpdate.emit(self.view.microscopeMode)
@QtCore.pyqtSlot() @QtCore.pyqtSlot()
def cancelThread(self): def cancelThread(self):
...@@ -602,7 +603,7 @@ class ParticleDetectionView(QtWidgets.QWidget): ...@@ -602,7 +603,7 @@ class ParticleDetectionView(QtWidgets.QWidget):
self.thread = None self.thread = None
self.unBlockUI() self.unBlockUI()
self.pdetectall.setText("Detect all") self.pdetectall.setText("Detect all")
self.imageUpdate.emit() self.imageUpdate.emit(self.view.microscopeMode)
if self.dataset is not None: if self.dataset is not None:
self.setWindowTitle(str(len(self.dataset.ramanpoints)) + " Particles") self.setWindowTitle(str(len(self.dataset.ramanpoints)) + " Particles")
else: else:
......
...@@ -21,7 +21,9 @@ If not, see <https://www.gnu.org/licenses/>. ...@@ -21,7 +21,9 @@ If not, see <https://www.gnu.org/licenses/>.
from PyQt5 import QtCore, QtWidgets, QtGui from PyQt5 import QtCore, QtWidgets, QtGui
from sampleview import SampleView from sampleview import SampleView
from scalebar import ScaleBar from scalebar import ScaleBar
from ramancontrol import defaultPath from ramancom.ramancontrol import defaultPath
from ramancom.ramanSwitch import RamanSwitch
from analysis.analysisWidgets import Legend
import os import os
class MeasureParticleWindow(QtWidgets.QMainWindow): class MeasureParticleWindow(QtWidgets.QMainWindow):
...@@ -36,10 +38,17 @@ class MeasureParticleWindow(QtWidgets.QMainWindow): ...@@ -36,10 +38,17 @@ class MeasureParticleWindow(QtWidgets.QMainWindow):
self.view.imparent = self self.view.imparent = self
self.view.ScalingChanged.connect(self.scalingChanged) self.view.ScalingChanged.connect(self.scalingChanged)
self.scalebar = ScaleBar(self) self.scalebar = ScaleBar(self)
self.legend = Legend(self)
self.ramanSwitch = RamanSwitch(self)
self.view.ScalingChanged.connect(self.scalebar.updateScale) self.view.ScalingChanged.connect(self.scalebar.updateScale)
mdiarea = QtWidgets.QMdiArea(self) mdiarea = QtWidgets.QMdiArea(self)
mdiarea.addSubWindow(self.scalebar) mdiarea.addSubWindow(self.scalebar)
mdiarea.addSubWindow(self.legend)
mdiarea.addSubWindow(self.ramanSwitch)
self.legend.hide()
self.ramanSwitch.hide()
subview = mdiarea.addSubWindow(self.view) subview = mdiarea.addSubWindow(self.view)
subview.showMaximized() subview.showMaximized()
subview.setWindowFlags(QtCore.Qt.FramelessWindowHint) subview.setWindowFlags(QtCore.Qt.FramelessWindowHint)
...@@ -53,7 +62,9 @@ class MeasureParticleWindow(QtWidgets.QMainWindow): ...@@ -53,7 +62,9 @@ class MeasureParticleWindow(QtWidgets.QMainWindow):
self.updateModes() self.updateModes()
def resizeEvent(self, event): def resizeEvent(self, event):
self.scalebar.move(0,self.height()-self.scalebar.height()) self.scalebar.move(0,self.height()-self.scalebar.height()-30)
self.legend.move(self.width()-self.legend.width()-130, 10)
self.ramanSwitch.move(5, 5)
def closeEvent(self, event): def closeEvent(self, event):
self.view.closeEvent(event) self.view.closeEvent(event)
...@@ -152,13 +163,20 @@ class MeasureParticleWindow(QtWidgets.QMainWindow): ...@@ -152,13 +163,20 @@ class MeasureParticleWindow(QtWidgets.QMainWindow):
self.ramanScanAct.setCheckable(True) self.ramanScanAct.setCheckable(True)
self.ramanScanAct.triggered.connect(QtCore.pyqtSlot()(lambda :self.view.switchMode("RamanScan"))) self.ramanScanAct.triggered.connect(QtCore.pyqtSlot()(lambda :self.view.switchMode("RamanScan")))
self.particelAnalysisAct = QtWidgets.QAction("Particle analysis", self) self.particelAnalysisAct = QtWidgets.QAction("Particle analysis", self)
self.particelAnalysisAct.setEnabled(False) self.particelAnalysisAct.setEnabled(False)
self.particelAnalysisAct.setCheckable(True) self.particelAnalysisAct.setCheckable(True)
self.particelAnalysisAct.triggered.connect(QtCore.pyqtSlot()(lambda :self.view.switchMode("ParticleAnalysis"))) self.particelAnalysisAct.triggered.connect(QtCore.pyqtSlot()(lambda :self.view.switchMode("ParticleAnalysis")))
self.snapshotAct = QtWidgets.QAction("Save Screenshot", self)
self.snapshotAct.triggered.connect(self.view.takeScreenshot)
self.snapshotAct.setDisabled(True)
self.configRamanCtrlAct = QtWidgets.QAction("Configure Raman Control", self)
self.configRamanCtrlAct.triggered.connect(self.view.configureRamanControl)
if self.view.simulatedRaman:
self.configRamanCtrlAct.setDisabled(True)
def updateModes(self, active=None, maxenabled=None): def updateModes(self, active=None, maxenabled=None):
ose, osc, pde, pdc, rse, rsc, pae, pac = [False]*8 ose, osc, pde, pdc, rse, rsc, pae, pac = [False]*8
if maxenabled=="OpticalScan": if maxenabled=="OpticalScan":
...@@ -219,7 +237,7 @@ class MeasureParticleWindow(QtWidgets.QMainWindow): ...@@ -219,7 +237,7 @@ class MeasureParticleWindow(QtWidgets.QMainWindow):
self.fileMenu.addAction(self.openAct) self.fileMenu.addAction(self.openAct)
self.fileMenu.addSeparator() self.fileMenu.addSeparator()
self.fileMenu.addAction(self.exitAct) self.fileMenu.addAction(self.exitAct)
self.viewMenu = QtWidgets.QMenu("&View", self) self.viewMenu = QtWidgets.QMenu("&View", self)
self.viewMenu.addAction(self.zoomInAct) self.viewMenu.addAction(self.zoomInAct)
self.viewMenu.addAction(self.zoomOutAct) self.viewMenu.addAction(self.zoomOutAct)
...@@ -232,14 +250,20 @@ class MeasureParticleWindow(QtWidgets.QMainWindow): ...@@ -232,14 +250,20 @@ class MeasureParticleWindow(QtWidgets.QMainWindow):
self.modeMenu.addAction(self.detectParticleAct) self.modeMenu.addAction(self.detectParticleAct)
self.modeMenu.addAction(self.particelAnalysisAct) self.modeMenu.addAction(self.particelAnalysisAct)
self.toolsMenu = QtWidgets.QMenu("Tools")
self.toolsMenu.addAction(self.snapshotAct)
self.toolsMenu.addAction(self.configRamanCtrlAct)
self.helpMenu = QtWidgets.QMenu("&Help", self) self.helpMenu = QtWidgets.QMenu("&Help", self)
self.helpMenu.addAction(self.aboutAct) self.helpMenu.addAction(self.aboutAct)
self.menuBar().addMenu(self.fileMenu) self.menuBar().addMenu(self.fileMenu)
self.menuBar().addMenu(self.viewMenu) self.menuBar().addMenu(self.viewMenu)
self.menuBar().addMenu(self.modeMenu) self.menuBar().addMenu(self.modeMenu)
self.menuBar().addMenu(self.toolsMenu)
self.menuBar().addMenu(self.helpMenu) self.menuBar().addMenu(self.helpMenu)