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

Adding function ctd_plot and solving conflicts #115

Merged
merged 24 commits into from
Aug 6, 2024
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
b3a5d1f
Add new function plot_ctd
FloraSauerbronn Jun 26, 2024
aa566d5
Add new test function plot_ctd
FloraSauerbronn Jun 26, 2024
d6af191
Add new baseline image plot_ctd
FloraSauerbronn Jun 26, 2024
d4d575f
Adjusting errors
FloraSauerbronn Jun 28, 2024
3499664
Add tolerance to image compare test
FloraSauerbronn Jul 9, 2024
ead3af8
changing back test_plotting
FloraSauerbronn Jul 10, 2024
2cc887d
Update test_plotting.py
FloraSauerbronn Jul 10, 2024
e7e25d5
updating ctd_plot with idx param
FloraSauerbronn Jul 11, 2024
4398cf9
updating test_plotting
FloraSauerbronn Jul 11, 2024
2f55d9e
Adding test_plot_ctd
FloraSauerbronn Jul 11, 2024
e909a38
creating new figure for image test compare plot_ctd
FloraSauerbronn Jul 11, 2024
65e4ef2
Merge branch 'main' of github.com:ioos/gliderpy into ctd_plots
FloraSauerbronn Jul 11, 2024
1e7eb20
Merge branch 'ctd_plots' of https://github.com/FloraSauerbronn/glider…
FloraSauerbronn Jul 11, 2024
32c5fa9
fix ruff tests
FloraSauerbronn Jul 23, 2024
1ed0776
fix import order
FloraSauerbronn Jul 23, 2024
4edd36d
fix end of file
FloraSauerbronn Jul 23, 2024
9232e5c
positive pressure
FloraSauerbronn Jul 28, 2024
5240abb
Fixing ax in plot_ctd and creating new baseline image
FloraSauerbronn Jul 29, 2024
dae31ba
Removing ax object in excess
FloraSauerbronn Jul 29, 2024
51f9685
Removing unnecessary ax features from plot_ctd
FloraSauerbronn Jul 29, 2024
f03cbf0
Solving problems from pre-commit and image
FloraSauerbronn Jul 29, 2024
0babf90
Removing unecessary features from plot_ctd
FloraSauerbronn Aug 6, 2024
4fdf02b
Removing legend
FloraSauerbronn Aug 6, 2024
223bd4c
updating image
FloraSauerbronn Aug 6, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions gliderpy/plotting.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,55 @@ def plot_transect(
ax.set_ylim(ax.get_ylim()[0], 0)

return fig, ax


@register_dataframe_method
def plot_ctd(
df: pd.DataFrame,
profile_number: int,
var: str,
ax: plt.Axes = None,
color: str | None = None,
) -> tuple:
"""Make a CTD profile plot of pressure vs property
depending on what variable was chosen.

:param profile_number: profile number of CTD
:param var: variable to plot against pressure
:param ax: existing axis to plot on (default: None)
:param color: color for the plot line (default: None)
:return: figure, axes
"""
g = df.groupby(["longitude", "latitude"])
profile = g.get_group(list(g.groups)[profile_number])

if ax is None:
fig, ax = plt.subplots(figsize=(5, 6))
ax.plot(profile[var], profile["pressure"], label=var, color=color)
ax.set_ylabel("Pressure")
ax.set_xlabel(var)
ax.invert_yaxis()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be an if-check block outside of the ax creation. We had it before if I'm not mistaken.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem occurs when calling the legend while using the twiny axis. We have three scenarios:

1. When using just one axis (not referring to a second one like ax2), the legend will only display the last variable plotted if twiny is used, so we need to create twoo box one for each legend and specify where they should be placed.

`
@register_dataframe_method
def plot_ctd(
df: pd.DataFrame,
profile_number: int,
var: str,
ax: plt.Axes = None,
color: str | None = None,
) -> tuple:
"""Make a CTD profile plot of pressure vs property
depending on what variable was chosen.

:param profile_number: profile number of CTD
:param var: variable to plot against pressure
:param ax: existing axis to plot on (default: None)
:param color: color for the plot line (default: None)
:return: figure, axes
"""
g = df.groupby(["longitude", "latitude"])
profile = g.get_group(list(g.groups)[profile_number])

if ax is None:
    fig, ax = plt.subplots(figsize=(5, 6))
    ax.plot(profile[var], profile["pressure"], label=var, color=color)
    ax.set_ylabel("Pressure")
    ax.set_xlabel(var)
    ax.invert_yaxis()
    ax.legend(loc="lower center", bbox_to_anchor=(0.5, 0.07))
    return fig, ax
else:
    ax = ax.twiny()  # Create a new x-axis on top
    ax.plot(profile[var], profile["pressure"], label=var, color=color)
    ax.set_xlabel(var)
    ax.legend(loc="lower center")
    return ax.figure, ax

fig, ax = plot_ctd(df, 0, var="temperature", color="blue")
fig, ax = plot_ctd(df, 0, var="salinity", ax=ax, color="red")`

2. Or calling the legend inside each clouse (if ax is none and else) without defining each ax they would overlap eachother.

3. Or we defined each ax and call the legens like this so they can be in the same box

`@register_dataframe_method
def plot_ctd(
df: pd.DataFrame,
profile_number: int,
var: str,
ax: plt.Axes = None,
color: str | None = None,
) -> tuple:
"""Make a CTD profile plot of pressure vs property
depending on what variable was chosen.

:param profile_number: profile number of CTD
:param var: variable to plot against pressure
:param ax: existing axis to plot on (default: None)
:param color: color for the plot line (default: None)
:return: figure, axes
"""
g = df.groupby(["longitude", "latitude"])
profile = g.get_group(list(g.groups)[profile_number])

if ax is None:
    fig, ax = plt.subplots(figsize=(5, 6))
    lns1 = ax.plot(profile[var], profile["pressure"], label=var, color=color)
    ax.set_ylabel("Pressure")
    ax.set_xlabel(var)
    ax.invert_yaxis()
    
    # Get handles and labels for the legend
    handles, labels = ax.get_legend_handles_labels()
    ax.legend(handles, labels, loc="best")
    return fig, ax
else:
    ax2 = ax.twiny()  # Create a new x-axis on top
    lns2 = ax2.plot(profile[var], profile["pressure"], label=var, color=color)
    ax2.set_xlabel(var)
    
    # Get handles and labels for both axes
    handles1, labels1 = ax.get_legend_handles_labels()
    handles2, labels2 = ax2.get_legend_handles_labels()
    
    # Combine handles and labels
    handles = handles1 + handles2
    labels = labels1 + labels2
    
    # Set the combined legend
    ax.legend(handles, labels, loc="best")
    
    return ax.figure, ax2

Example usage:

fig, ax = plot_ctd(df, 0, var="temperature", color="blue")
fig, ax = plot_ctd(df, 0, var="salinity", ax=ax, color="red")
`

ax.legend(loc="lower center", bbox_to_anchor=(0.5, 0.09)
)
return fig, ax

fig = ax.get_figure()

# Check if the ax is already a twinx or twiny
if hasattr(ax, "twinned_axis"):
# If already twinned, get the correct twinned axis
ax = ax.twinned_axis
else:
# Create a new twiny axis and keep reference
ax = ax.twiny()
ax.twinned_axis = ax
FloraSauerbronn marked this conversation as resolved.
Show resolved Hide resolved

# Plotting the current variable
ax.plot(profile[var], profile["pressure"], label=var, color=color)
ax.set_xlabel(var)

# Update legend
lines, labels = ax.get_legend_handles_labels()
ax.legend(lines, labels, loc="lower center")

return fig, ax
Binary file added tests/baseline/test_plot_ctd.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 9 additions & 7 deletions tests/test_plotting.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import pytest

from gliderpy.fetchers import GliderDataFetcher
from gliderpy.plotting import plot_track, plot_transect
from gliderpy.plotting import plot_ctd, plot_track, plot_transect

root = Path(__file__).parent

Expand All @@ -34,7 +34,7 @@ def test_plot_track(glider_data):
@pytest.mark.mpl_image_compare(baseline_dir=root.joinpath("baseline/"))
def test_plot_transect(glider_data):
"""Test plot_transect accessor."""
fig, ax = plot_transect(glider_data, "temperature", cmap="viridis")
fig, ax = plot_transect(glider_data, var="temperature", cmap="viridis")
return fig


Expand All @@ -50,23 +50,18 @@ def test_plot_transect_multiple_figures(glider_data):
glider_data.plot_transect(var="temperature", ax=ax0, cmap="viridis")
glider_data.plot_transect(var="salinity", ax=ax1, cmap="cividis")

# Check if the y-label is named "pressure"
assert ax0.get_ylabel() == "pressure"
assert ax1.get_ylabel() == "pressure"

# Since sharex=True and sharey=True, xlim and ylim should be the same
assert ax0.get_xlim() == ax1.get_xlim()
assert ax0.get_ylim() == ax1.get_ylim()

# Get the colorbars
cbar0 = ax0.collections[0].colorbar
cbar1 = ax1.collections[0].colorbar

# Check colormap
assert cbar0.cmap.name == "viridis"
assert cbar1.cmap.name == "cividis"

# Check labels
assert cbar0.ax.get_ylabel() == "temperature"
assert cbar1.ax.get_ylabel() == "salinity"

Expand All @@ -78,3 +73,10 @@ def test_plot_transect_size(glider_data):
fig, ax = plt.subplots(figsize=(15, 9))
glider_data.plot_transect(var="temperature")
np.testing.assert_array_equal(fig.get_size_inches(), np.array([15.0, 9.0]))


@pytest.mark.mpl_image_compare(baseline_dir=root.joinpath("baseline/"))
def test_plot_ctd(glider_data):
"""Test plot_ctd accessor."""
fig, ax = plot_ctd(glider_data, 0, var="temperature", color="blue")
return fig