Skip to content

Commit

Permalink
✨ Implement add_hips, remove_layer and set_layer_opacity
Browse files Browse the repository at this point in the history
  • Loading branch information
Xen0Xys committed Aug 6, 2024
1 parent cb34db4 commit 1591c71
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 27 deletions.
75 changes: 64 additions & 11 deletions js/models/event_handler.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,10 +129,68 @@ export default class EventHandler {
this.aladin.setFoV(fov);
});

/* Survey control */
const jsSurveyLock = new Lock();
const pySurveyLock = new Lock();

this.model.on("change:survey", () => {
if (jsSurveyLock.locked) {
jsSurveyLock.unlock();
return;
}
pySurveyLock.lock();
this.aladin.setImageSurvey(this.model.get("survey"));
});

/* Overlay survey control */
const jsOverlaySurveyLock = new Lock();
const pyOverlaySurveyLock = new Lock();

this.model.on("change:overlay_survey", () => {
if (jsOverlaySurveyLock.locked) {
jsOverlaySurveyLock.unlock();
return;
}
pyOverlaySurveyLock.lock();
this.aladin.setOverlayImageLayer(this.model.get("overlay_survey"));
});

this.aladin.on("layerChanged", (imageLayer, layerName, state) => {
if (layerName !== "base" || state !== "ADDED") return;
this.updateWCS();
this.model.set("_base_layer_last_view", imageLayer.id);
// If the layer is added or removed, update the layers traitlets
if (state === "ADDED") {
let layers = this.model.get("layers") || {};
// If the object is not copied, the model will not detect the change
layers = { ...layers };
if (imageLayer.url.startsWith("blob:"))
layers[layerName] = imageLayer.name;
else layers[layerName] = imageLayer.url;
this.model.set("layers", layers);

// If the layer is added, update the WCS, FoV, survey and overlay survey
if (layerName === "base") {
this.updateWCS();
this.model.set("_base_layer_last_view", imageLayer.url);
if (pySurveyLock.locked) {
pySurveyLock.unlock();
return;
}
jsSurveyLock.lock();
this.model.set("survey", imageLayer.url);
} else if (layerName === "overlay") {
if (pyOverlaySurveyLock.locked) {
pyOverlaySurveyLock.unlock();
return;
}
jsOverlaySurveyLock.lock();
this.model.set("overlay_survey", imageLayer.url);
}
} else if (state === "REMOVED") {
let layers = this.model.get("layers") || {};
// If the object is not copied, the model will not detect the change
layers = { ...layers };
delete layers[layerName];
this.model.set("layers", layers);
}
this.model.save_changes();
});

Expand Down Expand Up @@ -244,14 +302,6 @@ export default class EventHandler {
this.aladin.setFrame(this.model.get("coo_frame"));
});

this.model.on("change:survey", () => {
this.aladin.setImageSurvey(this.model.get("survey"));
});

this.model.on("change:overlay_survey", () => {
this.aladin.setOverlayImageLayer(this.model.get("overlay_survey"));
});

