OSOceanAcoustics / echopype

Enabling interoperability and scalability in ocean sonar data analysis
https://echopype.readthedocs.io/
Apache License 2.0
98 stars 73 forks source link

echopype.visualize.create_echogram got AttributeError: module 'echopype' has no attribute 'visualize' for 0.5.6 #569

Closed cywhale closed 2 years ago

cywhale commented 2 years ago

The same .raw, when using echopype 0.5.6, ep.visualize.create_echogram got Attribute Error. But got correct result by using 0.5.5

ed = ep.open_raw(
    raw_file="xxx.raw", 
    sonar_model="EK80", 
)

fg = ep.visualize.create_echogram(ed, frequency=200000, 
        get_range=True, robust=True, 
        range_kwargs={"encode_mode":"complex", "waveform_mode":"CW"})

Result figs:

https://github.com/cywhale/ODB/blob/master/EK/create_echogram_0_5_5.png

https://github.com/cywhale/ODB/blob/master/EK/create_echogram_0_5_6.png

-- Error message

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
/home/cmd/ek/test_openraw.ipynb Cell 7' in <module>
----> 1 fg = ep.visualize.create_echogram(ed, frequency=200000, 
      2         get_range=True, robust=True, 
      3         range_kwargs={"encode_mode":"complex", "waveform_mode":"CW"},figsize=(16,48),ylim=[150,0])

AttributeError: module 'echopype' has no attribute 'visualize'

