From f4d8fa53fbccdc12f599de80b4a3653742a801cf Mon Sep 17 00:00:00 2001 From: MARCHAND MANON Date: Thu, 19 Sep 2024 11:07:08 +0200 Subject: [PATCH] feat: make all aladin-lite init options work --- CHANGELOG.md | 3 ++ docs/conf.py | 5 +- js/widget.js | 16 +++--- src/ipyaladin/widget.py | 114 ++++++++-------------------------------- 4 files changed, 37 insertions(+), 101 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aaf7b364..79a50455 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Upgrade Aladin Lite version to 3.5.1-beta +- instantiation options are now directly mirroring those of Aladin-Lite instead of being + hand-picked for the widget. Any option in + https://cds-astro.github.io/aladin-lite/global.html#AladinOptions will be accepted. ## [0.4.0] diff --git a/docs/conf.py b/docs/conf.py index b76bc28c..93eaa375 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -12,7 +12,7 @@ with Path.open("../pyproject.toml", "rb") as config: toml = tomllib.load(config) import datetime -from ipyaladin import __version__, Aladin +from ipyaladin import __version__ project = toml["project"]["name"] author = "Strasbourg Astronomical Date Centre (CDS)" @@ -90,6 +90,7 @@ # -- Document Init Options --------------------------------------------------- +"""" # commented out since init_options are now given directly to aladin lite init_options = Aladin().traits(only_init=True) with Path.open("user_documentation/init_options.csv", "w"): @@ -98,7 +99,7 @@ with Path.open("user_documentation/init_options.csv", "a") as f: for k, v in init_options.items(): f.write(f"{k};{v.default_value};{v.help}\n") - +""" # -- Options for HTML output ------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output diff --git a/js/widget.js b/js/widget.js index 2cf2b535..92a0a4d2 100644 --- a/js/widget.js +++ b/js/widget.js @@ -5,14 +5,15 @@ import A from "./aladin_lite"; function initAladinLite(model, el) { setDivNumber(divNumber + 1); + let initFromPython = model.get("_init_options"); let initOptions = {}; - model.get("init_options").forEach((option_name) => { - initOptions[snakeCaseToCamelCase(option_name)] = model.get(option_name); - }); + for (const key in initFromPython) { + initOptions[snakeCaseToCamelCase(key)] = initFromPython[key]; + } let aladinDiv = document.createElement("div"); aladinDiv.classList.add("aladin-widget"); - aladinDiv.style.height = `${initOptions["height"]}px`; + aladinDiv.style.height = `${model.get("_height")}px`; aladinDiv.id = `aladin-lite-div-${divNumber}`; let aladin = new A.aladin(aladinDiv, initOptions); @@ -20,16 +21,17 @@ function initAladinLite(model, el) { // Set the target again after the initialization to be sure that the target is set // from icrs coordinates because of the use of gotoObject in the Aladin Lite API - const raDec = initOptions["target"].split(" "); + const raDec = model.get("_target").split(" "); aladin.gotoRaDec(raDec[0], raDec[1]); // Set current FoV and WCS - const twoAxisFoV = aladin.getFov(); + const twoAxisFoV = { ...aladin.getFov() }; model.set("_fov_xy", { x: twoAxisFoV[0], y: twoAxisFoV[1], }); - model.set("_wcs", aladin.getViewWCS()); + const wcs = { ...aladin.getViewWCS() }; + model.set("_wcs", wcs); model.set("_is_loaded", true); model.save_changes(); diff --git a/src/ipyaladin/widget.py b/src/ipyaladin/widget.py index 5a4c342b..a6974e11 100644 --- a/src/ipyaladin/widget.py +++ b/src/ipyaladin/widget.py @@ -53,7 +53,6 @@ Unicode, Bool, Any, - default, ) SupportedRegion = Union[ @@ -131,6 +130,7 @@ class Aladin(anywidget.AnyWidget): _css: Final = pathlib.Path(__file__).parent / "static" / "widget.css" # Options for the view initialization + _init_options = traitlets.Dict().tag(sync=True) _height = Int(400).tag(sync=True, init_option=True) _target = Unicode( "0 0", @@ -153,91 +153,12 @@ class Aladin(anywidget.AnyWidget): ) coo_frame = Unicode( "ICRS", - help="The frame coordinate. Can be either 'ICRS', 'ICRSd', or 'Galactic'.", + help="The frame coordinate. Can be either 'ICRS', 'ICRSd', or 'galactic'.", ).tag(sync=True, init_option=True) projection = Unicode( "SIN", help="The projection for the view. The keywords follow the FITS standard.", ).tag(sync=True, init_option=True) - samp = Bool(False, help="Wether to allow sending data via the SAMP protocol.").tag( - sync=True, init_option=True, only_init=True - ) - # Buttons on/off - background_color = Unicode( - "rgb(60, 60, 60)", help="The color behind the surveys in RGB format." - ).tag(sync=True, init_option=True, only_init=True) - show_zoom_control = Bool( - False, help="Whether to show the zoom control toolbar." - ).tag(sync=True, init_option=True, only_init=True) - show_layers_control = Bool( - True, help="Whether to show the layers control button." - ).tag(sync=True, init_option=True, only_init=True) - show_fullscreen_control = Bool( - True, help="Whether to show the fullscreen control toolbar." - ).tag(sync=True, init_option=True, only_init=True) - show_simbad_pointer_control = Bool( - True, help="Whether to show the Simbad pointer control toolbar." - ).tag(sync=True, init_option=True, only_init=True) - show_settings_control = Bool( - True, help="Whether to show the settings control toolbar." - ).tag(sync=True, init_option=True, only_init=True) - show_share_control = Bool( - False, help="Whether to show the share control toolbar." - ).tag(sync=True, init_option=True, only_init=True) - show_status_bar = Bool(True, help="Whether to show the status bar.").tag( - sync=True, init_option=True, only_init=True - ) - show_frame = Bool(True, help="Whether to show the viewport frame.").tag( - sync=True, init_option=True, only_init=True - ) - show_fov = Bool(True, help="Whether to show the field of view indicator.").tag( - sync=True, init_option=True, only_init=True - ) - show_coo_location = Bool(True, help="Whether to show the coordinates bar.").tag( - sync=True, init_option=True, only_init=True - ) - show_projection_control = Bool( - True, help="Whether to show the coordinate location indicator." - ).tag(sync=True, init_option=True, only_init=True) - show_context_menu = Bool( - True, help="Whether the right click should start the contextual menu." - ).tag(sync=True, init_option=True, only_init=True) - show_catalog = Bool(True, help="Whether to show the catalog.").tag( - sync=True, init_option=True, only_init=True - ) - full_screen = Bool(False, help="Whether to start in full-screen mode.").tag( - sync=True, init_option=True, only_init=True - ) - # reticle - show_reticle = Bool( - True, help="Whether to show the reticle in the middle of the view." - ).tag(sync=True, init_option=True, only_init=True) - reticle_color = Unicode("rgb(178, 50, 178)", help="The color of the reticle.").tag( - sync=True, init_option=True, only_init=True - ) - reticle_size = Int(20, help="Whether to show the reticle in the middle.").tag( - sync=True, init_option=True, only_init=True - ) - # grid - show_coo_grid = Bool( - False, help="Whether the coordinates grid should be shown at startup." - ).tag(sync=True, init_option=True, only_init=True) - show_coo_grid_control = Bool( - True, help="Whether to show the coordinate grid control toolbar." - ).tag(sync=True, init_option=True, only_init=True) - grid_color = Unicode( - "rgb(178, 50, 178)", - help="Color of the grid. Can be specified as a named color " - "(see html named colors), as rgb (ex: 'rgb(178, 50, 178)'), " - "or as a hex color (ex: '#86D6AE').", - ).tag(sync=True, init_option=True, only_init=True) - grid_opacity = Float( - 0.5, help="Opacity of the grid and labels. It is comprised between 0 and 1." - ).tag(sync=True, init_option=True, only_init=True) - grid_options = traitlets.Dict(help="More options for the grid.").tag( - sync=True, init_option=True, only_init=True - ) - # Values _ready = Bool( False, @@ -282,17 +203,26 @@ class Aladin(anywidget.AnyWidget): "is reduced in size when hidden.", ).tag(sync=True) - init_options = traitlets.List(trait=traitlets.Any()).tag(sync=True) - - @default("init_options") - def _init_options(self) -> List[str]: - return list(self.traits(init_option=True)) - - def __init__(self, *args: any, **kwargs: any) -> None: - super().__init__(*args, **kwargs) - self.height = kwargs.get("height", 400) - self.target = kwargs.get("target", "0 0") - self.fov = kwargs.get("fov", 60.0) + def __init__(self, *args: any, **init_options: any) -> None: + super().__init__(*args, **init_options) + # pop init options of ipywidgets.DOMWidget that would choke ipyaladin + # https://github.com/jupyter-widgets/ipywidgets/blob/main/python/ipywidgets/ipywidgets/widgets/domwidget.py + for key in ["layout", "tabbable", "tooltip"]: + init_options.pop(key, None) + # some init options are properties here + self.height = init_options.get("height", self._height) + self.target = init_options.get("target", self._target) + self.fov = init_options.get("fov", self._fov) + # apply different default options from Aladin-Lite + ipyaladin_default = { + "show_simbad_pointer_control": True, + "show_coo_grid_control": True, + "show_settings_control": True, + "show_context_menu": True, + } + init_options = {**ipyaladin_default, **init_options} + # set the traitlet + self._init_options = init_options self.on_msg(self._handle_custom_message) def _handle_custom_message(self, _: any, message: dict, buffers: any) -> None: