Commit c438bcca authored by Hackmet's avatar Hackmet

Peparation for RenishawCom, inclusion of analysis module

parent bddc18b2
......@@ -21,7 +21,7 @@ Requirements:
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
* the tsp module in external 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
......
# -*- 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
from helperfunctions import cv2imread_fix, cv2imwrite_fix
from copy import copy
currentversion = 1
currentversion = 2
def loadData(fname):
retds = None
......@@ -60,8 +60,11 @@ class DataSet(object):
self.version = currentversion
self.lastpos = None
self.maxdim = None
self.pixelscale = None # µm / pixel
self.imagedim = None # width, height, angle
self.pixelscale_df = None # µm / pixel --> scale of DARK FIELD camera (used for image stitching)
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.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
......@@ -92,6 +95,18 @@ class DataSet(object):
self.ramanscansortindex = None
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
# and mark that the coordinate system might be changed in the meantime
self.mode = "prepare"
......@@ -136,7 +151,7 @@ class DataSet(object):
zvalimg = None
Ngrid = len(self.grid)
width, height, rotationvalue = self.imagedim
width, height, rotationvalue = self.imagedim_df
p0, p1 = self.maxdim[:2], self.maxdim[2:]
for i in range(Ngrid):
print(f"Processing image {i+1} of {Ngrid}")
......@@ -154,6 +169,23 @@ class DataSet(object):
del self.particleimgs
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
def getSubImage(self, img, index, draw=True):
......@@ -176,24 +208,42 @@ class DataSet(object):
assert self.heightmap is not None
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:
assert not self.readin
p0 = copy(self.lastpos)
p0[0] -= self.imagedim[0]/2
p0[1] += self.imagedim[1]/2
return (p[0] - p0[0])/self.pixelscale, (p0[1] - p[1])/self.pixelscale
if mode == 'df':
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:
assert not self.readin
p0 = copy(self.lastpos)
p0[0] -= self.imagedim[0]/2
p0[1] += self.imagedim[1]/2
return (pixelpos[0]*self.pixelscale + p0[0]), (p0[1] - pixelpos[1]*self.pixelscale)
if mode == 'df':
p0[0] -= self.imagedim_df[0]/2
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):
p0x, p0y = self.mapToLength(pixelpos)
def mapToLengthRaman(self, pixelpos, microscopeMode='df', noz=False):
p0x, p0y = self.mapToLength(pixelpos, mode = microscopeMode)
x, y = p0x + self.pshift[0], p0y + self.pshift[1]
z = None
if not noz:
......@@ -223,8 +273,8 @@ class DataSet(object):
self.name = os.path.splitext(os.path.basename(self.fname))[0]
def getImageName(self):
return os.path.join(self.path, "fullimage.tif")
return os.path.join(self.path, 'fullimage.tif')
def getZvalImageName(self):
return os.path.join(self.path, "zvalues.tif")
......@@ -241,20 +291,38 @@ class DataSet(object):
return os.path.join(self.path, "tmp.bmp")
def saveParticleData(self):
if len(self.ramanscansortindex)>0:
data = []
for i in self.ramanscansortindex:
data.append(list(self.ramanpoints[i])+list(self.particlestats[i]))
data = np.array(data)
data[:,0], data[:,1], z = self.mapToLengthRaman((data[:,0], data[:,1]), noz=True)
data[:,2:7] *= self.pixelscale
header = "x [µm], y [µm], length [µm], height [µm], length_ellipse [µm], height_ellipse [µm]"
if data.shape[1]>6:
header = header + ", area [µm^2]"
data[:,6] *= self.pixelscale
np.savetxt(os.path.join(self.path, "particledata.txt"), data,
header=header)
print('not saving ParticleData into text file..\nThe current output format might be wrong, if multiple spectra per particle are present...')
# if len(self.ramanscansortindex)>0:
# data = []
# pixelscale = (self.pixelscale_df if self.imagescanMode == 'df' else self.pixelscale_bf)
# for i in self.ramanscansortindex:
# data.append(list(self.ramanpoints[i])+list(self.particlestats[i]))
# data = np.array(data)
# data[:,0], data[:,1], z = self.mapToLengthRaman((data[:,0], data[:,1]), microscopeMode=self.imagescanMode, noz=True)
# data[:,2:7] *= pixelscale
# header = "x [µm], y [µm], length [µm], height [µm], length_ellipse [µm], height_ellipse [µm]"
# if data.shape[1]>6:
# header = header + ", area [µm^2]"
# data[:,6] *= pixelscale
# np.savetxt(os.path.join(self.path, "particledata.txt"), data,
# header=header)
def save(self):
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):
painter.drawEllipse(p[0]-p[2], p[1]-p[2], 2*p[2], 2*p[2])
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')
def __init__(self, img, dataset, parent=None):
......@@ -277,6 +277,7 @@ class ParticleDetectionView(QtWidgets.QWidget):
self.imgclip = 0,0,0,0
self.seg = Segmentation(self.dataset)
self.thread = None
self.view = parent
vbox = QtWidgets.QVBoxLayout()
hbox = QtWidgets.QHBoxLayout()
......@@ -462,7 +463,7 @@ class ParticleDetectionView(QtWidgets.QWidget):
def closeEvent(self, event):
self.detectionFinished.emit()
self.destroy()
# self.destroy()
def mousePressEvent(self, event):
if event.button()==QtCore.Qt.RightButton:
......@@ -561,7 +562,7 @@ class ParticleDetectionView(QtWidgets.QWidget):
self.dataset.ramanscandone = False
self.dataset.mode = "opticalscan"
self.dataset.save()
self.imageUpdate.emit()
self.imageUpdate.emit(self.view.microscopeMode)
@QtCore.pyqtSlot()
def cancelThread(self):
......@@ -602,7 +603,7 @@ class ParticleDetectionView(QtWidgets.QWidget):
self.thread = None
self.unBlockUI()
self.pdetectall.setText("Detect all")
self.imageUpdate.emit()
self.imageUpdate.emit(self.view.microscopeMode)
if self.dataset is not None:
self.setWindowTitle(str(len(self.dataset.ramanpoints)) + " Particles")
else:
......
......@@ -21,7 +21,9 @@ If not, see <https://www.gnu.org/licenses/>.
from PyQt5 import QtCore, QtWidgets, QtGui
from sampleview import SampleView
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
class MeasureParticleWindow(QtWidgets.QMainWindow):
......@@ -36,10 +38,17 @@ class MeasureParticleWindow(QtWidgets.QMainWindow):
self.view.imparent = self
self.view.ScalingChanged.connect(self.scalingChanged)
self.scalebar = ScaleBar(self)
self.legend = Legend(self)
self.ramanSwitch = RamanSwitch(self)
self.view.ScalingChanged.connect(self.scalebar.updateScale)
mdiarea = QtWidgets.QMdiArea(self)
mdiarea.addSubWindow(self.scalebar)
mdiarea.addSubWindow(self.legend)
mdiarea.addSubWindow(self.ramanSwitch)
self.legend.hide()
self.ramanSwitch.hide()
subview = mdiarea.addSubWindow(self.view)
subview.showMaximized()
subview.setWindowFlags(QtCore.Qt.FramelessWindowHint)
......@@ -53,7 +62,9 @@ class MeasureParticleWindow(QtWidgets.QMainWindow):
self.updateModes()
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):
self.view.closeEvent(event)
......@@ -152,13 +163,20 @@ class MeasureParticleWindow(QtWidgets.QMainWindow):
self.ramanScanAct.setCheckable(True)
self.ramanScanAct.triggered.connect(QtCore.pyqtSlot()(lambda :self.view.switchMode("RamanScan")))
self.particelAnalysisAct = QtWidgets.QAction("Particle analysis", self)
self.particelAnalysisAct.setEnabled(False)
self.particelAnalysisAct.setCheckable(True)
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):
ose, osc, pde, pdc, rse, rsc, pae, pac = [False]*8
if maxenabled=="OpticalScan":
......@@ -219,7 +237,7 @@ class MeasureParticleWindow(QtWidgets.QMainWindow):
self.fileMenu.addAction(self.openAct)
self.fileMenu.addSeparator()
self.fileMenu.addAction(self.exitAct)
self.viewMenu = QtWidgets.QMenu("&View", self)
self.viewMenu.addAction(self.zoomInAct)
self.viewMenu.addAction(self.zoomOutAct)
......@@ -232,14 +250,20 @@ class MeasureParticleWindow(QtWidgets.QMainWindow):
self.modeMenu.addAction(self.detectParticleAct)
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.addAction(self.aboutAct)
self.menuBar().addMenu(self.fileMenu)
self.menuBar().addMenu(self.viewMenu)
self.menuBar().addMenu(self.modeMenu)
self.menuBar().addMenu(self.toolsMenu)
self.menuBar().addMenu(self.helpMenu)
def createToolBar(self):
self.toolbar = QtWidgets.QToolBar("Tools")
self.toolbar.setIconSize(QtCore.QSize(100,50))
......@@ -263,10 +287,10 @@ if __name__ == '__main__':
import sys
from time import localtime, strftime
logname = os.path.join(os.path.split(__file__)[0], os.path.join("logfile.txt"))
fp = open(logname, "a")
sys.stderr = fp
sys.stdout = fp
# logname = os.path.join(os.path.split(__file__)[0], os.path.join("logfile.txt"))
# fp = open(logname, "a")
# sys.stderr = fp
# sys.stdout = fp
print("starting GEPARD at: " + strftime("%d %b %Y %H:%M:%S", localtime()))
app = QtWidgets.QApplication(sys.argv)
......
......@@ -24,15 +24,11 @@ import cv2
import os
def cv2imread_fix(fname, flags=cv2.IMREAD_COLOR):
if not os.path.exists(fname): #This seems to be a source of potential errors. Having these lines here probably aids finding errors for other groups?
print('Error, image file not found\Please check if the used save-Image command returns before the image was fully written to disk.')
return
with open(fname, "rb") as fp:
cont = fp.read()
img = cv2.imdecode(np.fromstring(cont, dtype=np.uint8), flags)
return img
return None
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)
......
This diff is collapsed.
......@@ -28,12 +28,25 @@ except ImportError:
os.environ["NO_WITEC_CONTROL"] = "True"
from time import sleep, time
from ramanbase import RamanBase
try: #when running the witectesting, the paths have to be differently, as it is in the same directory as the other raman com modules
from ramancom.ramanbase import RamanBase
from ramancom.configRaman import RamanSettingParam
except:
from ramanbase import RamanBase
from configRaman import RamanSettingParam
from socket import gethostname
from PyQt5 import QtWidgets
class WITecCOM(RamanBase):
CLSID = "{C45E77CE-3D66-489A-B5E2-159F443BD1AA}"
magn = 20
ramanParameters = [RamanSettingParam('IntegrationTime (s)', 'double', default=0.5, minVal=0.01, maxVal=100),
RamanSettingParam('Accumulations', 'int', default=5, minVal=1, maxVal=100)]
def __init__(self, hostname=None):
super().__init__()
if hostname is None:
......@@ -193,7 +206,7 @@ class WITecCOM(RamanBase):
z = self.PosZCurUserFloatMan.GetSingleValueAsDouble()[1]
return z
def moveToAbsolutePosition(self, x, y, z=None, epsxy=0.11, epsz=0.011):
def moveToAbsolutePosition(self, x, y, z=None, epsxy=0.11, epsz=0.011, debugReturn=False, measurementRunning=False):
assert self.connected
initpos = self.getPosition()
# move only if new position is really different; repeat if new position is ignored (happens some times)
......@@ -208,9 +221,8 @@ class WITecCOM(RamanBase):
while distance > epsxy:# and (lastpos is None or lastpos!=curpos):
curpos = self.getPosition()
distance = max(abs(curpos[0]-x), abs(curpos[1]-y))
# if ((time()-t0>0.5) and max(abs(curpos[0]-initpos[0]), abs(curpos[1]-initpos[1]))<epsxy) or (time()-t0>10.):
if ((time()-t0>2) and max(abs(curpos[0]-initpos[0]), abs(curpos[1]-initpos[1]))<epsxy) or (time()-t0>10.):
print("WARNING: signal ignored; time: {} s, x, y: {}, {}, curPos: {}, initPos: {}".format((time()-t0), x, y, curpos, initpos))
if ((time()-t0>0.5) and max(abs(curpos[0]-initpos[0]), abs(curpos[1]-initpos[1]))<epsxy) or (time()-t0>10.):
print("WARNING: signal ignored:", time()-t0, x, y, curpos, initpos)
sys.stdout.flush()
break
sleep(.01)
......@@ -244,7 +256,7 @@ class WITecCOM(RamanBase):
self.ImageSaveMan.OperateTrigger()
sleep(.1)
def getImageDimensions(self):
def getImageDimensions(self, mode = 'df'):
""" Get the image width and height in um and the orientation angle in degrees.
"""
assert self.connected
......@@ -262,16 +274,17 @@ class WITecCOM(RamanBase):
if not Busy:
break
def initiateTimeSeriesScan(self, label, numberofscans,