diff --git a/CHANGES.rst b/CHANGES.rst
index 676130399a..a6c24df5de 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -12,6 +12,8 @@ Cubeviz
Imviz
^^^^^
+* Orientation plugin API now exposes create_north_up_east_left and create_north_up_east_right methods. [#3308]
+
Mosviz
^^^^^^
diff --git a/jdaviz/configs/imviz/plugins/orientation/orientation.py b/jdaviz/configs/imviz/plugins/orientation/orientation.py
index 13b66c5152..7d32a20519 100644
--- a/jdaviz/configs/imviz/plugins/orientation/orientation.py
+++ b/jdaviz/configs/imviz/plugins/orientation/orientation.py
@@ -52,15 +52,21 @@ class Orientation(PluginTemplateMixin, ViewerSelectMixin):
* :meth:`~jdaviz.core.template_mixin.PluginTemplateMixin.close_in_tray`
* ``align_by`` (`~jdaviz.core.template_mixin.SelectPluginComponent`)
* ``wcs_fast_approximation``
- * ``delete_subsets``
+ * :meth:`delete_subsets`
* ``viewer``
* ``orientation``
* ``rotation_angle``
* ``east_left``
- * ``add_orientation``
+ * :meth:`add_orientation`
+ * :meth:`set_north_up_east_left`
+ * :meth:`set_north_up_east_right`
"""
template_file = __file__, "orientation.vue"
+ # defined as traitlet in addition to global variable above to
+ # allow access from UI - leave fixed
+ base_wcs_layer_label = Unicode(base_wcs_layer_label).tag(sync=True)
+
align_by_items = List().tag(sync=True)
align_by_selected = Unicode().tag(sync=True)
wcs_use_fallback = Bool(True).tag(sync=True)
@@ -146,7 +152,8 @@ def user_api(self):
expose=(
'align_by', 'link_type', 'wcs_fast_approximation', 'wcs_use_affine',
'delete_subsets', 'viewer', 'orientation',
- 'rotation_angle', 'east_left', 'add_orientation'
+ 'rotation_angle', 'east_left', 'add_orientation',
+ 'set_north_up_east_left', 'set_north_up_east_right',
)
)
@@ -283,6 +290,9 @@ def _on_subset_change(self, msg):
self.need_clear_subsets = len(self.app.data_collection.subset_groups) > 0
def delete_subsets(self):
+ """
+ Delete all subsets app-wide. Required before changing ``align_by``.
+ """
# subsets will be deleted on changing link type:
for subset_group in self.app.data_collection.subset_groups:
self.app.data_collection.remove_subset_group(subset_group)
@@ -526,39 +536,59 @@ def _on_viewer_change(self, msg={}):
if ref_data.label in self.orientation.choices:
self.orientation.selected = ref_data.label
- def create_north_up_east_left(self, label="North-up, East-left", set_on_create=False,
- from_ui=False):
- """
- Set the rotation angle and flip to achieve North up and East left
- according to the reference image WCS.
- """
+ def _set_north_up_east_left(self, label="North-up, East-left", set_as_orientation=False,
+ from_ui=False):
if label not in self.orientation.choices:
degn = self._get_wcs_angles()[-3]
self._add_orientation(rotation_angle=degn, east_left=True,
- label=label, set_on_create=set_on_create,
+ label=label, set_on_create=set_as_orientation,
from_ui=from_ui)
- elif set_on_create:
+ elif set_as_orientation:
self.orientation.selected = label
- def create_north_up_east_right(self, label="North-up, East-right", set_on_create=False,
- from_ui=False):
+ def set_north_up_east_left(self, label="North-up, East-left"):
"""
- Set the rotation angle and flip to achieve North up and East right
- according to the reference image WCS.
+ Set (and create if necessary) the rotation angle and flip to achieve North up
+ and East left according to the reference image WCS.
+
+ Parameters
+ ----------
+ label : str
+ Data label for the orientation layer. If already exists, will be set as the
+ current orientation layer according to ``set_as_orientation``. Otherwise,
+ a new layer will be created with this label.
"""
+ self._set_north_up_east_left(label=label, set_as_orientation=True)
+
+ def _set_north_up_east_right(self, label="North-up, East-right", set_as_orientation=False,
+ from_ui=False):
if label not in self.orientation.choices:
degn = self._get_wcs_angles()[-3]
self._add_orientation(rotation_angle=180 - degn, east_left=False,
- label=label, set_on_create=set_on_create,
+ label=label, set_on_create=set_as_orientation,
from_ui=from_ui)
- elif set_on_create:
+ elif set_as_orientation:
self.orientation.selected = label
+ def set_north_up_east_right(self, label="North-up, East-right"):
+ """
+ Set (and create, if necessary) the rotation angle and flip to achieve North up
+ and East right according to the reference image WCS.
+
+ Parameters
+ ----------
+ label : str
+ Data label for the orientation layer. If already exists, will be set as the
+ current orientation layer according to ``set_as_orientation``. Otherwise,
+ a new layer will be created with this label.
+ """
+ self._set_north_up_east_right(label=label, set_as_orientation=True)
+
def vue_select_north_up_east_left(self, *args, **kwargs):
- self.create_north_up_east_left(set_on_create=True, from_ui=True)
+ self._set_north_up_east_left(set_as_orientation=True, from_ui=True)
def vue_select_north_up_east_right(self, *args, **kwargs):
- self.create_north_up_east_right(set_on_create=True, from_ui=True)
+ self._set_north_up_east_right(set_as_orientation=True, from_ui=True)
def vue_select_default_orientation(self, *args, **kwargs):
self.orientation.selected = base_wcs_layer_label
diff --git a/jdaviz/configs/imviz/plugins/orientation/orientation.vue b/jdaviz/configs/imviz/plugins/orientation/orientation.vue
index d272d0d9fb..4cb514d58e 100644
--- a/jdaviz/configs/imviz/plugins/orientation/orientation.vue
+++ b/jdaviz/configs/imviz/plugins/orientation/orientation.vue
@@ -128,18 +128,45 @@
Presets:
-
+
mdi-image-outline
+ {{ api_hints_enabled ?
+ 'plg.orientation = \''+base_wcs_layer_label+'\''
+ :
+ null
+ }}
-
+
+ {{ api_hints_enabled ?
+ 'plg.set_north_up_east_left()'
+ :
+ null
+ }}
-
+
+ {{ api_hints_enabled ?
+ 'plg.set_north_up_east_right()'
+ :
+ null
+ }}
diff --git a/jdaviz/configs/imviz/tests/test_delete_data.py b/jdaviz/configs/imviz/tests/test_delete_data.py
index e5f03ab9a5..11f855c9e6 100644
--- a/jdaviz/configs/imviz/tests/test_delete_data.py
+++ b/jdaviz/configs/imviz/tests/test_delete_data.py
@@ -87,7 +87,7 @@ def test_delete_wcs_layer_with_subset(self):
lc_plugin.align_by = 'WCS'
# Should automatically be applied as reference to first viewer.
- lc_plugin._obj.create_north_up_east_left(set_on_create=True)
+ lc_plugin.set_north_up_east_left()
# Create a rotated ellipse.
reg = EllipsePixelRegion(
diff --git a/jdaviz/configs/imviz/tests/test_footprints.py b/jdaviz/configs/imviz/tests/test_footprints.py
index 29a09d92fe..e5fe4c8f47 100644
--- a/jdaviz/configs/imviz/tests/test_footprints.py
+++ b/jdaviz/configs/imviz/tests/test_footprints.py
@@ -240,8 +240,8 @@ def test_footprint_updates_on_rotation(imviz_helper):
assert np.concatenate([marks[0].y, marks[1].y]).min() < -3
# now rotate to north-up east-left:
- orientation = imviz_helper.plugins['Orientation']._obj
- orientation.create_north_up_east_left(set_on_create=True)
+ orientation = imviz_helper.plugins['Orientation']
+ orientation.set_north_up_east_left()
# If all footprint orientations have been updated, the lowest
# mark should still be centered low. If the footprint
diff --git a/jdaviz/configs/imviz/tests/test_orientation.py b/jdaviz/configs/imviz/tests/test_orientation.py
index 9049840207..6f6e9f6429 100644
--- a/jdaviz/configs/imviz/tests/test_orientation.py
+++ b/jdaviz/configs/imviz/tests/test_orientation.py
@@ -125,14 +125,14 @@ def test_N_up_multi_viewer(self):
lc_plugin.align_by = 'WCS'
# Should automatically be applied as reference to first viewer.
- lc_plugin._obj.create_north_up_east_left(set_on_create=True)
+ lc_plugin.set_north_up_east_left()
# This would set a different reference to second viewer.
viewer_2 = self.imviz.create_image_viewer()
self.imviz.app.add_data_to_viewer("imviz-1", "has_wcs_1[SCI,1]")
lc_plugin.viewer = "imviz-1"
- lc_plugin._obj.create_north_up_east_right(set_on_create=True)
+ lc_plugin.set_north_up_east_right()
assert self.viewer.state.reference_data.label == "North-up, East-left"
assert viewer_2.state.reference_data.label == "North-up, East-right"
@@ -157,8 +157,8 @@ def test_custom_orientation(self):
lc_plugin.viewer = "imviz-0"
lc_plugin.rotation_angle = 42 # Triggers auto-label
- lc_plugin._obj.add_orientation(rotation_angle=None, east_left=True, label=None,
- set_on_create=True, wrt_data=None)
+ lc_plugin.add_orientation(rotation_angle=None, east_left=True, label=None,
+ set_on_create=True, wrt_data=None)
assert self.viewer.state.reference_data.label == "CCW 42.00 deg (E-left)"
@@ -169,7 +169,7 @@ def test_delete_orientation_multi_viewer(self):
lc_plugin.align_by = 'WCS'
# Should automatically be applied as reference to first viewer.
- lc_plugin._obj.create_north_up_east_left(set_on_create=True)
+ lc_plugin.set_north_up_east_left()
# This would set a different reference to second viewer.
viewer_2 = self.imviz.create_image_viewer()
@@ -192,7 +192,7 @@ def test_delete_orientation_with_subset(self, klass, angle, sbst_theta):
lc_plugin.align_by = 'WCS'
# Should automatically be applied as reference to first viewer.
- lc_plugin._obj.create_north_up_east_left(set_on_create=True)
+ lc_plugin.set_north_up_east_left()
# Create rotated shape
reg = klass(center=SkyCoord(ra=337.51931488, dec=-20.83187472, unit="deg"),
@@ -200,7 +200,7 @@ def test_delete_orientation_with_subset(self, klass, angle, sbst_theta):
self.imviz.plugins['Subsets'].import_region(reg)
# Switch to N-up E-right
- lc_plugin._obj.create_north_up_east_right(set_on_create=True)
+ lc_plugin.set_north_up_east_right()
self.imviz.app.vue_data_item_remove({"item_name": "North-up, East-left"})
@@ -234,13 +234,13 @@ def test_create_no_data(self):
lc_plugin.viewer = "imviz-1"
with pytest.raises(ValueError, match="Viewer must have data loaded"):
- lc_plugin._obj.create_north_up_east_left(set_on_create=True)
+ lc_plugin.set_north_up_east_left()
def test_select_no_data(self):
lc_plugin = self.imviz.plugins['Orientation']
lc_plugin.align_by = 'WCS'
- lc_plugin._obj.create_north_up_east_left(set_on_create=True)
+ lc_plugin.set_north_up_east_left()
self.imviz.create_image_viewer()
lc_plugin.viewer = "imviz-1"