Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
kmap
xsocs
Commits
6822878d
Commit
6822878d
authored
Apr 27, 2017
by
Damien Naudet
Browse files
Split a file into several.
parent
6d667c91
Changes
4
Hide whitespace changes
Inline
Side-by-side
xsocs/gui/silx_imports/ImageRois.py
View file @
6822878d
...
...
@@ -399,6 +399,13 @@ class ImageRoiManager(qt.QObject):
self
.
_plot
.
sigInteractiveModeChanged
.
connect
(
self
.
_interactiveModeChanged
,
qt
.
Qt
.
QueuedConnection
)
def
plot
(
self
):
"""
Returns the plot controlled by this manager.
:return:
"""
return
self
.
_plot
def
_createRoiActions
(
self
):
if
self
.
_roiActions
:
...
...
xsocs/gui/view/intensity/IntensityModel.py
0 → 100644
View file @
6822878d
# coding: utf-8
# /*##########################################################################
#
# Copyright (c) 2015-2016 European Synchrotron Radiation Facility
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
# ###########################################################################*/
from
__future__
import
absolute_import
__authors__
=
[
"D. Naudet"
]
__license__
=
"MIT"
__date__
=
"15/09/2016"
from
silx.gui
import
qt
as
Qt
from
...model.TreeView
import
TreeView
from
...model.ModelDef
import
ModelRoles
from
...model.Model
import
Model
,
RootNode
,
Node
from
...project.Hdf5Nodes
import
H5GroupNode
from
...project.IntensityGroup
import
IntensityGroup
class
IntensityTotalNode
(
H5GroupNode
):
"""
Node displaying info about the number of entries selected.
"""
total
=
property
(
lambda
self
:
self
.
__total
)
samplePos
=
property
(
lambda
self
:
self
.
__samplePos
)
icons
=
None
def
__init__
(
self
,
checkableChildren
=
True
,
**
kwargs
):
"""
Node representing the total intensity. Its children
are the intensity for each angle.
:param checkableChildren: if set to True (default) the angle
intensity nodes will be checkable.
:param kwargs:
"""
super
(
IntensityTotalNode
,
self
).
__init__
(
**
kwargs
)
# TODO : check item type
self
.
nodeName
=
'Total'
self
.
__total
=
None
self
.
__samplePos
=
None
self
.
__notifyModel
=
True
self
.
__checkableChildren
=
checkableChildren
def
_loadChildren
(
self
):
iGroup
=
IntensityGroup
(
self
.
h5File
,
self
.
h5Path
)
iItems
=
iGroup
.
getIntensityItems
()
children
=
[]
for
iItem
in
iItems
:
if
iItem
.
entry
==
'Total'
:
continue
iNode
=
IntensityViewItemNode
(
iItem
)
iNode
.
checkable
=
self
.
__checkableChildren
if
iNode
.
checkable
:
iNode
.
setCheckState
(
Qt
.
Qt
.
Checked
)
children
.
append
(
iNode
)
self
.
nodeName
=
'Total {0} / {0}'
.
format
(
len
(
children
))
return
children
def
_childInternalDataChanged
(
self
,
sender
,
*
args
):
super
(
IntensityTotalNode
,
self
).
_childInternalDataChanged
(
sender
,
*
args
)
if
sender
.
parent
()
!=
self
:
return
if
self
.
__notifyModel
:
self
.
__getTotal
()
self
.
sigInternalDataChanged
.
emit
([
0
])
def
__getTotal
(
self
):
total
=
None
samplePos
=
None
nSelected
=
0
childCount
=
self
.
childCount
()
for
childIdx
in
range
(
childCount
):
child
=
self
.
child
(
childIdx
)
if
child
.
checkState
==
Qt
.
Qt
.
Unchecked
:
continue
nSelected
+=
1
intensity
,
pos
=
child
.
item
.
getScatterData
()
if
total
is
None
:
total
=
intensity
samplePos
=
pos
else
:
total
+=
intensity
blocked
=
self
.
blockSignals
(
True
)
self
.
nodeName
=
'Total {0} / {1}'
.
format
(
nSelected
,
childCount
)
self
.
__total
=
total
self
.
__samplePos
=
samplePos
self
.
blockSignals
(
blocked
)
def
scatterData
(
self
):
if
self
.
total
is
None
:
self
.
__getTotal
()
return
self
.
total
,
self
.
samplePos
def
getCheckedEntries
(
self
):
"""
Returns the list of entries, the list of checked entries indices,
and the list of unchecked entries indices.
:return:
"""
selected
=
[]
unselected
=
[]
entries
=
[]
for
childIdx
in
range
(
self
.
childCount
()):
child
=
self
.
child
(
childIdx
)
entries
.
append
(
child
.
item
.
entry
)
if
child
.
checkState
==
Qt
.
Qt
.
Unchecked
:
unselected
.
append
(
childIdx
)
else
:
selected
.
append
(
childIdx
)
return
entries
,
selected
,
unselected
def
checkAll
(
self
):
"""
Check all entries.
:return:
"""
# blocked = self.blockSignals(True)
self
.
__notifyModel
=
False
for
childIdx
in
range
(
self
.
childCount
()):
child
=
self
.
child
(
childIdx
)
child
.
setCheckState
(
Qt
.
Qt
.
Checked
)
# self.blockSignals(blocked)
self
.
__getTotal
()
self
.
__notifyModel
=
True
self
.
_notifyDataChange
()
def
uncheckAll
(
self
):
"""
Uncheck all entries.
:return:
"""
# blocked = self.blockSignals(True)
self
.
__notifyModel
=
False
for
childIdx
in
range
(
self
.
childCount
()):
child
=
self
.
child
(
childIdx
)
child
.
setCheckState
(
Qt
.
Qt
.
Unchecked
)
# self.blockSignals(blocked)
self
.
__getTotal
()
self
.
__notifyModel
=
True
self
.
_notifyDataChange
()
class
IntensityViewItemNode
(
Node
):
checkable
=
True
item
=
property
(
lambda
self
:
self
.
__item
)
def
__init__
(
self
,
iItem
,
**
kwargs
):
super
(
IntensityViewItemNode
,
self
).
__init__
(
**
kwargs
)
# TODO : check item type
self
.
__item
=
iItem
self
.
nodeName
=
str
(
iItem
.
projectRoot
().
shortName
(
iItem
.
entry
))
# self.setCheckState(Qt.Qt.Checked)
self
.
_setDataInternal
(
IntensityModelColumns
.
AngleColumn
,
iItem
.
entry
,
Qt
.
Qt
.
ToolTipRole
)
def
scatterData
(
self
):
return
self
.
item
.
getScatterData
()
class
IntensityModelColumns
(
object
):
AngleColumn
=
0
ColumnNames
=
[
'Angle'
]
class
IntensityRootNode
(
RootNode
):
"""
Root node for the FitModel
"""
ColumnNames
=
IntensityModelColumns
.
ColumnNames
class
IntensityModel
(
Model
):
"""
Model displaying a FitH5 file contents.
"""
RootNode
=
IntensityRootNode
ModelColumns
=
IntensityModelColumns
ColumnsWithDelegates
=
None
def
__iTotalNode
(
self
):
iTotalIndex
=
self
.
index
(
0
,
0
)
return
iTotalIndex
.
data
(
ModelRoles
.
InternalDataRole
)
def
getCheckedEntries
(
self
):
iTotalNode
=
self
.
__iTotalNode
()
if
iTotalNode
is
None
:
return
[]
return
iTotalNode
.
getCheckedEntries
()
def
selectAll
(
self
):
iTotalNode
=
self
.
__iTotalNode
()
if
iTotalNode
is
None
:
return
[]
iTotalNode
.
checkAll
()
def
unselectAll
(
self
):
iTotalNode
=
self
.
__iTotalNode
()
if
iTotalNode
is
None
:
return
[]
iTotalNode
.
uncheckAll
()
class
IntensityTree
(
TreeView
):
sigCurrentChanged
=
Qt
.
Signal
(
object
)
def
__init__
(
self
,
intensityGroupItem
,
checkable
=
True
,
**
kwargs
):
"""
A tree linked to the summed intensity of an acquisition
(IntensityGroup project item).
:param intensityGroupItem:
:param checkable: if True (default) the individual nodes will be
checkable.
:param kwargs:
"""
super
(
IntensityTree
,
self
).
__init__
(
**
kwargs
)
model
=
IntensityModel
()
iGroupNode
=
IntensityTotalNode
(
h5File
=
intensityGroupItem
.
filename
,
h5Path
=
intensityGroupItem
.
path
,
checkableChildren
=
checkable
)
model
.
appendGroup
(
iGroupNode
)
self
.
setModel
(
model
)
self
.
setShowUniqueGroup
(
True
)
self
.
setExpanded
(
self
.
model
().
index
(
0
,
0
),
True
)
model
.
startModel
()
def
currentChanged
(
self
,
current
,
previous
):
super
(
IntensityTree
,
self
).
currentChanged
(
current
,
previous
)
node
=
current
.
data
(
ModelRoles
.
InternalDataRole
)
if
not
node
:
return
self
.
sigCurrentChanged
.
emit
(
node
)
if
__name__
==
'__main__'
:
pass
xsocs/gui/view/intensity/IntensityView.py
View file @
6822878d
...
...
@@ -36,373 +36,17 @@ import numpy as np
from
silx.gui
import
qt
as
Qt
from
.PlotModel
import
PlotTree
from
.IntensityModel
import
IntensityTree
,
IntensityTotalNode
from
.RectRoiWidget
import
RectRoiWidget
from
...model.TreeView
import
TreeView
from
...model.ModelDef
import
ModelRoles
from
...model.Model
import
Model
,
RootNode
,
Node
from
...project.Hdf5Nodes
import
H5GroupNode
from
...project.IntensityGroup
import
IntensityGroup
from
...widgets.Containers
import
GroupBox
from
...widgets.Input
import
StyledLineEdit
from
...widgets.XsocsPlot2D
import
XsocsPlot2D
from
...widgets.Buttons
import
FixedSizePushButon
try
:
from
silx.gui.plot.ImageRois
import
ImageRoiManager
except
ImportError
:
# TODO remove this import once the ROIs are added to the silx release.
from
...silx_imports.ImageRois
import
ImageRoiManager
IntensityViewEvent
=
namedtuple
(
'IntensityViewEvent'
,
[
'roi'
,
'entries'
])
class
RectRoiWidget
(
Qt
.
QWidget
):
sigRoiApplied
=
Qt
.
Signal
(
object
)
def
__init__
(
self
,
roiManager
,
parent
=
None
):
# TODO :
# support multiple ROIs then batch them
super
(
RectRoiWidget
,
self
).
__init__
(
parent
)
self
.
__roiToolBar
=
roiToolBar
=
roiManager
.
toolBar
(
rois
=
[
'rectangle'
],
options
=
[
'show'
])
roiToolBar
.
setMovable
(
False
)
topLayout
=
Qt
.
QVBoxLayout
(
self
)
grpBox
=
GroupBox
(
'ROI'
)
layout
=
Qt
.
QGridLayout
(
grpBox
)
row
=
0
layout
.
addWidget
(
roiToolBar
,
row
,
0
,
1
,
2
,
Qt
.
Qt
.
AlignTop
)
row
+=
1
self
.
_xEdit
=
edit
=
StyledLineEdit
(
nChar
=
6
)
edit
.
setReadOnly
(
True
)
layout
.
addWidget
(
Qt
.
QLabel
(
'x='
),
row
,
0
,
Qt
.
Qt
.
AlignTop
)
layout
.
addWidget
(
edit
,
row
,
1
,
Qt
.
Qt
.
AlignTop
)
row
+=
1
self
.
_yEdit
=
edit
=
StyledLineEdit
(
nChar
=
6
)
edit
.
setReadOnly
(
True
)
layout
.
addWidget
(
Qt
.
QLabel
(
'y='
),
row
,
0
,
Qt
.
Qt
.
AlignTop
)
layout
.
addWidget
(
edit
,
row
,
1
,
Qt
.
Qt
.
AlignTop
)
row
+=
1
self
.
_wEdit
=
edit
=
StyledLineEdit
(
nChar
=
6
)
edit
.
setReadOnly
(
True
)
layout
.
addWidget
(
Qt
.
QLabel
(
'w='
),
row
,
0
,
Qt
.
Qt
.
AlignTop
)
layout
.
addWidget
(
edit
,
row
,
1
,
Qt
.
Qt
.
AlignTop
)
row
+=
1
self
.
_hEdit
=
edit
=
StyledLineEdit
(
nChar
=
6
)
edit
.
setReadOnly
(
True
)
layout
.
addWidget
(
Qt
.
QLabel
(
'h='
),
row
,
0
,
Qt
.
Qt
.
AlignTop
)
layout
.
addWidget
(
edit
,
row
,
1
,
Qt
.
Qt
.
AlignTop
)
row
+=
1
hLayout
=
Qt
.
QHBoxLayout
()
style
=
Qt
.
QApplication
.
style
()
icon
=
style
.
standardIcon
(
Qt
.
QStyle
.
SP_DialogApplyButton
)
self
.
__applyBn
=
applyBn
=
Qt
.
QToolButton
()
applyBn
.
setToolTip
(
'Apply ROI'
)
applyBn
.
setStatusTip
(
'Apply ROI'
)
applyBn
.
setIcon
(
icon
)
applyBn
.
setToolButtonStyle
(
Qt
.
Qt
.
ToolButtonTextBesideIcon
)
applyBn
.
setText
(
'To Q Space'
)
applyBn
.
setEnabled
(
False
)
hLayout
.
addWidget
(
applyBn
)
applyBn
.
clicked
.
connect
(
self
.
__applyRoi
)
icon
=
style
.
standardIcon
(
Qt
.
QStyle
.
SP_DialogCloseButton
)
self
.
__discardBn
=
discardBn
=
Qt
.
QToolButton
()
discardBn
.
setToolTip
(
'Discard ROI'
)
discardBn
.
setStatusTip
(
'Discard ROI'
)
discardBn
.
setIcon
(
icon
)
discardBn
.
setEnabled
(
False
)
hLayout
.
addWidget
(
discardBn
,
Qt
.
Qt
.
AlignRight
)
discardBn
.
clicked
.
connect
(
self
.
__discardRoi
)
layout
.
addLayout
(
hLayout
,
row
,
0
,
1
,
2
,
Qt
.
Qt
.
AlignCenter
)
# topLayout.setSizeConstraint(Qt.QLayout.SetMinimumSize)
topLayout
.
addWidget
(
grpBox
)
topLayout
.
addStretch
(
100
)
# TODO : weakref
self
.
__roiManager
=
roiManager
roiManager
.
sigRoiDrawingFinished
.
connect
(
self
.
__roiDrawingFinished
,
Qt
.
Qt
.
QueuedConnection
)
roiManager
.
sigRoiRemoved
.
connect
(
self
.
__roiRemoved
,
Qt
.
Qt
.
QueuedConnection
)
roiManager
.
sigRoiMoved
.
connect
(
self
.
__roiMoved
,
Qt
.
Qt
.
QueuedConnection
)
def
sizeHint
(
self
):
return
Qt
.
QSize
(
self
.
__roiToolBar
.
sizeHint
().
width
()
+
10
,
0
)
def
__discardRoi
(
self
,
checked
):
self
.
__roiManager
.
clear
()
def
__applyRoi
(
self
,
checked
):
# At the moment we only support one roi at a time.
roi
=
self
.
__roiManager
.
rois
roiItem
=
self
.
__roiManager
.
roiItem
(
roi
[
0
])
xMin
=
roiItem
.
pos
[
0
]
xMax
=
xMin
+
roiItem
.
width
yMin
=
roiItem
.
pos
[
1
]
yMax
=
yMin
+
roiItem
.
height
self
.
sigRoiApplied
.
emit
([
xMin
,
xMax
,
yMin
,
yMax
])
def
__roiDrawingFinished
(
self
,
event
):
self
.
__display
(
event
[
'xdata'
],
event
[
'ydata'
])
self
.
__discardBn
.
setEnabled
(
True
)
self
.
__applyBn
.
setEnabled
(
True
)
def
__clear
(
self
):
self
.
_xEdit
.
clear
()
self
.
_yEdit
.
clear
()
self
.
_wEdit
.
clear
()
self
.
_hEdit
.
clear
()
def
__display
(
self
,
xData
,
yData
):
xMin
,
xMax
=
xData
[
0
],
xData
[
2
]
if
xMax
<
xMin
:
xMin
,
xMax
=
xMax
,
xMin
yMin
,
yMax
=
yData
[
0
],
yData
[
1
]
if
yMax
<
yMin
:
yMin
,
yMax
=
yMax
,
yMin
self
.
_xEdit
.
setText
(
str
(
xMin
))
self
.
_yEdit
.
setText
(
str
(
yMin
))
self
.
_wEdit
.
setText
(
str
(
xMax
-
xMin
))
self
.
_hEdit
.
setText
(
str
(
yMax
-
yMin
))
def
__roiRemoved
(
self
,
name
):
self
.
__clear
()
self
.
__discardBn
.
setEnabled
(
False
)
self
.
__applyBn
.
setEnabled
(
False
)
def
__roiMoved
(
self
,
event
):
self
.
__display
(
event
[
'xdata'
],
event
[
'ydata'
])
class
IntensityTotalNode
(
H5GroupNode
):
"""
Node displaying info about the number of entries selected.
"""
total
=
property
(
lambda
self
:
self
.
__total
)
samplePos
=
property
(
lambda
self
:
self
.
__samplePos
)
icons
=
None
def
__init__
(
self
,
**
kwargs
):
super
(
IntensityTotalNode
,
self
).
__init__
(
**
kwargs
)
# TODO : check item type
self
.
nodeName
=
'Total'
self
.
__total
=
None
self
.
__samplePos
=
None
self
.
__notifyModel
=
True
def
_loadChildren
(
self
):
iGroup
=
IntensityGroup
(
self
.
h5File
,
self
.
h5Path
)
iItems
=
iGroup
.
getIntensityItems
()
children
=
[]
for
iItem
in
iItems
:
if
iItem
.
entry
==
'Total'
:
continue
iNode
=
IntensityViewItemNode
(
iItem
)
children
.
append
(
iNode
)
self
.
nodeName
=
'Total {0} / {0}'
.
format
(
len
(
children
))
return
children
def
_childInternalDataChanged
(
self
,
sender
,
*
args
):
super
(
IntensityTotalNode
,
self
).
_childInternalDataChanged
(
sender
,
*
args
)
if
sender
.
parent
()
!=
self
:
return
if
self
.
__notifyModel
:
self
.
__getTotal
()
self
.
sigInternalDataChanged
.
emit
([
0
])
def
__getTotal
(
self
):
total
=
None
samplePos
=
None
nSelected
=
0
childCount
=
self
.
childCount
()
for
childIdx
in
range
(
childCount
):
child
=
self
.
child
(
childIdx
)
if
child
.
checkState
==
Qt
.
Qt
.
Unchecked
:
continue
nSelected
+=
1
intensity
,
pos
=
child
.
item
.
getScatterData
()
if
total
is
None
:
total
=
intensity
samplePos
=
pos
else
:
total
+=
intensity
blocked
=
self
.
blockSignals
(
True
)
self
.
nodeName
=
'Total {0} / {1}'
.
format
(
nSelected
,
childCount
)
self
.
__total
=
total
self
.
__samplePos
=
samplePos
self
.
blockSignals
(
blocked
)
def
scatterData
(
self
):
if
self
.
total
is
None
:
self
.
__getTotal
()
return
self
.
total
,
self
.
samplePos
def
getSelectedEntries
(
self
):
"""
Returns the list of entries, the list of selected entries indices,
and the list of unselected entries indices.
:return:
"""
selected
=
[]
unselected
=
[]
entries
=
[]
for
childIdx
in
range
(
self
.
childCount
()):
child
=
self
.
child
(
childIdx
)
entries
.
append
(
child
.
item
.
entry
)
if
child
.
checkState
==
Qt
.
Qt
.
Unchecked
:
unselected
.
append
(
childIdx
)
else
:
selected
.
append
(
childIdx
)
return
entries
,
selected
,
unselected
def
selectAll
(
self
):
"""
Selects all entries.
:return:
"""
# blocked = self.blockSignals(True)
self
.
__notifyModel
=
False
for
childIdx
in
range
(
self
.
childCount
()):
child
=
self
.
child
(
childIdx
)
child
.
setCheckState
(
Qt
.
Qt
.
Checked
)
# self.blockSignals(blocked)
self
.
__getTotal
()
self
.
__notifyModel
=
True
self
.
_notifyDataChange
()
def
unselectAll
(
self
):
"""
Unselects all entries.
:return:
"""
# blocked = self.blockSignals(True)
self
.
__notifyModel
=
False
for
childIdx
in
range
(
self
.
childCount
()):
child
=
self
.
child
(
childIdx
)
child
.
setCheckState
(
Qt
.
Qt
.
Unchecked
)
# self.blockSignals(blocked)
self
.
__getTotal
()
self
.
__notifyModel
=
True
self
.
_notifyDataChange
()
class
IntensityViewItemNode
(
Node
):
checkable
=
True
item
=
property
(
lambda
self
:
self
.
__item
)
def
__init__
(
self
,
iItem
,
**
kwargs
):
super
(
IntensityViewItemNode
,
self
).
__init__
(
**
kwargs
)
# TODO : check item type
self
.
__item
=
iItem
self
.
nodeName
=
str
(
iItem
.
projectRoot
().
shortName
(
iItem
.
entry
))
self
.
setCheckState
(
Qt
.
Qt
.
Checked
)
self
.
_setDataInternal
(
IntensityModelColumns
.
AngleColumn
,
iItem
.
entry
,
Qt
.
Qt
.
ToolTipRole
)
def
scatterData
(
self
):
return
self
.
item
.
getScatterData
()
class
IntensityModelColumns
(
object
):