Skip to content

Releases: raphaelquast/EOmaps

EOmaps v4.1.1

27 May 18:46
8e9db5a
Compare
Choose a tag to compare

A bugfix release that brings some nice updates for the colorbar.

🌈 updates for the colorbar

  • ⭐ Colorbars now have proper extension-arrows to indicate values outside the colorbar-range
  • m.add_colorbar() supports some new arguments to further customize the colorbar:
    • histogram_size : set the relative height of the histogram in relation to the height of the colorbar
      (use 0 for a plain colorbar and 999 for a plain histogram)
    • extend_frac: set the relative size of the extension-arrows
    • add_extend_arrows: toggle drawing extension-arrows
      (by default arrows are only drawn if there are values outside the [vmin, vmax] range)

🌦️ changes

  • setting vmin/vmax no longer clips data-values
    (e.g. callbacks now always retrieve actual data-values independent of vmin/vmax)

🔨 fixes

  • fix setting zorder for WebMap layers
  • make sure the default zorder for m.plot_map() is 1 for all shapes
  • fix test-action issues (use mamba + updated version of conda-incubator)
  • fix adding static annotations by dataset-ID with m.add_annotation()
  • fix some issues with draggable axes
  • fix sorting of callback-execution order

EOmaps v4.1

16 May 18:20
43eaaca
Compare
Choose a tag to compare

A minor release that brings an awesome new feature and some bugfixes.

🔬 New feature: Inset-maps!

  • Quickly create zoomed-in views on selected regions of a map with m.new_inset_map()

Checkout the docs for more details: 🔬 Inset-maps - zoom-in on interesting areas

test

🔨 fixes

  • allow using a scalar radius for calculating ellipse and rectangle points
  • make sure the blit-manager always uses the correct figure object
  • make histogram plot background visible (but set boundary color to none)
  • fix wrong error-catching for layer-slider
  • fix issues with colored histograms for discrete colormaps

EOmaps v4.0

04 May 21:13
3b83c5f
Compare
Choose a tag to compare

A new major release that brings some nice new features, a lot of updates and some outstanding api-changes.

🌩 changes

❗ There are breaking changes to EOmaps v3.x ❗
🌞 For a quick-guide on how to port existing scripts to v4.x see: ⚙️ port script from v3.x to v4.x

[or click on the text below for details!]

🔸 m.plot_specs and m.set_plot_specs(...) have been removed
  • "vmin", "vmax" and "cmap" are now set when calling m.plot_map(...)
  • "density", "tick_precision", "histbins" and "label" are now set when calling m.add_colorbar(...)
  • "cpos" and "cpos_radius" are now set with m.set_data_specs(...)
🔸 voroni_diagram is now correctly called voronoi_diagram

This just fixes the typo in the name.

# --- OLD ---
m.set_shape.voroni_diagram()

# --- NEW ---
m.set_shape.voronoi_diagram()
🔸 The data-specs xcoord and ycoord have been renamed to x and y

This change is optional and will only raise a depreciation warning for now...
The old naming-convention will however be removed in future releases so it's highly recommended to use the new (shorter and more intuitive🙂) x and y variable names.

# --- OLD ---
m.set_data(data=..., xcoord=..., ycoord=..., ...)
m.data_specs.xcoord

# --- NEW ---
m.set_data(data=..., x=..., y=..., ...)
m.data_specs.x
🔸 Custom callback functions now have a slightly different call-signature

This removes the contra-intuitive "binding" of functions to the Maps-objects and ensures that class-methods can be used as callbacks without unwanted side-effects.

  • The first argument is no longer identified automatically as the Maps-object!
    (if you need access to the underlying Maps-object, simply pass it as an argument!)
m = Maps()
def cb(m, **kwargs):
    pos = kwargs["pos"]
    print("the Maps-object:", m)
    print("the click-position is", pos)

m.cb.click.attach(cb, m=m)
👾 [click to show] how to get back the old behaviour

To get back the old behavior you have to "bind" the callback functions to the Maps-object, e.g:

