Skip to content

Commit

Permalink
Fix track wrapping at edges of map (#1163)
Browse files Browse the repository at this point in the history
* allow lon values belond -180, 180

* use EPSG:3857 for track projection

* reformat coords in cmems data importers
  • Loading branch information
JustinElms authored Sep 6, 2024
1 parent e290632 commit 769acc3
Show file tree
Hide file tree
Showing 7 changed files with 131 additions and 19 deletions.
2 changes: 1 addition & 1 deletion data/observational/orm/station.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def __init__(self, **kwargs):
if self.latitude > 90 or self.latitude < -90:
raise ValueError(f"Latitude {self.latitude} out of range (-90,90)")

if self.longitude > 180 or self.longitude < -180:
if self.longitude > 360 or self.longitude < -360:
raise ValueError(f"Longitude {self.longitude} out of range (-180,180)")

def __repr__(self):
Expand Down
13 changes: 6 additions & 7 deletions oceannavigator/frontend/src/components/MainMap.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ import * as olLoadingstrategy from "ol/loadingstrategy";
import * as olProj from "ol/proj";
import * as olProj4 from "ol/proj/proj4";
import * as olTilegrid from "ol/tilegrid";
import {getDistance} from 'ol/sphere';
import { getDistance } from 'ol/sphere';
import { isMobile } from "react-device-detect";

import "ol/ol.css";
Expand Down Expand Up @@ -197,7 +197,6 @@ const MainMap = forwardRef((props, ref) => {
mapRef0
);

// let newSelect = createSelect();
const newSelect = new olinteraction.Select({
style: function (feat, res) {
if (feat.get("type") != "area") {
Expand Down Expand Up @@ -1115,10 +1114,10 @@ const MainMap = forwardRef((props, ref) => {
feat.set(
"name",
feat.get("name") +
"<span>" +
"RMS Error: " +
feat.get("error").toPrecision(3) +
"</span>"
"<span>" +
"RMS Error: " +
feat.get("error").toPrecision(3) +
"</span>"
);
}
if (id) {
Expand Down Expand Up @@ -1461,7 +1460,7 @@ const MainMap = forwardRef((props, ref) => {
let c = feature
.getGeometry()
.clone()
.transform(props.mapSettings.projection, "EPSG:4326")
.transform(props.mapSettings.projection, "EPSG:3857")
.getCoordinates();
content.push([c[1], c[0], feature.get("id")]);
}
Expand Down
1 change: 0 additions & 1 deletion routes/api_v2_0.py
Original file line number Diff line number Diff line change
Expand Up @@ -1254,7 +1254,6 @@ def observation_track(
if len(coordinates) > 1:
df = pd.DataFrame(np.array(coordinates), columns=["id", "type", "lon", "lat"])
df["id"] = df.id.astype(int)
df["lon"] = (df["lon"] + 360) % 360

vc = df.id.value_counts()
for p_id in vc.where(vc > 1).dropna().index:
Expand Down
29 changes: 29 additions & 0 deletions scripts/data_importers/cmems_argo.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,33 @@ def extract_metadata(ds, metadata):
}


def reformat_coordinates(ds: xr.Dataset) -> xr.Dataset:
"""
Shifts coordinates so that tracks are continuous on each side of map limits
(-180,180 degrees longitude). i.e if a track crosses -180 deg such that the
first point is -178 and the next is 178 then the second coordinate will be
replaced with -182. This allows the navigator to draw the track continusouly
without bounching between points on the far sides of the map.
"""

lons = ds.LONGITUDE.data.copy()

lon_diff = np.diff(lons)
crossings = np.where(np.abs(lon_diff) > 180)[0]

while len(crossings) > 0:
if lons[crossings[0]] > lons[crossings[0] + 1]:
lons[crossings[0] + 1 :] = 360 + lons[crossings[0] + 1 :]
else:
lons[crossings[0] + 1 :] = -360 + lons[crossings[0] + 1 :]
lon_diff = np.diff(lons)
crossings = np.where(np.abs(lon_diff) > 180)[0]

ds.LONGITUDE.data = lons

return ds


def main(uri: str, filename: str):
"""Import Argo Profiles
Expand Down Expand Up @@ -80,6 +107,8 @@ def main(uri: str, filename: str):
print("Moored instrument: skipping file.")
continue

ds = reformat_coordinates(ds)

times = pd.to_datetime(ds.TIME.values)

meta_data = extract_metadata(ds, META_FIELDS)
Expand Down
29 changes: 28 additions & 1 deletion scripts/data_importers/cmems_ctd.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,31 @@

from data.observational import DataType, Platform, Sample, Station

def reformat_coordinates(ds: xr.Dataset) -> xr.Dataset:
"""
Shifts coordinates so that tracks are continuous on each side of map limits
(-180,180 degrees longitude). i.e if a track crosses -180 deg such that the
first point is -178 and the next is 178 then the second coordinate will be
replaced with -182. This allows the navigator to draw the track continusouly
without bounching between points on the far sides of the map.
"""

lons = ds.LONGITUDE.data.copy()

lon_diff = np.diff(lons)
crossings = np.where(np.abs(lon_diff) > 180)[0]

while len(crossings) > 0:
if lons[crossings[0]] > lons[crossings[0] + 1]:
lons[crossings[0] + 1 :] = 360 + lons[crossings[0] + 1 :]
else:
lons[crossings[0] + 1 :] = -360 + lons[crossings[0] + 1 :]
lon_diff = np.diff(lons)
crossings = np.where(np.abs(lon_diff) > 180)[0]

ds.LONGITUDE.data = lons

return ds

def main(uri: str, filename: str):

Expand Down Expand Up @@ -52,7 +77,9 @@ def main(uri: str, filename: str):
if ds.LATITUDE.size == 1:
print("Moored instrument: skipping file.")
continue


ds = reformat_coordinates(ds)

times = pd.to_datetime(ds.TIME.values)

if len(datatype_map) == 0:
Expand Down
29 changes: 29 additions & 0 deletions scripts/data_importers/cmems_drifter.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import sys
import defopt

import numpy as np
import xarray as xr
from sqlalchemy import create_engine, select
from sqlalchemy.exc import IntegrityError
Expand All @@ -23,6 +24,31 @@
# Add more variables here if necessary
}

def reformat_coordinates(ds: xr.Dataset) -> xr.Dataset:
"""
Shifts coordinates so that tracks are continuous on each side of map limits
(-180,180 degrees longitude). i.e if a track crosses -180 deg such that the
first point is -178 and the next is 178 then the second coordinate will be
replaced with -182. This allows the navigator to draw the track continusouly
without bounching between points on the far sides of the map.
"""

lons = ds.LONGITUDE.data.copy()

lon_diff = np.diff(lons)
crossings = np.where(np.abs(lon_diff) > 180)[0]

while len(crossings) > 0:
if lons[crossings[0]] > lons[crossings[0] + 1]:
lons[crossings[0] + 1 :] = 360 + lons[crossings[0] + 1 :]
else:
lons[crossings[0] + 1 :] = -360 + lons[crossings[0] + 1 :]
lon_diff = np.diff(lons)
crossings = np.where(np.abs(lon_diff) > 180)[0]

ds.LONGITUDE.data = lons

return ds

def main(uri: str, filename: str):
"""Import data from NetCDF file(s) into the database.
Expand All @@ -49,6 +75,9 @@ def main(uri: str, filename: str):
for fname in filenames:
print(fname)
with xr.open_dataset(fname) as ds:

ds = reformat_coordinates(ds)

df = ds.to_dataframe().reset_index().dropna(axis=1, how="all").dropna()

# Iterate over variables defined in the mapping
Expand Down
47 changes: 38 additions & 9 deletions scripts/data_importers/cmems_glider.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,34 @@
VARIABLES = ["PRES", "PSAL", "TEMP", "CNDC"]


def main(uri: str, filename: str):
def reformat_coordinates(ds: xr.Dataset) -> xr.Dataset:
"""
Shifts coordinates so that tracks are continuous on each side of map limits
(-180,180 degrees longitude). i.e if a track crosses -180 deg such that the
first point is -178 and the next is 178 then the second coordinate will be
replaced with -182. This allows the navigator to draw the track continusouly
without bounching between points on the far sides of the map.
"""

lons = ds.LONGITUDE.data.copy()

lon_diff = np.diff(lons)
crossings = np.where(np.abs(lon_diff) > 180)[0]

while len(crossings) > 0:
if lons[crossings[0]] > lons[crossings[0] + 1]:
lons[crossings[0] + 1 :] = 360 + lons[crossings[0] + 1 :]
else:
lons[crossings[0] + 1 :] = -360 + lons[crossings[0] + 1 :]
lon_diff = np.diff(lons)
crossings = np.where(np.abs(lon_diff) > 180)[0]

ds.LONGITUDE.data = lons

return ds


def main(uri: str, filename: str):
"""Import Glider NetCDF
:param str uri: Database URI
Expand All @@ -46,21 +72,23 @@ def main(uri: str, filename: str):
datatype_map = {}
for fname in filenames:
print(fname)
with xr.open_dataset(fname).drop_duplicates("TIME") as ds:
time_diff = np.diff(ds.TIME.data).astype('timedelta64[D]').astype(int)
with xr.open_dataset(fname).drop_duplicates("TIME") as ds:
time_diff = np.diff(ds.TIME.data).astype("timedelta64[D]").astype(int)
breaks = np.argwhere(time_diff > 5).flatten()
deployment_times = np.split(ds.TIME, breaks + 1)

variables = [v for v in VARIABLES if v in ds.variables]

for deployment in deployment_times:
subset = ds.sel(TIME=deployment)
dep_date = np.datetime_as_string(deployment, unit='D')[0]
subset = reformat_coordinates(subset)

dep_date = np.datetime_as_string(deployment, unit="D")[0]
df = (
subset[["TIME", "LATITUDE", "LONGITUDE", *variables]]
.to_dataframe()
.reset_index()
.dropna(axis=1, how='all')
.dropna(axis=1, how="all")
.dropna()
)

Expand Down Expand Up @@ -90,7 +118,6 @@ def main(uri: str, filename: str):
platform_id = subset.attrs["platform_code"]
p = Platform(
type=Platform.Type.glider, unique_id=f"{platform_id}-{dep_date}"

)
attrs = {
"Glider Platform": platform_id,
Expand All @@ -105,10 +132,12 @@ def main(uri: str, filename: str):
except IntegrityError:
print("Error committing platform.")
session.rollback()
stmt = select(Platform.id).where(Platform.unique_id == f"{platform_id}-{dep_date}")
stmt = select(Platform.id).where(
Platform.unique_id == f"{platform_id}-{dep_date}"
)
p.id = session.execute(stmt).first()[0]

n_chunks = np.ceil(len(df)/1e4)
n_chunks = np.ceil(len(df) / 1e4)

if n_chunks < 1:
continue
Expand All @@ -133,7 +162,7 @@ def main(uri: str, filename: str):
except IntegrityError:
print("Error committing station.")
session.rollback()
stmt = select(Station).where(Station.platform_id==p.id)
stmt = select(Station).where(Station.platform_id == p.id)
chunk["STATION_ID"] = session.execute(stmt).all()

chunk["STATION_ID"] = [s.id for s in stations]
Expand Down

0 comments on commit 769acc3

Please sign in to comment.