|
23 | 23 | from .patheffects import ColdFront, OccludedFront, StationaryFront, WarmFront |
24 | 24 | from .station_plot import StationPlot |
25 | 25 | from .text import scattertext, TextCollection |
26 | | -from ..calc import reduce_point_density, smooth_n_point, zoom_xarray |
| 26 | +from ..calc import find_peaks, reduce_point_density, smooth_n_point, zoom_xarray |
27 | 27 | from ..package_tools import Exporter |
28 | 28 | from ..units import units |
29 | 29 |
|
@@ -1032,7 +1032,7 @@ class ContourPlot(PlotScalar, ContourTraits, ValidationMixin): |
1032 | 1032 | black. |
1033 | 1033 |
|
1034 | 1034 | This trait can be set to any Matplotlib color |
1035 | | - (https://matplotlib.org/3.1.0/gallery/color/named_colors.html) |
| 1035 | + (https://matplotlib.org/stable/gallery/color/named_colors.html) |
1036 | 1036 | """ |
1037 | 1037 |
|
1038 | 1038 | linewidth = Int(2) |
@@ -1170,7 +1170,7 @@ class PlotVector(Plots2D): |
1170 | 1170 | black. |
1171 | 1171 |
|
1172 | 1172 | This trait can be set to any named color from |
1173 | | - `Matplotlibs Colors <https://matplotlib.org/3.1.0/gallery/color/named_colors.html>` |
| 1173 | + `Matplotlibs Colors <https://matplotlib.org/stable/gallery/color/named_colors.html>` |
1174 | 1174 | """ |
1175 | 1175 |
|
1176 | 1176 | @observe('field') |
@@ -1385,6 +1385,131 @@ def _build(self): |
1385 | 1385 | self.parent.ax.quiverkey(self.handle, labelcolor=self.color, **key_kwargs) |
1386 | 1386 |
|
1387 | 1387 |
|
| 1388 | +@exporter.export |
| 1389 | +class PlotExtrema(PlotScalar, MetPyHasTraits, ValidationMixin): |
| 1390 | + """Plot maximum and/or minimum symbols and values of gridded datasets.""" |
| 1391 | + |
| 1392 | + peaks = List(default_value=['maxima']) |
| 1393 | + peaks.__doc__ = """A list of strings indicating which extrema to plot. |
| 1394 | + The default value is ['maxima']. |
| 1395 | +
|
| 1396 | + The only valid strings are 'maxima' and 'minima' for this attribute. |
| 1397 | +
|
| 1398 | + See Also |
| 1399 | + -------- |
| 1400 | + metpy.calc.find_peaks |
| 1401 | + """ |
| 1402 | + |
| 1403 | + peak_ratio = List(default_value=[2.0]) |
| 1404 | + peak_ratio.__doc__ = """A list of float values for the inerquartile range ratio. |
| 1405 | + The default value is [2.0]. |
| 1406 | +
|
| 1407 | + This ratio value is an optional setting for the find_peaks function that uses the |
| 1408 | + inner-quartile range to create a threshold for persistence of local peaks. |
| 1409 | + """ |
| 1410 | + |
| 1411 | + symbol = List(default_value=['H']) |
| 1412 | + symbol.__doc__ = """A list of strings representing the extrema being plotted. |
| 1413 | + The default value is ['H']. |
| 1414 | +
|
| 1415 | + This can be set to any string you wish to plot at the extrema point. For example, use |
| 1416 | + 'L' to signify a pressure minima. |
| 1417 | + """ |
| 1418 | + |
| 1419 | + symbol_size = List(default_value=[20.0]) |
| 1420 | + symbol_size.__doc__ = """A list of float values setting the size of the extrema symbol. |
| 1421 | + The default value is [20.0]. |
| 1422 | +
|
| 1423 | + The value of the float will set the size of the symbol with larger values generating |
| 1424 | + a larger symbol. |
| 1425 | + """ |
| 1426 | + |
| 1427 | + symbol_color = List(default_value=['black']) |
| 1428 | + symbol_color.__doc__ = """A list of strings representing the color of the symbol. |
| 1429 | + The default value is ['black']. |
| 1430 | +
|
| 1431 | + This trait can be set to any named color from |
| 1432 | + `Matplotlibs Colors <https://matplotlib.org/stable/gallery/color/named_colors.html>` |
| 1433 | + """ |
| 1434 | + |
| 1435 | + plot_value = List(default_value=[False]) |
| 1436 | + plot_value.__doc__ = """A list of booleans representing whether to plot the numeric |
| 1437 | + extrema integer value. The default value is [False]. |
| 1438 | +
|
| 1439 | + This parameter controls plotting the numeric local maxima or minima value in |
| 1440 | + addition to the extrema symbol. |
| 1441 | + """ |
| 1442 | + |
| 1443 | + text_size = List(default_value=[12]) |
| 1444 | + text_size.__doc__ = """A list of float values setting the text size of the extrema value. |
| 1445 | + The default value is [12.0]. |
| 1446 | + """ |
| 1447 | + |
| 1448 | + text_location = List(default_value=['bottom']) |
| 1449 | + text_location.__doc__ = """A list of strings representing the vertical alignment for |
| 1450 | + plotting the extrema value text. The default value is ['bottom']. |
| 1451 | +
|
| 1452 | + The available options are 'baseline', 'bottom', 'center', 'center_baseline', 'top'. |
| 1453 | + """ |
| 1454 | + |
| 1455 | + @observe('extrema', 'symbol', 'symbol_size', 'plot_value', 'symbol_color', 'text_size', |
| 1456 | + 'text_location') |
| 1457 | + def _set_need_rebuild(self, _): |
| 1458 | + """Handle changes to attributes that need to regenerate everything.""" |
| 1459 | + # Because matplotlib doesn't let you just change these properties, we need |
| 1460 | + # to trigger a clear and re-call of quiver() |
| 1461 | + self.clear() |
| 1462 | + |
| 1463 | + def _build(self): |
| 1464 | + """Build the raster plot by calling any plotting methods as necessary.""" |
| 1465 | + x_like, y_like, imdata = self.plotdata |
| 1466 | + |
| 1467 | + kwargs = plot_kwargs(imdata, self.mpl_args) |
| 1468 | + |
| 1469 | + for i, extreme in enumerate(self.peaks): |
| 1470 | + peak_ratio = self.peak_ratio[i] if len(self.peak_ratio) > 1 else self.peak_ratio[0] |
| 1471 | + |
| 1472 | + if extreme == 'minima': |
| 1473 | + extrema_y, extrema_x = find_peaks(imdata.values, maxima=False, |
| 1474 | + iqr_ratio=peak_ratio) |
| 1475 | + elif extreme == 'maxima': |
| 1476 | + extrema_y, extrema_x = find_peaks(imdata.values, iqr_ratio=peak_ratio) |
| 1477 | + |
| 1478 | + plot_value = self.plot_value[i] if len(self.plot_value) > 1 else self.plot_value[0] |
| 1479 | + |
| 1480 | + location = 'top' if plot_value else 'center' |
| 1481 | + |
| 1482 | + symbol = self.symbol[i] if len(self.symbol) > 1 else self.symbol[0] |
| 1483 | + |
| 1484 | + if len(self.symbol_color) > 1: |
| 1485 | + color = self.symbol_color[i] |
| 1486 | + else: |
| 1487 | + color = self.symbol_color[0] |
| 1488 | + |
| 1489 | + if len(self.symbol_size) > 1: |
| 1490 | + symbol_size = self.symbol_size[i] |
| 1491 | + else: |
| 1492 | + symbol_size = self.symbol_size[0] |
| 1493 | + |
| 1494 | + text_size = self.text_size[i] if len(self.text_size) > 1 else self.text_size[0] |
| 1495 | + |
| 1496 | + if len(self.text_location) > 1: |
| 1497 | + text_loc = self.text_location[i] |
| 1498 | + else: |
| 1499 | + text_loc = self.text_location[0] |
| 1500 | + |
| 1501 | + scattertext(self.parent.ax, x_like[extrema_x], y_like[extrema_y], symbol, |
| 1502 | + color=color, size=int(symbol_size), |
| 1503 | + verticalalignment=location, clip_on=True, **kwargs) |
| 1504 | + |
| 1505 | + if plot_value: |
| 1506 | + scattertext(self.parent.ax, x_like[extrema_x], y_like[extrema_y], |
| 1507 | + imdata.values[extrema_y, extrema_x], |
| 1508 | + color=color, size=int(text_size), |
| 1509 | + verticalalignment=text_loc, formatter='.0f', |
| 1510 | + clip_on=True, **kwargs) |
| 1511 | + |
| 1512 | + |
1388 | 1513 | @exporter.export |
1389 | 1514 | class PlotObs(MetPyHasTraits, ValidationMixin): |
1390 | 1515 | """The highest level class related to plotting observed surface and upperair data. |
|
0 commit comments