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
5e79c241
Commit
5e79c241
authored
Aug 31, 2020
by
Josef Brandt
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Automated Test until Spectrum Scan
parent
31eb4bb9
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
105 additions
and
2107 deletions
+105
-2107
__main__.py
__main__.py
+4
-4
detectionview.py
detectionview.py
+0
-861
gui/detectionview.py
gui/detectionview.py
+9
-10
gui/opticalscanui.py
gui/opticalscanui.py
+4
-4
helperfunctions.py
helperfunctions.py
+6
-0
opticalscan.py
opticalscan.py
+0
-773
ramancom/simulated/imageGenerator.py
ramancom/simulated/imageGenerator.py
+2
-14
ramancom/simulated/simulatedStage.py
ramancom/simulated/simulatedStage.py
+3
-8
ramanscanui.py
ramanscanui.py
+0
-392
unittests/test_gepard.py
unittests/test_gepard.py
+77
-36
unittests/test_simulatedStage.py
unittests/test_simulatedStage.py
+0
-5
No files found.
__main__.py
View file @
5e79c241
...
...
@@ -79,7 +79,7 @@ class GEPARDMainWindow(QtWidgets.QMainWindow):
closeAll
()
@
QtCore
.
pyqtSlot
(
float
)
def
scalingChanged
(
self
,
scale
):
def
scalingChanged
(
self
):
self
.
zoomInAct
.
setEnabled
(
self
.
view
.
scaleFactor
<
20.0
)
self
.
zoomOutAct
.
setEnabled
(
self
.
view
.
scaleFactor
>
.
01
)
self
.
normalSizeAct
.
setEnabled
(
self
.
view
.
scaleFactor
!=
1.
)
...
...
@@ -91,7 +91,7 @@ class GEPARDMainWindow(QtWidgets.QMainWindow):
if
fileName
:
self
.
fname
=
str
(
fileName
)
self
.
view
.
open
(
self
.
fname
)
self
.
scalingChanged
(
1.
)
self
.
scalingChanged
()
@
QtCore
.
pyqtSlot
()
def
importProject
(
self
,
fileName
=
False
):
...
...
@@ -101,7 +101,7 @@ class GEPARDMainWindow(QtWidgets.QMainWindow):
if
fileName
:
self
.
fname
=
str
(
fileName
)
self
.
view
.
importProject
(
self
.
fname
)
self
.
scalingChanged
(
1.
)
self
.
scalingChanged
()
@
QtCore
.
pyqtSlot
()
def
new
(
self
,
fileName
=
False
):
...
...
@@ -113,7 +113,7 @@ class GEPARDMainWindow(QtWidgets.QMainWindow):
if
isValid
:
self
.
fname
=
str
(
fileName
)
self
.
view
.
new
(
self
.
fname
)
self
.
scalingChanged
(
1.
)
self
.
scalingChanged
()
else
:
QtWidgets
.
QMessageBox
.
critical
(
self
,
"Error"
,
msg
)
...
...
detectionview.py
deleted
100644 → 0
View file @
31eb4bb9
# -*- 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
os
import
logging
import
logging.handlers
from
PyQt5
import
QtCore
,
QtWidgets
,
QtGui
from
matplotlib.backends.backend_qt5agg
import
FigureCanvasQTAgg
import
matplotlib.pyplot
as
plt
from
threading
import
Thread
# from win32api import GetSystemMetrics # I use that to find out screen resolution. Might not work on Linux that way??
from
.segmentation
import
Segmentation
from
.analysis.particleCharacterization
import
getParticleStatsWithPixelScale
,
loadZValImageFromDataset
from
.errors
import
InvalidParticleError
,
showErrorMessageAsWidget
from
.uielements
import
TimeEstimateProgressbar
from
.scenePyramid
import
ScenePyramid
from
.gepardlogging
import
setDefaultLoggingConfig
from
.helperfunctions
import
hasFTIRControl
def
getScreenHeight
()
->
int
:
app
=
QtWidgets
.
QApplication
.
instance
()
screen_resolution
:
QtCore
.
QRect
=
app
.
desktop
().
screenGeometry
()
screenHeight
=
screen_resolution
.
height
()
Nscreen
=
np
.
clip
(
1000
,
0
,
round
(
screenHeight
*
0.9
))
# account for too small displays
return
Nscreen
class
HistWidget
(
QtWidgets
.
QWidget
):
def
__init__
(
self
,
histcallback
,
curvecallback
,
parent
=
None
):
super
().
__init__
(
parent
)
self
.
updateCallbacks
(
histcallback
,
curvecallback
)
if
parent
.
dataset
is
None
:
self
.
points
=
np
.
array
([[
50
,
0
],[
100
,
220
],[
200
,
255
]])
else
:
self
.
points
=
parent
.
dataset
.
detectParams
[
'points'
]
self
.
fig
=
plt
.
Figure
()
self
.
canvas
=
FigureCanvasQTAgg
(
self
.
fig
)
self
.
canvas
.
setParent
(
self
)
self
.
ax
=
self
.
fig
.
add_subplot
(
111
,
autoscale_on
=
False
)
self
.
ax
.
axis
(
"off"
)
self
.
fig
.
subplots_adjust
(
left
=
0.05
,
top
=
0.98
,
bottom
=
0.05
,
right
=
0.995
)
self
.
canvas
.
mpl_connect
(
'pick_event'
,
self
.
moveControlPoint
)
self
.
canvas
.
mpl_connect
(
'button_release_event'
,
self
.
releaseAxes
)
self
.
canvas
.
mpl_connect
(
'motion_notify_event'
,
self
.
moveAxes
)
self
.
moveind
=
None
self
.
plot
()
self
.
setMaximumSize
(
200
,
200
)
vbox
=
QtWidgets
.
QVBoxLayout
()
vbox
.
addWidget
(
self
.
canvas
)
self
.
setLayout
(
vbox
)
def
value
(
self
):
return
self
.
points
def
moveAxes
(
self
,
event
):
if
(
event
.
inaxes
==
self
.
ax
)
and
self
.
moveind
is
not
None
:
x
=
event
.
xdata
y
=
event
.
ydata
if
self
.
moveind
==
0
:
self
.
points
[
0
,
0
]
=
max
(
0
,
min
(
x
,
self
.
points
[
1
,
0
]))
elif
self
.
moveind
==
1
:
self
.
points
[
1
,
0
]
=
max
(
self
.
points
[
0
,
0
]
+
1
,
min
(
x
,
self
.
points
[
2
,
0
]
-
1
))
self
.
points
[
1
,
1
]
=
max
(
0
,
min
(
y
,
255
))
else
:
self
.
points
[
2
,
0
]
=
max
(
self
.
points
[
1
,
0
]
+
1
,
min
(
x
,
255
))
self
.
plot
()
def
releaseAxes
(
self
,
event
):
self
.
moveind
=
None
def
plot
(
self
):
self
.
ax
.
lines
=
[]
self
.
ax
.
collections
=
[]
self
.
ax
.
artists
=
[]
hist
=
self
.
histcallback
()[:,
0
]
hist
/=
hist
.
max
()
hist
*=
255
hist
[
0
]
=
0
hist
[
-
1
]
=
0
xarr
,
arr
=
self
.
curvecallback
(
self
.
points
)
self
.
ax
.
fill
(
xarr
,
hist
,
color
=
(.
7
,.
7
,.
7
))
self
.
ax
.
plot
([
0
,
0
],
[
255
,
255
],
"k-"
)
self
.
ax
.
plot
(
xarr
,
arr
,
"b-"
)
self
.
ax
.
plot
(
self
.
points
[:,
0
],
self
.
points
[:,
1
],
"go"
,
picker
=
5
)
self
.
ax
.
set_xlim
(
0
,
255
)
self
.
ax
.
set_ylim
(
0
,
255
)
self
.
canvas
.
draw
()
self
.
repaint
()
def
updateCallbacks
(
self
,
histcallback
,
curvecallback
):
self
.
histcallback
=
histcallback
self
.
curvecallback
=
curvecallback
def
moveControlPoint
(
self
,
event
):
if
self
.
moveind
is
None
:
self
.
moveind
=
event
.
ind
class
ImageView
(
QtWidgets
.
QLabel
):
seedChanged
=
QtCore
.
pyqtSignal
()
def
__init__
(
self
,
parent
=
None
):
super
().
__init__
(
parent
)
self
.
overlay
=
None
self
.
drag
=
False
self
.
alpha
=
.
8
self
.
contours
=
[]
self
.
seedradius
=
3
self
.
showseedpoints
=
True
self
.
measpoints
=
[]
self
.
seedpoints
=
[]
self
.
seeddeletepoints
=
[]
@
QtCore
.
pyqtSlot
(
int
)
def
resetAlpha
(
self
,
num
):
self
.
alpha
=
num
/
100.
self
.
update
()
@
QtCore
.
pyqtSlot
(
int
)
def
setSeedRadius
(
self
,
num
):
self
.
seedradius
=
num
self
.
update
()
@
QtCore
.
pyqtSlot
(
int
)
def
changeSeedDisplay
(
self
,
state
):
self
.
showseedpoints
=
(
state
==
QtCore
.
Qt
.
Checked
)
self
.
update
()
def
showStep
(
self
,
img
,
imgtype
):
self
.
overlay
=
None
if
imgtype
==
0
:
img
=
img
.
repeat
(
3
).
reshape
(
img
.
shape
[
0
],
img
.
shape
[
1
],
3
)
self
.
setOverlay
(
img
)
elif
imgtype
==
1
:
levels
=
img
img
=
np
.
zeros
(
tuple
(
levels
.
shape
)
+
(
3
,),
dtype
=
np
.
uint8
)
img
[:,:,
0
][
np
.
nonzero
(
levels
&
1
)]
=
255.
img
[:,:,
1
][
np
.
nonzero
(
levels
&
2
)]
=
255.
self
.
setOverlay
(
img
)
self
.
update
()
def
removeSeeds
(
self
,
p0
):
p0
=
np
.
array
([
p0
])
if
len
(
self
.
seedpoints
)
>
0
:
arr
=
np
.
array
(
self
.
seedpoints
)
d
=
np
.
linalg
.
norm
(
arr
[:,
:
2
]
-
p0
,
axis
=
1
)
ind
=
d
>
self
.
seedradius
self
.
seedpoints
=
arr
[
ind
,:].
tolist
()
if
len
(
self
.
seeddeletepoints
)
>
0
:
arr
=
np
.
array
(
self
.
seeddeletepoints
)
d
=
np
.
linalg
.
norm
(
arr
[:,
:
2
]
-
p0
,
axis
=
1
)
ind
=
d
>
self
.
seedradius
self
.
seeddeletepoints
=
arr
[
ind
,:].
tolist
()
def
mousePressEvent
(
self
,
event
):
if
event
.
button
()
==
QtCore
.
Qt
.
LeftButton
:
if
event
.
modifiers
()
&
QtCore
.
Qt
.
ShiftModifier
:
self
.
drag
=
"delete"
elif
event
.
modifiers
()
&
QtCore
.
Qt
.
AltModifier
:
self
.
drag
=
"remove"
else
:
self
.
drag
=
"add"
p0
=
event
.
pos
()
self
.
appendSeedPoints
(
p0
)
self
.
update
()
super
().
mousePressEvent
(
event
)
def
mouseMoveEvent
(
self
,
event
):
if
self
.
drag
:
p0
=
event
.
pos
()
self
.
appendSeedPoints
(
p0
)
self
.
update
()
super
().
mouseMoveEvent
(
event
)
def
mouseReleaseEvent
(
self
,
event
):
if
self
.
drag
:
self
.
seedChanged
.
emit
()
self
.
drag
=
False
super
().
mouseReleaseEvent
(
event
)
def
appendSeedPoints
(
self
,
pos
):
Nscreen
=
getScreenHeight
()
if
0
<=
pos
.
x
()
<
Nscreen
and
0
<=
pos
.
y
()
<
Nscreen
:
print
(
pos
)
if
self
.
drag
==
"add"
:
self
.
seedpoints
.
append
([
pos
.
x
(),
pos
.
y
(),
self
.
seedradius
])
elif
self
.
drag
==
"delete"
:
self
.
seeddeletepoints
.
append
([
pos
.
x
(),
pos
.
y
(),
self
.
seedradius
])
elif
self
.
drag
==
"remove"
:
self
.
removeSeeds
([
pos
.
x
(),
pos
.
y
()])
def
clearData
(
self
):
self
.
contours
=
[]
self
.
measpoints
=
[]
self
.
seedpoints
=
[]
self
.
seeddeletepoints
=
[]
self
.
overlay
=
None
def
updateSeedPoints
(
self
,
seedpoints
=
[],
seeddeletepoints
=
[]):
self
.
seedpoints
=
seedpoints
self
.
seeddeletepoints
=
seeddeletepoints
def
updateDetectionResults
(
self
,
contours
,
measpoints
):
self
.
overlay
=
None
cp
=
[]
for
c
in
contours
:
polygon
=
QtGui
.
QPolygonF
()
for
ci
in
c
:
polygon
.
append
(
QtCore
.
QPointF
(
ci
[
0
,
0
],
ci
[
0
,
1
]))
cp
.
append
(
polygon
)
self
.
contours
=
cp
self
.
measpoints
=
measpoints
self
.
update
()
def
setOverlay
(
self
,
img
):
height
,
width
,
channel
=
img
.
shape
assert
channel
==
3
bytesPerLine
=
3
*
width
pix
=
QtGui
.
QPixmap
()
pix
.
convertFromImage
(
QtGui
.
QImage
(
img
.
data
,
width
,
height
,
bytesPerLine
,
QtGui
.
QImage
.
Format_RGB888
))
self
.
overlay
=
pix
def
paintEvent
(
self
,
event
):
painter
=
QtGui
.
QPainter
(
self
)
painter
.
drawPixmap
(
0
,
0
,
self
.
pixmap
())
painter
.
setOpacity
(
self
.
alpha
)
if
self
.
overlay
is
not
None
:
painter
.
drawPixmap
(
0
,
0
,
self
.
overlay
)
else
:
painter
.
setPen
(
QtCore
.
Qt
.
blue
)
painter
.
setBrush
(
QtCore
.
Qt
.
green
)
for
c
in
self
.
contours
:
painter
.
drawPolygon
(
c
)
painter
.
setPen
(
QtCore
.
Qt
.
red
)
painter
.
setBrush
(
QtCore
.
Qt
.
red
)
for
points
in
self
.
measpoints
:
for
point
in
points
:
painter
.
drawEllipse
(
point
.
x
-
2
,
point
.
y
-
2
,
5
,
5
)
if
self
.
showseedpoints
:
painter
.
setPen
(
QtCore
.
Qt
.
white
)
painter
.
setBrush
(
QtCore
.
Qt
.
white
)
for
p
in
self
.
seedpoints
:
painter
.
drawEllipse
(
p
[
0
]
-
p
[
2
],
p
[
1
]
-
p
[
2
],
2
*
p
[
2
],
2
*
p
[
2
])
painter
.
setPen
(
QtCore
.
Qt
.
magenta
)
#I think it is more useful when the deletpoints override the seedpoints
painter
.
setBrush
(
QtCore
.
Qt
.
magenta
)
for
p
in
self
.
seeddeletepoints
:
painter
.
drawEllipse
(
p
[
0
]
-
p
[
2
],
p
[
1
]
-
p
[
2
],
2
*
p
[
2
],
2
*
p
[
2
])
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
,
pyramid
:
ScenePyramid
,
dataset
,
parent
=
None
):
super
().
__init__
(
parent
,
QtCore
.
Qt
.
Window
)
self
.
dataset
=
self
.
verifySeedpoints
(
dataset
)
self
.
pyramid
=
pyramid
self
.
img
=
None
self
.
imgclip
=
0
,
0
,
0
,
0
self
.
seg
=
Segmentation
(
self
.
dataset
,
self
)
self
.
seg
.
detectionState
.
connect
(
self
.
updateDetectionState
)
self
.
thread
=
None
self
.
threadrunning
=
False
self
.
view
=
parent
logPath
=
os
.
path
.
join
(
self
.
dataset
.
path
,
'detectionlog.txt'
)
self
.
logger
=
logging
.
getLogger
(
'detection'
)
self
.
logger
.
addHandler
(
logging
.
handlers
.
RotatingFileHandler
(
logPath
,
maxBytes
=
5
*
(
1
<<
20
),
backupCount
=
10
)
)
setDefaultLoggingConfig
(
self
.
logger
)
vbox
=
QtWidgets
.
QVBoxLayout
()
hbox
=
QtWidgets
.
QHBoxLayout
()
def
makeShowLambda
(
name
):
def
f
():
return
self
.
detectShow
(
name
)
return
QtCore
.
pyqtSlot
()(
f
)
def
makeValueLambda
(
objmethod
):
return
lambda
:
objmethod
()
self
.
imglabel
=
ImageView
(
self
)
self
.
imglabel
.
seedChanged
.
connect
(
self
.
seedChanged
)
self
.
drag
=
False
self
.
seedradiusedit
=
QtWidgets
.
QSpinBox
(
self
)
self
.
seedradiusedit
.
setMinimum
(
1
)
self
.
seedradiusedit
.
valueChanged
.
connect
(
self
.
imglabel
.
setSeedRadius
)
self
.
seedradiusedit
.
valueChanged
.
connect
(
self
.
updateImageSeeds
)
self
.
seedradiusedit
.
setValue
(
3
)
self
.
showseedpoints
=
QtWidgets
.
QCheckBox
(
"Show manual seed points"
,
self
)
self
.
showseedpoints
.
stateChanged
.
connect
(
self
.
imglabel
.
changeSeedDisplay
)
self
.
showseedpoints
.
setChecked
(
True
)
self
.
setImageCenter
()
self
.
globalScaleFactor
=
QtWidgets
.
QDoubleSpinBox
(
self
)
self
.
globalScaleLabel
=
QtWidgets
.
QLabel
(
''
)
self
.
globalScaleFactor
.
valueChanged
.
connect
(
self
.
updatePixelScaleLabel
)
self
.
globalScaleFactor
.
setMinimum
(
0.01
)
self
.
globalScaleFactor
.
setMaximum
(
1.
)
self
.
globalScaleFactor
.
setSingleStep
(
0.1
)
self
.
globalScaleFactor
.
setDecimals
(
2
)
self
.
globalScaleFactor
.
setValue
(
1.
)
self
.
globalScaleFactor
.
valueChanged
.
connect
(
self
.
autoUpdateIfDesired
)
globalScaleValueFunc
=
makeValueLambda
(
self
.
globalScaleFactor
.
value
)
self
.
detectParamsGroup
=
QtWidgets
.
QGroupBox
(
"Detection settings"
,
self
)
grid
=
QtWidgets
.
QGridLayout
()
self
.
parameters
=
[]
self
.
parameters
.
append
([
self
.
globalScaleFactor
,
'globalScaleFactor'
,
globalScaleValueFunc
,
None
])
checkBoxesToLink
=
{}
grid
.
addWidget
(
self
.
globalScaleLabel
,
0
,
0
,
QtCore
.
Qt
.
AlignLeft
)
grid
.
addWidget
(
self
.
globalScaleFactor
,
0
,
1
,
QtCore
.
Qt
.
AlignRight
)
# create editable parameters:
for
i
,
p
in
enumerate
(
self
.
seg
.
parlist
):
i
+=
1
label
,
colstretch
=
None
,
1
if
p
.
name
==
"contrastCurve"
:
paramui
=
HistWidget
(
lambda
:
self
.
seg
.
calculateHist
(
self
.
seg
.
convert2Gray
(
self
.
subimg
)),
self
.
seg
.
calculateHistFunction
,
self
)
valuefunc
=
makeValueLambda
(
paramui
.
value
)
colstretch
=
2
if
p
.
dtype
==
np
.
bool
:
paramui
=
QtWidgets
.
QCheckBox
(
p
.
helptext
,
self
)
paramui
.
stateChanged
.
connect
(
self
.
autoUpdateIfDesired
)
paramui
.
setChecked
(
p
.
value
)
valuefunc
=
makeValueLambda
(
paramui
.
isChecked
)
colstretch
=
2
if
p
.
linkedParameter
is
not
None
:
checkBoxesToLink
[
paramui
]
=
p
.
linkedParameter
elif
p
.
dtype
==
int
or
p
.
dtype
==
float
:
label
=
QtWidgets
.
QLabel
(
p
.
helptext
,
self
)
if
p
.
dtype
==
int
:
paramui
=
QtWidgets
.
QSpinBox
(
self
)
else
:
paramui
=
QtWidgets
.
QDoubleSpinBox
(
self
)
paramui
.
setDecimals
(
p
.
decimals
)
if
p
.
valrange
[
0
]
is
not
None
:
paramui
.
setMinimum
(
p
.
valrange
[
0
])
if
p
.
valrange
[
1
]
is
not
None
:
paramui
.
setMaximum
(
p
.
valrange
[
1
])
paramui
.
setSingleStep
(
p
.
stepsize
)
paramui
.
setValue
(
p
.
value
)
paramui
.
setMinimumWidth
(
70
)
paramui
.
valueChanged
.
connect
(
self
.
autoUpdateIfDesired
)
valuefunc
=
makeValueLambda
(
paramui
.
value
)
elif
p
.
dtype
is
None
:
label
=
QtWidgets
.
QLabel
(
p
.
helptext
,
self
)
paramui
=
None
if
paramui
is
not
None
:
self
.
parameters
.
append
([
paramui
,
p
.
name
,
valuefunc
,
None
])
if
colstretch
==
1
:
grid
.
addWidget
(
paramui
,
i
,
1
,
QtCore
.
Qt
.
AlignLeft
)
else
:
grid
.
addWidget
(
paramui
,
i
,
0
,
1
,
2
,
QtCore
.
Qt
.
AlignLeft
)
if
label
is
not
None
:
grid
.
addWidget
(
label
,
i
,
0
,
QtCore
.
Qt
.
AlignLeft
)
if
p
.
show
is
True
:
pshow
=
QtWidgets
.
QPushButton
(
">"
,
self
)
pshow
.
released
.
connect
(
makeShowLambda
(
p
.
name
))
grid
.
addWidget
(
pshow
,
i
,
2
,
QtCore
.
Qt
.
AlignRight
)
if
paramui
is
not
None
:
self
.
parameters
[
-
1
][
3
]
=
pshow
#link checkboxes to other parameters:
def
makeEnableLambda
(
checkbox
,
parameter
):
return
lambda
:
parameter
.
setEnabled
(
checkbox
.
isChecked
())
for
box
in
checkBoxesToLink
:
linkedName
=
checkBoxesToLink
[
box
]
for
p
in
self
.
parameters
:
if
p
[
1
]
==
linkedName
:
p
[
0
].
setEnabled
(
box
.
isChecked
())
box
.
stateChanged
.
connect
(
makeEnableLambda
(
box
,
p
[
0
]))
#the actual control element
if
p
[
3
]
is
not
None
:
#the "show" box, if present
box
.
stateChanged
.
connect
(
makeEnableLambda
(
box
,
p
[
3
]))
p
[
3
].
setEnabled
(
box
.
isChecked
())
label
=
QtWidgets
.
QLabel
(
"Seed radius"
,
self
)
grid
.
addWidget
(
label
,
i
+
1
,
0
,
QtCore
.
Qt
.
AlignLeft
)
grid
.
addWidget
(
self
.
seedradiusedit
,
i
+
1
,
1
,
QtCore
.
Qt
.
AlignLeft
)
grid
.
addWidget
(
self
.
showseedpoints
,
i
+
2
,
0
,
1
,
2
,
QtCore
.
Qt
.
AlignLeft
)
grid
.
addWidget
(
QtWidgets
.
QLabel
(
"Click mouse to add seeds, Click+Shift to add deletepoints"
),
i
+
3
,
0
,
1
,
2
,
QtCore
.
Qt
.
AlignLeft
)
grid
.
addWidget
(
QtWidgets
.
QLabel
(
"Click+Alt removes seeds near cursor"
),
i
+
4
,
0
,
1
,
2
,
QtCore
.
Qt
.
AlignLeft
)
self
.
detectParamsGroup
.
setLayout
(
grid
)
paramGroupScrollArea
=
QtWidgets
.
QScrollArea
(
self
)
Nscreen
=
getScreenHeight
()
maxHeight
=
np
.
clip
(
1000
,
0
,
Nscreen
*
0.8
)
paramGroupScrollArea
.
setFixedHeight
(
maxHeight
)
paramGroupScrollArea
.
setWidget
(
self
.
detectParamsGroup
)
vbox
.
addWidget
(
paramGroupScrollArea
)
self
.
updateSeedsInSampleViewBtn
=
QtWidgets
.
QPushButton
(
"Update Seedpoints in fullimage view"
,
self
)
self
.
updateSeedsInSampleViewBtn
.
released
.
connect
(
self
.
updateSeedsInSampleview
)
self
.
hideSeedsInSampleViewBtn
=
QtWidgets
.
QPushButton
(
"Hide Seedpoints in fullimage view"
,
self
)
self
.
hideSeedsInSampleViewBtn
.
released
.
connect
(
self
.
removeSeedsInSampleView
)
vbox
.
addWidget
(
self
.
updateSeedsInSampleViewBtn
)
vbox
.
addWidget
(
self
.
hideSeedsInSampleViewBtn
)
self
.
slider
=
QtWidgets
.
QSlider
(
self
)
self
.
slider
.
setRange
(
0
,
100
)
self
.
slider
.
setValue
(
80
)
self
.
slider
.
setOrientation
(
QtCore
.
Qt
.
Horizontal
)
self
.
slider
.
sliderMoved
.
connect
(
self
.
imglabel
.
resetAlpha
)
vbox
.
addWidget
(
self
.
slider
)
self
.
autoUpdateCheckBox
=
QtWidgets
.
QCheckBox
(
'Auto-update detection'
)
self
.
autoUpdateCheckBox
.
setMaximumWidth
(
200
)
self
.
autoUpdateCheckBox
.
setChecked
(
True
)
vbox
.
addWidget
(
self
.
autoUpdateCheckBox
)
self
.
progressbar
=
TimeEstimateProgressbar
()
vbox
.
addWidget
(
self
.
progressbar
)
hbox2
=
QtWidgets
.
QHBoxLayout
()
self
.
pdetectsub
=
QtWidgets
.
QPushButton
(
"Detect"
,
self
)
self
.
pdetectall
=
QtWidgets
.
QPushButton
(
"Detect all"
,
self
)
self
.
pclear
=
QtWidgets
.
QPushButton
(
"Clear detection"
,
self
)
self
.
pdetectsub
.
released
.
connect
(
makeShowLambda
(
None
))
self
.
pdetectall
.
released
.
connect
(
self
.
detectParticles
)
self
.
pclear
.
released
.
connect
(
self
.
clearDetection
)
hbox2
.
addWidget
(
self
.
pdetectsub
)
hbox2
.
addWidget
(
self
.
pdetectall
)
hbox2
.
addWidget
(
self
.
pclear
)
vbox
.
addLayout
(
hbox2
)
vbox
.
addStretch
()
hbox
.
addLayout
(
vbox
,
0
)
hbox
.
addWidget
(
self
.
imglabel
,
1
)
self
.
setLayout
(
hbox
)
self
.
setWindowTitle
(
"Particle Detection"
)
def
updatePixelScaleLabel
(
self
):
newScale
=
self
.
dataset
.
getPixelScale
(
self
.
dataset
.
imagescanMode
)
/
self
.
globalScaleFactor
.
value
()
newScale
=
np
.
round
(
newScale
,
2
)
self
.
globalScaleLabel
.
setText
(
f
'Scale for image (PixelScale:
{
newScale
}
µm/px)'
)
def
saveDetectParams
(
self
,
ds
=
None
):
if
ds
is
not
None
:
for
param
in
self
.
parameters
:
if
param
[
1
]
==
'contrastCurve'
:
print
(
param
[
0
].
value
())
try
:
# is it a spinbox or the histWidget? Read out the value
ds
.
detectParams
[
param
[
1
]]
=
param
[
0
].
value
()
except
:
# otherwise checkbox -> take its state
ds
.
detectParams
[
param
[
1
]]
=
param
[
0
].
isChecked
()
ds
.
detectParams
[
'seedRad'
]
=
self
.
seedradiusedit
.
value
()
ds
.
save
()
def
verifySeedpoints
(
self
,
dataset
):
seedpoints
=
dataset
.
seedpoints
seeddeletepoints
=
dataset
.
seeddeletepoints
if
len
(
seedpoints
)
>
0
:
# points are present
if
seedpoints
.
shape
[
1
]
==
2
:
# old entries with only x,y coordinates
radii
=
np
.
ones
((
seedpoints
.
shape
[
0
],
1
))
*
3
dataset
.
seedpoints
=
np
.
hstack
((
seedpoints
,
radii
))
else
:
dataset
.
seedpoints
=
np
.
array
([])
if
len
(
seeddeletepoints
)
>
0
:
# points are present
if
seeddeletepoints
.
shape
[
1
]
==
2
:
#old entries with only x,y coordinates
radii
=
np
.
ones
((
seeddeletepoints
.
shape
[
0
],
1
))
*
3
dataset
.
seeddeletepoints
=
np
.
hstack
((
seeddeletepoints
,
radii
))
else
:
dataset
.
seeddeletepoints
=
np
.
array
([])
return
dataset
@
QtCore
.
pyqtSlot
()
def
seedChanged
(
self
):
seedradius
=
self
.
seedradiusedit
.
value
()
def
clipdata
(
arr0
,
arr1
,
p0
,
n1
,
n2
,
m1
,
m2
):
if
arr0
.
shape
[
0
]
>
0
:
ind
=
(
arr0
[:,
0
]
>
m1
-
seedradius
)
&
(
arr0
[:,
0
]
<=
m2
+
seedradius
)
ind
&=
(
arr0
[:,
1
]
>
n1
-
seedradius
)
&
(
arr0
[:,
1
]
<=
n2
+
seedradius
)
arr0
=
arr0
[
~
ind
,:]
else
:
arr0
=
arr0
.
reshape
(
0
,
3
)
if
arr1
.
shape
[
0
]
>
0
:
arr1
[:,:
2
]
+=
p0
else
:
arr1
=
arr1
.
reshape
(
0
,
3
)
return
np
.
concatenate
((
arr0
,
arr1
),
axis
=
0
)
if
self
.
dataset
is
not
None
:
n1
,
n2
,
m1
,
m2
=
self
.
imgclip
p0
=
np
.
array
([[
m1
,
n1
]],
dtype
=
np
.
int32
)
self
.
dataset
.
seedpoints
=
clipdata
(
self
.
dataset
.
seedpoints
,
np
.
array
(
self
.
imglabel
.
seedpoints
,
dtype
=
np
.
int32
),
p0
,
n1
,
n2
,
m1
,
m2
)
self
.
dataset
.
seeddeletepoints
=
clipdata
(
self
.
dataset
.
seeddeletepoints
,
np
.
array
(
self
.
imglabel
.
seeddeletepoints
,
dtype
=
np
.
int32
),
p0
,
n1
,
n2
,
m1
,
m2
)
self
.
dataset
.
save
()
@
QtCore
.
pyqtSlot
()
def
updateImageSeeds
(
self
):
if
self
.
dataset
is
not
None
:
n1
,
n2
,
m1
,
m2
=
self
.
imgclip
p0
=
np
.
array
([[
m1
,
n1
]],
dtype
=
np
.
int32
)
seedpoints
=
[]
seeddeletepoints
=
[]
arr1
=
self
.
dataset
.
seedpoints
# what seeds are actually in image view?
for
point
in
arr1
:
if
point
[
0
]
>
(
m1
-
point
[
2
])
and
point
[
0
]
<=
(
m2
+
point
[
2
])
and
point
[
1
]
>
(
n1
-
point
[
2
])
and
point
[
1
]
<=
(
n2
+
point
[
2
]):
seedpoints
.
append
([
point
[
0
]
-
p0
[
0
][
0
],
point
[
1
]
-
p0
[
0
][
1
],
point
[
2
]])
arr2
=
self
.
dataset
.
seeddeletepoints