m = Maps()
def cb(self, **kwargs):
    ...

m.cb.click.attach(cb.__get__(m))

or simply pass the Maps-object as kwarg, e.g.:

m = Maps()
def cb(self, **kwargs):
    ...

m.cb.click.attach(cb self=m)

🌳 NEW

  • ⭐ The Sentinel-2 cloudless WebMap service can now be used via m.add_wms.s2_cloudless
  • 🌟 It is now possible to set "coordinate-only" datasets!
    • This is particularly useful if you want to manually assign colors
    m.set_data(None, [1,2,3], [1,2,3])
    m.plot_map(fc=["r", "g", "b"])

🚀 there's a new plot shape! m.set_shape.raster

A fast way to plot 2D datasets.

[click to show] 🔸 details
  • it's quite similar to plt.imshow (e.g. a QuadMesh is used to speed up plotting of 2D datasets)
  • the differences to shade_raster are:
    • the whole dataset is always plotted (so for very very large datasets shade_raster is much faster!)
    • it supports manual color specifications (shade_raster does not)
  • the differences between rectangles and raster are:
    • raster does not take the curvature of the edges into account
    • raster determines the pixel-size based on neighboring pixels, rectangles allows arbitrary pixel-dimensions

🌈 there have been some major improvements for manual color specifications!

Checkout the 🌎 Customizing the plot section of the docs for details!

Colors can now be set manually with all shapes (except shade shapes) using
m.plot_map(fc=[...]) (or facecolor= or color=)!

[click to show] 🔸 Possible ways to specify colors.
  • a single value (RGB/RGBA tuple, a matplotlib color-name or a hex-color)
  • a tuple of 3/4 arrays in the same shape as the coordinates (identified as RGB/RGBA values)
  • a list/array of RGB tuples, e.g. [(1, 0, 0.25), (0.3, 0.4, 0.5), ....]
  • a list/array of RGBA tuples, e.g.: [(1, 0, 0.25, 0.15), (0.3, 0.4, 0.5, 0.25), ....]
  • a list/array of matplotlib named-colors, e.g. ["r", "olive", "darkblue", ...]
  • a list/array of hex-colors, e.g.: ['#ff0040', '#4c6680', ...]
    For example:
