Commit 5a43b674 authored by Lars Bittrich's avatar Lars Bittrich

Merge branch 'ZeissImport' into RefactoringAnalysisModules

# Conflicts:
#	__main__.py
#	analysis/datastats.py
#	dataset.py
#	detectionview.py
#	sampleview.py
#	viewitems.py

# fixed a lot of other relative import bugs
parents a6fa4f0e 9e096e02
......@@ -18,13 +18,13 @@ 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 sampleview import SampleView
from scalebar import ScaleBar
from ramancom.ramancontrol import defaultPath
from ramancom.ramanSwitch import RamanSwitch
from analysis.colorlegend import ColorLegend
import os
from PyQt5 import QtCore, QtWidgets, QtGui
from .sampleview import SampleView
from .scalebar import ScaleBar
from .ramancom.ramancontrol import defaultPath
from .ramancom.ramanSwitch import RamanSwitch
from .analysis.colorlegend import ColorLegend
class GEPARDMainWindow(QtWidgets.QMainWindow):
def __init__(self, logpath):
......@@ -37,7 +37,7 @@ class GEPARDMainWindow(QtWidgets.QMainWindow):
self.view.imparent = self
self.view.ScalingChanged.connect(self.scalingChanged)
self.scalebar = ScaleBar(self)
self.legend = ColorLegend()
self.legend = ColorLegend(self)
self.ramanSwitch = RamanSwitch(self)
self.view.ScalingChanged.connect(self.scalebar.updateScale)
......@@ -126,7 +126,7 @@ class GEPARDMainWindow(QtWidgets.QMainWindow):
def createActions(self):
fname = os.path.join(os.path.split(__file__)[0],
os.path.join("data","brand.png"))
os.path.join('data', 'brand.png'))
self.aboutAct = QtWidgets.QAction(QtGui.QIcon(fname),
"About Particle Measurment", self)
self.aboutAct.triggered.connect(self.about)
......@@ -177,7 +177,7 @@ class GEPARDMainWindow(QtWidgets.QMainWindow):
self.opticalScanAct = QtWidgets.QAction("Optical Scan", self)
self.opticalScanAct.setEnabled(False)
self.opticalScanAct.setCheckable(True)# self.importWindow.exec()
self.opticalScanAct.setCheckable(True)
self.opticalScanAct.triggered.connect(QtCore.pyqtSlot()(lambda :self.view.switchMode("OpticalScan")))
self.detectParticleAct = QtWidgets.QAction("Detect Particles", self)
......@@ -360,4 +360,4 @@ if __name__ == '__main__':
gepard.showMaximized()
ret = app.exec_()
if fp is not None:
fp.close()
\ No newline at end of file
fp.close()
......@@ -46,7 +46,7 @@ class DataBaseWindow(QtWidgets.QMainWindow):
self.path = os.path.join(logpath, 'databases')
self.importPath = self.path
if not os.path.exists(self.path):
os.mkdir(self.path)
os.makedirs(self.path)
self.activeDatabase = None
self.activeSpectrum = None
self.activeSpectrumName = None
......
......@@ -26,8 +26,8 @@ from copy import deepcopy
from .particleClassification.colorClassification import ColorClassifier
from .particleClassification.shapeClassification import ShapeClassifier
from segmentation import closeHolesOfSubImage
from errors import InvalidParticleError
from ..segmentation import closeHolesOfSubImage
from ..errors import InvalidParticleError
class ParticleStats(object):
longSize = None
......
......@@ -20,7 +20,7 @@ along with this program, see COPYING.
If not, see <https://www.gnu.org/licenses/>.
"""
import cv2
from errors import InvalidParticleError
from ...errors import InvalidParticleError
class ShapeClassifier(object):
def __init__(self):
......
......@@ -23,8 +23,8 @@ import operator
import os
from PyQt5 import QtWidgets
from analysis import importSpectra
from analysis.particleAndMeasurement import Particle, Measurement
from . import importSpectra
from .particleAndMeasurement import Particle, Measurement
class ParticleContainer(object):
......
......@@ -23,8 +23,8 @@ import numpy as np
from PyQt5 import QtWidgets, QtCore
from .particlePainter import ParticlePainter
import analysis.particleCharacterization as pc
from errors import NotConnectedContoursError
from . import particleCharacterization as pc
from ..errors import NotConnectedContoursError
class ParticleContextMenu(QtWidgets.QMenu):
combineParticlesSignal = QtCore.pyqtSignal(list, str)
......
......@@ -22,10 +22,15 @@ import os
import pickle
import numpy as np
import cv2
from helperfunctions import cv2imread_fix, cv2imwrite_fix
import sys
from .helperfunctions import cv2imread_fix, cv2imwrite_fix
from copy import copy
from analysis.particleContainer import ParticleContainer
from legacyConvert import legacyConversion, currentVersion
from .analysis.particleContainer import ParticleContainer
from .legacyConvert import legacyConversion, currentVersion
# for legacy pickle import the old module name dataset must be found
# (no relative import)
from . import dataset
sys.modules['dataset'] = dataset
def loadData(fname):
retds = None
......@@ -122,6 +127,9 @@ class DataSet(object):
self.zpositions = [] # z-positions for optical scan
self.heightmap = None
self.zvalimg = None
self.coordinatetransform = None # if imported form extern source coordinate system may be rotated
self.signx = 1.
self.signy = -1.
# parameters specifically for raman scan
self.pshift = None # shift of raman scan position relative to image center
......@@ -181,8 +189,15 @@ class DataSet(object):
def getZval(self, pixelpos):
assert self.zvalimg is not None
zp = self.zvalimg[round(pixelpos[1]), round(pixelpos[0])]
z0, z1 = self.zpositions.min(), self.zpositions.max()
i, j = int(round(pixelpos[1])), int(round(pixelpos[0]))
if i>=self.zvalimg.shape[0]:
print('error in getZval:', self.zvalimg.shape, i, j)
i = self.zvalimg.shape[0]-1
if j>=self.zvalimg.shape[1]:
print('error in getZval:', self.zvalimg.shape, i, j)
j = self.zvalimg.shape[1]-1
zp = self.zvalimg[i,j]
z0, z1 = self.zpositions[0], self.zpositions[-1]
return zp/255.*(z1-z0) + z0
def mapHeight(self, x, y):
......@@ -195,44 +210,59 @@ class DataSet(object):
assert not self.readin
p0 = copy(self.lastpos)
if self.coordinatetransform is not None:
z = 0. if len(p)<3 else p[2]
T, pc = self.coordinatetransform
p = (np.dot(np.array([p[0], p[1], z])-pc, T.T))
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
p0[0] -= self.signx*self.imagedim_df[0]/2
p0[1] -= self.signy*self.imagedim_df[1]/2
x, y = self.signx*(p[0] - p0[0])/self.pixelscale_df, self.signy*(p[1] - p0[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
p0[0] -= self.signx*self.imagedim_bf[0]/2
p0[1] -= self.signy*self.imagedim_bf[1]/2
x, y = self.signx*(p[0] - p0[0])/self.pixelscale_bf, self.signy*(p[1] - p0[1])/self.pixelscale_bf
else:
print('mapToPixelMode not understood')
return
def mapToLength(self, pixelpos, mode='df', force=False):
raise ValueError(f'mapToPixel mode: {mode} not understood')
return x, y
def mapToLength(self, pixelpos, mode='df', force=False, returnz=False):
if not force:
assert not self.readin
p0 = copy(self.lastpos)
p0[0] += self.coordOffset[0]
p0[1] += self.coordOffset[1]
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)
p0[0] -= self.signx*self.imagedim_df[0]/2
p0[1] -= self.signy*self.imagedim_df[1]/2
x, y = (self.signx*pixelpos[0]*self.pixelscale_df + p0[0]), (p0[1] + self.signy*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)
p0[0] -= self.signx*self.imagedim_bf[0]/2
p0[1] -= self.signy*self.imagedim_bf[1]/2
x, y = (self.signx*pixelpos[0]*self.pixelscale_bf + p0[0]), (p0[1] + self.signy*pixelpos[1]*self.pixelscale_bf)
else:
raise ValueError(f'mapToLength mode: {mode} not understood')
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:
if (returnz and self.zvalimg is not None) or self.coordinatetransform is not None:
z = self.mapHeight(x, y)
z += self.getZval(pixelpos)
if self.coordinatetransform is not None:
T, pc = self.coordinatetransform
x, y, z = (np.dot(np.array([x,y,z]), T) + pc)
if returnz:
return x, y, z
return x, y
def mapToLengthRaman(self, pixelpos, microscopeMode='df', noz=False):
p0x, p0y, z = self.mapToLength(pixelpos, mode=microscopeMode, returnz=True)
x, y = p0x + self.pshift[0], p0y + self.pshift[1]
return x, y, z
def newProject(self, fname):
......
......@@ -20,7 +20,7 @@ If not, see <https://www.gnu.org/licenses/>.
"""
import numpy as np
from PyQt5 import QtCore, QtWidgets, QtGui
from segmentation import Segmentation
from .segmentation import Segmentation
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg
import matplotlib.pyplot as plt
from threading import Thread
......
......@@ -23,7 +23,16 @@ import numpy as np
import cv2
import os
try:
from skimage.io import imread as skimread
from skimage.io import imsave as skimsave
except ImportError:
skimread = None
skimsave = None
def cv2imread_fix(fname, flags=cv2.IMREAD_COLOR):
if skimread is not None:
return skimread(fname, as_gray=(flags==cv2.IMREAD_GRAYSCALE))
with open(fname, "rb") as fp:
cont = fp.read()
img = cv2.imdecode(np.fromstring(cont, dtype=np.uint8), flags)
......@@ -31,6 +40,8 @@ def cv2imread_fix(fname, flags=cv2.IMREAD_COLOR):
return None
def cv2imwrite_fix(fname, img, params=None):
if skimsave is not None:
skimsave(fname, img)
pathname, ext = os.path.splitext(fname)
if params is None:
ret, data = cv2.imencode(ext, img)
......
......@@ -23,10 +23,10 @@ import numpy as np
import cv2
import os
from helperfunctions import cv2imread_fix, cv2imwrite_fix
from analysis.particleContainer import ParticleContainer
from analysis import particleCharacterization as pc
from errors import InvalidParticleError
from .helperfunctions import cv2imread_fix, cv2imwrite_fix
from .analysis.particleContainer import ParticleContainer
from .analysis import particleCharacterization as pc
from .errors import InvalidParticleError
currentVersion = 4
......
......@@ -24,7 +24,7 @@ import cv2
import numpy as np
import os
from helperfunctions import cv2imread_fix
from .helperfunctions import cv2imread_fix
class BackGroundManager(QtWidgets.QWidget):
managerClosed = QtCore.pyqtSignal()
......
......@@ -23,14 +23,14 @@ from PyQt5 import QtCore, QtWidgets
import numpy as np
from multiprocessing import Process, Queue, Event
import queue
from imagestitch import imageStacking
from .imagestitch import imageStacking
import os
import cv2
from helperfunctions import cv2imread_fix, cv2imwrite_fix
from .helperfunctions import cv2imread_fix, cv2imwrite_fix
from time import time
import datetime
import sys
from opticalbackground import BackGroundManager
from .opticalbackground import BackGroundManager
def scan(path, sol, zpositions, grid, controlclass, dataqueue,
stopevent, logpath='', ishdr=False):
......@@ -691,4 +691,4 @@ if __name__ == "__main__":
ds = DataSet('Test')
optscan = OpticalScan(SimulatedRaman(), ds)
optscan.show()
sys.exit(app.exec_())
\ No newline at end of file
sys.exit(app.exec_())
......@@ -43,19 +43,19 @@ except KeyError:
pass
if interface == "SIMULATED_RAMAN_CONTROL":
from ramancom.simulatedraman import SimulatedRaman
from .simulatedraman import SimulatedRaman
RamanControl = SimulatedRaman
print("WARNING: using only simulated raman control!")
simulatedRaman = True
elif interface == "WITEC_CONTROL":
from ramancom.WITecCOM import WITecCOM
from .WITecCOM import WITecCOM
RamanControl = WITecCOM
RamanControl.magn = int(config["General Microscope Setup"]["magnification"]) # not yet implemented in WITecCOM, but would probably be a good idea...
simulatedRaman = False
elif interface == "RENISHAW_CONTROL":
from ramancom.renishawcom import RenishawCOM
from .renishawcom import RenishawCOM
RamanControl = RenishawCOM
RamanControl.magn = int(config["General Microscope Setup"]["magnification"])
try:
......
......@@ -21,10 +21,12 @@ If not, see <https://www.gnu.org/licenses/>.
Simualted Raman interface module for testing without actual raman system connected
"""
import sys
stdout = sys.stdout
from time import sleep
import numpy as np
from shutil import copyfile
from ramancom.ramanbase import RamanBase
from .ramanbase import RamanBase
class SimulatedRaman(RamanBase):
......@@ -36,9 +38,9 @@ class SimulatedRaman(RamanBase):
self.currentpos = None, 0., 0.
self.currentZ = 0.
# some plausible data to simulate consecutively changing positions
self.positionlist = np.array([[ 1526. , -1379.9, -131. ],
[ 3762.5, -1197.7, -138.1],
[ 2313.7, -2627.2, -138.1],
self.positionlist = np.array([[ -12012, 13716, -1290],
[ -11955, -9200, -1279],
[ 10978, -9254, -1297],
[ 2704.1, -1788.2, -138.1],
[ 3884. , -2650.8, -138.1]])
self.znum = 4
......@@ -78,6 +80,7 @@ class SimulatedRaman(RamanBase):
def moveToAbsolutePosition(self, x, y, z=None, epsxy=0.11, epsz=0.011, debugReturn=False, measurementRunning=False):
assert self.connected
print('moving to:', x, y, z, file=stdout)
if z is None:
self.currentpos = x, y, self.currentpos[2]
else:
......@@ -118,4 +121,4 @@ class SimulatedRaman(RamanBase):
print("Scan number:", num)
sleep(.1)
if num==self.timeseries-1:
self.timeseries = False
\ No newline at end of file
self.timeseries = False
......@@ -24,7 +24,7 @@ import numpy as np
from multiprocessing import Process, Queue, Event
import queue
from time import time
from external import tsp
from .external import tsp
import datetime
import sys
import os
......@@ -286,4 +286,4 @@ class RamanScanUI(QtWidgets.QWidget):
self.close()
return
self.timer.start(100.)
\ No newline at end of file
......@@ -23,20 +23,18 @@ import numpy as np
import os
import cv2
import time
from dataset import DataSet, loadData
from ramancom.ramancontrol import RamanControl, simulatedRaman
from opticalscan import OpticalScan
from ramanscanui import RamanScanUI
from detectionview import ParticleDetectionView
from analysis.analysisview import ParticleAnalysis
from zeissimporter import ZeissImporter
from viewitems import FitPosIndicator, Node, Edge, ScanIndicator, RamanScanIndicator, SegmentationContour, ParticleInfo
from analysis.colorlegend import getColorFromNameWithSeed
from helperfunctions import polygoncovering, cv2imread_fix
from ramancom.configRaman import RamanConfigWin
from analysis.particleEditor import ParticleEditor
from .dataset import DataSet, loadData
from .ramancom.ramancontrol import RamanControl, simulatedRaman
from .opticalscan import OpticalScan
from .ramanscanui import RamanScanUI
from .detectionview import ParticleDetectionView
from .analysis.analysisview import ParticleAnalysis
from .zeissimporter import ZeissImporter
from .viewitems import FitPosIndicator, Node, Edge, ScanIndicator, RamanScanIndicator, SegmentationContour, ParticleInfo
from .helperfunctions import polygoncovering, cv2imread_fix
from .analysis.colorlegend import getColorFromNameWithSeed
from .analysis.particleEditor import ParticleEditor
from .ramancom.configRaman import RamanConfigWin
class SampleView(QtWidgets.QGraphicsView):
ScalingChanged = QtCore.pyqtSignal(float)
......@@ -178,7 +176,12 @@ class SampleView(QtWidgets.QGraphicsView):
if mode is None:
return
assert mode in ["OpticalScan", "ParticleDetection", "RamanScan", "ParticleAnalysis"]
print("switching to mode:", mode, flush=True)
self.oscanwidget.setVisible(False)
if self.detectionwidget is not None:
self.detectionwidget.close()
self.detectionwidget.destroy()
self.detectionwidget = None
self.ramanwidget.setVisible(False)
self.mode = mode
self.loadPixmap(self.microscopeMode)
......
......@@ -28,7 +28,7 @@ from skimage.feature import peak_local_max
from skimage.morphology import watershed
from random import random
from errors import InvalidParticleError
from .errors import InvalidParticleError
def closeHolesOfSubImage(subimg):
......
......@@ -18,10 +18,9 @@ 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 PyQt5 import QtCore, QtWidgets, QtGui
from analysis.particleEditor import ParticleContextMenu
from analysis.particleCharacterization import getParticleCenterPoint
from .analysis.particleEditor import ParticleContextMenu
from .analysis.particleCharacterization import getParticleCenterPoint
class SegmentationContour(QtWidgets.QGraphicsItem):
def __init__(self, viewparent, contourData, pos=(0,0)):
......
This diff is collapsed.
......@@ -39,13 +39,15 @@ class Region:
def __init__(self):
self.centerx, self.centery = None, None
self.width, self.height = None, None
self.scalex, self.scaley = None, None
def __repr__(self):
return str(self)
def __str__(self):
return f'Region center: {self.centerx, self.centery} µm\n' + \
f'Region size: {self.width, self.height} µm'
f'Region size: {self.width, self.height} µm\n' + \
f'Scale: {self.scalex, self.scaley} µm/pixel'
class ZRange:
def __init__(self):
......@@ -65,6 +67,7 @@ class ZeissHandler(handler.ContentHandler):
self.zrange = ZRange()
self.intag = False
self.subtag = ''
self.scaledim = ''
def characters(self, content):
if self.intag:
......@@ -75,20 +78,27 @@ class ZeissHandler(handler.ContentHandler):
self.markers.append(Marker(attrs['Id'], attrs['StageXPosition'],
attrs['StageYPosition'],
attrs['FocusPosition']))
elif name == 'TileRegion' or name == 'ZStackSetup':
elif name == 'TileRegion' or name == 'ZStackSetup' or name == 'Scaling':
self.intag = True
if self.intag:
self.content = ''
if name in ['First','Last','Interval']:
if self.subtag == 'Items' and name == 'Distance':
self.scaledim = attrs['Id']
if name in ['First','Last','Interval','Items']:
self.subtag = name
def endElement(self, name):
if name == 'TileRegion' or name == 'ZStackSetup':
if name == 'TileRegion' or name == 'ZStackSetup' or name == 'Scaling':
self.intag = False
if self.intag and name == 'CenterPosition':
self.region.centerx, self.region.centery = map(float, self.content.split(','))
elif self.intag and name == 'ContourSize':
self.region.width, self.region.height = map(float, self.content.split(','))
elif self.intag and self.subtag == 'Items' and name == 'Value':
if self.scaledim == 'X':
self.region.scalex = float(self.content)
elif self.scaledim == 'Y':
self.region.scaley = float(self.content)
elif self.intag and name == 'Value' and \
self.subtag in ['First','Last','Interval']:
attrmap = {'First':'z0','Last':'zn','Interval':'dz'}
......
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