Skip to content

Commit

Permalink
feat: add support for earth, return longitude and latitude objects in…
Browse files Browse the repository at this point in the history
…stead of floats
  • Loading branch information
ManonMarchand committed Sep 16, 2024
1 parent 91f5706 commit 1079336
Show file tree
Hide file tree
Showing 4 changed files with 205 additions and 85 deletions.
177 changes: 145 additions & 32 deletions examples/12_Planetary_surveys.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"metadata": {},
"source": [
"# Planetary surveys\n",
"With Aladin Lite, you can display a planetary survey and use all existing features with it. "
"\n",
"With `ipyaladin`, you can also display planetary surfaces."
]
},
{
Expand Down Expand Up @@ -35,48 +36,76 @@
"metadata": {},
"outputs": [],
"source": [
"aladin = Aladin(\n",
"mars = Aladin(\n",
" target=\"159.2135528 -58.6241989\",\n",
" survey=\"https://alasky.u-strasbg.fr/Planets/Mars_Viking_MDIM21\",\n",
" fov=10,\n",
")\n",
"aladin"
"mars"
]
},
{
"cell_type": "markdown",
"id": "34747eb38e0db450",
"id": "35ea9256",
"metadata": {},
"source": [
"Now, let's change the target to Olympus Mons, and get the coordinates as a tuple of floats."
"The target does not return a `SkyCoord` object anymore, since we don't represent the sky here. It is a couple of `Longitude` and `Latitude`."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "dbe012440a30b6fe",
"id": "43c34b52",
"metadata": {},
"outputs": [],
"source": [
"mars.target"
]
},
{
"cell_type": "markdown",
"id": "e6f17ff7",
"metadata": {},
"source": [
"The WCS are also defined on planetary surfaces (in [Marmo *et.al.* 2018](https://doi.org/10.1029/2018EA000388)). This is why you see a CTYPE starting with `MA` for Mars."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "59bcf84c",
"metadata": {},
"outputs": [],
"source": [
"aladin.target = \"Olympus Mons\""
"mars.wcs"
]
},
{
"cell_type": "markdown",
"id": "34747eb38e0db450",
"metadata": {},
"source": [
"Let's change the center of the view to Olympus Mons."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f8bd2e1814b72bd8",
"id": "dbe012440a30b6fe",
"metadata": {},
"outputs": [],
"source": [
"aladin.target"
"mars.target = \"Olympus Mons\""
]
},
{
"cell_type": "markdown",
"id": "1329063f49da8d52",
"id": "879f484a",
"metadata": {},
"source": [
"Now create and add a table with the names and positions of the main geological features on Mars."
"Any name recognized by the [Gazetter of Planetary Nomenclature](https://planetarynames.wr.usgs.gov/Nomenclature) will work. \n",
"\n",
"We can also add tables:"
]
},
{
Expand All @@ -86,30 +115,114 @@
"metadata": {},
"outputs": [],
"source": [
"data = [\n",
" {\"longitude\": 226.2, \"latitude\": 18.65, \"name\": \"Olympus Mons\"},\n",
" {\"longitude\": 70.5, \"latitude\": -42.4, \"name\": \"Hellas Planitia\"},\n",
" {\"longitude\": 250.4, \"latitude\": 40.5, \"name\": \"Alba Mons\"},\n",
" {\"longitude\": -59.2, \"latitude\": -13.9, \"name\": \"Valles Marineris\"},\n",
" {\"longitude\": 147.21, \"latitude\": 25.02, \"name\": \"Elysium Mons\"},\n",
" {\"longitude\": 316.0, \"latitude\": -49.7, \"name\": \"Argyre Basin\"},\n",
" {\"longitude\": 32.53, \"latitude\": 70.0, \"name\": \"Vastitas Borealis\"},\n",
" {\"longitude\": -112.58, \"latitude\": 1.57, \"name\": \"Tharsis Montes\"},\n",
" {\"longitude\": 298.0, \"latitude\": 25.0, \"name\": \"Outflow channels\"},\n",
" {\"longitude\": 30.0, \"latitude\": 19.79, \"name\": \"Arabia Terra\"},\n",
" {\"longitude\": 70.5, \"latitude\": -42.4, \"name\": \"Hellas Basin\"},\n",
" {\"longitude\": 280.0, \"latitude\": 45.0, \"name\": \"Tempe Terra\"},\n",
" {\"longitude\": 87.0, \"latitude\": 12.9, \"name\": \"Isidis Basin\"},\n",
" {\"longitude\": 117.5, \"latitude\": 46.7, \"name\": \"Utopia Basin\"},\n",
" {\"longitude\": 350.0, \"latitude\": -45.0, \"name\": \"Noachis Terra\"},\n",
"longitudes = [\n",
" 226.2,\n",
" 70.5,\n",
" 250.4,\n",
" -59.2,\n",
" 147.21,\n",
" 316.0,\n",
" 32.53,\n",
" -112.58,\n",
" 298.0,\n",
" 30.0,\n",
" 70.5,\n",
" 280.0,\n",
" 87.0,\n",
" 117.5,\n",
" 350.0,\n",
"]\n",
"latitudes = [\n",
" 18.65,\n",
" -42.4,\n",
" 40.5,\n",
" -13.9,\n",
" 25.02,\n",
" -49.7,\n",
" 70.0,\n",
" 1.57,\n",
" 25.0,\n",
" 19.79,\n",
" -42.4,\n",
" 45.0,\n",
" 12.9,\n",
" 46.7,\n",
" -45.0,\n",
"]\n",
"names = [\n",
" \"Olympus Mons\",\n",
" \"Hellas Planitia\",\n",
" \"Alba Mons\",\n",
" \"Valles Marineris\",\n",
" \"Elysium Mons\",\n",
" \"Argyre Basin\",\n",
" \"Vastitas Borealis\",\n",
" \"Tharsis Montes\",\n",
" \"Outflow channels\",\n",
" \"Arabia Terra\",\n",
" \"Hellas Basin\",\n",
" \"Tempe Terra\",\n",
" \"Isidis Basin\",\n",
" \"Utopia Basin\",\n",
" \"Noachis Terra\",\n",
"]\n",
"\n",
"longitudes = [item[\"longitude\"] for item in data]\n",
"latitudes = [item[\"latitude\"] for item in data]\n",
"names = [item[\"name\"] for item in data]\n",
"\n",
"table = Table([longitudes, latitudes, names], names=(\"Longitude\", \"Latitude\", \"Name\"))\n",
"aladin.add_table(table)"
"mars.add_table(\n",
" table, color=\"#67d38d\", source_size=15, shape=\"cross\", name=\"Mars_features\"\n",
")"
]
},
{
"cell_type": "markdown",
"id": "4af1422b",
"metadata": {},
"source": [
"## Surveys of Earth"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "479ddc87",
"metadata": {},
"outputs": [],
"source": [
"earth = Aladin(\n",
" survey=\"CDS/P/Earth/DEM/elevation\",\n",
" fov=100,\n",
")\n",
"earth"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "983e6c40",
"metadata": {},
"outputs": [],
"source": [
"earth.target"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "4609cf6b",
"metadata": {},
"outputs": [],
"source": [
"earth.wcs"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3b887792",
"metadata": {},
"outputs": [],
"source": [
"earth.target = \"Strasbourg\" # ipyaladin's home"
]
}
],
Expand Down
2 changes: 1 addition & 1 deletion src/ipyaladin/__about__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
__version__ = "0.4.0"
__aladin_lite_version__ = "3.4.4-beta"
__aladin_lite_version__ = "3.5.1-alpha"
56 changes: 33 additions & 23 deletions src/ipyaladin/utils/_coordinate_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@
from typing import Tuple

import requests
from astropy.coordinates import SkyCoord, Angle
from astropy.coordinates import SkyCoord, Angle, Longitude, Latitude
import re

from ipyaladin.utils.exceptions import NameResolverWarning


def parse_coordinate_string(string: str, body: str = "sky") -> SkyCoord:
def _parse_coordinate_string(
string: str, body: str = "sky"
) -> Tuple[Longitude, Latitude]:
"""Parse a string containing coordinates.
Parameters
Expand All @@ -26,22 +28,26 @@ def parse_coordinate_string(string: str, body: str = "sky") -> SkyCoord:
"""
if not _is_coordinate_string(string):
if body == "sky":
return SkyCoord.from_name(string)
if body == "sky" or body is None:
sesame = SkyCoord.from_name(string)
return sesame.icrs.ra.deg, sesame.icrs.dec.deg
return _from_name_on_planet(string, body)
coordinates: Tuple[str, str] = _split_coordinate_string(string)
# coordinates should be parsed from the string
coordinates = _split_coordinate_string(string)
# Parse ra and dec to astropy Angle objects
dec: Angle = Angle(coordinates[1], unit="deg")
lat: Angle = Angle(coordinates[1], unit="deg")
if _is_hour_angle_string(coordinates[0]):
ra = Angle(coordinates[0], unit="hour")
lon = Angle(coordinates[0], unit="hour")
else:
ra = Angle(coordinates[0], unit="deg")
lon = Angle(coordinates[0], unit="deg")
# Create SkyCoord object
if string[0] == "B":
return SkyCoord(ra=ra, dec=dec, equinox="B1950", frame="fk4")
if string[0] == "G":
return SkyCoord(l=ra, b=dec, frame="galactic")
return SkyCoord(ra=ra, dec=dec, frame="icrs")
coo = SkyCoord(ra=lon, dec=lat, equinox="B1950", frame="fk4")
elif string[0] == "G":
coo = SkyCoord(l=lon, b=lat, frame="galactic")
else:
coo = SkyCoord(ra=lon, dec=lat, frame="icrs")
return coo.icrs.ra.deg, coo.icrs.dec.deg


def _from_name_on_planet(string: str, body: str) -> SkyCoord:
Expand All @@ -65,24 +71,28 @@ def _from_name_on_planet(string: str, body: str) -> SkyCoord:
)
request = requests.get(url)
if request.status_code != requests.codes.ok:
raise ValueError(f"Invalid coordinate string: {string}")
data = request.json()
identifier = data["data"][0][1]
lat = data["data"][0][5]
lon = data["data"][0][6]
system = data["data"][0][11]
raise ValueError(
"No coordinates found for this requested planetary feature: " f"'{string}'"
)
data = request.json()["data"]
# response is different for earth
if body == "earth":
return data[0][0], data[0][1]
# case of every other planetary bodies
identifier = data[0][1]
lat = data[0][5] # inverted lon and lat in response
lon = data[0][6]
system = data[0][11]
if identifier != string:
warnings.warn(
f"Nothing found for '{string}', but found close"
f" name '{identifier}'. Moving to {identifier}.",
f"Nothing found for '{string}' on {body}. However, a {identifier} exists. "
f"Moving to {identifier}.",
NameResolverWarning,
stacklevel=2,
)
if "+West" in system:
lon = 360 - lon
# Currently we use ICRS for all planetary bodies, but this could be changed
# in a future Aladin Lite version.
return SkyCoord(ra=lon, dec=lat, frame="icrs", unit="deg")
return lon, lat


def _is_coordinate_string(string: str) -> bool:
Expand Down
Loading

0 comments on commit 1079336

Please sign in to comment.