I used previous testing raw file ( https://github.com/cywhale/ODB/blob/master/EK/test_v3.raw ) in ver 0.5.6 got the same Attribute Error, but cannot get correct plot when using version 0.5.5. In aboving testing, the raw file is just too big. But seems that this error always occurs on any other raw files when using version 0.5.6

leewujung commented 2 years ago

I think this is related to our decision in v0.5.6 to slim down the default requirements of echopype so that now you actually have to do import echopype.visualize in order to use the viz function (see here). Could you give it a try?

@lsetiawan @emiliom : ugh, a breaking change we didn't intend... let's make sure to add this to the documentation to avoid this issue!

cywhale commented 2 years ago

@leewujung Yes. But it raises a Value Error if using get_range=True:

ValueError                                Traceback (most recent call last)
/home/cmd/ek/test_openraw.ipynb Cell 7' in <module>
----> 1 fg = ep.visualize.create_echogram(ed0, frequency=200000,
      2         get_range=True, #robust=True, 
      3         range_kwargs={"encode_mode":"complex", "waveform_mode":"CW"},figsize=(16,48))

File ~/py3.8/lib/python3.8/site-packages/echopype/visualize/api.py:164, in create_echogram(data, frequency, get_range, range_kwargs, water_level, **kwargs)
    161 else:
    162     raise ValueError(f"Unsupported data type: {type(data)}")
--> 164 return _plot_echogram(
    165     ds,
    166     xaxis='ping_time',
    167     yaxis=yaxis,
    168     variable=variable,
    169     frequency=frequency,
    170     **kwargs,
    171 )

File ~/py3.8/lib/python3.8/site-packages/echopype/visualize/plot.py:188, in _plot_echogram(ds, frequency, variable, xaxis, yaxis, **kwargs)
    174 if (
    175     np.any(filtered_ds.isnull()).values == np.array(True)
    176     and 'range' in filtered_ds.coords
   (...)
    179 ):
    180     # Handle the nans for echodata and Sv
    181     filtered_ds = filtered_ds.sel(
    182         range_bin=filtered_ds.range_bin.where(
    183             ~filtered_ds.range.isel(ping_time=0).isnull()
   (...)
    186         .data
    187     )
--> 188 plot = filtered_ds.plot.pcolormesh(
    189     x=xaxis,
    190     y=yaxis,
    191     col=col,
    192     row=row,
    193     **kwargs,
    194 )
    195 _set_label(plot, frequency=frequency, col=col)
    196 plots.append(plot)

File ~/py3.8/lib/python3.8/site-packages/xarray/plot/plot.py:1308, in _plot2d.<locals>.plotmethod(_PlotMethods_obj, x, y, figsize, size, aspect, ax, row, col, col_wrap, xincrease, yincrease, add_colorbar, add_labels, vmin, vmax, cmap, colors, center, robust, extend, levels, infer_intervals, subplot_kws, cbar_ax, cbar_kwargs, xscale, yscale, xticks, yticks, xlim, ylim, norm, **kwargs)
   1306 for arg in ["_PlotMethods_obj", "newplotfunc", "kwargs"]:
   1307     del allargs[arg]
-> 1308 return newplotfunc(**allargs)

File ~/py3.8/lib/python3.8/site-packages/xarray/plot/plot.py:1112, in _plot2d.<locals>.newplotfunc(darray, x, y, figsize, size, aspect, ax, row, col, col_wrap, xincrease, yincrease, add_colorbar, add_labels, vmin, vmax, cmap, center, robust, extend, levels, infer_intervals, colors, subplot_kws, cbar_ax, cbar_kwargs, xscale, yscale, xticks, yticks, xlim, ylim, norm, **kwargs)
   1110     # Need the decorated plotting function
   1111     allargs["plotfunc"] = globals()[plotfunc.__name__]
-> 1112     return _easy_facetgrid(darray, kind="dataarray", **allargs)
   1114 plt = import_matplotlib_pyplot()
   1116 if (
   1117     plotfunc.__name__ == "surface"
   1118     and not kwargs.get("_is_facetgrid", False)
   1119     and ax is not None
   1120 ):

File ~/py3.8/lib/python3.8/site-packages/xarray/plot/facetgrid.py:689, in _easy_facetgrid(data, plotfunc, kind, x, y, row, col, col_wrap, sharex, sharey, aspect, size, subplot_kws, ax, figsize, **kwargs)
    686     return g.map_dataarray_line(plotfunc, x, y, **kwargs)
    688 if kind == "dataarray":
--> 689     return g.map_dataarray(plotfunc, x, y, **kwargs)
    691 if kind == "dataset":
    692     return g.map_dataset(plotfunc, x, y, **kwargs)

File ~/py3.8/lib/python3.8/site-packages/xarray/plot/facetgrid.py:285, in FacetGrid.map_dataarray(self, func, x, y, **kwargs)
    283     if d is not None:
    284         subset = self.data.loc[d]
--> 285         mappable = func(
    286             subset, x=x, y=y, ax=ax, **func_kwargs, _is_facetgrid=True
    287         )
    288         self._mappables.append(mappable)
    290 self._finalize_grid(x, y)

File ~/py3.8/lib/python3.8/site-packages/xarray/plot/plot.py:1210, in _plot2d.<locals>.newplotfunc(darray, x, y, figsize, size, aspect, ax, row, col, col_wrap, xincrease, yincrease, add_colorbar, add_labels, vmin, vmax, cmap, center, robust, extend, levels, infer_intervals, colors, subplot_kws, cbar_ax, cbar_kwargs, xscale, yscale, xticks, yticks, xlim, ylim, norm, **kwargs)
   1206     raise ValueError("plt.imshow's `aspect` kwarg is not available in xarray")
   1208 ax = get_axis(figsize, size, aspect, ax, **subplot_kws)
-> 1210 primitive = plotfunc(
   1211     xplt,
   1212     yplt,
   1213     zval,
   1214     ax=ax,
   1215     cmap=cmap_params["cmap"],
   1216     vmin=cmap_params["vmin"],
   1217     vmax=cmap_params["vmax"],
   1218     norm=cmap_params["norm"],
   1219     **kwargs,
   1220 )
   1222 # Label the plot with metadata
   1223 if add_labels:

File ~/py3.8/lib/python3.8/site-packages/xarray/plot/plot.py:1476, in pcolormesh(x, y, z, ax, xscale, yscale, infer_intervals, **kwargs)
   1473         y = _infer_interval_breaks(y, axis=1, scale=yscale)
   1474         y = _infer_interval_breaks(y, axis=0, scale=yscale)
-> 1476 primitive = ax.pcolormesh(x, y, z, **kwargs)
   1478 # by default, pcolormesh picks "round" values for bounds
   1479 # this results in ugly looking plots with lots of surrounding whitespace
   1480 if not hasattr(ax, "projection") and x.ndim == 1 and y.ndim == 1:
   1481     # not a cartopy geoaxis

File ~/py3.8/lib/python3.8/site-packages/matplotlib/__init__.py:1412, in _preprocess_data.<locals>.inner(ax, data, *args, **kwargs)
   1409 @functools.wraps(func)
   1410 def inner(ax, *args, data=None, **kwargs):
   1411     if data is None:
-> 1412         return func(ax, *map(sanitize_sequence, args), **kwargs)
   1414     bound = new_sig.bind(ax, *args, **kwargs)
   1415     auto_label = (bound.arguments.get(label_namer)
   1416                   or bound.kwargs.get(label_namer))

File ~/py3.8/lib/python3.8/site-packages/matplotlib/axes/_axes.py:6062, in Axes.pcolormesh(self, alpha, norm, cmap, vmin, vmax, shading, antialiased, *args, **kwargs)
   6059 shading = shading.lower()
   6060 kwargs.setdefault('edgecolors', 'none')
-> 6062 X, Y, C, shading = self._pcolorargs('pcolormesh', *args,
   6063                                     shading=shading, kwargs=kwargs)
   6064 coords = np.stack([X, Y], axis=-1)
   6065 # convert to one dimensional array

File ~/py3.8/lib/python3.8/site-packages/matplotlib/axes/_axes.py:5540, in Axes._pcolorargs(self, funcname, shading, *args, **kwargs)
   5538 if funcname == 'pcolormesh':
   5539     if np.ma.is_masked(X) or np.ma.is_masked(Y):
-> 5540         raise ValueError(
   5541             'x and y arguments to pcolormesh cannot have '
   5542             'non-finite values or be of type '
   5543             'numpy.ma.core.MaskedArray with masked values')
   5544     # safe_masked_invalid() returns an ndarray for dtypes other
   5545     # than floating point.
   5546     if isinstance(X, np.ma.core.MaskedArray):

ValueError: x and y arguments to pcolormesh cannot have non-finite values or be of type numpy.ma.core.MaskedArray with masked values
leewujung commented 2 years ago

@cywhale : to clarify, so the issue right now is that get_range=True would return the error above, but that importing echopype.visualize was fine?

emiliom commented 2 years ago

@lsetiawan @emiliom : ugh, a breaking change we didn't intend... let's make sure to add this to the documentation to avoid this issue!

Currently the visualize functionality is not in the documentation at all. How about opening a new issue to discuss its addition? That may need to be a whole new page in the docs.

cywhale commented 2 years ago

@cywhale : to clarify, so the issue right now is that get_range=True would return the error above, but that importing echopype.visualize was fine?

@leewujung Yes, exactly. But if a reproducible .raw is needed, I need to upload it to my google cloud. It's too big in size. The previous testing .raw (test_v3.raw) got another error though.

leewujung commented 2 years ago

@cywhale : sounds good, let us know when you have the test files up. Please do provide some info re different error from different files. Thanks!

Tagging @lsetiawan

leewujung commented 2 years ago

I believe #653 solves (but not allowing it) the issue @cywhale had for test_v3.raw. @cywhale could you please confirm?

The other test files you provided appear to have corrupted datagram or cause memory issues, and we should look into those in another issue. Please feel free to raise new issues for those so that we can keep track of them.

cywhale commented 2 years ago

I believe #653 solves (but not allowing it) the issue @cywhale had for test_v3.raw. @cywhale could you please confirm?

The other test files you provided appear to have corrupted datagram or cause memory issues, and we should look into those in another issue. Please feel free to raise new issues for those so that we can keep track of them.

Confirmed. It works. Got the same results as #653 both test_v3.raw open_raw and test_v3_D20211108-T033024.raw create_echogram. I'll use this version to test other raw files in my later trials. Lots of thanks!

leewujung commented 2 years ago

Thanks! I'll close this issue now.

Note that we are making some breaking changes in the variable names and moving a group in the netCDF file -- right now summarized in #641 (probably need some reorganization) and will be explained in the documentation -- so there may be some changes needed in your downstream. We are working on backward compatibility up to getting things into the EchoData object and all of these will go into v0.6.0.