Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions changelog/144.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed an issue where plotting spectrograms with non-UTC time scales (e.g., 'tt') would result in time offsets by ensuring conversion to UTC before plotting.
2 changes: 2 additions & 0 deletions pytest.ini
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,5 @@ filterwarnings =
ignore:The --rsyncdir command line argument and rsyncdirs config variable are deprecated.:DeprecationWarning
ignore:File may have been truncated.*
ignore:pattern has been replaced with the format keyword
# pyparsing deprecation warning from old matplotlib in oldestdeps
ignore:.*deprecated:pyparsing.warnings.PyparsingDeprecationWarning
35 changes: 19 additions & 16 deletions radiospectra/mixins.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
from astropy.visualization import time_support


class PcolormeshPlotMixin:
"""
Class provides plotting functions using `~pcolormesh`.
Expand All @@ -18,7 +21,6 @@ def plot(self, axes=None, **kwargs):
-------
`matplotlib.collections.QuadMesh`
"""
import matplotlib.dates as mdates
from matplotlib import pyplot as plt

if axes is None:
Expand All @@ -36,17 +38,15 @@ def plot(self, axes=None, **kwargs):
title = f"{title}, {self.detector}"

axes.set_title(title)
axes.plot(self.times.datetime[[0, -1]], self.frequencies[[0, -1]], linestyle="None", marker="None")
if self.times.shape[0] == self.data.shape[0] and self.frequencies.shape[0] == self.data.shape[1]:
ret = axes.pcolormesh(self.times.datetime, self.frequencies.value, data, shading="auto", **kwargs)
else:
ret = axes.pcolormesh(self.times.datetime, self.frequencies.value, data[:-1, :-1], shading="auto", **kwargs)
axes.set_xlim(self.times.datetime[0], self.times.datetime[-1])
locator = mdates.AutoDateLocator(minticks=4, maxticks=8)
formatter = mdates.ConciseDateFormatter(locator)
axes.xaxis.set_major_locator(locator)
axes.xaxis.set_major_formatter(formatter)
fig.autofmt_xdate()
with time_support():
axes.plot(self.times[[0, -1]], self.frequencies[[0, -1]], linestyle="None", marker="None")
if self.times.shape[0] == self.data.shape[0] and self.frequencies.shape[0] == self.data.shape[1]:
ret = axes.pcolormesh(self.times, self.frequencies.value, data, shading="auto", **kwargs)
else:
ret = axes.pcolormesh(self.times, self.frequencies.value, data[:-1, :-1], shading="auto", **kwargs)
axes.set_xlim(self.times[0], self.times[-1])
fig.autofmt_xdate()

# Set current axes/image if pyplot is being used (makes colorbar work)
for i in plt.get_fignums():
if axes in plt.figure(i).axes:
Expand All @@ -61,13 +61,16 @@ class NonUniformImagePlotMixin:
"""

def plotim(self, fig=None, axes=None, **kwargs):
import matplotlib.dates as mdates
from matplotlib import pyplot as plt
from matplotlib.image import NonUniformImage

if axes is None:
fig, axes = plt.subplots()

im = NonUniformImage(axes, interpolation="none", **kwargs)
im.set_data(mdates.date2num(self.times.datetime), self.frequencies.value, self.data)
axes.images.append(im)
with time_support():
axes.plot(self.times[[0, -1]], self.frequencies[[0, -1]], linestyle="None", marker="None")
im = NonUniformImage(axes, interpolation="none", **kwargs)
im.set_data(axes.convert_xunits(self.times), self.frequencies.value, self.data)
axes.add_image(im)
axes.set_xlim(self.times[0], self.times[-1])
axes.set_ylim(self.frequencies.value[0], self.frequencies.value[-1])
3 changes: 3 additions & 0 deletions radiospectra/spectrogram/tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import matplotlib

matplotlib.use("Agg")
57 changes: 57 additions & 0 deletions radiospectra/spectrogram/tests/test_spectrogrambase.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
from unittest import mock

import matplotlib.pyplot as plt
import numpy as np

import astropy.units as u
from astropy.time import Time

from radiospectra.spectrogram.spectrogrambase import GenericSpectrogram


def _get_spectrogram_with_time_scale(scale):
times = Time("2020-01-01T00:00:00", format="isot", scale=scale) + np.arange(4) * u.min
frequencies = np.linspace(10, 40, 4) * u.MHz
meta = {
"observatory": "Test",
"instrument": "TestInst",
"detector": "TestDet",
"start_time": times[0],
"end_time": times[-1],
"wavelength": np.array([1, 10]) * u.m,
"times": times,
"freqs": frequencies,
}
return GenericSpectrogram(np.arange(16).reshape(4, 4), meta)


def test_plot_uses_time_support_for_datetime_conversion():
spec = _get_spectrogram_with_time_scale("tt")

mesh = spec.plot()
x_limits = np.array(mesh.axes.get_xlim())
expected_tt_limits = mesh.axes.convert_xunits(spec.times[[0, -1]])

plt.close(mesh.axes.figure)

np.testing.assert_allclose(x_limits, expected_tt_limits)


def test_plotim_uses_time_support_for_datetime_conversion():
spec = _get_spectrogram_with_time_scale("tt")
fig, axes = plt.subplots()

with (
mock.patch("matplotlib.image.NonUniformImage.set_interpolation", autospec=True),
mock.patch("matplotlib.image.NonUniformImage.set_data", autospec=True) as set_data,
):
spec.plotim(fig=fig, axes=axes)

plt.close(fig)

_, x_values, y_values, image = set_data.call_args.args
expected_tt = axes.convert_xunits(spec.times)

np.testing.assert_allclose(x_values, expected_tt)
np.testing.assert_allclose(y_values, spec.frequencies.value)
np.testing.assert_allclose(image, spec.data)