m = Maps()
m.set_data(None, [1,2,3,4,5], [1,2,3,4,5])
# use named colors
m.plot_map(ec="k", fc=["r", "olive", "darkblue", "orange", "indigo"])
# or RGB tuples
m.plot_map(color=[(1, 0, 0), (.4, .5, .6), (.2, .7, .2), (.45, .12, .98), (.94, .45, .56)])
# or a single color for all datapoints
m.plot_map(facecolor="g", edgecolor="r")
# or use 3 individual arrays that should be identified as RGB values
m.plot_map(fc=([0.1,0.2,0.3,0.4,0.5], [0.1,0.2,0.3,0.4,0.5], [0.1,0.2,0.3,0.4,0.5])

☁️ minor (non-breaking) changes

  • the default radius_crs for the mark callback is now determined based on the radius_crs assigned in the plot-shape
    ... this definition allows using m.cb.pick.attach.mark(buffer=3) directly without having to worry about the crs
    (previously in, e.g. the input-crs was used by default)
  • the background patch of the compass is now by default set to None

🔨 fixes

  • fix issues with manual color specifications for various plot-shapes
    (e.g. when providing explicit color-arrays via m.plot_map(color=[...]) )
  • fix issues with shapes close to crs-bounds
  • support estimation of different x- and y- radius for 2D datasets
  • warn if datapoints are masked or if datapoints are outside the CRS-bounds
  • cache shape transformers (so they are not re-initialized all the time)

EOmaps v3.5

13 Apr 22:30
48fb42c
Compare
Choose a tag to compare

🚀 updates

⭐ EOmaps now properly handles encoded datasets!

  • This saves a lot of memory and provides a huge speedup when plotting integer-encoded datasets!
  • If you plot GeoTIFFs or NetCDFs with the functions Maps.read_data, Maps.from_file or m.new_layer_from_file, the data is now kept in the encoded dtype and conversions are only performed "on demand" (e.g. when adding colorbars or in pick-callbacks)
    • (if you really want to immediately convert all data-values, use mask_and_scale=True )
  • The encoding information can be get/set via m.data_specs.encoding or m.set_data_specs(encoding=...)
m = Maps()
m.set_data(data=[1,2,3], xcoord=[1,2,3], ycoord=[1,2,3], encoding=dict(scale_factor=0.01, add_offset=1))
# the "decoding" of the values is evaluated via   "add_offset" + "scale_factor" * x
# e.g.: in this case the actual data-values are :   [1.01, 1.02, 1.03]

🌳 New

  • ⭐ The colorbar can now be used as a dynamic shade indicator with m.add_colorbar(dynamic_shade_indicator=True)

    • it is dynamically updated based on the distribution of shaded pixels in the current field of view.
      (only possible with m.set_shape.shade_raster() or m.set_shape.shade_points() )
  • ⭐ There is now a way to use pick callbacks on datasets without plotting the data first.

    • To make a "pick-only" dataset, use m.set_data(...) to assign the dataset and then
      call m.make_dataset_pickable() to initialize all required information to make the dataset pickable.
    • This is useful if you want to indicate certain informations "on click" without plotting the data

⚙️ changes

  • The default plot-shape is now determined based on the size of the assigned dataset.
    • <500k datapoints: m.set_shape.ellipses()
    • >500k datapoints: m.set_shape.shade_raster()
  • Maps.from_file and m.new_layer_from_file now no longer attempt multiple shapes for plotting in case the first attempt fails
    (the default shape is used if no explicit shape-name is provided)

🔨 fixes

  • Fix typo in m.add_colorbar
  • Fix some typos in the docs
  • Fix unnecessary dtype conversions in "shade_raster" and "shade_points"
  • Avoid dtype conversions when reading NetCDFs and GeoTIFFs

EOmaps v3.4.1

05 Apr 21:21
865f435
Compare
Choose a tag to compare

[hotfix release to fix issues with multiple maps in one figure]

... EOmaps v3.4

A release that brings a lot of updates on speed and memory management and some very nice (but possibly breaking) changes compared previous versions of EOmaps.

❗ IMPORTANT CHANGES ❗

⭐ Starting with EOmaps v3.4 all callbacks and colorbars are layer-specific !

This means that callbacks only trigger if the layer of the associated Maps object is visible!
(...and colorbars are only visible if the associated layer is visible)

  • To trigger callbacks or add features & datasets independent of the visible layer, use m.all.cb. ...
    (or attach them to a Maps object on the "all" layer)

  • Note: pick callbacks now always react to the visible collection!
    (except for the ones on the "all" layer)

    m = Maps(layer=0)
    m.cb.click.attach.annotate()       # this callback is ONLY executed if the layer 0 is visible
    
    m1 = m.new_layer(layer=1)
    m1.cb.click.attach.mark()          # this callback is ONLY executed if the layer 1 is visible
    
    m.all.cb.click.attach.annotate()   # this callback is executed independent of the visible layer!

🍃 removed arguments

  • the obsolete "orientation" argument has been removed from Maps(...)
    (it set the colorbar-orientation which is now specified via m.add_colorbar(orientation=...)

🌳 NEW

  • m.show() can be used to make the associated layer visible. (a shortcut for m.show_layer(m.layer)
  • m.BM.on_layer(...) can be used to trigger functions if the visible layer changes.
  • 🌟 WebMap layers are now lazily evaluated and only added to the map if the corresponding layer is actually visible.
  • 🌟 [experimental feature] memory-mapping can now be used to avoid using up a lot of ram for very large datasets
    • Intermediate datasets are stored as memory-mapped files in a temp-folder on disk to release memory
    • By default memory-mapping is disabled! (to activate it, use: m.plot_map(memmap=False) )

🌦️ changes

  • Adding data from files (e.g. m.from_file or m.new_layer_from_file) now always uses "shade_raster" as the default plot-shape (since EOmaps v3.3.2, raster-shading works perfectly fine with re-projected rasters as well)
  • If a file with >2M data-points is plotted, only "shade" shapes are attempted by default to avoid overloading memory.
  • only one colorbar is allowed for Maps objects (use multiple objects for multiple colorbars)

🔨 fixes

  • Fix several issues with memory-leaks and garbage-collection of objects
  • Fix autoscale_fraction not recognized when using preset="bw" in m.add_scalebar
  • Maps objects are now properly garbage-collected
  • Fix auto-scaling of scalebars for very small scales
  • Maps.from_file now properly handles pathlib.Path objects
  • Fix utility widget start-layer should be the currently visible layer
  • Fix pick-events should only identify points on visible layers
  • Fix m.add_colorbar(log=True) for horizontal colorbars
  • Fix colorbar limit autoscaling
  • Fix logo size changes on zoom
  • Remove obsolete layer kwarg from m.add_logo
  • Fix incorrect color-normalization for shade_raster or shade_points if vmin/vmax outside the data-range are used
    (thanks to @maxhollmann)

🔥 hotfix EOmaps v3.4.1

  • fix issues with delayed WebMap services on multiple maps in one figure
  • fix issues with m.all for multiple maps in one figure

EOmaps v3.4

05 Apr 18:14
fcb4a85
Compare
Choose a tag to compare

A release that brings a lot of updates on speed and memory management and some very nice (but possibly breaking) changes compared previous versions of EOmaps.

❗ IMPORTANT CHANGES ❗

⭐ Starting with EOmaps v3.4 all callbacks and colorbars are layer-specific !

This means that callbacks only trigger if the layer of the associated Maps object is visible!
(...and colorbars are only visible if the associated layer is visible)

  • To trigger callbacks or add features & datasets independent of the visible layer, use m.all.cb. ...
    (or attach them to a Maps object on the "all" layer)

  • Note: pick callbacks now always react to the visible collection!
    (except for the ones on the "all" layer)

    m = Maps(layer=0)
    m.cb.click.attach.annotate()       # this callback is ONLY executed if the layer 0 is visible
    
    m1 = m.new_layer(layer=1)
    m1.cb.click.attach.mark()          # this callback is ONLY executed if the layer 1 is visible
    
    m.all.cb.click.attach.annotate()   # this callback is executed independent of the visible layer!

🍃 removed arguments

  • the obsolete "orientation" argument has been removed from Maps(...)
    (it set the colorbar-orientation which is now specified via m.add_colorbar(orientation=...)

🌳 NEW

  • m.show() can be used to make the associated layer visible. (a shortcut for m.show_layer(m.layer)
  • m.BM.on_layer(...) can be used to trigger functions if the visible layer changes.
  • 🌟 WebMap layers are now lazily evaluated and only added to the map if the corresponding layer is actually visible.
  • 🌟 [experimental feature] memory-mapping can now be used to avoid using up a lot of ram for very large datasets
    • Intermediate datasets are stored as memory-mapped files in a temp-folder on disk to release memory
    • By default memory-mapping is disabled! (to activate it, use: m.plot_map(memmap=False) )

🌦️ changes

  • Adding data from files (e.g. m.from_file or m.new_layer_from_file) now always uses "shade_raster" as the default plot-shape (since EOmaps v3.3.2, raster-shading works perfectly fine with re-projected rasters as well)
  • If a file with >2M data-points is plotted, only "shade" shapes are attempted by default to avoid overloading memory.
  • only one colorbar is allowed for Maps objects (use multiple objects for multiple colorbars)

🔨 fixes

  • Fix several issues with memory-leaks and garbage-collection of objects
  • Fix autoscale_fraction not recognized when using preset="bw" in m.add_scalebar
  • Maps objects are now properly garbage-collected
  • Fix auto-scaling of scalebars for very small scales
  • Maps.from_file now properly handles pathlib.Path objects
  • Fix utility widget start-layer should be the currently visible layer
  • Fix pick-events should only identify points on visible layers
  • Fix m.add_colorbar(log=True) for horizontal colorbars
  • Fix colorbar limit autoscaling
  • Fix logo size changes on zoom
  • Remove obsolete layer kwarg from m.add_logo
  • Fix incorrect color-normalization for shade_raster or shade_points if vmin/vmax outside the data-range are used
    (thanks to @maxhollmann)

EOmaps v3.3.2

25 Mar 19:03
28d725a
Compare
Choose a tag to compare

A minor bugfix release that brings some nice updates for raster-shading!

🌳 NEW

  • ⭐ Raster-shading with m.set_shape.shade_raster() can now finally be used with re-projected datasets as well!
    • The previous limitation plot_crs == data_crs is now gone for good 🥳

🔨 fixes

  • fix issues for m.util.layer_slider when switching between xyz-WebMap layers if axis-extent changed
  • fix glitches of dynamic artists during pan/zoom
  • fix image parsing in github-pages jekyll parser

EOmaps v3.3.1

21 Mar 11:54
0819d7d
Compare
Choose a tag to compare

A minor bugfix release (that also brings some miscellaneous convenience functions)

🌳 NEW

(⭐: new feature, 🍃: new functionality for existing feature)

  • ⭐ there's a new function m.subplots_adjust() for Maps and MapsGrid objects to quickly set the margins of the plots as well as the horizontal and vertical spacing between subplots:
    m = Maps()
    m.subplots_adjust(left=0.2, right=0.8, top=0.9, bottom=0.1)
    mg = MapsGrid()
    mg.subplots_adjust(left=0.2, right=0.8, top=0.9, bottom=0.1, hspace=0.05, wspace=0.15)
    (these are just shortcuts for m.figure.gridspec.update() + m.redraw())
  • 🍃 m.add_colorbar now has an additional kwarg log=True/False to make the y-axis of the histogram logarithmic.
  • 🍃 m.add_scalebar now provides style-presets via preset="<preset-name>"
    • at the moment there's only 1 preset... more to come in future releases!
    • "bw": a simple black-and-white style without a background

🔨 fixes

  • fix m.savefig with different dpi-settings requres a re-draw
  • fix m.plot_map with dynamic=True does not require a update
  • incorporated some updates to ensure that layers are only re-drawn if necessary
  • make sure cached backgrounds are always re-drawn if new artists are added
  • fix annotation in example 9 (still used old syntax)

EOmaps v3.3

16 Mar 10:19
6916424
Compare
Choose a tag to compare

A release with some nice new features and a lot of usability updates and fixes.
❗ note that there is a breaking change compared to <v3.2 (only affecting the ambiguous "layer" kwarg of dynamic artists (see 🌦️ changes below for details) )

🌳 NEW

(⭐: new feature, 🍃: new functionalities for existing features)

  • ⭐ There's a new pre-defined WebMap service: m.add_wms.GEBCO that provides nice underwater topography (https://www.gebco.net/)
  • ⭐ Theres a new function m.redraw() that can be used to force a re-draw of the entire figure
  • ⭐ shortcuts for mg.redraw and mg.util have been added to MapsGrid
  • 🍃 m.add_wms. ... <layer>.set_extent_to_bbox() now supports a new kwarg shrink which can be used to set the extent to a "shrinked" bbox (useful to avoid request-errors for tiles outside the bbox)
  • 🍃 m.add_colorbar can now be used to add individual colorbars for different plot-layers
    (the colorbars will always reflect the currently displayed layer)
  • 🍃the peek_layer callback can now be used to either view one (or more) layers or to overlay one (or more) layers on top of the current background layer.
  • 🍃 some major improvements have been implemented for fetching WebTiles from xyz-TileServer links.
    • m.add_wms.get_service now supports using custom wms, wmts, restAPI or xyz services

🌦️ changes

  • the ambiguous (and misleading) layer kwarg has finally been removed from dynamic artists.
    (note this "layer" was NOT referring to the actual plot-layer but to the stacking of dynamic artists!)
    • layer now always refers to the background layer name and not to the stack-order of dynamic artists!
    • ❗ the plot-order of multiple artists on the same layer is now determined by matplotlib's zorder property.
      - ❕ old: m.cb.click.attach.mark(layer=5) ➡️ new: m.cb.click.attach.mark(zorder=5)
      - ❕ old: m.cb.click.attach.annotate(layer=5) ➡️ new: m.cb.click.attach.annotate(zorder=5)
      - ❕ old: m.BM.add_artist(art, layer=5) ➡️ new: m.BM.add_artist(art) + art.set_zorder(5)
    • all examples have been updated accordingly

🔨 fixes

  • fix _onrelease() missing 1 required positional argument
  • fix issues with nbagg and ipympl backends (e.g. jupyter notebooks)
  • fix plt.show should only be called if we're in an interactive backend!
  • fix some issues with the scalebar and colorbar
  • re-work of draggable_axes
  • fix maxzoom for stamen_watercolor layer

EOmaps v3.2

07 Mar 18:21
3486d98
Compare
Choose a tag to compare

A release with some nice new features and a lot of fixes & improvements.
... Note: many parts of the 📚 documentation have been updated with small code-examples and images!

🌳 New

  • m.add_annotation and m.add_marker now support adding multiple objects in one go!
  • ⭐ raster-shading with datashader now supports 2D arrays for values and coordinates (e.g. curvilinear QuadMeshes)
  • ⭐ there's a new function m.show_layer(name) that provides a shortcut for switching the currently displayed layer
  • ⭐ layer-names can now be arbitrary strings! (e.g. Maps(layer=...) or m.plot_map(layer=...))
    • ❗ The layer-name "all", has a special meaning: all features on this layer will be visible in ALL other layers!

⭐ 🦜 Utility widgets !

EOmaps now has a slot for utility widgets that provides some nice tools to simplify common tasks.

  • Utilities are accessible via m.util.<...>

At the moment, there are 2 utilities that simplify switching between layers:

  • m.util.layer_selector() : get a "legend-like" object with buttons that can be used to switch between layers
  • m.util.layer_slider() : get a slider that can be used to switch between layers

Checkout the 🦜 Utility widgets section in the docs and the updated example: 🛰 WebMap services and layer-switching


⭐🌈 Updates for the scalebar

The scalebar has been re-worked for a much improved "out-of-the-box" usability.

  • By default, the scalebar is now automatically re-scaled on pan/zoom events based on the current extent of the map.
    • the new autoscale_fraction argument can be used to set the relative size of the (autoscaled) scalebar
    • the new auto_position argument can be used to set the position targeted for automatic re-positioning on pan/zoom events.
  • The background patch is now automatically scaled to enclose the labels.
  • When dragging the scalebar with the mouse, it is now immediately released if you release the mouse-button.
m.add_scalebar()               # get a scalebar that autoscales itself on pan/zoom events
m.add_scaleblar(scale=10000)   # get a scalebar with a fixed segment-separation of 10km

🌦️ changes

  • some changes to m.new_layer :
    • It now supports the additional layer kwarg
    • ❗ By default ONLY the "plot-shape" is now copied to the new layer.
      • this avoids side-effects from unintentional copying of plot-specs (vmin vmax etc.)
      • you can still copy plot-specs by using m.new_layer(copy_plot_specs=True)
  • Maps.from_file and Maps.read_file and m.new_layer_from_file now support using already opened NetCDF and GeoTIFF files

⚙️ fixes

  • fix treatment of colorbar orientation in m.figure.set_colorbar_position
  • fix reprojection of wms-layers with a native crs specified as "EPSG:3857"
  • fix sorting of layer-names
  • avoid identification of pixel-ID if no pick-callback is attached
  • fix label-axis should not respond to navigation events
  • fix adding multiple markers in one go
  • fallback to WSG84 boundary in wms_layer.set_bbox_to_extent()