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

image_range trait in declarative plotting interface doesn't accept arbitrary floating point values #3027

Closed
wxmann opened this issue Apr 28, 2023 · 1 comment · Fixed by #3028
Labels
Area: Plots Pertains to producing plots Type: Bug Something is not working like it should
Milestone

Comments

@wxmann
Copy link
Contributor

wxmann commented Apr 28, 2023

What went wrong?

There's really two issues in one, but I didn't want to clog up the issue list. The two are related, and both seem to be small changes.

  1. The image_range trait for ImagePlot in the declarative plotting interface doesn't accept arbitrary floating point values, only integer ranges.

  2. The image_range trait accepts mpl.Normalize instances, but setting an mpl.Normalize instance causes the plotting to blow up.

These are small changes and I'm more than happy to put up PR's to fix these, but wanted to run them by the team.

Operating System

MacOS

Version

1.4.1

Python Version

3.11.3

Code to Reproduce

ds = xr.open_dataset(get_test_data('narr_example.nc')).metpy.parse_cf().sel(time='1987-04-04T18:00:00', isobaric=500)

img = ImagePlot()
img.data = ds
img.field = 'Temperature'

# first issue:
img.image_range = (14.5, 25.5)

# second issue: 
from matplotlib.colors import Normalize
img.image_range = Normalize(vmin=14.5, vmax=25.5)

panel = MapPanel()
panel.area = [-107, -93, 29, 41]
panel.projection = 'lcc'
panel.layers = ['states', 'coastline', 'borders']
panel.plots = [img]

pc = PanelContainer()
pc.size = (14, 18)
pc.panels = [panel]

pc.show()

Errors, Traceback, and Logs

TraitError                                Traceback (most recent call last)
Cell In[5], line 4
      2 img.data = ds
      3 img.field = 'Temperature'
----> 4 img.image_range = (14.5, 25.5)
      6 panel = MapPanel()
      7 panel.area = [-107, -93, 29, 41]

File ~/miniconda3/envs/yt-env/lib/python3.11/site-packages/metpy/plots/declarative.py:526, in ValidationMixin.__setattr__(self, name, value)
    524 allowlist.extend(self.trait_names())
    525 if name in allowlist or name.startswith('_'):
--> 526     super().__setattr__(name, value)
    527 else:
    528     closest = get_close_matches(name, allowlist, n=1)

File ~/miniconda3/envs/yt-env/lib/python3.11/site-packages/traitlets/traitlets.py:732, in TraitType.__set__(self, obj, value)
    730     raise TraitError('The "%s" trait is read-only.' % self.name)
    731 else:
--> 732     self.set(obj, value)

File ~/miniconda3/envs/yt-env/lib/python3.11/site-packages/traitlets/traitlets.py:706, in TraitType.set(self, obj, value)
    705 def set(self, obj, value):
--> 706     new_value = self._validate(obj, value)
    707     try:
    708         old_value = obj._trait_values[self.name]

File ~/miniconda3/envs/yt-env/lib/python3.11/site-packages/traitlets/traitlets.py:738, in TraitType._validate(self, obj, value)
    736     return value
    737 if hasattr(self, "validate"):
--> 738     value = self.validate(obj, value)
    739 if obj._cross_validation_lock is False:
    740     value = self._cross_validate(obj, value)

File ~/miniconda3/envs/yt-env/lib/python3.11/site-packages/traitlets/traitlets.py:2306, in Union.validate(self, obj, value)
   2304         except TraitError:
   2305             continue
-> 2306 self.error(obj, value)

File ~/miniconda3/envs/yt-env/lib/python3.11/site-packages/traitlets/traitlets.py:844, in TraitType.error(self, obj, value, error, info)
    838 else:
    839     e = "The '{}' trait expected {}, not {}.".format(
    840         self.name,
    841         self.info(),
    842         describe("the", value),
    843     )
--> 844 raise TraitError(e)

TraitError: The 'image_range' trait of an ImagePlot instance expected a tuple or a Normalize, not the tuple (14.5, 25.5).

Here's the traceback for the Normalize issue:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[7], line 18
     15 pc.size = (14, 18)
     16 pc.panels = [panel]
---> 18 pc.show()

File ~/miniconda3/envs/yt-env/lib/python3.11/site-packages/metpy/plots/declarative.py:622, in PanelContainer.show(self)
    620 def show(self):
    621     """Show the constructed graphic on the screen."""
--> 622     self.draw()
    623     plt.show()

File ~/miniconda3/envs/yt-env/lib/python3.11/site-packages/metpy/plots/declarative.py:609, in PanelContainer.draw(self)
    607 for panel in self.panels:
    608     with panel.hold_trait_notifications():
--> 609         panel.draw()

File ~/miniconda3/envs/yt-env/lib/python3.11/site-packages/metpy/plots/declarative.py:897, in MapPanel.draw(self)
    895 for p in self.plots:
    896     with p.hold_trait_notifications():
--> 897         p.draw()
    899 # Add all of the maps
    900 if len(self.layers) > len(self.layers_edgecolor):

File ~/miniconda3/envs/yt-env/lib/python3.11/site-packages/metpy/plots/declarative.py:1259, in PlotScalar.draw(self)
   1257 if self._need_redraw:
   1258     if getattr(self, 'handle', None) is None:
-> 1259         self._build()
   1260     if getattr(self, 'colorbar', None) is not None:
   1261         cbar = self.parent.ax.figure.colorbar(
   1262             self.handle, orientation=self.colorbar, pad=0, aspect=50)

File ~/miniconda3/envs/yt-env/lib/python3.11/site-packages/metpy/plots/declarative.py:1383, in ImagePlot._build(self)
   1377 kwargs['extent'] = (x_like[0], x_like[-1], y_like.min(), y_like.max())
   1378 kwargs['origin'] = 'upper' if y_like[0] > y_like[-1] else 'lower'
   1380 self.handle = self.parent.ax.imshow(
   1381     imdata,
   1382     cmap=self._cmap_obj,
-> 1383     norm=self._norm_obj,
   1384     **kwargs
   1385 )

File ~/miniconda3/envs/yt-env/lib/python3.11/site-packages/metpy/plots/declarative.py:1049, in Plots2D._norm_obj(self)
   1042 @property
   1043 def _norm_obj(self):
   1044     """Return the normalization object.
   1045 
   1046     Converts the tuple image range to a matplotlib normalization instance.
   1047 
   1048     """
-> 1049     return plt.Normalize(*self.image_range)

TypeError: matplotlib.colors.Normalize() argument after * must be an iterable, not Normalize
@wxmann wxmann added the Type: Bug Something is not working like it should label Apr 28, 2023
@dopplershift
Copy link
Member

Yes, please! We're preparing for a release early next week, so if you'd like fixes for this issue to be included get in a PR quickly!

@dopplershift dopplershift added the Area: Plots Pertains to producing plots label Apr 28, 2023
@dopplershift dopplershift added this to the 1.5.0 milestone Apr 28, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: Plots Pertains to producing plots Type: Bug Something is not working like it should
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants