Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions js/models/event_handler.js
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,8 @@ export default class EventHandler {
add_MOC_from_URL: this.messageHandler.handleAddMOCFromURL,
add_MOC_from_dict: this.messageHandler.handleAddMOCFromDict,
add_overlay: this.messageHandler.handleAddOverlay,
remove_overlay: this.messageHandler.handleRemoveOverlay,
get_overlays: this.messageHandler.handleGetOverlays,
change_colormap: this.messageHandler.handleChangeColormap,
get_JPG_thumbnail: this.messageHandler.handleGetJPGThumbnail,
trigger_selection: this.messageHandler.handleTriggerSelection,
Expand Down
25 changes: 25 additions & 0 deletions js/models/message_handler.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,31 @@ export default class MessageHandler {
}
}

handleRemoveOverlay = (msg) => {
const overlay_names = msg["overlay_names"];
for (const overlay_name of overlay_names) {
console.info(`Sending removeOverlay for ${overlay_name}`);
this.aladin.removeOverlay(overlay_name);
}
this.handleGetOverlays();
};

handleGetOverlays = () => {
const overlay_names = [];
const overlays = this.aladin.getOverlays();
for (const overlay of overlays) {
const overlay_name = overlay["name"];
overlay_names.push(overlay_name);
}
console.info(`Current overlays are ${overlay_names}`);
this.model.send({
event_type: "current_overlays",
content: {
overlays: overlay_names,
},
});
};

handleChangeColormap(msg) {
this.aladin.getBaseImageLayer().setColormap(msg["colormap"]);
}
Expand Down
56 changes: 54 additions & 2 deletions src/ipyaladin/widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,11 @@ class Aladin(anywidget.AnyWidget):
).tag(sync=True)
_wcs = traitlets.Dict().tag(sync=True)
_fov_xy = traitlets.Dict().tag(sync=True)
# Overlays
_overlays = traitlets.List(
[],
help="A list of overlays on the widget.",
).tag(sync=True)

# content of the last click
clicked_object = traitlets.Dict().tag(sync=True)
Expand Down Expand Up @@ -259,6 +264,9 @@ def _handle_custom_message(self, _: any, message: dict, buffers: any) -> None:
self.listener_callback["select"](message["content"])
elif event_type == "save_view_as_image":
self._save_file(message["path"], buffers[0])
elif event_type == "current_overlays":
self._overlays = message["content"]["overlays"]
self.listener_callback["current_overlays"](message["content"])

@property
def selected_objects(self) -> List[Table]:
Expand All @@ -276,6 +284,17 @@ def selected_objects(self) -> List[Table]:
catalogs.append(Table(objects_data))
return catalogs

@property
def overlays(self) -> List:
"""The list of overlays on the widget.

Returns
-------
list
A list of strings representing the widget overlays.
"""
return self._overlays

@property
def height(self) -> int:
"""The height of the widget.
Expand Down Expand Up @@ -992,6 +1011,35 @@ def add_graphic_overlay_from_stcs(
}
)

@widget_should_be_loaded
def remove_overlay(self, overlay_name: Union[Iterable[str], str]) -> None:
"""Remove an overlay layer defined by a string.

Parameters
----------
overlay_name : str, Iterable[str]
The string or an iterable of strings.
"""
overlay_names = (
[overlay_name] if isinstance(overlay_name, str) else overlay_name
)

self.send(
{
"event_name": "remove_overlay",
"overlay_names": overlay_names,
}
)

@widget_should_be_loaded
def get_overlays(self) -> List:
"""Update the current overlays defined by their names."""
self.send(
{
"event_name": "get_overlays",
}
)

@widget_should_be_loaded
def set_color_map(self, color_map_name: str) -> None:
"""Change the color map of the Aladin Lite widget.
Expand Down Expand Up @@ -1043,7 +1091,8 @@ def set_listener(self, listener_type: str, callback: Callable) -> None:
Parameters
----------
listener_type : str
Can either be 'object_hovered', 'object_clicked', 'click' or 'select'
Can either be 'object_hovered', 'object_clicked', 'click', 'select',
or 'current_overlays'
callback : Callable
A python function to be called when the event corresponding to the
listener_type is detected
Expand All @@ -1057,10 +1106,13 @@ def set_listener(self, listener_type: str, callback: Callable) -> None:
self.listener_callback["click"] = callback
elif listener_type == "select":
self.listener_callback["select"] = callback
elif listener_type == "current_overlays":
self.listener_callback["current_overlays"] = callback
else:
raise ValueError(
"listener_type must be 'object_hovered', "
"'object_clicked', 'click' or 'select'"
"'object_clicked', 'click', 'select', "
"or 'current_overlays'"
)

@widget_should_be_loaded
Expand Down
48 changes: 48 additions & 0 deletions src/tests/test_aladin.py
Original file line number Diff line number Diff line change
Expand Up @@ -322,3 +322,51 @@ def test_add_table(monkeypatch: Callable) -> None:
"conversion_maj_axis": 1,
}
assert table_sent_message["options"]["ellipse_error"] == ellipse_options


test_overlay_names = [
"overlay",
["overlay", "overlay_1", "2MASS"],
"catalog",
["overlay_1", "2MASS"],
]


@pytest.mark.parametrize("overlay_names", test_overlay_names)
def test_remove_overlay(
monkeypatch: Callable,
overlay_names: Union[Iterable[str], str],
) -> None:
"""Test proper messages sent for removing overlays using their name string(s).

Parameters
----------
overlay_names : Union[Iterable[str], str]
The name strings of overlays.
"""
mock_send = Mock()
monkeypatch.setattr(Aladin, "send", mock_send)
aladin.remove_overlay(overlay_names)

event_name = mock_send.call_args[0][0]["event_name"]
assert isinstance(event_name, str)
assert event_name == "remove_overlay"

name_info = mock_send.call_args[0][0]["overlay_names"]
assert isinstance(name_info, list)
assert name_info[0] in overlay_names

if isinstance(overlay_names, list):
assert name_info == overlay_names


def test_get_overlays(
monkeypatch: Callable,
) -> None:
"""Test proper message sent for getting current overlays."""
mock_send = Mock()
monkeypatch.setattr(Aladin, "send", mock_send)
aladin.get_overlays()
event_name = mock_send.call_args[0][0]["event_name"]
assert isinstance(event_name, str)
assert event_name == "get_overlays"