this.model.on("change:overlay_survey_opacity", () => {
this.aladin
.getOverlayImageLayer()
Expand All @@ -262,6 +312,9 @@ export default class EventHandler {
change_fov: this.messageHandler.handleChangeFoV,
goto_ra_dec: this.messageHandler.handleGotoRaDec,
save_view_as_image: this.messageHandler.handleSaveViewAsImage,
add_hips: this.messageHandler.handleAddHips,
remove_layer: this.messageHandler.handleRemoveLayer,
set_layer_opacity: this.messageHandler.handleSetLayerOpacity,
add_fits: this.messageHandler.handleAddFits,
add_catalog_from_URL: this.messageHandler.handleAddCatalogFromURL,
add_MOC_from_URL: this.messageHandler.handleAddMOCFromURL,
Expand Down
24 changes: 24 additions & 0 deletions js/models/message_handler.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,30 @@ export default class MessageHandler {
);
}

handleAddHips(msg) {
const options = convertOptionNamesToCamelCase(msg["options"] || {});
if (!options.name)
options.name = `hips_${String(++imageCount).padStart(3, "0")}`;
const hipsIdOrUrl = msg["hips"];
const imageHips = A.imageHiPS(hipsIdOrUrl, options);
this.aladin.setOverlayImageLayer(imageHips, options.name);
}

handleRemoveLayer(msg) {
const layerName = msg["name"];
this.aladin.removeImageLayer(layerName);
}

handleSetLayerOpacity(msg) {
const layerName = msg["name"];
const opacity = msg["opacity"];
if (layerName === "overlay") {
this.model.set("overlay_survey_opacity", opacity);
this.model.save_changes();
}
this.aladin.getOverlayImageLayer(layerName).setAlpha(opacity);
}

handleAddFits(msg, buffers) {
const options = convertOptionNamesToCamelCase(msg["options"] || {});
if (!options.name)
Expand Down
46 changes: 30 additions & 16 deletions src/ipyaladin/widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,12 @@ class Aladin(anywidget.AnyWidget):
# listener callback is on the python side and contains functions to link to events
listener_callback: ClassVar[Dict[str, callable]] = {}

# overlay survey
# Surveys management
layers = traitlets.Dict(
{},
help="A dictionary of surveys to add to the widget. The keys are the names of "
"the surveys and the values are the URLs of the surveys.",
).tag(sync=True)
overlay_survey = Unicode("").tag(sync=True, init_option=True)
overlay_survey_opacity = Float(0.0).tag(sync=True, init_option=True)
_base_layer_last_view = Unicode(
Expand Down Expand Up @@ -389,16 +394,15 @@ def target(self, target: Union[str, SkyCoord]) -> None:
}
)

def add_hips(self, hips: str, layer_name: str, **hips_options: any) -> None:
def add_hips(self, hips: str, **options: any) -> None:
"""Add a HiPS to the Aladin Lite widget.
Parameters
----------
hips : str
The HiPS to add to the widget.
layer_name : str
The name of the layer.
hips_options : keyword arguments
The HiPS to add to the widget as a URL or a CDS id
<https://aladin.cds.unistra.fr/hips/list>`_
options : keyword arguments
The options for the HiPS. See `Aladin Lite's HiPS options
<https://cds-astro.github.io/aladin-lite/global.html#HiPSOptions>`_
Expand All @@ -407,35 +411,40 @@ def add_hips(self, hips: str, layer_name: str, **hips_options: any) -> None:
{
"event_name": "add_hips",
"hips": hips,
"layer_name": layer_name,
"options": hips_options,
"options": options,
}
)

def remove_layer(self, layer_name: str) -> None:
def remove_layer(self, name: str) -> None:
"""Remove a layer from the Aladin Lite widget.
Parameters
----------
layer_name : str
name : str
The name of the layer to remove.
"""
self.send({"event_name": "remove_layer", "layer_name": layer_name})
if name == "base":
raise ValueError("The base layer cannot be removed.")
self.send({"event_name": "remove_layer", "name": name})

def set_opacity(self, layer_name: str, opacity: float) -> None:
def set_layer_opacity(self, name: str, opacity: float) -> None:
"""Set the opacity of a layer in the Aladin Lite widget.
Parameters
----------
layer_name : str
name : str
The name of the layer to set the opacity.
opacity : float
The opacity value to set.
"""
self.send(
{"event_name": "set_opacity", "layer_name": layer_name, "opacity": opacity}
{
"event_name": "set_layer_opacity",
"name": name,
"opacity": opacity,
}
)

def _save_file(self, path: str, buffer: bytes) -> None:
Expand Down Expand Up @@ -577,8 +586,13 @@ def add_fits(self, fits: Union[str, Path, HDUList], **image_options: any) -> Non

self._wcs = {}
self.send(
{"event_name": "add_fits", "options": image_options},
buffers=[fits_bytes.getvalue()],
{
"event_name": "add_fits",
"options": image_options,
},
buffers=[
fits_bytes.getvalue(),
],
)

# MOCs
Expand Down

0 comments on commit 1591c71

Please sign in to comment.