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
47db59a2
Commit
47db59a2
authored
Jul 15, 2019
by
JosefBrandt
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ParticlePainting Working, still bug in contour selection...
parent
9ae5cb90
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
333 additions
and
120 deletions
+333
-120
analysis/analysisview.py
analysis/analysisview.py
+34
-13
analysis/particleInfo.py
analysis/particleInfo.py
+6
-1
analysis/particlePainter.py
analysis/particlePainter.py
+125
-33
analysis/particleeditor.py
analysis/particleeditor.py
+72
-21
sampleview.py
sampleview.py
+87
-50
viewitems.py
viewitems.py
+9
-2
No files found.
analysis/analysisview.py
View file @
47db59a2
...
@@ -113,11 +113,18 @@ class ParticleAnalysis(QtWidgets.QMainWindow):
...
@@ -113,11 +113,18 @@ class ParticleAnalysis(QtWidgets.QMainWindow):
self
.
navigationGroup
=
QtWidgets
.
QGroupBox
(
'Navigate through polymers'
)
self
.
navigationGroup
=
QtWidgets
.
QGroupBox
(
'Navigate through polymers'
)
self
.
navigationGroup
.
setDisabled
(
True
)
self
.
navigationGroup
.
setDisabled
(
True
)
navigationLayout
=
QtWidgets
.
QHBoxLayout
()
navigationLayout
=
QtWidgets
.
QHBoxLayout
()
self
.
specNumberSelector
=
QtWidgets
.
QSpinBox
()
self
.
specNumberSelector
.
setMinimumWidth
(
150
)
self
.
specNumberSelector
.
setMinimum
(
1
)
self
.
specNumberSelector
.
setMaximum
(
1E6
)
self
.
jumpToSpecBtn
=
QtWidgets
.
QPushButton
(
'Jump To Spectrum of Number:'
)
self
.
jumpToSpecBtn
.
released
.
connect
(
self
.
jumpToSpectrumOfNumber
)
self
.
typeSelectorCombo
=
QtWidgets
.
QComboBox
()
self
.
typeSelectorCombo
=
QtWidgets
.
QComboBox
()
self
.
typeSelectorCombo
.
currentIndexChanged
.
connect
(
self
.
displayNewPolymerType
)
self
.
typeSelectorCombo
.
currentIndexChanged
.
connect
(
self
.
displayNewPolymerType
)
self
.
typeSelectorCombo
.
setMinimumWidth
(
150
)
self
.
typeSelectorCombo
.
setMinimumWidth
(
150
)
self
.
particleSelector
=
QtWidgets
.
QSpinBox
()
self
.
particleSelector
=
QtWidgets
.
QSpinBox
()
self
.
particleSelector
.
valueChanged
.
connect
(
self
.
updateToSelectedParticle
)
self
.
particleSelector
.
valueChanged
.
connect
(
self
.
update
SpecPlot
ToSelectedParticle
)
self
.
particleNumberLabel
=
QtWidgets
.
QLabel
(
'of xx particles; '
)
self
.
particleNumberLabel
=
QtWidgets
.
QLabel
(
'of xx particles; '
)
self
.
spectrumSelector
=
QtWidgets
.
QSpinBox
()
self
.
spectrumSelector
=
QtWidgets
.
QSpinBox
()
...
@@ -128,6 +135,8 @@ class ParticleAnalysis(QtWidgets.QMainWindow):
...
@@ -128,6 +135,8 @@ class ParticleAnalysis(QtWidgets.QMainWindow):
spinbox
.
setSingleStep
(
1
)
spinbox
.
setSingleStep
(
1
)
spinbox
.
setValue
(
1
)
spinbox
.
setValue
(
1
)
navigationLayout
.
addWidget
(
self
.
jumpToSpecBtn
)
navigationLayout
.
addWidget
(
self
.
specNumberSelector
)
navigationLayout
.
addWidget
(
QtWidgets
.
QLabel
(
'Select Polymer Type:'
))
navigationLayout
.
addWidget
(
QtWidgets
.
QLabel
(
'Select Polymer Type:'
))
navigationLayout
.
addWidget
(
self
.
typeSelectorCombo
)
navigationLayout
.
addWidget
(
self
.
typeSelectorCombo
)
navigationLayout
.
addStretch
()
navigationLayout
.
addStretch
()
...
@@ -214,7 +223,7 @@ class ParticleAnalysis(QtWidgets.QMainWindow):
...
@@ -214,7 +223,7 @@ class ParticleAnalysis(QtWidgets.QMainWindow):
self
.
updateDisplays
()
self
.
updateDisplays
()
self
.
initializeSpecPlot
()
self
.
initializeSpecPlot
()
self
.
displayNewPolymerType
()
self
.
displayNewPolymerType
()
self
.
updateToSelectedParticle
()
self
.
update
SpecPlot
ToSelectedParticle
()
# self.createPolymerOverlay()
# self.createPolymerOverlay()
def
createActions
(
self
):
def
createActions
(
self
):
...
@@ -390,16 +399,16 @@ class ParticleAnalysis(QtWidgets.QMainWindow):
...
@@ -390,16 +399,16 @@ class ParticleAnalysis(QtWidgets.QMainWindow):
self
.
createHistogramData
()
self
.
createHistogramData
()
t0
=
time
.
time
()
t0
=
time
.
time
()
self
.
updateTypeHistogram
()
self
.
updateTypeHistogram
()
print
(
'update type hist:
'
,
round
((
time
.
time
()
-
t0
)
*
1000
))
print
(
'update type hist:
{} ms'
.
format
(
round
((
time
.
time
()
-
t0
)
*
1000
))
)
t0
=
time
.
time
()
t0
=
time
.
time
()
self
.
updateSizeHistogram
()
self
.
updateSizeHistogram
()
print
(
'update size hist:
'
,
round
((
time
.
time
()
-
t0
)
*
1000
))
print
(
'update size hist:
{} ms'
.
format
(
round
((
time
.
time
()
-
t0
)
*
1000
))
)
t0
=
time
.
time
()
t0
=
time
.
time
()
self
.
updateContourColors
()
self
.
updateContourColors
()
print
(
'update contours:
'
,
round
((
time
.
time
()
-
t0
)
*
1000
))
print
(
'update contours:
{} ms'
.
format
(
round
((
time
.
time
()
-
t0
)
*
1000
))
)
t0
=
time
.
time
()
t0
=
time
.
time
()
self
.
updateLegend
()
self
.
updateLegend
()
print
(
'update legend:
'
,
round
((
time
.
time
()
-
t0
)
*
1000
))
print
(
'update legend:
{} ms'
.
format
(
round
((
time
.
time
()
-
t0
)
*
1000
))
)
self
.
dataset
.
save
()
self
.
dataset
.
save
()
def
initializeSpecPlot
(
self
):
def
initializeSpecPlot
(
self
):
...
@@ -474,7 +483,7 @@ class ParticleAnalysis(QtWidgets.QMainWindow):
...
@@ -474,7 +483,7 @@ class ParticleAnalysis(QtWidgets.QMainWindow):
def
updateContourColors
(
self
):
def
updateContourColors
(
self
):
contours
=
self
.
parent
.
contourItems
contours
=
self
.
parent
.
contourItems
alpha
=
(
128
if
self
.
transpAct
.
isChecked
()
else
255
)
alpha
=
(
64
if
self
.
transpAct
.
isChecked
()
else
255
)
selectedPolymers
=
self
.
getSelectedPolymers
()
selectedPolymers
=
self
.
getSelectedPolymers
()
for
particleIndex
,
contour
in
enumerate
(
contours
):
for
particleIndex
,
contour
in
enumerate
(
contours
):
...
@@ -501,10 +510,22 @@ class ParticleAnalysis(QtWidgets.QMainWindow):
...
@@ -501,10 +510,22 @@ class ParticleAnalysis(QtWidgets.QMainWindow):
def
getSelectedPolymers
(
self
):
def
getSelectedPolymers
(
self
):
return
[
checkbox
.
text
()
for
checkbox
in
self
.
polymerCheckBoxes
if
checkbox
.
isChecked
()]
return
[
checkbox
.
text
()
for
checkbox
in
self
.
polymerCheckBoxes
if
checkbox
.
isChecked
()]
def
jumpToSpectrumOfNumber
(
self
):
specIndex
=
self
.
specNumberSelector
.
value
()
-
1
assert
specIndex
is
not
None
partIndex
=
self
.
particleContainer
.
getParticleIndexContainingSpecIndex
(
specIndex
)
assignment
=
self
.
particleContainer
.
getParticleAssignmentByIndex
(
partIndex
)
self
.
typeSelectorCombo
.
setCurrentText
(
assignment
)
#TODO: Connect to widget that allows jumping to particular particle
partIndices
=
self
.
particleContainer
.
getIndicesOfParticleType
(
assignment
)
def
selectParticleIndex
(
self
,
particleIndex
,
centerOn
=
True
):
self
.
particleSelector
.
setValue
(
partIndices
.
index
(
partIndex
)
+
1
)
self
.
typeSelectorCombo
.
currentIndexChanged
.
disconnect
()
specIndices
=
self
.
particleContainer
.
getSpectraIndicesOfParticle
(
partIndex
)
self
.
spectrumSelector
.
setValue
(
specIndices
.
index
(
specIndex
)
+
1
)
def
selectParticleOfIndex
(
self
,
particleIndex
,
centerOn
=
True
):
assignment
=
self
.
particleContainer
.
getParticleAssignmentByIndex
(
particleIndex
)
assignment
=
self
.
particleContainer
.
getParticleAssignmentByIndex
(
particleIndex
)
self
.
typeSelectorCombo
.
setCurrentText
(
assignment
)
self
.
typeSelectorCombo
.
setCurrentText
(
assignment
)
self
.
typeSelectorCombo
.
currentIndexChanged
.
connect
(
self
.
displayNewPolymerType
)
self
.
typeSelectorCombo
.
currentIndexChanged
.
connect
(
self
.
displayNewPolymerType
)
...
@@ -512,9 +533,9 @@ class ParticleAnalysis(QtWidgets.QMainWindow):
...
@@ -512,9 +533,9 @@ class ParticleAnalysis(QtWidgets.QMainWindow):
self
.
particleSelector
.
valueChanged
.
disconnect
()
self
.
particleSelector
.
valueChanged
.
disconnect
()
particleIndices
=
self
.
particleContainer
.
getIndicesOfParticleType
(
assignment
)
particleIndices
=
self
.
particleContainer
.
getIndicesOfParticleType
(
assignment
)
self
.
particleSelector
.
setValue
(
particleIndices
.
index
(
particleIndex
)
+
1
)
self
.
particleSelector
.
setValue
(
particleIndices
.
index
(
particleIndex
)
+
1
)
self
.
particleSelector
.
valueChanged
.
connect
(
self
.
updateToSelectedParticle
)
self
.
particleSelector
.
valueChanged
.
connect
(
self
.
update
SpecPlot
ToSelectedParticle
)
self
.
updateToSelectedParticle
(
resetSpectrumCount
=
True
,
centerOn
=
centerOn
)
self
.
update
SpecPlot
ToSelectedParticle
(
resetSpectrumCount
=
True
,
centerOn
=
centerOn
)
def
displayNewPolymerType
(
self
,
resetCurrentIndex
=
True
):
def
displayNewPolymerType
(
self
,
resetCurrentIndex
=
True
):
polymerName
=
self
.
typeSelectorCombo
.
currentText
()
polymerName
=
self
.
typeSelectorCombo
.
currentText
()
...
@@ -532,7 +553,7 @@ class ParticleAnalysis(QtWidgets.QMainWindow):
...
@@ -532,7 +553,7 @@ class ParticleAnalysis(QtWidgets.QMainWindow):
self
.
currentSpectrumIndex
=
self
.
getSpectrumIndexFromSpectrumSelector
()
self
.
currentSpectrumIndex
=
self
.
getSpectrumIndexFromSpectrumSelector
()
self
.
updateSpecPlot
(
centerOn
=
False
)
self
.
updateSpecPlot
(
centerOn
=
False
)
def
updateToSelectedParticle
(
self
,
resetSpectrumCount
=
True
,
centerOn
=
True
):
def
update
SpecPlot
ToSelectedParticle
(
self
,
resetSpectrumCount
=
True
,
centerOn
=
True
):
polymerName
=
self
.
typeSelectorCombo
.
currentText
()
polymerName
=
self
.
typeSelectorCombo
.
currentText
()
if
polymerName
!=
''
:
if
polymerName
!=
''
:
self
.
currentParticleIndex
=
self
.
getParticleIndexFromParticleSelector
()
self
.
currentParticleIndex
=
self
.
getParticleIndexFromParticleSelector
()
...
...
analysis/particleInfo.py
View file @
47db59a2
...
@@ -115,7 +115,12 @@ class ParticleContainer(object):
...
@@ -115,7 +115,12 @@ class ParticleContainer(object):
particle
=
self
.
particles
[
index
]
particle
=
self
.
particles
[
index
]
assert
particle
.
index
==
index
,
f
'particle.index (
{
particle
.
index
}
) does match requested index in particleList (
{
index
}
)'
assert
particle
.
index
==
index
,
f
'particle.index (
{
particle
.
index
}
) does match requested index in particleList (
{
index
}
)'
return
particle
return
particle
def
getParticleIndexContainingSpecIndex
(
self
,
index
):
for
particle
in
self
.
particles
:
if
index
in
particle
.
getMeasurementIndices
():
return
particle
.
index
def
getNumberOfParticles
(
self
):
def
getNumberOfParticles
(
self
):
return
len
(
self
.
particles
)
return
len
(
self
.
particles
)
...
...
analysis/particlePainter.py
View file @
47db59a2
...
@@ -21,54 +21,146 @@ If not, see <https://www.gnu.org/licenses/>.
...
@@ -21,54 +21,146 @@ If not, see <https://www.gnu.org/licenses/>.
"""
"""
from
PyQt5
import
QtWidgets
,
QtCore
,
QtGui
from
PyQt5
import
QtWidgets
,
QtCore
,
QtGui
import
numpy
as
np
import
numpy
as
np
import
cv2
class
ParticlePainter
(
QtWidgets
.
QGraphicsItem
):
class
ParticlePainter
(
QtWidgets
.
QGraphicsItem
):
def
__init__
(
self
,
particleC
ontour
,
pos
=
(
0
,
0
)):
def
__init__
(
self
,
editorParent
,
c
ontour
s
,
pos
=
(
500
,
5
00
)):
super
().
__init__
()
super
(
ParticlePainter
,
self
).
__init__
()
self
.
setZValue
(
1
)
self
.
editorParent
=
editorParent
self
.
setPos
(
pos
[
0
],
pos
[
1
])
self
.
viewparent
=
self
.
editorParent
.
viewparent
self
.
setZValue
(
5
)
self
.
polygon
=
None
self
.
polygon
s
=
None
self
.
particleC
ontour
=
particleC
ontour
self
.
c
ontour
s
=
c
ontour
s
self
.
mousePos
=
None
self
.
mousePos
=
None
self
.
minRadius
=
1
self
.
minRadius
=
1
0
self
.
maxRadius
=
500
self
.
maxRadius
=
500
self
.
radius
=
2
0
self
.
radius
=
5
0
self
.
brect
=
QtCore
.
QRectF
(
0
,
0
,
1
,
1
)
self
.
brect
=
QtCore
.
QRectF
(
0
,
0
,
1
,
1
)
# self.getBrectAndPolygon()
self
.
getBrectAndPolygon
()
self
.
painting
=
False
# def getBrectAndPolygon(self):
self
.
erasing
=
False
# polygon = QtGui.QPolygonF()
# x0 = self.particleContour[:,0,0].min()
# x1 = self.particleContour[:,0,0].max()
# y0 = self.particleContour[:,0,1].min()
# y1 = self.particleContour[:,0,1].max()
# for point in self.particleContour:
# polygon.append(QtCore.QPointF(point[0,0], point[0,1]))
# self.brect.setCoords(x0, y0, x1, y1)
def
getBrectAndPolygon
(
self
):
# self.polygon = polygon
polygons
=
[]
x0
=
None
for
c
in
self
.
contours
:
polygon
=
QtGui
.
QPolygonF
()
if
x0
is
None
:
x0
=
c
[:,
0
,
0
].
min
()
x1
=
c
[:,
0
,
0
].
max
()
y0
=
c
[:,
0
,
1
].
min
()
y1
=
c
[:,
0
,
1
].
max
()
else
:
x0
=
min
(
x0
,
c
[:,
0
,
0
].
min
())
x1
=
max
(
x1
,
c
[:,
0
,
0
].
max
())
y0
=
min
(
y0
,
c
[:,
0
,
1
].
min
())
y1
=
max
(
y1
,
c
[:,
0
,
1
].
max
())
for
ci
in
c
:
polygon
.
append
(
QtCore
.
QPointF
(
ci
[
0
,
0
],
ci
[
0
,
1
]))
polygons
.
append
(
polygon
)
if
x0
is
None
:
self
.
brect
=
QtCore
.
QRectF
(
0
,
0
,
1
,
1
)
else
:
self
.
brect
.
setCoords
(
x0
,
y0
,
x1
,
y1
)
self
.
polygons
=
polygons
def
boundingRect
(
self
):
def
boundingRect
(
self
):
return
self
.
brect
return
self
.
brect
def
mousePressEvent
(
self
,
event
):
self
.
mousePos
=
self
.
viewparent
.
mapToScene
(
event
.
pos
())
self
.
erasing
=
self
.
painting
=
False
if
event
.
modifiers
()
==
QtCore
.
Qt
.
ControlModifier
:
self
.
painting
=
True
elif
event
.
modifiers
()
==
QtCore
.
Qt
.
ShiftModifier
:
self
.
erasing
=
True
if
self
.
painting
or
self
.
erasing
:
drawPos
=
self
.
viewparent
.
mapToScene
(
event
.
pos
())
-
self
.
brect
.
topLeft
()
self
.
drawParticle
(
drawPos
)
def
mouseMoveEvent
(
self
,
event
):
def
mouseMoveEvent
(
self
,
event
):
p
=
event
.
pos
()
self
.
mousePos
=
self
.
viewparent
.
mapToScene
(
event
.
pos
())
self
.
brect
.
setCoords
(
p
.
x
()
-
self
.
radius
/
2
,
p
.
y
()
-
self
.
radius
/
2
,
p
.
x
()
+
self
.
radius
/
2
,
p
.
y
()
+
self
.
radius
/
2
)
self
.
update
()
self
.
mousePos
=
p
if
self
.
painting
or
self
.
erasing
:
drawPos
=
self
.
viewparent
.
mapToScene
(
event
.
pos
())
-
self
.
brect
.
topLeft
()
self
.
drawParticle
(
drawPos
)
def
wheelEvent
(
self
,
event
):
def
wheelEvent
(
self
,
event
):
if
event
.
angleDelta
().
y
()
>
0
:
if
event
.
angleDelta
().
y
()
<
0
:
self
.
radius
=
np
.
clip
(
self
.
radius
+
1
,
self
.
minRadius
,
self
.
maxRadius
)
self
.
radius
=
int
(
np
.
clip
(
self
.
radius
+
self
.
radius
*
0.1
,
self
.
minRadius
,
self
.
maxRadius
))
else
:
self
.
radius
=
int
(
np
.
clip
(
self
.
radius
-
self
.
radius
*
0.1
,
self
.
minRadius
,
self
.
maxRadius
))
self
.
update
()
def
mouseReleaseEvent
(
self
,
event
):
self
.
erasing
=
self
.
painting
=
False
def
keyPressEvent
(
self
,
event
):
if
event
.
key
()
==
QtCore
.
Qt
.
Key_Escape
:
self
.
editorParent
.
destroyParticlePainter
()
elif
event
.
key
()
==
QtCore
.
Qt
.
Key_Return
:
self
.
editorParent
.
acceptPaintedResult
()
def
drawParticle
(
self
,
pos
):
img
,
xmin
,
ymin
,
padding
=
self
.
contoursToImg
(
self
.
contours
)
center
=
(
int
(
pos
.
x
()
+
self
.
radius
),
int
(
pos
.
y
()
+
self
.
radius
))
if
self
.
painting
:
cv2
.
circle
(
img
,
center
,
self
.
radius
,
255
,
-
1
)
elif
self
.
erasing
:
cv2
.
circle
(
img
,
center
,
self
.
radius
,
0
,
-
1
)
img
=
np
.
uint8
(
img
)
self
.
contours
=
self
.
imgToCnt
(
img
,
xmin
,
ymin
,
padding
)
self
.
getBrectAndPolygon
()
self
.
update
()
def
contoursToImg
(
self
,
contours
):
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
=
self
.
radius
+
2
#pixel in each direction
rangex
=
int
(
np
.
round
((
xmax
-
xmin
)
+
2
*
padding
))
rangey
=
int
(
np
.
round
((
ymax
-
ymin
)
+
2
*
padding
))
img
=
np
.
zeros
((
rangey
,
rangex
),
dtype
=
np
.
uint8
)
for
curCnt
in
contours
:
for
i
in
range
(
len
(
curCnt
)):
curCnt
[
i
][
0
][
0
]
-=
xmin
-
padding
curCnt
[
i
][
0
][
1
]
-=
ymin
-
padding
cv2
.
drawContours
(
img
,
[
curCnt
],
-
1
,
255
,
-
1
)
cv2
.
drawContours
(
img
,
[
curCnt
],
-
1
,
255
,
1
)
return
img
,
xmin
,
ymin
,
padding
def
imgToCnt
(
self
,
img
,
xmin
,
ymin
,
padding
):
if
cv2
.
__version__
>
'3.5'
:
contours
,
hierarchy
=
cv2
.
findContours
(
img
,
cv2
.
RETR_CCOMP
,
cv2
.
CHAIN_APPROX_NONE
)
else
:
else
:
self
.
radius
=
np
.
clip
(
self
.
radius
-
1
,
self
.
minRadius
,
self
.
maxRadius
)
temp
,
contours
,
hierarchy
=
cv2
.
findContours
(
img
,
cv2
.
RETR_CCOMP
,
cv2
.
CHAIN_APPROX_NONE
)
def
paint
(
self
,
painter
,
option
,
widget
):
for
contour
in
contours
:
for
i
in
range
(
len
(
contour
)):
contour
[
i
][
0
][
0
]
+=
xmin
-
padding
contour
[
i
][
0
][
1
]
+=
ymin
-
padding
return
contours
def
paint
(
self
,
painter
,
option
,
widget
):
painter
.
setPen
(
QtCore
.
Qt
.
white
)
painter
.
drawRect
(
self
.
brect
)
if
self
.
mousePos
is
not
None
:
if
self
.
mousePos
is
not
None
:
p
=
[
self
.
mousePos
.
x
(),
self
.
mousePos
.
y
(),
self
.
radius
]
p
=
[
self
.
mousePos
.
x
(),
self
.
mousePos
.
y
(),
self
.
radius
]
painter
.
drawEllipse
(
p
[
0
]
-
p
[
2
],
p
[
1
]
-
p
[
2
],
2
*
p
[
2
],
2
*
p
[
2
])
painter
.
drawEllipse
(
p
[
0
]
-
p
[
2
],
p
[
1
]
-
p
[
2
],
2
*
p
[
2
],
2
*
p
[
2
])
# if self.polygon is not None:
if
self
.
polygons
is
not
None
:
# painter.setPen(QtCore.Qt.white)
for
poly
in
self
.
polygons
:
# painter.setBrush(QtGui.QColor(200, 200, 200, 128))
painter
.
setBrush
(
QtGui
.
QColor
(
200
,
200
,
255
,
128
))
# painter.drawPolygon(self.polygon)
painter
.
drawPolygon
(
poly
)
\ No newline at end of file
\ No newline at end of file
analysis/particleeditor.py
View file @
47db59a2
...
@@ -29,9 +29,12 @@ import numpy as np
...
@@ -29,9 +29,12 @@ import numpy as np
import
cv2
import
cv2
from
PyQt5
import
QtWidgets
,
QtCore
from
PyQt5
import
QtWidgets
,
QtCore
from
analysis.particlePainter
import
ParticlePainter
class
ParticleContextMenu
(
QtWidgets
.
QMenu
):
class
ParticleContextMenu
(
QtWidgets
.
QMenu
):
combineParticlesSignal
=
QtCore
.
pyqtSignal
(
list
,
str
)
combineParticlesSignal
=
QtCore
.
pyqtSignal
(
list
,
str
)
reassignParticlesSignal
=
QtCore
.
pyqtSignal
(
list
,
str
)
reassignParticlesSignal
=
QtCore
.
pyqtSignal
(
list
,
str
)
paintParticlesSignal
=
QtCore
.
pyqtSignal
(
list
,
str
)
def
__init__
(
self
,
viewparent
):
def
__init__
(
self
,
viewparent
):
super
(
ParticleContextMenu
,
self
).
__init__
()
super
(
ParticleContextMenu
,
self
).
__init__
()
self
.
viewparent
=
viewparent
self
.
viewparent
=
viewparent
...
@@ -41,18 +44,25 @@ class ParticleContextMenu(QtWidgets.QMenu):
...
@@ -41,18 +44,25 @@ class ParticleContextMenu(QtWidgets.QMenu):
def
executeAtScreenPos
(
self
,
screenPos
):
def
executeAtScreenPos
(
self
,
screenPos
):
self
.
combineActs
=
[]
self
.
combineActs
=
[]
self
.
combineMenu
=
QtWidgets
.
QMenu
(
"Combine Particles into"
)
self
.
combineMenu
=
QtWidgets
.
QMenu
(
"Combine Particles into"
)
assignments
=
[]
self
.
paintActs
=
[]
self
.
paintMenu
=
QtWidgets
.
QMenu
(
"Paint Mode, merge into"
)
selctedAssignments
=
[]
for
particleIndex
in
self
.
selectedParticleIndices
:
for
particleIndex
in
self
.
selectedParticleIndices
:
try
:
try
:
assignment
=
self
.
particleContainer
.
getParticleAssignmentByIndex
(
particleIndex
)
assignment
=
self
.
particleContainer
.
getParticleAssignmentByIndex
(
particleIndex
)
except
:
except
:
return
return
a
ssignments
.
append
(
assignment
)
selctedA
ssignments
.
append
(
assignment
)
for
assignment
in
np
.
unique
(
a
ssignments
):
for
assignment
in
np
.
unique
(
selctedA
ssignments
):
self
.
combineActs
.
append
(
self
.
combineMenu
.
addAction
(
assignment
))
self
.
combineActs
.
append
(
self
.
combineMenu
.
addAction
(
assignment
))
self
.
paintActs
.
append
(
self
.
paintMenu
.
addAction
(
assignment
))
self
.
combineActs
.
append
(
self
.
combineMenu
.
addAction
(
"other"
))
self
.
combineActs
.
append
(
self
.
combineMenu
.
addAction
(
"other"
))
self
.
paintActs
.
append
(
self
.
paintMenu
.
addAction
(
"other"
))
self
.
reassignActs
=
[]
self
.
reassignActs
=
[]
self
.
reassignMenu
=
QtWidgets
.
QMenu
(
"Reassign particle(s) into"
)
self
.
reassignMenu
=
QtWidgets
.
QMenu
(
"Reassign particle(s) into"
)
...
@@ -69,15 +79,19 @@ class ParticleContextMenu(QtWidgets.QMenu):
...
@@ -69,15 +79,19 @@ class ParticleContextMenu(QtWidgets.QMenu):
self
.
addMenu
(
self
.
combineMenu
)
self
.
addMenu
(
self
.
combineMenu
)
self
.
addMenu
(
self
.
reassignMenu
)
self
.
addMenu
(
self
.
reassignMenu
)
self
.
addMenu
(
self
.
paintMenu
)
action
=
self
.
exec_
(
screenPos
)
action
=
self
.
exec_
(
screenPos
)
if
action
in
self
.
combineActs
:
if
action
:
newAssignment
=
self
.
validifyAssignment
(
action
.
text
())
self
.
combineParticlesSignal
.
emit
(
self
.
selectedParticleIndices
,
newAssignment
)
elif
action
in
self
.
reassignActs
:
newAssignment
=
self
.
validifyAssignment
(
action
.
text
())
newAssignment
=
self
.
validifyAssignment
(
action
.
text
())
self
.
reassignParticlesSignal
.
emit
(
self
.
selectedParticleIndices
,
newAssignment
)
if
action
in
self
.
combineActs
:
self
.
combineParticlesSignal
.
emit
(
self
.
selectedParticleIndices
,
newAssignment
)
elif
action
in
self
.
reassignActs
:
self
.
reassignParticlesSignal
.
emit
(
self
.
selectedParticleIndices
,
newAssignment
)
elif
action
in
self
.
paintActs
:
self
.
paintParticlesSignal
.
emit
(
self
.
selectedParticleIndices
,
newAssignment
)
def
validifyAssignment
(
self
,
assignment
):
def
validifyAssignment
(
self
,
assignment
):
if
assignment
==
"other"
:
if
assignment
==
"other"
:
...
@@ -85,7 +99,7 @@ class ParticleContextMenu(QtWidgets.QMenu):
...
@@ -85,7 +99,7 @@ class ParticleContextMenu(QtWidgets.QMenu):
return
assignment
return
assignment
def
getNewEntry
(
self
):
def
getNewEntry
(
self
):
text
,
okClicked
=
QtWidgets
.
QInputDialog
.
getText
(
QtWidgets
.
QWidget
()
,
"Custom assignment"
,
"Enter new assignment"
)
text
,
okClicked
=
QtWidgets
.
QInputDialog
.
getText
(
self
.
viewparent
,
"Custom assignment"
,
"Enter new assignment"
)
if
okClicked
and
text
!=
''
:
if
okClicked
and
text
!=
''
:
return
text
return
text
...
@@ -93,22 +107,26 @@ class ParticleContextMenu(QtWidgets.QMenu):
...
@@ -93,22 +107,26 @@ class ParticleContextMenu(QtWidgets.QMenu):
class
ParticleEditor
(
QtCore
.
QObject
):
class
ParticleEditor
(
QtCore
.
QObject
):
particleContoursChanged
=
QtCore
.
pyqtSignal
()
particleContoursChanged
=
QtCore
.
pyqtSignal
()
particleAssignmentChanged
=
QtCore
.
pyqtSignal
()
particleAssignmentChanged
=
QtCore
.
pyqtSignal
()
def
__init__
(
self
,
analysis
parent
,
particleContainer
):
def
__init__
(
self
,
view
parent
,
particleContainer
):
super
(
ParticleEditor
,
self
).
__init__
()
super
(
ParticleEditor
,
self
).
__init__
()
self
.
particleContainer
=
particleContainer
self
.
particleContainer
=
particleContainer
self
.
analysis
parent
=
analysis
parent
#the assigned analysis widget
self
.
view
parent
=
view
parent
#the assigned analysis widget
self
.
backupFreq
=
3
#save a backup every n actions
self
.
backupFreq
=
3
#save a backup every n actions
self
.
neverBackedUp
=
True
self
.
neverBackedUp
=
True
self
.
actionCounter
=
0
self
.
actionCounter
=
0
self
.
storedIndices
=
[]
self
.
storedAssignmend
=
None
def
connectToSignals
(
self
,
contextMenu
):
def
connectToSignals
(
self
,
contextMenu
):
contextMenu
.
combineParticlesSignal
.
connect
(
self
.
combineParticles
)
contextMenu
.
combineParticlesSignal
.
connect
(
self
.
combineParticles
)
contextMenu
.
reassignParticlesSignal
.
connect
(
self
.
reassignParticles
)
contextMenu
.
reassignParticlesSignal
.
connect
(
self
.
reassignParticles
)
contextMenu
.
paintParticlesSignal
.
connect
(
self
.
paintParticles
)
def
createSafetyBackup
(
self
):
def
createSafetyBackup
(
self
):
self
.
actionCounter
+=
1
self
.
actionCounter
+=
1
if
self
.
actionCounter
==
self
.
backupFreq
-
1
or
self
.
neverBackedUp
:
if
self
.
actionCounter
==
self
.
backupFreq
-
1
or
self
.
neverBackedUp
:
backupname
=
self
.
analysis
parent
.
dataset
.
saveBackup
()
backupname
=
self
.
view
parent
.
dataset
.
saveBackup
()
print
(
'backing up as'
,
backupname
)
print
(
'backing up as'
,
backupname
)
self
.
neverBackedUp
=
False
self
.
neverBackedUp
=
False
self
.
actionCounter
=
0
self
.
actionCounter
=
0
...
@@ -122,14 +140,13 @@ class ParticleEditor(QtCore.QObject):
...
@@ -122,14 +140,13 @@ class ParticleEditor(QtCore.QObject):
stats
=
self
.
characterizeParticle
(
newContour
)
stats
=
self
.
characterizeParticle
(
newContour
)
self
.
particleContainer
.
mergeParticles
(
contourIndices
,
newContour
,
stats
,
newAssignment
=
newAssignment
)
self
.
particleContainer
.
mergeParticles
(
contourIndices
,
newContour
,
stats
,
newAssignment
=
newAssignment
)
self
.
particleContoursChanged
.
emit
()
for
ind
in
contourIndices
:
# #save data
self
.
viewparent
.
removeParticleContour
(
ind
)
# minHQI = self.parent.hqiSpinBox.value()
# compHQI = self.parent.compHqiSpinBox.value()
self
.
viewparent
.
resetContourIndices
()
# if not self.datastats.saveAnalysisResults(minHQI, compHQI):
self
.
viewparent
.
addParticleContour
(
newContour
,
len
(
self
.
viewparent
.
contourItems
))
# QtWidgets.QMessageBox.warning(self.parent, 'Error!',
# 'Data inconsistency after saving!', QtWidgets.QMessageBox.Ok,
#TODO: INCLUDE SANITY CHECK!!!!!!!!!
# QtWidgets.QMessageBox.Ok)
@
QtCore
.
pyqtSlot
(
list
,
str
)
@
QtCore
.
pyqtSlot
(
list
,
str
)
def
reassignParticles
(
self
,
contourindices
,
newAssignment
):
def
reassignParticles
(
self
,
contourindices
,
newAssignment
):
...
@@ -139,6 +156,41 @@ class ParticleEditor(QtCore.QObject):
...
@@ -139,6 +156,41 @@ class ParticleEditor(QtCore.QObject):
self
.
particleContainer
.
reassignParticleToAssignment
(
partIndex
,
newAssignment
)
self
.
particleContainer
.
reassignParticleToAssignment
(
partIndex
,
newAssignment
)
self
.
particleAssignmentChanged
.
emit
()
self
.
particleAssignmentChanged
.
emit
()
@
QtCore
.
pyqtSlot
(
list
,
str
)
def
paintParticles
(
self
,
contourIndices
,
newAssignment
):
self
.
createSafetyBackup
self
.
storedIndices
=
contourIndices
self
.
storedAssignmend
=
newAssignment
contours
=
self
.
particleContainer
.
getParticleContoursByIndex
(
contourIndices
)
self
.
particlePainter
=
ParticlePainter
(
self
,
contours
)
self
.
viewparent
.
normalSize
()
self
.
viewparent
.
particlePainter
=
self
.
particlePainter
self
.
viewparent
.
scene
().
addItem
(
self
.
particlePainter
)
self
.
viewparent
.
update
()
def
acceptPaintedResult
(
self
):
newContour
=
self
.
mergeContours
(
self
.
particlePainter
.
contours
.
copy
())
stats
=
self
.
characterizeParticle
(
newContour
)
self
.
particleContainer
.
mergeParticles
(
self
.
storedIndices
,
newContour
,
stats
,
newAssignment
=
self
.
storedAssignmend
)
for
ind
in
self
.
storedIndices
:
self
.
viewparent
.
removeParticleContour
(
ind
)
self
.
viewparent
.
resetContourIndices
()
self
.
viewparent
.
addParticleContour
(
newContour
,
len
(
self
.
viewparent
.
contourItems
))
#TODO: INCLUDE SANITY CHECK!!!!!!!!!
self
.
storedIndices
=
[]
self
.
storedAssignmend
=
None
self
.
destroyParticlePainter
()
def
destroyParticlePainter
(
self
):
if
self
.
particlePainter
is
not
None
:
self
.
viewparent
.
particlePainter
=
None
self
.
viewparent
.
scene
().
removeItem
(
self
.
particlePainter
)
self
.
viewparent
.
update
()
self
.
particlePainter
=
None
def
mergeContours
(
self
,
contours
):
def
mergeContours
(
self
,
contours
):
cnt
=
np
.
vstack
(
tuple
(
contours
))
#combine contous