Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

plots crossing the "-180/+180" wrapping longitude line #126

Open
jerabaul29 opened this issue Oct 17, 2024 · 5 comments
Open

plots crossing the "-180/+180" wrapping longitude line #126

jerabaul29 opened this issue Oct 17, 2024 · 5 comments

Comments

@jerabaul29
Copy link
Collaborator

jerabaul29 commented Oct 17, 2024

Plots crossing the "-180/+180" wrapping longitude line have "ugly" lines appearing on them. Consider for example the dummy trajectory:

# %%

import matplotlib.pyplot as plt
import numpy as np
import xarray as xr

import cartopy.crs as ccrs

import trajan as _

# %%

# generate the xarray in trajan format
xr_data = xr.Dataset(
    {
        # meta vars
        'trajectory':
        xr.DataArray(data=np.array(["test"]),
                     dims=['trajectory'],
                     attrs={
                         "cf_role": "trajectory_id",
                         "standard_name": "platform_id",
                         "units": "1",
                         "long_name": "ID / name of each buoy present in the deployment data.",
                     }).astype(str),

        # trajectory vars
        'time':
            xr.DataArray(dims=["trajectory", "obs"],
                         data=np.array([[np.datetime64('2024-10-17T16:00:00'), np.datetime64('2024-10-17T17:00:00'), np.datetime64('2024-10-17T18:00:00'), np.datetime64('2024-10-17T19:00:00')],]),
                         attrs={
                             "standard_name": "time",
                             "long_name": "Time for the GNSS position records.",
            }),
            #
            'lat':
            xr.DataArray(dims=["trajectory", "obs"],
                         data=np.array([[0.0, -10.0, -11, -20],]),
                         attrs={
                             "_FillValue": "NaN",
                             "standard_name": "latitude",
                             "units": "degree_north",
            }),
            #
            'lon':
            xr.DataArray(dims=["trajectory", "obs"],
                         data=360.0 * 0.0 + np.array([[-159.5, -179.5, 179.5, 159.5],]),
                         attrs={
                             "_FillValue": "NaN",
                             "standard_name": "longitude",
                             "units": "degree_east",
            }),
    }
)

# %%

plt.figure()

xr_data.traj.plot(color="red")

plt.show()

# %%

This generates a plot that looks like:

Screenshot from 2024-10-17 15-07-37

Would this make sense to improve on in trajan?

I think that there are several aspects to consider:

  • the "ugly line" in itself: this could be removed so that the trajectory plot only goes from the left side, to the "left end", and then to the "right end" to the right side, without the "ugly line".

  • in cases when there is only information around the -180/+180 area, and no information / lines e.g. around longitude 0, the projection for the plot could be centered around the "center of mass" of the trajectories, rather than around longitude 0. Note that this would only solve the problem if having for example only data between [175; wrapped 185], but this would not help if there are "global" trajectories running globally around Earth.

I am looking a bit into this, I can try to populate this issue as I dig in fixes in cartopy and similar.

@jerabaul29
Copy link
Collaborator Author

jerabaul29 commented Oct 17, 2024

thought 1: simple workaround to avoid the ugly line: use linestyle="none", marker="."

A simple workaround to avoid the ugly line is to use linestyle="none", marker=".", markersize=10 or similar. For example:

# %%

plt.figure()

proj = ccrs.PlateCarree(central_longitude=179.0)

ax = plt.axes(projection=proj)
xr_data.traj.plot(linestyle="none", marker=".", markersize=10, color="red")
ax.coastlines()

lon1, lon2, lat1, lat2 = 155, 210, -25.0, 5.0
ax.set_extent([lon1, lon2, lat1, lat2], crs=ccrs.PlateCarree())

plt.show()

# %%

generates something that looks like:

Screenshot from 2024-10-17 17-18-57

A few notes:

  • it seems that quite a bit of the trajan "nicely plotting" disappears; for example, if I do not have the ax.coastlines() part, there are no map information at all. Not sure why, and this happens also if I put some ax=ax in the trajan plot call.

  • if not setting the limits, i.e. the

lon1, lon2, lat1, lat2 = 155, 210, -25.0, 5.0
ax.set_extent([lon1, lon2, lat1, lat2], crs=ccrs.PlateCarree())

part, then the plot looks like

Screenshot from 2024-10-17 17-22-02

  • a trick in setting the limits is to "unwrap" by hand, i.e. putting the 210 value; somehow, this works automagically even though the initial lat data was being -160 and 160, i.e. the -160 is automatically translated into 200.

@jerabaul29
Copy link
Collaborator Author

jerabaul29 commented Oct 17, 2024

I see a few things that could be considered here; what are your thoughts / what would you like me to give a try at implementing @gauteh ? :)

  • implementing a scatter rather than line plot in trajan; not sure if this could be for example a xr_data.traj.scatter(color="red"), or making sure the xr_data.traj.plot(color="red") behaves well with an extra linestyle="none" argument (i.e. making sure that extra coast / land etc information is still rendered then)?

  • I could also write some simple function that goes through the lon time series for each drifter to i) detect likely wrapping, ii) "unwrap" the likely wrapping; by iii) providing an extra flag (unwrap_lon for example?) to traj.plot to call this unwrapping on the longitude data, we could avoid the "ugly" lines?

@gauteh
Copy link
Member

gauteh commented Oct 17, 2024

Just a quick comment now, we already have scatter:

def scatter(self, *args, **kwargs):
. ds.traj.plot() is short for ds.traj.plot.lines().

@jerabaul29
Copy link
Collaborator Author

@gauteh thank you for the tips about scatter! :)

By running

xr_data.traj.plot.scatter()
plt.show()

I get this plotted, fast:

Screenshot from 2024-10-18 12-25-48

So this is very nice and nearly fits my need :) . I think the "only" issue is that now all trajectories are in teh same color, but I am not sure if there is an easy way around with the scatter function.

@gauteh
Copy link
Member

gauteh commented Oct 18, 2024

trajan uses a lower alpha if there are "many" trajectories, but in theory it should be possible to do that exactly as with the lines function. I don't think it is implemented yet though: https://github.com/OpenDrift/trajan/blob/main/trajan/plot/__init__.py#L172

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants