From ba2f9fdb38ef6102e190442c4b8a60700e041a8f Mon Sep 17 00:00:00 2001 From: Xen0Xys Date: Fri, 24 May 2024 15:21:57 +0200 Subject: [PATCH 1/5] :twisted_rightwards_arrows: Fix merge conflicts --- js/models/event_handler.js | 3 ++- js/models/message_handler.js | 10 +++++++++- src/ipyaladin/aladin.py | 38 ++++++++++++++++++++++++++++++++++-- 3 files changed, 47 insertions(+), 4 deletions(-) diff --git a/js/models/event_handler.js b/js/models/event_handler.js index 1bdb163c..7f6c15f7 100644 --- a/js/models/event_handler.js +++ b/js/models/event_handler.js @@ -12,7 +12,7 @@ export default class EventHandler { this.aladin = aladin; this.aladinDiv = aladinDiv; this.model = model; - this.messageHandler = new MessageHandler(aladin); + this.messageHandler = new MessageHandler(aladin, model); } /** @@ -171,6 +171,7 @@ export default class EventHandler { this.eventHandlers = { change_fov: this.messageHandler.handleChangeFoV, goto_ra_dec: this.messageHandler.handleGotoRaDec, + synchronize_wcs: this.messageHandler.handleSynchronizeWCS, add_catalog_from_URL: this.messageHandler.handleAddCatalogFromURL, add_MOC_from_URL: this.messageHandler.handleAddMOCFromURL, add_MOC_from_dict: this.messageHandler.handleAddMOCFromDict, diff --git a/js/models/message_handler.js b/js/models/message_handler.js index e4b54b55..47208c2b 100644 --- a/js/models/message_handler.js +++ b/js/models/message_handler.js @@ -2,8 +2,9 @@ import { convertOptionNamesToCamelCase } from "../utils"; import A from "../aladin_lite"; export default class MessageHandler { - constructor(aladin) { + constructor(aladin, model) { this.aladin = aladin; + this.model = model; } handleChangeFoV(msg) { @@ -14,6 +15,13 @@ export default class MessageHandler { this.aladin.gotoRaDec(msg["ra"], msg["dec"]); } + handleSynchronizeWCS() { + const wcs = this.aladin.getViewWCS(); + console.log(wcs); + this.model.set("_wcs", wcs); + this.model.save_changes(); + } + handleAddCatalogFromURL(msg) { const options = convertOptionNamesToCamelCase(msg["options"] || {}); this.aladin.addCatalog(A.catalogFromURL(msg["votable_URL"], options)); diff --git a/src/ipyaladin/aladin.py b/src/ipyaladin/aladin.py index 17beb478..c93de0bd 100644 --- a/src/ipyaladin/aladin.py +++ b/src/ipyaladin/aladin.py @@ -11,10 +11,10 @@ import warnings import anywidget +from astropy.coordinates import SkyCoord, Angle from astropy.table.table import QTable from astropy.table import Table -from astropy.coordinates import SkyCoord, Angle -import traitlets +from astropy.wcs import WCS try: from regions import ( @@ -34,6 +34,7 @@ RectangleSkyRegion = None Region = None Regions = None +import traitlets from traitlets import ( Float, Int, @@ -122,6 +123,9 @@ class Aladin(anywidget.AnyWidget): grid_opacity = Float(0.5).tag(sync=True, init_option=True) grid_options = traitlets.Dict().tag(sync=True, init_option=True) + # Synchronized traitlets + _wcs = traitlets.Dict().tag(sync=True) + # content of the last click clicked_object = traitlets.Dict().tag(sync=True) # listener callback is on the python side and contains functions to link to events @@ -220,6 +224,36 @@ def target(self, target: Union[str, SkyCoord]) -> None: } ) + @property + def wcs(self) -> WCS: + """The WCS of the Aladin Lite widget. + + Returns + ------- + WCS + An `~astropy.wcs.WCS` object representing the WCS of the widget. + + """ + if self._wcs == {}: + raise ValueError( + "You need to call synchronize_wcs first and in " + "another Jupyter cell to get the WCS." + ) + wcs = WCS(naxis=self._wcs["NAXIS"]) + wcs.wcs.cdelt = [self._wcs["CDELT1"], self._wcs["CDELT2"]] + wcs.wcs.crpix = [self._wcs["CRPIX1"], self._wcs["CRPIX2"]] + wcs.wcs.crval = [self._wcs["CRVAL1"], self._wcs["CRVAL2"]] + wcs.wcs.ctype = [self._wcs["CTYPE1"], self._wcs["CTYPE2"]] + wcs.wcs.cunit = [self._wcs["CUNIT1"].strip(), self._wcs["CUNIT2"].strip()] + wcs.wcs.radesys = self._wcs["RADECSYS"].strip() + wcs.array_shape = (self._wcs["NAXIS2"], self._wcs["NAXIS1"]) + return wcs + + def synchronize_wcs(self) -> None: + """Synchronize the WCS of the Aladin Lite widget with the given WCS.""" + self._wcs = {} + self.send({"event_name": "synchronize_wcs"}) + def add_catalog_from_URL( self, votable_URL: str, votable_options: Optional[dict] = None ) -> None: From c6d9b5fab05703cb63b261cbf407b7f312027a88 Mon Sep 17 00:00:00 2001 From: Xen0Xys Date: Fri, 24 May 2024 15:42:53 +0200 Subject: [PATCH 2/5] :memo: Improve documentation --- README.md | 24 ++++++++++++++++++++++++ src/ipyaladin/aladin.py | 7 +++++-- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1c4070db..2ce2f8c5 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,30 @@ aladin = Aladin() aladin ``` +## Widget limitations + +Because some limitations of the widget framework, some operations need specific behaviors. + +### Aladin Lite values + +Some values need to be synchronized in their own cell before being used in a next one, like: + +- wcs + +#### Example with the wcs value: + +First cell: + +```python +aladin.synchronize_wcs() +``` + +Second cell: + +```python +print(aladin.wcs) +``` + ## Development installation First, make sure you have installed jupyter in your python environnement: `pip install jupyter`. diff --git a/src/ipyaladin/aladin.py b/src/ipyaladin/aladin.py index c93de0bd..24c7d9a4 100644 --- a/src/ipyaladin/aladin.py +++ b/src/ipyaladin/aladin.py @@ -228,6 +228,9 @@ def target(self, target: Union[str, SkyCoord]) -> None: def wcs(self) -> WCS: """The WCS of the Aladin Lite widget. + You need to call synchronize_wcs in a previous + cell before accessing this attribute. + Returns ------- WCS @@ -236,8 +239,8 @@ def wcs(self) -> WCS: """ if self._wcs == {}: raise ValueError( - "You need to call synchronize_wcs first and in " - "another Jupyter cell to get the WCS." + "You need to call synchronize_wcs before accessing the wcs attribute. " + "The WCS attribute need to be accessed from the next cell." ) wcs = WCS(naxis=self._wcs["NAXIS"]) wcs.wcs.cdelt = [self._wcs["CDELT1"], self._wcs["CDELT2"]] From 727e3d8b26f42df0ab912a0ee0dc8ce317dd11ad Mon Sep 17 00:00:00 2001 From: Xen0Xys Date: Mon, 27 May 2024 09:04:41 +0200 Subject: [PATCH 3/5] :art: Improve WCS instantiation --- src/ipyaladin/aladin.py | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/ipyaladin/aladin.py b/src/ipyaladin/aladin.py index 24c7d9a4..882ea525 100644 --- a/src/ipyaladin/aladin.py +++ b/src/ipyaladin/aladin.py @@ -242,15 +242,9 @@ def wcs(self) -> WCS: "You need to call synchronize_wcs before accessing the wcs attribute. " "The WCS attribute need to be accessed from the next cell." ) - wcs = WCS(naxis=self._wcs["NAXIS"]) - wcs.wcs.cdelt = [self._wcs["CDELT1"], self._wcs["CDELT2"]] - wcs.wcs.crpix = [self._wcs["CRPIX1"], self._wcs["CRPIX2"]] - wcs.wcs.crval = [self._wcs["CRVAL1"], self._wcs["CRVAL2"]] - wcs.wcs.ctype = [self._wcs["CTYPE1"], self._wcs["CTYPE2"]] - wcs.wcs.cunit = [self._wcs["CUNIT1"].strip(), self._wcs["CUNIT2"].strip()] - wcs.wcs.radesys = self._wcs["RADECSYS"].strip() - wcs.array_shape = (self._wcs["NAXIS2"], self._wcs["NAXIS1"]) - return wcs + if "RADECSYS" in self._wcs: # RADECSYS keyword is deprecated for astropy.WCS + self._wcs["RADESYS"] = self._wcs.pop("RADECSYS") + return WCS(self._wcs) def synchronize_wcs(self) -> None: """Synchronize the WCS of the Aladin Lite widget with the given WCS.""" From 37a5c3e63669891c62bbb7b693ee1c95ee661e82 Mon Sep 17 00:00:00 2001 From: Xen0Xys Date: Tue, 28 May 2024 09:04:27 +0200 Subject: [PATCH 4/5] :mute: Remove debug log --- js/models/message_handler.js | 1 - 1 file changed, 1 deletion(-) diff --git a/js/models/message_handler.js b/js/models/message_handler.js index 47208c2b..e59efbd6 100644 --- a/js/models/message_handler.js +++ b/js/models/message_handler.js @@ -17,7 +17,6 @@ export default class MessageHandler { handleSynchronizeWCS() { const wcs = this.aladin.getViewWCS(); - console.log(wcs); this.model.set("_wcs", wcs); this.model.save_changes(); } From 92cda8c9d1dee1e0f0ce52ce2a7aee584f681ad5 Mon Sep 17 00:00:00 2001 From: Xen0Xys Date: Tue, 28 May 2024 09:22:18 +0200 Subject: [PATCH 5/5] :memo: Update changelog --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 25ecd1e8..5e72a257 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,8 +19,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Support for `astropy.coordinates.SkyCoord` for assigning and reading the `target` property (#80) -- Support for `astropy.coordinates.Angle` for reading the `fov` property (#83) +- Support for `astropy.coordinates.Angle` for assigning and reading the `fov` property (#83) - Support for `regions.LineSkyRegion`, `regions.CircleSkyRegion`, `regions.EllipseSkyRegion`, `regions.PolygonSkyRegion`, `regions.RectangleSkyRegion`, `regions.Regions` with `add_graphic_overlay_from_region` (#88) +- Support for `wcs` property as an `astropy.WCS` that can be synchronized using the `synchronize_wcs` method (#89) ### Fixed