geowatch.utils.util_kwplot module¶
Many of these have been moved to kwplot and can be removed.
- SeeAlso:
~/code/kwplot/kwplot/managers.py
Todo
[ ] from kwplot.managers import LabelManager as LabelModifier
[ ] from kwplot.managers import FigureManager
[ ] from kwplot.managers import FigureFinalizer
[ ] from kwplot.managers import Palette
[ ] from kwplot.managers import PaletteManager
[ ] from kwplot.managers import ArtistManager
[ ] etc…
- class geowatch.utils.util_kwplot.TitleBuilder[source]¶
Bases:
object
Simple class for adding information to a line, and then adding new lines.
Example
>>> from geowatch.utils.util_kwplot import * # NOQA >>> builder = TitleBuilder() >>> builder.add_part('Part 1') >>> builder.add_part('Part 2') >>> builder.ensure_newline() >>> builder.add_part('Part 3') >>> text = builder.finalize() >>> print(text) Part 1, Part 2 Part 3
- geowatch.utils.util_kwplot.dataframe_table(table, fpath, title=None, fontsize=12, table_conversion='auto', dpi=None, fnum=None, show=False)[source]¶
Use dataframe_image (dfi) to render a pandas dataframe.
- Parameters:
table (pandas.DataFrame | pandas.io.formats.style.Styler)
fpath (str | PathLike) – where to save the image
table_conversion (str) – can be auto, chrome, or matplotlib (auto tries to default to chrome)
Example
>>> # xdoctest: +REQUIRES(module:dataframe_image) >>> from geowatch.utils.util_kwplot import * # NOQA >>> import ubelt as ub >>> dpath = ub.Path.appdir('kwplot/tests/test_dfi').ensuredir() >>> import pandas as pd >>> table = pd.DataFrame({'foo': ['one', 'one', 'one', 'two', 'two', 'two'], ... 'bar': ['A', 'B', 'C', 'A', 'B', 'C'], ... 'baz': [1, 2, 3, 4, 5, 6], ... 'zoo': ['x', 'y', 'z', 'q', 'w', 't']}) >>> fpath = dpath / 'dfi.png' >>> dataframe_table(table, fpath, title='A caption / title')
- geowatch.utils.util_kwplot.humanize_dataframe(df, col_formats=None, human_labels=None, index_format=None, title=None)[source]¶
- geowatch.utils.util_kwplot.scatterplot_highlight(data, x, y, highlight, size=10, color='orange', marker='*', val_to_color=None, ax=None, linewidths=None)[source]¶
- geowatch.utils.util_kwplot.relabel_xticks(mapping, ax=None)[source]¶
Change the tick labels on the x-axis.
- Parameters:
mapping (dict)
ax (Axes | None)
- class geowatch.utils.util_kwplot.LabelModifier(mapping=None)[source]¶
Bases:
object
Registers multiple ways to relabel text on axes
Todo
[ ] Maybe rename to label manager?
Example
>>> # xdoctest: +SKIP >>> import sys, ubelt >>> from geowatch.utils.util_kwplot import * # NOQA >>> import pandas as pd >>> import kwarray >>> rng = kwarray.ensure_rng(0) >>> models = ['category1', 'category2', 'category3'] >>> data = pd.DataFrame([ >>> { >>> 'node.metrics.tpr': rng.rand(), >>> 'node.metrics.fpr': rng.rand(), >>> 'node.metrics.f1': rng.rand(), >>> 'node.param.model': rng.choice(models), >>> } for _ in range(100)]) >>> # xdoctest: +REQUIRES(env:PLOTTING_DOCTESTS) >>> import kwplot >>> sns = kwplot.autosns() >>> fig = kwplot.figure(fnum=1, pnum=(1, 2, 1), doclf=1) >>> ax1 = sns.boxplot(data=data, x='node.param.model', y='node.metrics.f1') >>> ax1.set_title('My node.param.model boxplot') >>> kwplot.figure(fnum=1, pnum=(1, 2, 2)) >>> ax2 = sns.scatterplot(data=data, x='node.metrics.tpr', y='node.metrics.f1', hue='node.param.model') >>> ax2.set_title('My node.param.model scatterplot') >>> ax = ax2 >>> # >>> def mapping(text): >>> text = text.replace('node.param.', '') >>> text = text.replace('node.metrics.', '') >>> return text >>> # >>> self = LabelModifier(mapping) >>> self.add_mapping({'category2': 'FOO', 'category3': 'BAR'}) >>> #fig.canvas.draw() >>> # >>> self.relabel(ax=ax1) >>> self.relabel(ax=ax2) >>> fig.canvas.draw()
- class geowatch.utils.util_kwplot.FigureFinalizer(dpath='.', size_inches=None, cropwhite=True, tight_layout=True, verbose=0, **kwargs)[source]¶
Bases:
NiceRepr
Helper for defining where and how figures will be saved on disk.
- Known Parameters:
dpi : float format : str metadata : dict bbox_inches : str pad_inches : float facecolor : color edgecolor : color backend : str orientation : papertype : transparent : bbox_extra_artists : pil_kwargs :
Example
from geowatch.utils.util_kwplot import * # NOQA self = FigureFinalizer() print(‘self = {}’.format(ub.urepr(self, nl=1))) self.update(dpi=300)
- finalize(fig, fpath, **kwargs)[source]¶
Sets the figure properties, like size, tight layout, etc, writes to disk, and then crops the whitespace out.
- Parameters:
fig (matplotlib.figure.Figure) – figure to safe
fpath (str | PathLike) – where to save the figure image
**kwargs – overrides this config for this finalize only
- geowatch.utils.util_kwplot.fix_matplotlib_dates(dates, format='mdate')[source]¶
- Parameters:
dates (List[None | Coerceble[datetime]]) – input dates to fixup
format (str) – can be mdate for direct matplotlib usage or datetime for seaborn usage.
Note
seaborn seems to do just fine with timestamps… todo:
add regular matplotlib test for a real demo of where this is useful
Example
>>> from geowatch.utils.util_kwplot import * # NOQA >>> from kwutil.util_time import coerce_datetime >>> from kwutil.util_time import coerce_timedelta >>> import pandas as pd >>> import numpy as np >>> delta = coerce_timedelta('1 day') >>> n = 100 >>> min_date = coerce_datetime('2020-01-01').timestamp() >>> max_date = coerce_datetime('2021-01-01').timestamp() >>> from kwarray.distributions import Uniform >>> distri = Uniform(min_date, max_date) >>> timestamps = distri.sample(n) >>> timestamps[np.random.rand(n) > 0.5] = np.nan >>> dates = list(map(coerce_datetime, timestamps)) >>> scores = np.random.rand(len(dates)) >>> table = pd.DataFrame({ >>> 'isodates': [None if d is None else d.isoformat() for d in dates], >>> 'dates': dates, >>> 'timestamps': timestamps, >>> 'scores': scores >>> }) >>> table['fixed_dates'] = fix_matplotlib_dates(table.dates, format='datetime') >>> table['fixed_timestamps'] = fix_matplotlib_dates(table.timestamps, format='datetime') >>> table['fixed_isodates'] = fix_matplotlib_dates(table.isodates, format='datetime') >>> table['mdate_dates'] = fix_matplotlib_dates(table.dates, format='mdate') >>> table['mdate_timestamps'] = fix_matplotlib_dates(table.timestamps, format='mdate') >>> table['mdate_isodates'] = fix_matplotlib_dates(table.isodates, format='mdate') >>> # xdoctest: +REQUIRES(env:PLOTTING_DOCTESTS) >>> import kwplot >>> sns = kwplot.autosns() >>> pnum_ = kwplot.PlotNums(nSubplots=8) >>> ax = kwplot.figure(fnum=1, doclf=1) >>> for key in table.columns.difference({'scores'}): >>> ax = kwplot.figure(fnum=1, doclf=0, pnum=pnum_()).gca() >>> sns.scatterplot(data=table, x=key, y='scores', ax=ax) >>> if key.startswith('mdate_'): >>> # TODO: make this formatter fixup work better. >>> import matplotlib.dates as mdates >>> ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d')) >>> ax.xaxis.set_major_locator(mdates.DayLocator(interval=90))
- geowatch.utils.util_kwplot.extract_legend(ax)[source]¶
Creates a new figure that contains the original legend.
- class geowatch.utils.util_kwplot.ArtistManager[source]¶
Bases:
object
Accumulates artist collections (e.g. lines, patches, ellipses) the user is interested in drawing so we can draw them efficiently.
References
https://matplotlib.org/stable/api/collections_api.html https://matplotlib.org/stable/gallery/shapes_and_collections/ellipse_collection.html https://stackoverflow.com/questions/32444037/how-can-i-plot-many-thousands-of-circles-quickly
Example
>>> # xdoctest: +SKIP >>> from geowatch.utils.util_kwplot import * # NOQA >>> # xdoctest: +REQUIRES(env:PLOTTING_DOCTESTS) >>> import kwplot >>> sns = kwplot.autosns() >>> fig = kwplot.figure(fnum=1) >>> self = ArtistManager() >>> import kwimage >>> points = kwimage.Polygon.star().data['exterior'].data >>> self.add_linestring(points) >>> ax = fig.gca() >>> self.add_to_axes(ax) >>> ax.relim() >>> ax.set_xlim(-1, 1) >>> ax.set_ylim(-1, 1)
Example
>>> # xdoctest: +SKIP >>> from geowatch.utils.util_kwplot import * # NOQA >>> # xdoctest: +REQUIRES(env:PLOTTING_DOCTESTS) >>> import kwplot >>> sns = kwplot.autosns() >>> fig = kwplot.figure(fnum=1) >>> self = ArtistManager() >>> import kwimage >>> points = kwimage.Polygon.star().data['exterior'].data >>> y = 1 >>> self.add_linestring([(0, y), (1, y)], color='kitware_blue') >>> y = 2 >>> self.add_linestring([(0, y), (1, y)], color='kitware_green') >>> y = 3 >>> self.add_circle((0, y), r=.1, color='kitware_darkgreen') >>> self.add_circle((0.5, y), r=.1, color='kitware_darkblue') >>> self.add_circle((0.2, y), r=.1, color='kitware_darkblue') >>> self.add_circle((1.0, y), r=.1, color='kitware_darkblue') >>> self.add_ellipse((0.2, 1), .1, .2, angle=10, color='kitware_gray') >>> self.add_linestring([(0, y), (1, y)], color='kitware_blue') >>> y = 4 >>> self.add_linestring([(0, y), (1, y)], color='kitware_blue') >>> self.add_circle_marker((0, y), r=10, color='kitware_darkgreen') >>> self.add_circle_marker((0.5, y), r=10, color='kitware_darkblue') >>> self.add_circle_marker((0.2, y), r=10, color='kitware_darkblue') >>> self.add_circle_marker((1.0, y), r=10, color='kitware_darkblue') >>> self.add_ellipse_marker((0.2, 2), 10, 20, angle=10, color='kitware_gray') >>> self.add_linestring(np.array([ ... (0.2, 0.5), ... (0.45, 1.6), ... (0.62, 2.3), ... (0.82, 4.9), >>> ]), color='kitware_yellow') >>> self.add_to_axes() >>> ax = fig.gca() >>> ax.set_xlim(0, 1) >>> ax.set_ylim(0, 5) >>> ax.autoscale_view()
- add_linestring(points, **attrs)[source]¶
- Parameters:
points (List[Tuple[float, float]] | ndarray) – an Nx2 set of ordered points
Note
perhaps allow adding markers based on ax.scatter?
- add_ellipse_marker(xy, rx, ry, angle=0, color=None, **attrs)[source]¶
- Parameters:
xy – center
rx – radius in the first axis (size is in points, i.e. same way plot markers are sized)
ry – radius in the second axis
angle (float) – The angles of the first axes, degrees CCW from the x-axis.
- geowatch.utils.util_kwplot.time_sample_arcplot(time_samples, yloc=1, ax=None)[source]¶
Example
>>> from geowatch.utils.util_kwplot import * # NOQA >>> time_samples = [ >>> [1, 3, 5, 7, 9], >>> [2, 3, 4, 6, 8], >>> [1, 5, 6, 7, 9], >>> ] >>> import kwplot >>> kwplot.autompl() >>> time_sample_arcplot(time_samples) >>> kwplot.show_if_requested()
References
- class geowatch.utils.util_kwplot.Palette[source]¶
Bases:
UDict
Dictionary subclass that maps a label to a particular color.
Explicit colors per label can be given, but for other unspecified labels we attempt to generate a distinct color.
Example
>>> from geowatch.utils.util_kwplot import * # NOQA >>> self1 = Palette() >>> self1.add_labels(labels=['a', 'b']) >>> self1.update({'foo': 'blue'}) >>> self1.update(['bar', 'baz']) >>> self2 = Palette.coerce({'foo': 'blue'}) >>> self2.update(['a', 'b', 'bar', 'baz']) >>> self1 = self1.sorted_keys() >>> self2 = self2.sorted_keys() >>> # xdoctest: +REQUIRES(env:PLOTTING_DOCTESTS) >>> import kwplot >>> kwplot.autoplt() >>> canvas1 = self1.make_legend_img() >>> canvas2 = self2.make_legend_img() >>> canvas = kwimage.stack_images([canvas1, canvas2]) >>> kwplot.imshow(canvas)
- add_labels(label_to_color=None, labels=None)[source]¶
Forces particular labels to take a specific color and then chooses colors for any other unspecified label.
- Parameters:
label_to_color (Dict[str, Any] | None) – mapping to colors that are forced
labels (List[str] | None) – new labels that should take distinct colors
- class geowatch.utils.util_kwplot.PaletteManager[source]¶
Bases:
object
Manages colors that should be kept constant across different labels for multiple parameters.
self = PaletteManager() self.update_params(‘region_id’, {‘region1’: ‘red’})