From 5b1b906448d232d1e603be9317ca0b859baea288 Mon Sep 17 00:00:00 2001 From: Carifio24 Date: Fri, 28 Jun 2024 15:55:19 -0400 Subject: [PATCH 1/8] Update layer artist to work with ZXY data convention. --- glue_jupyter/common/state3d.py | 2 +- glue_jupyter/ipyvolume/common/viewer.py | 4 ++-- glue_jupyter/ipyvolume/volume/layer_artist.py | 2 ++ 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/glue_jupyter/common/state3d.py b/glue_jupyter/common/state3d.py index aa99321c..74997214 100644 --- a/glue_jupyter/common/state3d.py +++ b/glue_jupyter/common/state3d.py @@ -85,7 +85,7 @@ def aspect(self): # TODO: this could be cached based on the limits, but is not urgent aspect = np.array([1, 1, 1], dtype=float) if self.native_aspect: - aspect[0] = 1. + aspect[0] = 1.0 aspect[1] = (self.z_max - self.z_min) / (self.x_max - self.x_min) aspect[2] = (self.y_max - self.y_min) / (self.x_max - self.x_min) aspect /= aspect.max() diff --git a/glue_jupyter/ipyvolume/common/viewer.py b/glue_jupyter/ipyvolume/common/viewer.py index ef13d59e..21311d35 100644 --- a/glue_jupyter/ipyvolume/common/viewer.py +++ b/glue_jupyter/ipyvolume/common/viewer.py @@ -36,8 +36,8 @@ def __init__(self, *args, **kwargs): def attribute_to_label(attribute): return 'null' if attribute is None else attribute.label - dlink((self.state, 'x_att'), (self.figure, 'xlabel'), attribute_to_label) - dlink((self.state, 'y_att'), (self.figure, 'zlabel'), attribute_to_label) + dlink((self.state, 'x_att'), (self.figure, 'zlabel'), attribute_to_label) + dlink((self.state, 'y_att'), (self.figure, 'xlabel'), attribute_to_label) dlink((self.state, 'z_att'), (self.figure, 'ylabel'), attribute_to_label) self.state.add_callback('x_min', self.limits_to_scales) diff --git a/glue_jupyter/ipyvolume/volume/layer_artist.py b/glue_jupyter/ipyvolume/volume/layer_artist.py index 41943521..1d4b6bc6 100644 --- a/glue_jupyter/ipyvolume/volume/layer_artist.py +++ b/glue_jupyter/ipyvolume/volume/layer_artist.py @@ -106,6 +106,8 @@ def update(self): data *= mask else: data = self.layer[self.state.attribute] + + data = np.transpose(data, (2, 0, 1)) finite_mask = np.isfinite(data) finite_data = data[finite_mask] finite_mask_normalized = finite_data - finite_data.min() From 80a908321839132e626ebaf76ac38f35f4ab7374 Mon Sep 17 00:00:00 2001 From: Carifio24 Date: Tue, 2 Jul 2024 01:08:08 -0400 Subject: [PATCH 2/8] Update figure limits and comment. --- glue_jupyter/ipyvolume/common/viewer.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/glue_jupyter/ipyvolume/common/viewer.py b/glue_jupyter/ipyvolume/common/viewer.py index 21311d35..0fd53154 100644 --- a/glue_jupyter/ipyvolume/common/viewer.py +++ b/glue_jupyter/ipyvolume/common/viewer.py @@ -31,7 +31,7 @@ def __init__(self, *args, **kwargs): # FIXME: hack for the movie maker to have access to the figure self.state.figure = self.figure - # note that for ipyvolume, we use axis in the order x, z, y in order to have + # note that for ipyvolume, we use axis in the order z, x, y in order to have # the z axis of glue pointing up def attribute_to_label(attribute): return 'null' if attribute is None else attribute.label @@ -87,9 +87,9 @@ def apply_roi(self, roi, use_current=False): def limits_to_scales(self, *args): if self.state.x_min is not None and self.state.x_max is not None: - self.figure.xlim = self.state.x_min, self.state.x_max + self.figure.xlim = self.state.y_min, self.state.y_max if self.state.y_min is not None and self.state.y_max is not None: - self.figure.zlim = self.state.y_min, self.state.y_max + self.figure.zlim = self.state.x_min, self.state.x_max # if self.state.z_min is not None and self.state.z_max is not None: # self.figure.zlim = self.state.z_min, self.state.z_max if hasattr(self.state, 'z_min'): From 276e2b363e1c03ba609432c694231773e4e6642a Mon Sep 17 00:00:00 2001 From: Jon Carifio Date: Tue, 2 Jul 2024 02:24:18 -0400 Subject: [PATCH 3/8] Update scatter labels test --- glue_jupyter/ipyvolume/scatter/tests/test_viewer.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/glue_jupyter/ipyvolume/scatter/tests/test_viewer.py b/glue_jupyter/ipyvolume/scatter/tests/test_viewer.py index cb629a55..e98e3058 100644 --- a/glue_jupyter/ipyvolume/scatter/tests/test_viewer.py +++ b/glue_jupyter/ipyvolume/scatter/tests/test_viewer.py @@ -39,15 +39,15 @@ def test_labels(app, dataxyz): app.add_data(dataxyz) scatter = app.scatter3d(data=dataxyz) assert str(scatter.state.x_att) == 'x' - assert scatter.figure.xlabel == 'x' + assert scatter.figure.zlabel == 'x' assert str(scatter.state.y_att) == 'y' - assert scatter.figure.zlabel == 'y' + assert scatter.figure.xlabel == 'y' assert str(scatter.state.z_att) == 'z' assert scatter.figure.ylabel == 'z' scatter.state.x_att = dataxyz.id['y'] - assert scatter.figure.xlabel == 'y' + assert scatter.figure.zlabel == 'y' scatter.state.y_att = dataxyz.id['z'] - assert scatter.figure.zlabel == 'z' + assert scatter.figure.xlabel == 'z' scatter.state.z_att = dataxyz.id['x'] assert scatter.figure.ylabel == 'x' From de0c6ef55fce46de6644f5271ee42b8afee0a54e Mon Sep 17 00:00:00 2001 From: Carifio24 Date: Thu, 25 Jul 2024 15:36:06 -0400 Subject: [PATCH 4/8] Update limit attribute checks. --- glue_jupyter/ipyvolume/common/viewer.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/glue_jupyter/ipyvolume/common/viewer.py b/glue_jupyter/ipyvolume/common/viewer.py index 0fd53154..7bee2b89 100644 --- a/glue_jupyter/ipyvolume/common/viewer.py +++ b/glue_jupyter/ipyvolume/common/viewer.py @@ -86,12 +86,10 @@ def apply_roi(self, roi, use_current=False): self._session.command_stack.do(cmd) def limits_to_scales(self, *args): - if self.state.x_min is not None and self.state.x_max is not None: - self.figure.xlim = self.state.y_min, self.state.y_max if self.state.y_min is not None and self.state.y_max is not None: + self.figure.xlim = self.state.y_min, self.state.y_max + if self.state.x_min is not None and self.state.x_max is not None: self.figure.zlim = self.state.x_min, self.state.x_max - # if self.state.z_min is not None and self.state.z_max is not None: - # self.figure.zlim = self.state.z_min, self.state.z_max if hasattr(self.state, 'z_min'): if self.state.z_min is not None and self.state.z_max is not None: self.figure.ylim = self.state.z_min, self.state.z_max From 2d81936c499a4a5632c1a67bc1174064cb1bb988 Mon Sep 17 00:00:00 2001 From: Carifio24 Date: Thu, 25 Jul 2024 15:36:21 -0400 Subject: [PATCH 5/8] Apply similar coordinate changes to scatter viewer. --- glue_jupyter/ipyvolume/scatter/layer_artist.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/glue_jupyter/ipyvolume/scatter/layer_artist.py b/glue_jupyter/ipyvolume/scatter/layer_artist.py index 2ca97f4b..5458364b 100755 --- a/glue_jupyter/ipyvolume/scatter/layer_artist.py +++ b/glue_jupyter/ipyvolume/scatter/layer_artist.py @@ -95,9 +95,9 @@ def redraw(self): def update(self): # we don't use layer, but layer.data to get everything - self.scatter.x = ensure_numerical(self.layer.data[self._viewer_state.x_att]).ravel() - self.scatter.z = ensure_numerical(self.layer.data[self._viewer_state.y_att]).ravel() + self.scatter.z = ensure_numerical(self.layer.data[self._viewer_state.x_att]).ravel() self.scatter.y = ensure_numerical(self.layer.data[self._viewer_state.z_att]).ravel() + self.scatter.x = ensure_numerical(self.layer.data[self._viewer_state.y_att]).ravel() self.quiver.x = self.scatter.x self.quiver.z = self.scatter.y self.quiver.y = self.scatter.z @@ -123,9 +123,9 @@ def _clear_selection(self): def _update_quiver(self): with self.quiver.hold_sync(): - self.quiver.vx = self.layer.data[self.state.vx_att].ravel() - self.quiver.vz = self.layer.data[self.state.vy_att].ravel() + self.quiver.vz = self.layer.data[self.state.vx_att].ravel() self.quiver.vy = self.layer.data[self.state.vz_att].ravel() + self.quiver.vx = self.layer.data[self.state.vy_att].ravel() def _update_size(self): size = self.state.size From 9b9fe631fa56164d9c0b5c5addc5030c8c4f43ec Mon Sep 17 00:00:00 2001 From: Carifio24 Date: Thu, 25 Jul 2024 15:50:19 -0400 Subject: [PATCH 6/8] Update scatter tests to match axis updates. --- glue_jupyter/ipyvolume/tests/test_ipyvolume.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/glue_jupyter/ipyvolume/tests/test_ipyvolume.py b/glue_jupyter/ipyvolume/tests/test_ipyvolume.py index d9601e59..d8a4b996 100644 --- a/glue_jupyter/ipyvolume/tests/test_ipyvolume.py +++ b/glue_jupyter/ipyvolume/tests/test_ipyvolume.py @@ -36,16 +36,16 @@ def test_scatter3d(app, dataxyz, dataxz): assert s.layers[1].layer['y'].tolist() == [4] assert s.layers[1].layer['z'].tolist() == [7] - assert s.layers[1].scatter.x.tolist() == [1, 2, 3] - assert s.layers[1].scatter.z.tolist() == [2, 3, 4] + assert s.layers[1].scatter.z.tolist() == [1, 2, 3] + assert s.layers[1].scatter.x.tolist() == [2, 3, 4] assert s.layers[1].scatter.y.tolist() == [5, 6, 7] assert s.layers[1].scatter.selected == [2] s.state.x_att = dataxyz.id['y'] s.state.y_att = dataxyz.id['z'] s.state.z_att = dataxyz.id['x'] - assert s.layers[1].scatter.x.tolist() == [2, 3, 4] - assert s.layers[1].scatter.z.tolist() == [5, 6, 7] + assert s.layers[1].scatter.z.tolist() == [2, 3, 4] + assert s.layers[1].scatter.x.tolist() == [5, 6, 7] assert s.layers[1].scatter.y.tolist() == [1, 2, 3] assert s.layers[1].scatter.selected == [2] From cc06fd36003cda5be7b5d2280ca7ba9e0cf00b84 Mon Sep 17 00:00:00 2001 From: Carifio24 Date: Thu, 1 Aug 2024 13:12:01 -0400 Subject: [PATCH 7/8] Cast scatter data to floats if necessary. --- glue_jupyter/ipyvolume/scatter/layer_artist.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/glue_jupyter/ipyvolume/scatter/layer_artist.py b/glue_jupyter/ipyvolume/scatter/layer_artist.py index 5458364b..4796ad60 100755 --- a/glue_jupyter/ipyvolume/scatter/layer_artist.py +++ b/glue_jupyter/ipyvolume/scatter/layer_artist.py @@ -90,14 +90,22 @@ def _update_color(self, ignore=None): def _update_xyz_att(self, *args): self.update() + def _cast_to_float(self, arr): + if np.issubdtype(arr.dtype, np.floating): + return arr + + # `itemsize` returns the byte size of the dtype + size = 8 * arr.dtype.itemsize + return arr.astype(f"float{size}") + def redraw(self): pass def update(self): # we don't use layer, but layer.data to get everything - self.scatter.z = ensure_numerical(self.layer.data[self._viewer_state.x_att]).ravel() - self.scatter.y = ensure_numerical(self.layer.data[self._viewer_state.z_att]).ravel() - self.scatter.x = ensure_numerical(self.layer.data[self._viewer_state.y_att]).ravel() + self.scatter.z = self._cast_to_float(ensure_numerical(self.layer.data[self._viewer_state.x_att]).ravel()) + self.scatter.y = self._cast_to_float(ensure_numerical(self.layer.data[self._viewer_state.z_att]).ravel()) + self.scatter.x = self._cast_to_float(ensure_numerical(self.layer.data[self._viewer_state.y_att]).ravel()) self.quiver.x = self.scatter.x self.quiver.z = self.scatter.y self.quiver.y = self.scatter.z From d479fe95c9b7a48d2bae409fc23d87f1af427efc Mon Sep 17 00:00:00 2001 From: Carifio24 Date: Thu, 1 Aug 2024 13:47:08 -0400 Subject: [PATCH 8/8] Codestyle fixes. --- glue_jupyter/ipyvolume/scatter/layer_artist.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/glue_jupyter/ipyvolume/scatter/layer_artist.py b/glue_jupyter/ipyvolume/scatter/layer_artist.py index 4796ad60..0a49b2db 100755 --- a/glue_jupyter/ipyvolume/scatter/layer_artist.py +++ b/glue_jupyter/ipyvolume/scatter/layer_artist.py @@ -94,7 +94,7 @@ def _cast_to_float(self, arr): if np.issubdtype(arr.dtype, np.floating): return arr - # `itemsize` returns the byte size of the dtype + # `itemsize` returns the byte size of the dtype size = 8 * arr.dtype.itemsize return arr.astype(f"float{size}") @@ -103,9 +103,12 @@ def redraw(self): def update(self): # we don't use layer, but layer.data to get everything - self.scatter.z = self._cast_to_float(ensure_numerical(self.layer.data[self._viewer_state.x_att]).ravel()) - self.scatter.y = self._cast_to_float(ensure_numerical(self.layer.data[self._viewer_state.z_att]).ravel()) - self.scatter.x = self._cast_to_float(ensure_numerical(self.layer.data[self._viewer_state.y_att]).ravel()) + self.scatter.z = self._cast_to_float( + ensure_numerical(self.layer.data[self._viewer_state.x_att]).ravel()) + self.scatter.y = self._cast_to_float( + ensure_numerical(self.layer.data[self._viewer_state.z_att]).ravel()) + self.scatter.x = self._cast_to_float( + ensure_numerical(self.layer.data[self._viewer_state.y_att]).ravel()) self.quiver.x = self.scatter.x self.quiver.z = self.scatter.y self.quiver.y = self.scatter.z