Commit ac123cc1 authored by Lars Bittrich's avatar Lars Bittrich

Initial commit of current project status. Some modification will be needed...

Initial commit of current project status. Some modification will be needed before this will work without manual adaptations…
parent b20a8281
# GEPARD
GEPARD - Gepard-Enabled PARticle Detection for Raman microscopes.
Copyright (C) 2018 Lars Bittrich and Josef Brandt, Leibniz-Institut für
Polymerforschung Dresden e. V. <bittrich-lars@ipfdd.de>
Requirements:
* python 3.6, PyQt5, OpenCV 3.4.1, numpy 1.14, scikit-image 0.13.1, scipy 1.1.0,
win32com, pythoncom, cython 0.28
* we advise the use of Anaconda (python 3.6): https://www.anaconda.com/download
this package contains most of the python libraries
however, opencv and scikit-image are missing
start anaconda prompt and install opencv:
pip install opencv-python
conda install scikit-image
* we recommend working with a 64bit OS and also a python interpreter compiled
for 64bit as many use cases require a lot of memory (16 GB better 32 GB
recommended)
* the tsp module in externalmodules can be built with
python setuptsp.py
please note: for this step a valid compiler needs to be installed in the
system; Otherwise use the precompiled tsp-module
If you plan on using the WITec Raman interface to control your device, please
note: You use this interface at your OWN RISK! Make sure, that no obstacles
block the objective and that you UNDERSTAND and VALIDATE the code, that controls
the microscope! Start with "witectesting.py", which should read and move within
small margins.
At the moment the program is an executable python script. Copy the folder with
all its content to some place and run (e.g. using anaconda prompt):
python gepard.py
It is possible to create a windows link file, that executes python with the
gepard script as an argument and the working directory pointing to the folder
containing gepard for convenience.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
# -*- 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/>.
"""
try:
from setuptools import setup
from setuptools import Extension
except ImportError:
from distutils.core import setup
from distutils.extension import Extension
from Cython.Build import cythonize
import numpy as np
import sys
if len(sys.argv)==1:
sys.argv.append("build_ext")
sys.argv.append("--inplace")
ext = Extension("tsp", ["tsp.pyx"],
extra_compile_args=['-O3'],)
setup(
name = "optimized tsp-module",
ext_modules = cythonize([ext]), # accepts a glob pattern
include_dirs=[np.get_include()]
)
\ No newline at end of file
# -*- 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 numpy as np
from numpy.linalg import norm
from libc.math cimport exp, sqrt
from libc.stdlib cimport rand, RAND_MAX
cimport numpy as np
cimport cython
DTYPE = np.float
ctypedef np.float_t DTYPE_t
ctypedef np.int32_t INT32_t
ctypedef np.int64_t INT64_t
@cython.cdivision(True)
cdef double pyrand():
return rand()/float(RAND_MAX)
@cython.cdivision(True)
cdef int randint(int N):
return rand()%N
@cython.boundscheck(False) # assume: no index larger than N-1
@cython.wraparound(False) # assume: no neg. index
cdef double getdist(int n1, int n2, np.ndarray[DTYPE_t, ndim=2] points):
cdef double dx, dy
cdef int N=points.shape[0]
if n1==N or n2==N:
return 0.0
dx = points[n1,0]-points[n2,0]
dy = points[n1,1]-points[n2,1]
return sqrt(dx*dx + dy*dy)
cpdef TotalDistance(city, R):
dist = np.sum(np.sqrt(np.sum(np.diff(R[city[:-1],:],axis=0)**2,axis=1)))
return dist
# use this only after debugging!
@cython.boundscheck(False) # assume: no index larger than N-1
@cython.wraparound(False) # assume: no neg. index
cdef reverse(np.ndarray[INT32_t, ndim=1] city, int n0, int n1):
cdef int nct, nn, j, k, l
nct = city.shape[0]
nn = cython.cdiv((1+ ((n1-n0) % nct)),2) # half the lenght of the segment to be reversed
# the segment is reversed in the following way n[0]<->n[1], n[0]+1<->n[1]-1, n[0]+2<->n[1]-2,...
# Start at the ends of the segment and swap pairs of cities, moving towards the center.
for j in range(nn):
k = (n0+j) % nct
l = (n1-j) % nct
city[k], city[l] = city[l], city[k] # swap
# use this only after debugging!
@cython.boundscheck(False) # assume: no index larger than N-1
@cython.wraparound(False) # assume: no neg. index
cdef np.ndarray[INT32_t, ndim=1] transpt(np.ndarray[INT32_t, ndim=1] city, int n0, int n1, int n2, int n3, int n4, int n5):
cdef int nct, j, i
cdef np.ndarray[INT32_t, ndim=1] newcity = np.empty_like(city)
nct = city.shape[0]
i = 0
# Segment in the range n[0]...n[1]
for j in range( (n1-n0)%nct + 1):
newcity[i] = city[ (j+n0)%nct ]
i += 1
# is followed by segment n[5]...n[2]
for j in range( (n2-n5)%nct + 1):
newcity[i] = city[ (j+n5)%nct ]
i += 1
# is followed by segment n[3]...n[4]
for j in range( (n4-n3)%nct + 1):
newcity[i] = city[ (j+n3)%nct ]
i += 1
return newcity
# use this only after debugging!
@cython.boundscheck(False) # assume: no index larger than N-1
@cython.wraparound(False) # assume: no neg. index
def tspcomp(np.ndarray[DTYPE_t, ndim=2] points, np.ndarray[INT32_t, ndim=1] city=None, int maxTsteps=100, double Tstart=0.2, double fCool=0.9, int usemat=1):
"""
maxTsteps = 50 # Temperature is lowered not more than maxTsteps
Tstart = 0.2 # Starting temperature - has to be high enough
fCool = 0.9 # Factor to multiply temperature at each cooling step
"""
cdef int ncity, maxSteps, maxAccepted, nct, t, i, accepted, n0, n1, n2, n3, n4, n5, nn, nc
cdef double Preverse, T, de, dist
cdef np.ndarray[INT32_t, ndim=1] ind
cdef np.ndarray[DTYPE_t, ndim=1] d
cdef np.ndarray[DTYPE_t, ndim=2] distmat
ncity = points.shape[0]
maxSteps = 100*ncity # Number of steps at constant temperature
maxAccepted = 10*ncity # Number of accepted steps at constant temperature
Preverse = 0.5 # How often to choose reverse/transpose trial move
# Choosing city coordinates
if usemat:
distmat = np.zeros((ncity+1,ncity+1))
for i in range(ncity):
ind = np.arange(i+1,ncity, dtype=np.int32)
d = norm(points[ind,:]-points[i,:][np.newaxis,:],axis=1)
distmat[i,i+1:-1] = d
distmat[i+1:-1,i] = d
# The index table -- the order the cities are visited.
if city is None:
city = np.arange(ncity+1, dtype=np.int32)
else:
assert city.shape[0]==ncity
city = np.concatenate((city,np.int32([ncity])))
# Distance of the travel at the beginning
dist = TotalDistance(city, points)
# Stores points of a move
nct = ncity+1 # number of cities
T = Tstart # temperature
for t in range(maxTsteps): # Over temperature
accepted = 0
for i in range(maxSteps): # At each temperature, many Monte Carlo steps
while True: # Will find two random cities sufficiently close by
# Two cities n[0] and n[1] are choosen at random
n0 = randint((nct)) # select one city
n1 = randint((nct-1)) # select another city, but not the same
if (n1 >= n0): n1 += 1 #
elif (n1 < n0): n0, n1 = n1, n0 # swap, because it must be: n[0]<n[1]
nn = (n0+nct -n1-1) % nct # number of cities not on the segment n[0]..n[1]
if nn>=3: break
# We want to have one index before and one after the two cities
# The order hence is [n2,n0,n1,n3]
n2 = (n0-1) % nct # index before n0 -- see figure in the lecture notes
n3 = (n1+1) % nct # index after n2 -- see figure in the lecture notes
if Preverse > pyrand():
# Here we reverse a segment
# What would be the cost to reverse the path between city[n[0]]-city[n[1]]?
if usemat:
de = distmat[city[n2],city[n1]] + distmat[city[n3], city[n0]] - \
distmat[city[n2],city[n0]] - distmat[city[n3], city[n1]]
else:
de = getdist(city[n2],city[n1], points) + getdist(city[n3],city[n0], points) - \
getdist(city[n2],city[n0], points) - getdist(city[n3],city[n1], points)
if de<0 or exp(-cython.cdiv(de,T))>pyrand(): # Metropolis
accepted += 1
dist += de
reverse(city, n0, n1)
else:
# Here we transpose a segment
nc = (n1+1+ randint((nn-1)))%nct # Another point outside n[0],n[1] segment. See picture in lecture nodes!
n4 = nc
n5 = (nc+1) % nct
# Cost to transpose a segment
if usemat:
de = -distmat[city[n1],city[n3]] - \
distmat[city[n0],city[n2]] - \
distmat[city[n4],city[n5]]
de += distmat[city[n0],city[n4]] + \
distmat[city[n1],city[n5]] + \
distmat[city[n2],city[n3]]
else:
de = -getdist(city[n1],city[n3], points) - \
getdist(city[n0],city[n2], points) - \
getdist(city[n4],city[n5], points) + \
getdist(city[n0],city[n4], points) + \
getdist(city[n1],city[n5], points) + \
getdist(city[n2],city[n3], points)
if de<0 or exp(-cython.cdiv(de,T))>pyrand(): # Metropolis
accepted += 1
dist += de
city = transpt(city, n0, n1, n2, n3, n4, n5)
if accepted > maxAccepted: break
print("T=%10.5f , distance= %10.5f , accepted steps= %d" %(T, dist, accepted))
T *= fCool # The system is cooled down
if accepted == 0: break # If the path does not want to change any more, we can stop
for i in range(nct):
if city[i]==ncity:
break
c = np.concatenate((city[i+1:], city[:i]))
return c, T
\ No newline at end of file
This diff is collapsed.
# -*- 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 numpy as np
import cv2
import os
def cv2imread_fix(fname, flags=cv2.IMREAD_COLOR):
with open(fname, "rb") as fp:
cont = fp.read()
img = cv2.imdecode(np.fromstring(cont, dtype=np.uint8), flags)
return img
return None
def cv2imwrite_fix(fname, img, params=None):
pathname, ext = os.path.splitext(fname)
if params is None:
ret, data = cv2.imencode(ext, img)
else:
ret, data = cv2.imencode(ext, img, params)
with open(fname, "wb") as fp:
fp.write(data.tobytes())
return ret
def polygoncovering(boundary, wx, wy):
poslist = []
ymin, ymax = boundary[:,1].min(), boundary[:,1].max()
Ny = max(int(np.ceil((ymax-ymin)/wy)),1)
dyi = wy*Ny - (ymax-ymin)
y = ymin - .5*dyi + wy*np.arange(Ny)
dx = np.roll(boundary[:,0],-1)-boundary[:,0]
dy = np.roll(boundary[:,1],-1)-boundary[:,1]
x0c, x1c = boundary[:,0].min(), boundary[:,0].max()
x0clast, x1clast = x0c, x1c
for i, yi in enumerate(y):
if i==0:
if Ny>1:
ind = boundary[:,1]<y[1]
else:
ind = np.ones(boundary.shape[0], dtype=np.bool)
elif i==Ny-1:
ind = boundary[:,1]>yi
else:
ind = (boundary[:,1]>yi)&(boundary[:,1]<y[i+1])
if i<Ny-1:
dyc = y[i+1]-boundary[:,1]
with np.errstate(divide='ignore'):
ti = dyc/dy # some elements in dy may be zero, but ti will be inf or -inf in this case -> results are ok
indc = (ti>=0.)&(ti<1)
xi = boundary[indc,0] + ti[indc]*dx[indc]
x0c, x1c = xi.min(), xi.max()
if i==0:
x0clast, x1clast = x0c, x1c
if np.any(ind):
x0n, x1n = boundary[ind,0].min(), boundary[ind,0].max()
else:
x0n, x1n = x0c, x1c
x0 = min([x0n,x0c,x0clast])
x1 = max([x1n,x1c,x1clast])
Nx = int(np.ceil((x1-x0)/wx))
dxi = wx*Nx - (x1-x0)
x = x0 - .5*dxi + .5*wx + wx*np.arange(Nx)
poslist.extend([[xi,yi+.5*wy] for xi in (x if i%2==0 else x[::-1])])
x0clast, x1clast = x0c, x1c
return poslist
\ No newline at end of file
# -*- 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 cv2
import numpy as np
def imageStacking(colimgs):
full = []
images = []
laplacians = []
for img in colimgs:
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
lap = cv2.Laplacian(gray, cv2.CV_64F)
full.append(img)
images.append(gray)
blurlap = (cv2.GaussianBlur((lap)**2,(25,25),0))
laplacians.append(blurlap)
images = np.array(images)
laplacians = np.array(laplacians)
full = np.array(full)
full = np.uint8(full)
lap = laplacians+.1
zval = lap.argmax(axis=0)*(255./(lap.shape[0] - (1 if lap.shape[0]>1 else 0)))
im = np.sum(full * lap[:,:,:,np.newaxis], axis=0)/(lap[:,:,:,np.newaxis].sum(axis=0))
zval = np.uint8(zval)
im = np.uint8(im)
return im, zval
def combineImages(path, nx, ny, nk, width, height, angle):
imgs = []
full = None
for i in range(nx):
for j in range(ny):
colimgs = []
for k in range(nk):
colimgs.append(cv2.imread(path + f'test_{i}_{j}_{k}.bmp'))
img = imageStacking(colimgs)
imgs.append(img)
dx = i*.9*img.shape[1]
dy = j*.8*img.shape[0]
c, s = np.cos(np.radians(angle)), np.sin(np.radians(angle))
M = np.float32([[c,s,dx],[-s,c,dy]])
dst = cv2.warpAffine(img, M, (int(img.shape[1]*((nx-1)*.9 +1)), int(img.shape[0]*((ny-1)*.8 +1))))
if full is None:
full = dst
else:
full = cv2.max(full,dst)
cv2.imwrite("full_dunkel.png", full)
if __name__ == "__main__":
path = "../Bildserie-Scan/dunkelfeld/"
Nx, Ny, Nk = 10, 10, 4
width, height, angle = 463.78607177734375, 296.0336608886719, -0.04330849274992943
combineImages(path, Nx, Ny, Nk, width, height, angle)
\ No newline at end of file
This diff is collapsed.
# -*- 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/>.
"""
class RamanBase(object):
def __init__(self):
self.connected = False
self.timeseries = False
def getRamanPositionShift(self):
""" Compute the shift between laser spot and image center"""
raise NotImplementedError
def connect(self):
self.connected = True
return True
def disconnect(self):
self.connected = False
def getPosition(self):
raise NotImplementedError
def getSoftwareZ(self):
raise NotImplementedError
def getUserZ(self):
raise NotImplementedError
def moveToAbsolutePosition(self, x, y, z=None, epsxy=0.11, epsz=0.011):
raise NotImplementedError
def moveZto(self, z, epsz=0.011):
raise NotImplementedError
def saveImage(self, fname):
raise NotImplementedError
def getImageDimensions(self):
""" Get the image width and height in um and the orientation angle in degrees.
"""
raise NotImplementedError
def startSinglePointScan(self):
raise NotImplementedError
def initiateTimeSeriesScan(self, label, numberofscans, accumulations, integrtime):
raise NotImplementedError
def nextTimeSeriesScan(self, num):
raise NotImplementedError
\ No newline at end of file
# -*- 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
from socket import gethostname
from WITecCOM import WITecCOM
#from renishawcom import RenishawCOM
from simulatedraman import SimulatedRaman
__all__ = ["RamanControl", "simulatedRaman", "defaultPath"]
defaultPath = os.path.split(__file__)[0]
RamanControl = SimulatedRaman
hostname = gethostname()
if "SIMULATED_RAMAN_CONTROL" not in os.environ:
if "NO_WITEC_CONTROL" not in os.environ:
WITecCOM.hostname = hostname
#defaultPath = r"D:\Projekte\Mikroplastik"
RamanControl = WITecCOM
# elif hostname == RenishawCOM.hostname and "NO_RENISHAW_CONTROL" not in os.environ:
# RamanControl = RenishawCOM
if RamanControl == SimulatedRaman:
print("WARNING: using only simulated raman control!")
simulatedRaman = True
else:
simulatedRaman = False
\ No newline at end of file
# -*- 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
import numpy as np
from multiprocessing import Process, Pipe
from time import sleep, time
from externalmodules import tsp
import datetime
import sys
def reorder(points, N=20):
y0, y1 = points[:,1].min(), points[:,1].max()
y = np.linspace(y0,y1+.1,N+1)
allind = np.arange(points.shape[0])
newind = []
for i, yi in enumerate(y[:-1]):
yi1 = y[i+1]
indy = allind[(points[:,1]>=yi)&(points[:,1]<yi1)]
p = points[indy,:]
indx = p[:,0].argsort()
if i%2==1:
newind.append(indy[indx])
else:
newind.append(indy[indx[::-1]])
newind = np.concatenate(newind, axis=0)
assert np.unique(newind).shape[0]==allind.shape[0]
return newind
def scan(name, accu, inttime, positions, controlclass, connection):
with open("ramanscanlog.txt", "a") as fp:
sys.stderr = fp
sys.stdout = fp
ramanctrl = controlclass()
ramanctrl.connect()
ramanctrl.initiateTimeSeriesScan(name, len(positions), accu, inttime)
for i, p in enumerate(positions):
x, y, z = p
print("time:", time())
print("position:", x, y, z)
ramanctrl.moveToAbsolutePosition(x, y, z)
ramanctrl.nextTimeSeriesScan(i)
if connection.poll():
instruction = connection.recv()
if instruction=="stop":
ramanctrl.disconnect()
return
connection.send(i)
ramanctrl.disconnect()
while not connection.poll():
sleep(.1)
connection.recv()
class RamanScanUI(QtWidgets.QWidget):
imageUpdate = QtCore.pyqtSignal(name='imageUpdate')
ramanscanUpdate = QtCore.pyqtSignal()
def __init__(self, ramanctrl, dataset, parent=None):
super().__init__(parent, QtCore.Qt.Window)
self.view = parent
self.ramanctrl = ramanctrl
self.dataset = dataset
self.process = None
vbox = QtWidgets.QVBoxLayout()
hbox = QtWidgets.QHBoxLayout()
labelaccu = QtWidgets.QLabel("Accumulations:", self)
self.accumulationsedit = QtWidgets.QSpinBox(self)
self.accumulationsedit.setMinimum(1)
self.accumulationsedit.setMaximum(1000)
self.accumulationsedit.setValue(10)
self.accumulationsedit.setMinimumWidth(70)
labelinttime = QtWidgets.QLabel("Integration time:", self)
self.inttimeedit = QtWidgets.QDoubleSpinBox(self)
self.inttimeedit.setMinimum(0.1)
self.inttimeedit.setMaximum(100.0)
self.inttimeedit.setDecimals(1)
self.inttimeedit.setValue(0.1)
self.inttimeedit.setSingleStep(0.1)
self.inttimeedit.setMinimumWidth(70)
group2 = QtWidgets.QGroupBox("Raman settings", self)
grid2 = QtWidgets.QGridLayout()
grid2.addWidget(labelaccu, 0, 0, QtCore.Qt.AlignLeft)
grid2.addWidget(self.accumulationsedit, 0, 1, QtCore.Qt.AlignRight)
grid2.addWidget(labelinttime, 1, 0, QtCore.Qt.AlignLeft)
grid2.addWidget(self.inttimeedit, 1, 1, QtCore.Qt.AlignRight)
self.prun = QtWidgets.QPushButton("Raman scan", self)
self.prun.released.connect(self.run)
grid2.addWidget(self.prun, 1, 2, QtCore.Qt.AlignRight)
group2.setLayout(grid2)
self.pexit = QtWidgets.QPushButton("Cancel", self)
self.pexit.released.connect(self.stopScan)
self.prun.setEnabled(False)
self.progressbar = QtWidgets.QProgressBar(self)
self.timelabeltext = "Estimated time to finish: "
self.progresstime = QtWidgets.QLabel(self.timelabeltext, self)
self.progresstime.setEnabled(False)
self.progressbar.setEnabled(False)
hbox.addStretch()
hbox.addWidget(self.pexit)
vbox.addWidget(group2)
vbox.addLayout(hbox)
vbox.addWidget(self.progresstime)
vbox.addWidget(self.progressbar)
self.setLayout(vbox)
self.setWindowTitle("Particle Detection")
#self.show()
self.setVisible(False)
def resetDataset(self, ds):
self.dataset = ds
if len(self.dataset.ramanpoints)>0:
self.prun.setEnabled(True)
self.setWindowTitle(str(len(ds.ramanpoints)) + " Particles")
@QtCore.pyqtSlot()
def stopScan(self):
if self.process is not None and self.process.is_alive():
reply = QtWidgets.QMessageBox.question(self, 'Stop raman scan?',
"Do you want to terminate the running scan?",
QtWidgets.QMessageBox.Yes |
QtWidgets.QMessageBox.No, QtWidgets.QMessageBox.No)
if reply == QtWidgets.QMessageBox.Yes:
self.timer.stop()
self.connection.send("stop")
self.process.join()
self.view.unblockUI()
else:
return
self.close()
@QtCore.pyqtSlot()
def run(self):
if self.dataset.readin