Skip to content
27 changes: 23 additions & 4 deletions rocketpy/plots/environment_plots.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,19 @@ def __wind(self, ax):
ax.set_xlabel("Wind Speed (m/s)", color="#ff7f0e")
ax.tick_params("x", colors="#ff7f0e")
axup = ax.twiny()
directions = np.array(
[self.environment.wind_direction(i) for i in self.grid], dtype=float
)
altitudes = np.array(self.grid, dtype=float)
# Insert NaN where direction jumps by more than 180° (360°→0° wraparound)
# so matplotlib does not draw a horizontal line across the plot.
WRAP_THRESHOLD = 180 # degrees; half the full circle
wrap_indices = np.where(np.abs(np.diff(directions)) > WRAP_THRESHOLD)[0] + 1
directions = np.insert(directions, wrap_indices, np.nan)
altitudes = np.insert(altitudes, wrap_indices, np.nan)
Comment thread
khushalkottaru marked this conversation as resolved.
Outdated
axup.plot(
[self.environment.wind_direction(i) for i in self.grid],
self.grid,
directions,
altitudes,
color="#1f77b4",
label="Wind Direction",
)
Expand Down Expand Up @@ -309,11 +319,20 @@ def ensemble_member_comparison(self, *, filename=None):

# Create wind direction subplot
ax8 = plt.subplot(324)
WRAP_THRESHOLD = 180 # degrees; half the full circle
for i in range(self.environment.num_ensemble_members):
self.environment.select_ensemble_member(i)
dirs = np.array(
[self.environment.wind_direction(j) for j in self.grid], dtype=float
)
alts = np.array(self.grid, dtype=float)
# Insert NaN at wraparound points to avoid crossing lines
wrap_idx = np.where(np.abs(np.diff(dirs)) > WRAP_THRESHOLD)[0] + 1
dirs = np.insert(dirs, wrap_idx, np.nan)
alts = np.insert(alts, wrap_idx, np.nan)
ax8.plot(
[self.environment.wind_direction(i) for i in self.grid],
self.grid,
dirs,
alts,
label=i,
)
ax8.set_ylabel("Height Above Sea Level (m)")
Expand Down
38 changes: 38 additions & 0 deletions tests/integration/environment/test_environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from datetime import date, datetime, timezone
from unittest.mock import patch

import numpy as np
Comment thread
khushalkottaru marked this conversation as resolved.
Outdated
import pytest


Expand Down Expand Up @@ -92,6 +93,43 @@ def test_standard_atmosphere(mock_show, example_plain_env): # pylint: disable=u
assert example_plain_env.prints.print_earth_details() is None


@patch("matplotlib.pyplot.show")
def test_wind_plots_wrapping_direction(mock_show, example_plain_env): # pylint: disable=unused-argument
"""Tests that wind direction plots handle 360°→0° wraparound without
drawing a horizontal line across the graph.

Parameters
----------
mock_show : mock
Mock object to replace matplotlib.pyplot.show() method.
example_plain_env : rocketpy.Environment
Example environment object to be tested.
"""
# Set a custom atmosphere where wind direction wraps from ~350° to ~10°
# across the altitude range by choosing wind_u and wind_v to create a
# direction near 350° at low altitude and ~10° at higher altitude.
# wind_direction = (180 + atan2(wind_u, wind_v)) % 360
# For direction ~350°: need atan2(wind_u, wind_v) ≈ 170° → wind_u>0, wind_v<0
# For direction ~10°: need atan2(wind_u, wind_v) ≈ -170° → wind_u<0, wind_v<0
example_plain_env.set_atmospheric_model(
type="custom_atmosphere",
pressure=None,
temperature=300,
wind_u=[(0, 1), (5000, -1)], # changes sign across altitude
wind_v=[(0, -6), (5000, -6)], # stays negative → heading near 350°/10°
)
# Verify that the wind direction actually wraps through 0°/360° in this
# atmosphere so the test exercises the wraparound code path.
low_dir = example_plain_env.wind_direction(0)
high_dir = example_plain_env.wind_direction(5000)
assert abs(low_dir - high_dir) > 180, (
"Test setup error: wind direction should cross 0°/360° boundary"
)
# Verify info() and atmospheric_model() plots complete without error
assert example_plain_env.info() is None
assert example_plain_env.plots.atmospheric_model() is None
Comment thread
khushalkottaru marked this conversation as resolved.


@pytest.mark.parametrize(
"model_name",
[
Expand Down
Loading