Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
7
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Open sidebar
GEPARD
GEPARD
Commits
819efb02
Commit
819efb02
authored
Nov 14, 2019
by
Robert
Committed by
Robert Ohmacht
Nov 14, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
-initial integration of ScenePyramid from GepardEvaluation into Gepard
parent
1fff5fef
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
1906 additions
and
883 deletions
+1906
-883
dataset.py
dataset.py
+15
-0
detectionview.py
detectionview.py
+65
-26
legacyConvert.py
legacyConvert.py
+8
-1
opticalbackground.py
opticalbackground.py
+1
-1
opticalscan.py
opticalscan.py
+60
-31
sampleview.py
sampleview.py
+858
-824
scenePyramid.py
scenePyramid.py
+899
-0
No files found.
dataset.py
View file @
819efb02
...
...
@@ -135,6 +135,9 @@ class DataSet(object):
self
.
coordinatetransform
=
None
# if imported form extern source coordinate system may be rotated
self
.
signx
=
1.
self
.
signy
=
-
1.
# tiling parameters
self
.
pyramidParams
=
None
# parameters specifically for raman scan
self
.
pshift
=
None
# shift of raman scan position relative to image center
...
...
@@ -169,6 +172,12 @@ class DataSet(object):
def
__eq__
(
self
,
other
):
return
recursiveDictCompare
(
self
.
__dict__
,
other
.
__dict__
)
def
getPyramidParams
(
self
):
return
self
.
pyramidParams
def
setPyramidParams
(
self
,
pyramid_params
):
self
.
pyramidParams
=
pyramid_params
def
getPixelScale
(
self
,
mode
=
None
):
if
mode
is
None
:
...
...
@@ -275,6 +284,12 @@ class DataSet(object):
self
.
__dict__
.
update
(
loadData
(
fname
).
__dict__
)
return
fname
def
getTilePath
(
self
):
scandir
=
os
.
path
.
join
(
self
.
path
,
"tiles"
)
if
not
os
.
path
.
exists
(
scandir
):
os
.
mkdir
(
scandir
)
return
scandir
def
getScanPath
(
self
):
scandir
=
os
.
path
.
join
(
self
.
path
,
"scanimages"
)
if
not
os
.
path
.
exists
(
scandir
):
...
...
detectionview.py
View file @
819efb02
...
...
@@ -27,6 +27,7 @@ from threading import Thread
from
.segmentation
import
Segmentation
from
.analysis.particleCharacterization
import
getParticleStatsWithPixelScale
,
loadZValImageFromDataset
from
.errors
import
InvalidParticleError
from
.scenePyramid
import
ScenePyramid
Nscreen
=
1000
...
...
@@ -269,14 +270,15 @@ class ParticleDetectionView(QtWidgets.QWidget):
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
):
def
__init__
(
self
,
pyramid
:
ScenePyramid
,
dataset
,
parent
=
None
):
super
().
__init__
(
parent
,
QtCore
.
Qt
.
Window
)
self
.
dataset
=
self
.
verifySeedpoints
(
dataset
)
self
.
img
=
img
self
.
imgclip
=
0
,
0
,
0
,
0
self
.
pyramid
=
pyramid
self
.
img
=
pyramid
.
getFullImage
(.
5
)
self
.
imgclip
=
0
,
0
,
0
,
0
self
.
seg
=
Segmentation
(
self
.
dataset
,
self
)
self
.
thread
=
None
self
.
view
=
parent
self
.
view
:
QtWidgets
.
QGraphicsView
=
parent
vbox
=
QtWidgets
.
QVBoxLayout
()
hbox
=
QtWidgets
.
QHBoxLayout
()
...
...
@@ -529,33 +531,69 @@ class ParticleDetectionView(QtWidgets.QWidget):
self
.
updateImageSeeds
()
def
setImageCenter
(
self
,
center
=
None
):
'''
as more than the tiles are part of the scene
bounding rect may be bigger than just a rect around the tiles
tiles should be grouped
'''
width
,
height
=
self
.
pyramid
.
getBoundingRectDim
()
if
center
is
None
:
centerx
=
self
.
img
.
shape
[
1
]
//
2
centery
=
self
.
img
.
shape
[
0
]
//
2
centerx
=
width
//
2
centery
=
height
//
2
else
:
centerx
,
centery
=
center
if
self
.
img
.
shape
[
0
]
<
Nscreen
:
centery
=
self
.
img
.
shape
[
0
]
//
2
if
self
.
img
.
shape
[
1
]
<
Nscreen
:
centerx
=
self
.
img
.
shape
[
1
]
//
2
if
height
<
Nscreen
:
centery
=
height
//
2
if
width
<
Nscreen
:
centerx
=
width
//
2
if
not
self
.
drag
:
self
.
lastcenter
=
centerx
,
centery
n1
,
n2
=
int
(
centery
-
Nscreen
//
2
),
int
(
centery
+
Nscreen
//
2
+
1
)
m1
,
m2
=
int
(
centerx
-
Nscreen
//
2
),
int
(
centerx
+
Nscreen
//
2
+
1
)
if
n1
<
0
:
n2
-=
n1
n1
=
0
if
n2
>
self
.
img
.
shape
[
0
]:
n1
-=
n2
-
self
.
img
.
shape
[
0
]
if
n1
<
0
:
n1
=
0
n2
=
self
.
img
.
shape
[
0
]
if
m1
<
0
:
m2
-=
m1
m1
=
0
if
m2
>
self
.
img
.
shape
[
1
]:
m1
-=
m2
-
self
.
img
.
shape
[
1
]
if
m1
<
0
:
m1
=
0
m2
=
self
.
img
.
shape
[
1
]
y1
,
y2
=
centery
-
Nscreen
//
2
,
centery
+
Nscreen
//
2
+
1
x1
,
x2
=
centerx
-
Nscreen
//
2
,
centerx
+
Nscreen
//
2
+
1
if
y1
<
0
:
y2
-=
y1
y1
=
0
if
y2
>
height
:
y1
-=
y2
-
height
if
y1
<
0
:
y1
=
0
y2
=
height
if
x1
<
0
:
x2
-=
x1
x1
=
0
if
x2
>
width
:
x1
-=
x2
-
width
if
x1
<
0
:
x1
=
0
x2
=
width
self
.
imgclip
=
int
(
y1
),
int
(
y2
),
int
(
x1
),
int
(
x2
)
self
.
subimg
,
pix
=
self
.
pyramid
.
getSubImage
(
self
.
imgclip
)
'''
img = QtGui.QImage(x2 - x1, y2 - y1, QtGui.QImage.Format_RGB888)
self.view.scene().render(
QtGui.QPainter(img),
QtCore.QRectF(0, 0, img.width(), img.height()),
#QtCore.QRectF(x1 + x0, y1 + y0, x2 - x1, y2 - y1)
QtCore.QRectF(x1, y1, x2 - x1, y2 - y1)
)
#pix = self.view.grab(QtCore.QRect(x1 + x0, y1 + y0, x2 - x1, y2 - y1))
# @see https://stackoverflow.com/a/11399959
#img = pix.toImage().convertToFormat(QtGui.QImage.Format_RGB888)
ptr = img.bits()
#ptr.setsize(img.byteCount())
ptr.setsize(img.height() * img.width() * 3)
self.subimg = np.asarray(ptr).reshape(img.height(), img.width(), 3)
pix = QtGui.QPixmap()
pix.convertFromImage(img)
'''
'''
sub = self.img[n1:n2,m1:m2,:].copy()
self.imgclip = n1,n2,m1,m2
self.subimg = sub
...
...
@@ -564,6 +602,7 @@ class ParticleDetectionView(QtWidgets.QWidget):
pix = QtGui.QPixmap()
pix.convertFromImage(QtGui.QImage(sub.data, width, height,
bytesPerLine, QtGui.QImage.Format_RGB888))
'''
self
.
imglabel
.
clearData
()
self
.
imglabel
.
setPixmap
(
pix
)
self
.
updateImageSeeds
()
...
...
legacyConvert.py
View file @
819efb02
...
...
@@ -27,8 +27,9 @@ from .helperfunctions import cv2imread_fix, cv2imwrite_fix
from
.analysis.particleContainer
import
ParticleContainer
from
.analysis
import
particleCharacterization
as
pc
from
.errors
import
InvalidParticleError
from
.scenePyramid
import
ScenePyramid
currentVersion
=
4
currentVersion
=
5
def
legacyConversion
(
dset
,
recreatefullimage
=
False
):
if
dset
.
version
==
0
:
...
...
@@ -110,6 +111,12 @@ def legacyConversion(dset, recreatefullimage=False):
removeLegacyAttributes
(
dset
)
dset
.
version
=
4
dset
.
save
()
if
dset
.
version
==
4
:
print
(
"Converting legacy version 4 to 5"
)
ScenePyramid
.
createFromFullImage
(
dset
)
dset
.
version
=
5
dset
.
save
()
# add later conversion for higher version numbers here
...
...
opticalbackground.py
View file @
819efb02
...
...
@@ -106,7 +106,7 @@ class BackGroundManager(QtWidgets.QWidget):
p0
=
[
points
[:,
0
].
min
(),
points
[:,
1
].
max
()]
p1
=
[
points
[:,
0
].
max
(),
points
[:,
1
].
min
()]
reply
=
QtWidgets
.
QMessageBox
.
question
(
self
,
'Message'
,
f
"The stage will move
{
round
(
3
*
width
)
}
in x and
{
round
(
3
*
height
)
}
in y.
\n
Continue?"
,
reply
=
QtWidgets
.
QMessageBox
.
question
(
self
,
'Message'
,
f
"The stage will move
{
round
(
3
*
width
)
}
in x and
{
round
(
3
*
height
)
}
in y.
\n
Continue?"
,
QtWidgets
.
QMessageBox
.
Yes
|
QtWidgets
.
QMessageBox
.
No
,
QtWidgets
.
QMessageBox
.
No
)
if
reply
==
QtWidgets
.
QMessageBox
.
Yes
:
fullimg
=
None
...
...
opticalscan.py
View file @
819efb02
...
...
@@ -31,6 +31,7 @@ from time import time
import
datetime
from
.opticalbackground
import
BackGroundManager
from
.zlevelsetter
import
ZLevelSetter
from
.scenePyramid
import
ScenePyramid
def
scan
(
path
,
sol
,
zpositions
,
grid
,
controlclass
,
dataqueue
,
stopevent
,
logpath
=
''
,
ishdr
=
False
):
...
...
@@ -84,10 +85,10 @@ def scan(path, sol, zpositions, grid, controlclass, dataqueue,
def
subtractBackground
(
image
,
background
):
avg
=
np
.
mean
(
background
)
subtracted
=
np
.
clip
(
np
.
array
(
image
-
background
+
avg
,
dtype
=
np
.
uint8
),
0
,
255
)
subtracted
=
np
.
clip
(
np
.
array
(
image
-
background
+
avg
,
dtype
=
np
.
uint8
),
0
,
255
)
return
subtracted
def
loadAndPasteImage
(
srcnames
,
fullimage
,
fullzval
,
width
,
height
,
def
loadAndPasteImage
(
srcnames
,
pyramid
,
fullzval
,
width
,
height
,
rotationvalue
,
p0
,
p1
,
p
,
background
=
None
):
colimgs
=
[]
for
name
in
srcnames
:
...
...
@@ -102,15 +103,22 @@ def loadAndPasteImage(srcnames, fullimage, fullzval, width, height,
c
,
s
=
np
.
cos
(
np
.
radians
(
rotationvalue
)),
np
.
sin
(
np
.
radians
(
rotationvalue
))
dx
,
dy
=
(
x
-
p0
[
0
])
/
width
*
img
.
shape
[
1
],
(
p0
[
1
]
-
y
)
/
height
*
img
.
shape
[
0
]
M
=
np
.
float32
([[
c
,
s
,
dx
],[
-
s
,
c
,
dy
]])
if
fullimage
is
not
None
:
cv2
.
warpAffine
(
img
,
M
,
(
Nx
,
Ny
),
fullimage
,
borderMode
=
cv2
.
BORDER_TRANSPARENT
)
cv2
.
warpAffine
(
zval
,
M
,
(
Nx
,
Ny
),
fullzval
,
borderMode
=
cv2
.
BORDER_TRANSPARENT
)
dst
=
fullimage
zval
=
fullzval
else
:
dst
=
cv2
.
warpAffine
(
img
,
M
,
(
Nx
,
Ny
))
zval
=
cv2
.
warpAffine
(
zval
,
M
,
(
Nx
,
Ny
))
M
=
np
.
float32
([[
c
,
s
,
dx
],
[
-
s
,
c
,
dy
]])
dst
=
None
if
pyramid
is
not
None
:
if
fullzval
is
not
None
:
cv2
.
warpAffine
(
zval
,
M
,
(
Nx
,
Ny
),
fullzval
,
borderMode
=
cv2
.
BORDER_TRANSPARENT
)
zval
=
fullzval
else
:
zval
=
cv2
.
warpAffine
(
zval
,
M
,
(
Nx
,
Ny
))
pyramid
.
addSrcTile
(
img
,
np
.
float32
([[
c
,
s
,
0
],
[
-
s
,
c
,
0
]]),
(
dx
,
dy
),
(
Nx
,
Ny
)
)
return
dst
,
zval
...
...
@@ -231,12 +239,13 @@ class OpticalScan(QtWidgets.QWidget):
def
__init__
(
self
,
ramanctrl
,
dataset
,
logpath
=
''
,
parent
=
None
):
super
().
__init__
(
parent
,
QtCore
.
Qt
.
Window
)
self
.
logpath
=
logpath
self
.
view
=
parent
self
.
view
:
QtWidgets
.
QGraphicsView
=
parent
mainLayout
=
QtWidgets
.
QVBoxLayout
()
pointgroup
=
QtWidgets
.
QGroupBox
(
"Point coordinates [µm]"
,
self
)
self
.
ramanctrl
=
ramanctrl
self
.
dataset
=
dataset
self
.
pyramid
:
ScenePyramid
=
None
self
.
positions
=
[]
self
.
process
=
None
self
.
points
=
PointCoordinates
(
5
,
self
.
ramanctrl
,
self
)
...
...
@@ -425,6 +434,9 @@ class OpticalScan(QtWidgets.QWidget):
self
.
boundaryUpdate
.
emit
()
self
.
prun
.
setEnabled
(
True
)
def
setPyramid
(
self
,
pyramid
):
self
.
pyramid
=
pyramid
def
resetDataset
(
self
,
ds
):
self
.
dataset
=
ds
self
.
points
.
createWidgets
(
5
,
list
(
zip
(
ds
.
fitindices
,
ds
.
fitpoints
)))
...
...
@@ -482,22 +494,34 @@ class OpticalScan(QtWidgets.QWidget):
Nx
,
Ny
=
int
((
p1
[
0
]
-
p0
[
0
]
+
width
)
/
width
*
img
.
shape
[
1
]),
int
((
p0
[
1
]
-
p1
[
1
]
+
height
)
/
height
*
img
.
shape
[
0
])
+
10
# + 10 because of rotation and hopefully it will be small
c
,
s
=
np
.
cos
(
np
.
radians
(
rotationvalue
)),
np
.
sin
(
np
.
radians
(
rotationvalue
))
dx
,
dy
=
(
x
-
p0
[
0
])
/
width
*
img
.
shape
[
1
],
(
p0
[
1
]
-
y
)
/
height
*
img
.
shape
[
0
]
M
=
np
.
float32
([[
c
,
s
,
dx
],[
-
s
,
c
,
dy
]])
dst
=
cv2
.
warpAffine
(
img
,
M
,
(
Nx
,
Ny
))
if
self
.
view
.
imgdata
is
not
None
and
self
.
dataset
.
lastpos
is
not
None
:
lp
=
self
.
dataset
.
lastpos
dx
,
dy
=
(
lp
[
0
]
-
p0
[
0
])
/
width
*
img
.
shape
[
1
],
(
p0
[
1
]
-
lp
[
1
])
/
height
*
img
.
shape
[
0
]
full
=
self
.
view
.
imgdata
M
=
np
.
float32
([[
1
,
0
,
dx
],[
0
,
1
,
dy
]])
try
:
full
=
cv2
.
warpAffine
(
full
,
M
,
(
Nx
,
Ny
))
#fails, if image dimensions are >32767x32767px...
dst
=
cv2
.
max
(
full
,
dst
)
except
:
QtWidgets
.
QMessageBox
.
critical
(
self
,
'Error'
,
'Image is too large
\n
Select smaller region.'
)
raise
return
M
=
np
.
float32
([[
c
,
s
,
dx
],
[
-
s
,
c
,
dy
]])
#dst = cv2.warpAffine(img, M, (Nx, Ny))
M_rot
=
np
.
float32
([[
c
,
s
,
0
],
[
-
s
,
c
,
0
]])
img_rot
=
cv2
.
warpAffine
(
img
,
M_rot
,
(
img
.
shape
[
1
],
img
.
shape
[
0
]
+
10
))
# calc new pixel start coords for tile
# @see https://stackoverflow.com/a/43166421/9880753
c_dest
=
cv2
.
transform
(
np
.
float32
([[(
0
,
0
)]]),
np
.
float32
([[
c
,
s
,
dx
],
[
-
s
,
c
,
dy
]]))
self
.
pyramid
.
addSrcTileSimple
(
img_rot
,
(
c_dest
[
0
][
0
][
0
],
c_dest
[
0
][
0
][
1
]),
p0
)
#if self.view.imgdata is not None and self.dataset.lastpos is not None:
# lp = self.dataset.lastpos
# dx, dy = (lp[0]-p0[0])/width*img.shape[1], (p0[1]-lp[1])/height*img.shape[0]
# full = self.view.imgdata
# M = np.float32([[1,0,dx],[0,1,dy]])
# try:
# full = cv2.warpAffine(full, M, (Nx, Ny)) #fails, if image dimensions are >32767x32767px...
# dst = cv2.max(full, dst)
# except:
# QtWidgets.QMessageBox.critical(self, 'Error', 'Image is too large\nSelect smaller region.')
# raise
# return
self
.
view
.
imgdata
=
dst
#
self.view.imgdata = dst
self
.
dataset
.
lastpos
=
p0
self
.
dataset
.
maxdim
=
p0
+
p1
self
.
dataset
.
readin
=
False
...
...
@@ -621,7 +645,8 @@ class OpticalScan(QtWidgets.QWidget):
self
.
progressbar
.
setEnabled
(
True
)
self
.
progressbar
.
setRange
(
0
,
len
(
self
.
dataset
.
grid
))
self
.
progressbar
.
setValue
(
0
)
self
.
view
.
imgdata
=
None
#self.view.imgdata = None
self
.
pyramid
.
resetScene
()
self
.
view
.
blockUI
()
grid
=
np
.
asarray
(
self
.
dataset
.
grid
)
p0
=
[
grid
[:,
0
].
min
(),
grid
[:,
1
].
max
()]
...
...
@@ -657,7 +682,7 @@ class OpticalScan(QtWidgets.QWidget):
else
:
background_img
=
None
self
.
view
.
imgdata
,
self
.
dataset
.
zvalimg
=
loadAndPasteImage
(
names
,
self
.
view
.
imgdata
,
self
.
dataset
.
zvalimg
,
width
,
height
,
self
.
view
.
imgdata
,
self
.
dataset
.
zvalimg
=
loadAndPasteImage
(
names
,
self
.
pyramid
,
self
.
dataset
.
zvalimg
,
width
,
height
,
rotationvalue
,
p0
,
p1
,
p
,
background
=
background_img
)
self
.
progressbar
.
setValue
(
i
+
1
)
if
i
>
3
:
...
...
@@ -665,15 +690,19 @@ class OpticalScan(QtWidgets.QWidget):
ttot
=
timerunning
*
Ngrid
/
(
i
+
1
)
time2go
=
ttot
-
timerunning
self
.
progresstime
.
setText
(
self
.
timelabeltext
+
str
(
datetime
.
timedelta
(
seconds
=
round
(
time2go
))))
self
.
imageUpdate
.
emit
(
self
.
view
.
microscopeMode
)
# reload image in sampleview, calls loadPixmap
# not needed anymore as the scene gets manipulated directly via self.pyramid
#self.imageUpdate.emit(self.view.microscopeMode)
if
i
==
Ngrid
-
1
:
cv2imwrite_fix
(
self
.
dataset
.
getImageName
(),
cv2
.
cvtColor
(
self
.
view
.
imgdata
,
cv2
.
COLOR_RGB2BGR
))
#
cv2imwrite_fix(self.dataset.getImageName(), cv2.cvtColor(self.view.imgdata, cv2.COLOR_RGB2BGR))
self
.
dataset
.
saveZvalImg
()
self
.
process
.
join
()
self
.
dataqueue
.
close
()
self
.
dataqueue
.
join_thread
()
self
.
pyramid
.
toDataset
()
if
self
.
deleteImgChecker
.
isChecked
():
path
=
self
.
dataset
.
getScanPath
()
files
=
os
.
listdir
(
path
)
...
...
sampleview.py
View file @
819efb02
# -*- 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
,
QtGui
,
QtWidgets
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
,
SeedPoint
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
)
ParticleOfIndexSelected
=
QtCore
.
pyqtSignal
(
int
)
def
__init__
(
self
,
logpath
):
super
(
SampleView
,
self
).
__init__
()
self
.
logpath
=
logpath
self
.
item
=
QtWidgets
.
QGraphicsPixmapItem
()
self
.
item
.
setPos
(
0
,
0
)
self
.
item
.
setAcceptedMouseButtons
(
QtCore
.
Qt
.
NoButton
)
self
.
scaleFactor
=
1.0
scene
=
QtWidgets
.
QGraphicsScene
(
self
)
scene
.
setItemIndexMethod
(
QtWidgets
.
QGraphicsScene
.
NoIndex
)
scene
.
addItem
(
self
.
item
)
scene
.
setBackgroundBrush
(
QtCore
.
Qt
.
darkGray
)
self
.
setScene
(
scene
)
self
.
setCacheMode
(
QtWidgets
.
QGraphicsView
.
CacheBackground
)
self
.
setViewportUpdateMode
(
QtWidgets
.
QGraphicsView
.
BoundingRectViewportUpdate
)
self
.
setRenderHint
(
QtGui
.
QPainter
.
Antialiasing
)
self
.
setTransformationAnchor
(
QtWidgets
.
QGraphicsView
.
AnchorUnderMouse
)
self
.
setResizeAnchor
(
QtWidgets
.
QGraphicsView
.
AnchorViewCenter
)
self
.
ramanctrl
=
RamanControl
()
self
.
simulatedRaman
=
simulatedRaman
self
.
ramanSwitchNeeded
=
False
if
self
.
ramanctrl
.
name
==
'RenishawCOM'
:
#determine, if ramanSwitch is needed:
self
.
ramanctrl
.
connect
()
if
not
self
.
ramanctrl
.
connected
:
QtWidgets
.
QMessageBox
.
warning
(
self
,
'Error'
,
'Please enable Raman Connection'
)
return
if
self
.
ramanctrl
.
getImageDimensions
(
mode
=
'bf'
)[
0
]
==
self
.
ramanctrl
.
getImageDimensions
(
mode
=
'df'
)[
0
]:
self
.
ramanSwitchNeeded
=
False
else
:
self
.
ramanSwitchNeeded
=
True
self
.
ramanctrl
.
disconnect
()
self
.
drag
=
None
self
.
mode
=
None
self
.
dataset
=
None
self
.
particleEditor
=
None
self
.
fititems
=
[]
self
.
boundaryitems
=
[[],[]]
self
.
scanitems
=
[]
self
.
ramanscanitems
=
[]
self
.
particleInfoBox
=
None
self
.
imgdata
=
None
self
.
isblocked
=
False
self
.
contourItems
=
[]
self
.
selectedParticleIndices
=
[]
self
.
seedPoints
=
[]
self
.
particlePainter
=
None
self
.
detectionwidget
=
None
self
.
ramanwidget
=
RamanScanUI
(
self
.
ramanctrl
,
None
,
self
.
logpath
,
self
)
self
.
ramanwidget
.
imageUpdate
.
connect
(
self
.
loadPixmap
)
self
.
oscanwidget
=
OpticalScan
(
self
.
ramanctrl
,
None
,
self
.
logpath
,
self
)
self
.
oscanwidget
.
imageUpdate
.
connect
(
self
.
loadPixmap
)
self
.
oscanwidget
.
boundaryUpdate
.
connect
(
self
.
resetBoundary
)
self
.
analysiswidget
=
None
self
.
setMinimumSize
(
600
,
600
)
self
.
darkenPixmap
=
False
self
.
microscopeMode
=
None
self
.
update
()
def
takeScreenshot
(
self
):
#TODO:
#LIMIT SCREENSHOT TO ACTUAL VIEWSIZE OF LOADED IMAGE...
#hide scrollbars
self
.
setHorizontalScrollBarPolicy
(
1
)
self
.
setVerticalScrollBarPolicy
(
1
)
#capture screen
screen
=
QtWidgets
.
QApplication
.
primaryScreen
()
self
.
repaint
()
screenshot
=
screen
.
grabWindow
(
self
.
winId
())
#unhide scrollbars
self
.
setHorizontalScrollBarPolicy
(
0
)
self
.
setVerticalScrollBarPolicy
(
0
)
fname
=
self
.
dataset
.
path
+
'/screenshot.png'
validFileName
=
False
incr
=
1
while
not
validFileName
:
if
not
os
.
path
.
exists
(
fname
):
validFileName
=
True
else
:
fname
=
self
.
dataset
.
path
+
'/screenshot ({}).png'
.
format
(
incr
)
incr
+=
1
screenshot
.
save
(
fname
,
'png'
)
QtWidgets
.
QMessageBox
.
about
(
self
,
'Message'
,
'Saved as {} to project directory.'
.
format
(
fname
.
split
(
'/'
)[
-
1
]))
def
closeEvent
(
self
,
event
):
reply
=
QtWidgets
.
QMessageBox
.
question
(
self
,
'Message'
,
"Do you really want to quit?"
,
QtWidgets
.
QMessageBox
.
Yes
|
QtWidgets
.
QMessageBox
.
No
,
QtWidgets
.
QMessageBox
.
No
)
if
reply
==
QtWidgets
.
QMessageBox
.
Yes
:
self
.
disconnectRaman
()
self
.
saveDataSet
()
event
.
accept
()
self
.
oscanwidget
.
close
()
if
self
.
detectionwidget
is
not
None
:
self
.
detectionwidget
.
close
()
if
self
.
analysiswidget
is
not
None
:
self
.
analysiswidget
.
close
()
self
.
ramanwidget
.
close
()
else
:
event
.
ignore
()
def
configureRamanControl
(
self
):
"""
Launches a window for updating Raman instrument configuration.
:return:
"""
self
.
configWin
=
RamanConfigWin
(
self
)
self
.
configWin
.
show
()
def
saveDataSet
(
self
):
if
self
.
dataset
is
not
None
:
self
.
dataset
.
save
()
@
QtCore
.
pyqtSlot
()
def
zoomIn
(
self
):
self
.
zoomDisplay
(
1.25
)
@
QtCore
.
pyqtSlot
()
def
zoomOut
(
self
):
self
.
zoomDisplay
(
0.8
)
@
QtCore
.
pyqtSlot
()
def
normalSize
(
self
):
self
.
scaleFactor
=
1.0
self
.
setTransform
(
QtGui
.
QTransform
.
fromScale
(
1.
,
1.
))
self
.
announceScaling
()
@
QtCore
.
pyqtSlot
()
def
fitToWindow
(
self
):
"""
Fits the window to show the entire sample.
:return:
"""
brect
=
self
.
item
.
sceneBoundingRect
()
self
.
fitInView
(
0
,
0
,
brect
.
width
(),
brect
.
height
(),
QtCore
.
Qt
.
KeepAspectRatio
)
self
.
scaleFactor
=
self
.
transform
().
m11
()
self
.
announceScaling
()
def
switchMode
(
self
,
mode
,
loadnew
=
False
):
"""
Switch the gepard to another module
:return:
"""
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 = None
self
.
ramanwidget
.
setVisible
(
False
)
self
.
mode
=
mode
self
.
loadPixmap
(
self
.
microscopeMode
)
if
mode
==
"OpticalScan"
:
self
.
oscanwidget
.
setVisible
(
True
)
self
.
oscanwidget
.
resetDataset
(
self
.
dataset
)
elif
mode
==
"ParticleDetection"
:
if
self
.
detectionwidget
is
None
:
print
(
'creating new detect window'
)
self
.
detectionwidget
=
ParticleDetectionView
(
self
.
imgdata
,
self
.
dataset
,
self
)
self
.
detectionwidget
.
imageUpdate
.
connect
(
self
.
detectionUpdate
)
self
.
detectionwidget
.
detectionFinished
.
connect
(
self
.
activateMaxMode
)
self
.
updateSeedPointMarkers
()
self
.
detectionwidget
.
show
()
elif
mode
==
"RamanScan"
:
self
.
removeSeedPointMarkers
()
self
.
ramanwidget
.
resetDataset
(
self
.
dataset
)
self
.
ramanwidget
.
setVisible
(
True
)
elif
mode
==
"ParticleAnalysis"
:
self
.
removeSeedPointMarkers
()
if
self
.
ramanwidget
.
isVisible
():
self
.
ramanwidget
.
setVisible
(
False
)
if
self
.
analysiswidget
is
None
:
print
(
'creating new analysiswidget'
)
self
.
analysiswidget
=
ParticleAnalysis
(
self
.
dataset
,
self
)
self
.
analysiswidget
.
showMaximized
()
self
.
setupParticleEditor
()
else
:
print
(
'show maximized already exisiting analysiswidget'
)
self
.
analysiswidget
.
showMaximized
()
if
self
.
detectionwidget
is
not
None
:
self
.
detectionwidget
.
setVisible
(
False
)
#show legend:
self
.
imparent
.
legend
.
show
()
if
loadnew
:
self
.
fitToWindow
()
self
.
imparent
.
updateModes
(
mode
,
self
.
getMaxMode
())
def
open
(
self
,
fname
):
self
.
saveDataSet
()