Skip to content

Commit b54267e

Browse files
committed
ENH: Add point_set_sizes trait
1 parent bdc17bc commit b54267e

File tree

2 files changed

+132
-20
lines changed

2 files changed

+132
-20
lines changed

itkwidgets/widget_viewer.py

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,10 @@ class Viewer(ViewerParent):
272272
help="Opacities for the points sets")\
273273
.tag(sync=True, **array_serialization)\
274274
.valid(shape_constraints(None,))
275+
point_set_sizes = NDArray(dtype=np.uint8, default_value=np.zeros((0,), dtype=np.uint8),
276+
help="Sizes for the points sets")\
277+
.tag(sync=True, **array_serialization)\
278+
.valid(shape_constraints(None,))
275279
point_set_representations = List(
276280
trait=Unicode(),
277281
default_value=[],
@@ -332,6 +336,10 @@ def __init__(self, **kwargs): # noqa: C901
332336
proposal = {'value': kwargs['point_set_opacities']}
333337
opacities_array = self._validate_point_set_opacities(proposal)
334338
kwargs['point_set_opacities'] = opacities_array
339+
if 'point_set_sizes' in kwargs:
340+
proposal = {'value': kwargs['point_set_sizes']}
341+
sizes_array = self._validate_point_set_sizes(proposal)
342+
kwargs['point_set_sizes'] = sizes_array
335343
if 'point_set_representations' in kwargs:
336344
proposal = {'value': kwargs['point_set_representations']}
337345
representations_list = self._validate_point_set_representations(
@@ -650,6 +658,21 @@ def _validate_point_set_opacities(self, proposal):
650658
result[:n_values] = value
651659
return result
652660

661+
@validate('point_set_sizes')
662+
def _validate_point_set_sizes(self, proposal):
663+
value = proposal['value']
664+
n_values = 0
665+
if isinstance(value, float):
666+
n_values = 1
667+
else:
668+
n_values = len(value)
669+
n_sizes = n_values
670+
if self.point_sets:
671+
n_sizes = len(self.point_sets)
672+
result = 3 * np.ones((n_sizes,), dtype=np.uint8)
673+
result[:n_values] = value
674+
return result
675+
653676
@validate('point_set_representations')
654677
def _validate_point_set_representations(self, proposal):
655678
value = proposal['value']
@@ -672,6 +695,9 @@ def _on_point_sets_changed(self, change=None):
672695
# Make sure we have a sufficient number of opacities
673696
old_opacities = self.point_set_opacities
674697
self.point_set_opacities = old_opacities[:len(self.point_sets)]
698+
# Make sure we have a sufficient number of sizes
699+
old_sizes = self.point_set_sizes
700+
self.point_set_sizes = old_sizes[:len(self.point_sets)]
675701
# Make sure we have a sufficient number of representations
676702
old_representations = self.point_set_representations
677703
self.point_set_representations = old_representations[:len(
@@ -763,8 +789,8 @@ def view(image=None, # noqa: C901
763789
gradient_opacity=0.22, opacity_gaussians=None, channels=None,
764790
slicing_planes=False, shadow=True, blend_mode='composite',
765791
point_sets=[],
766-
point_set_colors=[], point_set_opacities=[], point_set_representations=[],
767-
# point_set_sizes=[],
792+
point_set_colors=[], point_set_opacities=[],
793+
point_set_representations=[], point_set_sizes=[],
768794
geometries=[],
769795
geometry_colors=[], geometry_opacities=[],
770796
ui_collapsed=False, rotate=False, annotations=True, mode='v',
@@ -907,13 +933,16 @@ def view(image=None, # noqa: C901
907933
point_sets: point set, or sequence of point sets
908934
The point sets to visualize.
909935
910-
point_set_colors: list of RGB colors
911-
Colors for the N geometries. See help(matplotlib.colors) for
936+
point_set_colors: list of (r, g, b) colors
937+
Colors for the N points. See help(matplotlib.colors) for
912938
specification. Defaults to the Glasbey series of categorical colors.
913939
914-
point_set_opacities: list of floats, default: [0.5,]*n
940+
point_set_opacities: array of floats, default: [0.5,]*n
915941
Opacity for the point sets, in the range (0.0, 1.0].
916942
943+
point_set_sizes: array of unsigned integers, default: [3,]*n
944+
Sizes for the point sets, in pixel size units.
945+
917946
point_set_representations: list of strings, default: ['points',]*n
918947
How to represent the point set. One of 'hidden', 'points', or 'spheres'.
919948

js/lib/viewer.js

Lines changed: 98 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,8 @@ const ViewerModel = widgets.DOMWidgetModel.extend(
122122
_rendering_image: false,
123123
interpolation: true,
124124
cmap: null,
125-
_custom_cmap: new Float32Array([0, 0, 0]),
125+
lut: 'glasbey',
126+
_custom_cmap: { array: new Float32Array([0, 0, 0]), shape: [1,3] },
126127
vmin: null,
127128
vmax: null,
128129
shadow: true,
@@ -142,8 +143,9 @@ const ViewerModel = widgets.DOMWidgetModel.extend(
142143
_scale_factors: new Uint8Array([1, 1, 1]),
143144
units: '',
144145
point_sets: null,
145-
point_set_colors: new Float32Array([0, 0, 0]),
146-
point_set_opacities: new Float32Array([1.0]),
146+
point_set_colors: { array: new Float32Array([0, 0, 0]), shape: [1,3] },
147+
point_set_opacities: { array: new Float32Array([1.0]), shape: [1] },
148+
point_set_sizes: { array: new Uint8Array([3]), shape: [1] },
147149
point_set_representations: new Array(),
148150
geometries: null,
149151
geometry_colors: new Float32Array([0, 0, 0]),
@@ -188,6 +190,7 @@ const ViewerModel = widgets.DOMWidgetModel.extend(
188190
camera: fixed_shape_serialization([3, 3]),
189191
point_set_colors: simplearray_serialization,
190192
point_set_opacities: simplearray_serialization,
193+
point_set_sizes: simplearray_serialization,
191194
geometry_colors: simplearray_serialization,
192195
geometry_opacities: simplearray_serialization
193196
},
@@ -447,6 +450,7 @@ function replacePointSets (domWidgetView, pointSets) {
447450
domWidgetView.model.itkVtkViewer.setPointSets(vtkPointSets)
448451
domWidgetView.point_set_colors_changed()
449452
domWidgetView.point_set_opacities_changed()
453+
domWidgetView.point_set_sizes_changed()
450454
domWidgetView.point_set_representations_changed()
451455
domWidgetView.model.itkVtkViewer.renderLater()
452456
}
@@ -838,14 +842,15 @@ const ViewerView = widgets.DOMWidgetView.extend({
838842
this.model.skipOnCroppingPlanesChanged = true
839843
this.model.set(
840844
'roi',
841-
new Float64Array([
842-
bboxCorners[0][0],
843-
bboxCorners[0][1],
844-
bboxCorners[0][2],
845-
bboxCorners[7][0],
846-
bboxCorners[7][1],
847-
bboxCorners[7][2]
848-
])
845+
{ array: new Float64Array([
846+
bboxCorners[0][0],
847+
bboxCorners[0][1],
848+
bboxCorners[0][2],
849+
bboxCorners[7][0],
850+
bboxCorners[7][1],
851+
bboxCorners[7][2]
852+
]),
853+
shape: [2,3] }
849854
)
850855
this.model.save_changes()
851856
} else {
@@ -1068,8 +1073,65 @@ const ViewerView = widgets.DOMWidgetView.extend({
10681073
if (point_sets) {
10691074
this.point_set_colors_changed()
10701075
this.point_set_opacities_changed()
1076+
this.point_set_sizes_changed()
10711077
this.point_set_representations_changed()
10721078
}
1079+
1080+
const onPointSetColorChanged = (index, color) => {
1081+
const modelColors = this.model.get('point_set_colors')
1082+
const modelColor = modelColors.array[index]
1083+
if (color !== modelColor) {
1084+
const newColors = modelColors.array.slice()
1085+
newColors[index] = color
1086+
this.model.set('point_set_colors', { array: newColors, shape: modelColors.shape })
1087+
this.model.save_changes()
1088+
}
1089+
}
1090+
this.model.itkVtkViewer.on('pointSetColorChanged',
1091+
onPointSetColorChanged
1092+
)
1093+
1094+
const onPointSetOpacityChanged = (index, opacity) => {
1095+
const modelOpacities = this.model.get('point_set_opacities')
1096+
const modelOpacity = modelOpacities.array[index]
1097+
if (opacity !== modelOpacity) {
1098+
const newOpacities = modelOpacities.array.slice()
1099+
newOpacities[index] = opacity
1100+
this.model.set('point_set_opacities', { array: newOpacities, shape: modelOpacities.shape })
1101+
this.model.save_changes()
1102+
}
1103+
}
1104+
this.model.itkVtkViewer.on('pointSetOpacityChanged',
1105+
onPointSetOpacityChanged
1106+
)
1107+
1108+
const onPointSetRepresentationChanged = (index, representation) => {
1109+
const modelRepresentations = this.model.get('point_set_representations')
1110+
const modelRepresentation = modelRepresentations[index]
1111+
if (representation !== modelRepresentation) {
1112+
modelRepresentations[index] = representation
1113+
this.model.set('point_set_representations', modelRepresentation)
1114+
this.model.save_changes()
1115+
}
1116+
}
1117+
this.model.itkVtkViewer.on('pointSetRepresentationChanged',
1118+
onPointSetRepresentationChanged
1119+
)
1120+
1121+
const onPointSetSizeChanged = (index, size) => {
1122+
const modelSizes = this.model.get('point_set_sizes')
1123+
const modelSize = modelSizes.array[index]
1124+
if (size !== modelSize) {
1125+
const newSize = modelSizes.array.slice()
1126+
newSize[index] = size
1127+
this.model.set('point_set_sizes', { array: newSize, shape: modelSizes.shape })
1128+
this.model.save_changes()
1129+
}
1130+
}
1131+
this.model.itkVtkViewer.on('pointSetSizeChanged',
1132+
onPointSetSizeChanged
1133+
)
1134+
10731135
const geometries = this.model.get('geometries')
10741136
if (geometries) {
10751137
this.geometry_colors_changed()
@@ -1115,6 +1177,11 @@ const ViewerView = widgets.DOMWidgetView.extend({
11151177
this.point_set_opacities_changed,
11161178
this
11171179
)
1180+
this.model.on(
1181+
'change:point_set_sizes',
1182+
this.point_set_sizes_changed,
1183+
this
1184+
)
11181185
this.model.on(
11191186
'change:point_set_representations',
11201187
this.point_set_representations_changed,
@@ -1308,27 +1375,42 @@ const ViewerView = widgets.DOMWidgetView.extend({
13081375
},
13091376

13101377
point_set_colors_changed: function () {
1311-
const point_setColors = this.model.get('point_set_colors').array
13121378
if (this.model.hasOwnProperty('itkVtkViewer')) {
1379+
const point_set_colors = this.model.get('point_set_colors').array
13131380
const point_sets = this.model.get('point_sets')
13141381
if (point_sets && !!point_sets.length) {
13151382
point_sets.forEach((point_set, index) => {
1316-
const color = point_setColors.slice(index * 3, (index + 1) * 3)
1383+
const color = point_set_colors.slice(index * 3, (index + 1) * 3)
13171384
this.model.itkVtkViewer.setPointSetColor(index, color)
13181385
})
13191386
}
13201387
}
13211388
},
13221389

13231390
point_set_opacities_changed: function () {
1324-
const point_setOpacities = this.model.get('point_set_opacities').array
13251391
if (this.model.hasOwnProperty('itkVtkViewer')) {
1392+
const point_set_opacities = this.model.get('point_set_opacities').array
13261393
const point_sets = this.model.get('point_sets')
13271394
if (point_sets && !!point_sets.length) {
13281395
point_sets.forEach((point_set, index) => {
13291396
this.model.itkVtkViewer.setPointSetOpacity(
13301397
index,
1331-
point_setOpacities[index]
1398+
point_set_opacities[index]
1399+
)
1400+
})
1401+
}
1402+
}
1403+
},
1404+
1405+
point_set_sizes_changed: function () {
1406+
if (this.model.hasOwnProperty('itkVtkViewer')) {
1407+
const point_set_sizes = this.model.get('point_set_sizes').array
1408+
const point_sets = this.model.get('point_sets')
1409+
if (point_sets && !!point_sets.length) {
1410+
point_sets.forEach((point_set, index) => {
1411+
this.model.itkVtkViewer.setPointSetSize(
1412+
index,
1413+
point_set_sizes[index]
13321414
)
13331415
})
13341416
}
@@ -1342,6 +1424,7 @@ const ViewerView = widgets.DOMWidgetView.extend({
13421424
if (this.model.hasOwnProperty('itkVtkViewer')) {
13431425
const point_sets = this.model.get('point_sets')
13441426
if (point_sets && !!point_sets.length) {
1427+
console.log(point_set_representations)
13451428
point_set_representations.forEach((representation, index) => {
13461429
switch (representation.toLowerCase()) {
13471430
case 'hidden':

0 commit comments

Comments
 (0)