lifewatch / pypam

Python Passive Acoustic Analysis tool for Passive Acoustic Monitoring (PAM)
GNU General Public License v3.0
41 stars 8 forks source link

plot_hmb_ltsa: x must be one of None, 'frequency', 'time'. Received 'datetime' instead #53

Closed carueda closed 1 year ago

carueda commented 1 year ago

I just tried exercising the recently introduced plot_hmb_ltsa function on one of our data products. I'm using an example code snippet given to me as a basis (there's no unit test or documentation yet AFAICT).

Below is the code and error. I'd say this ticket is more of a heads-up as the new function may still be undergoing pending updates(?).

My primary dev env is Mac but I can try reproducing on Linux if needed. Thanks!

$ poetry run ipython3
Python 3.11.3 (main, Apr  7 2023, 19:25:52) [Clang 14.0.0 (clang-1400.0.29.202)]
Type 'copyright', 'credits' or 'license' for more information
IPython 8.14.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: import xarray as xr

In [2]: mars_20220909 = xr.open_dataset("generated/MARS_20220909.nc")

In [3]: import pypam
(... NumbaDeprecationWarning lines here -- already known issue ...)

In [4]: pypam.plots.plot_hmb_ltsa(mars_20220909['psd'], show=True)

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[4], line 1
----> 1 pypam.plots.plot_hmb_ltsa(mars_20220909['psd'], show=True)

File ~/github/pypam/pypam/plots.py:194, in plot_hmb_ltsa(da_sxx, db, p_ref, log, save_path, show)
    191 else:
    192     units = r'$\mu Pa^2/Hz$'
--> 194 plot_2d(ds=da_sxx, x='datetime', y='frequency_bins', cbar_label='%s [%s]' % ('SPLrms', units), xlabel='Time',
    195         ylabel='Frequency [Hz]', title='Long Term Spectrogram', ylog=log)
    197 if save_path is not None:
    198     plt.savefig(save_path)

File ~/github/pypam/pypam/plots.py:215, in plot_2d(ds, x, y, cbar_label, xlabel, ylabel, title, ylog, ax, **kwargs)
    213 if 'robust' not in kwargs.keys():
    214     kwargs['robust'] = True
--> 215 xarray.plot.pcolormesh(ds, x=x, y=y, add_colorbar=True, yscale=yscale,
    216                        cbar_kwargs={'label': cbar_label}, ax=ax,
    217                        extend='neither', **kwargs)
    218 ax.set_title(title)
    219 ax.set_xlabel(xlabel)

File ~/Library/Caches/pypoetry/virtualenvs/pypam-gMnshrYd-py3.11/lib/python3.11/site-packages/xarray/plot/dataarray_plot.py:1541, in _plot2d.<locals>.newplotfunc(***failed resolving arguments***)
   1535 elif rgb is not None and not imshow_rgb:
   1536     raise ValueError(
   1537         'The "rgb" keyword is only valid for imshow()'
   1538         "with a three-dimensional array (per facet)"
   1539     )
-> 1541 xlab, ylab = _infer_xy_labels(
   1542     darray=darray, x=x, y=y, imshow=imshow_rgb, rgb=rgb
   1543 )
   1545 xval = darray[xlab]
   1546 yval = darray[ylab]

File ~/Library/Caches/pypoetry/virtualenvs/pypam-gMnshrYd-py3.11/lib/python3.11/site-packages/xarray/plot/utils.py:421, in _infer_xy_labels(darray, x, y, imshow, rgb)
    419     y = darray.dims[0] if x == darray.dims[1] else darray.dims[1]
    420 else:
--> 421     _assert_valid_xy(darray, x, "x")
    422     _assert_valid_xy(darray, y, "y")
    424     if darray._indexes.get(x, 1) is darray._indexes.get(y, 2):

File ~/Library/Caches/pypoetry/virtualenvs/pypam-gMnshrYd-py3.11/lib/python3.11/site-packages/xarray/plot/utils.py:450, in _assert_valid_xy(darray, xy, name)
    448 if (xy is not None) and (xy not in valid_xy):
    449     valid_xy_str = "', '".join(sorted(tuple(str(v) for v in valid_xy)))
--> 450     raise ValueError(
    451         f"{name} must be one of None, '{valid_xy_str}'. Received '{xy}' instead."
    452     )

ValueError: x must be one of None, 'frequency', 'time'. Received 'datetime' instead.
cparcerisas commented 1 year ago

Hi Carlos,

The problem is that your dataset has a 'time' dimension instead of 'datetime', which is the standard pypam output. To use this functionality the output should be the one from pypam. However, we could add arguments where the user can select the names of the coordinates which represent time and frequency to make it more general.

cparcerisas commented 1 year ago

And indeed, tests are in development

carueda commented 1 year ago

Sorry, I removed some other comments here as I was actually given the renaming steps you provided offline, but overlooked those when I tried this! All seems to work as you indicated.

daily_ds = xr.open_dataset("/.../generated/MARS_20220909.nc")
daily_ds = daily_ds.rename({'time': 'datetime', 'frequency': 'frequency_bins'})
pypam.plots.plot_hmb_ltsa(daily_ds.psd, show=True)

Screenshot 2023-06-19 at 12 19 04 PM