Releases: raphaelquast/EOmaps
EOmaps v5.2
A new minor releases with a lot of bugfixes and some awesome usability upgrades.
🌳 New
Some internals of EOmaps have been re-structured to make it easier to add Maps-objects to existing matplotlib-figures!
Check the docs for more details: 🍱 Adding Maps to existing figures
f = plt.figure()
ax = f.add_subplot(211)
m = Maps(f=f, ax=212)🌦️ Changes
💧 General
-
When using
m.savefig(dpi=...)with the plot-shapes"shade_points"or"shade_raster"the shading-pipeline is now automatically adjusted to reflect the dpi of the saved figure (e.g. exporting higher dpi figures will also result in more detailed shading of the data). -
The 🧰 Companion-Widget has some new functionalities! (e.g. basic click/pick callbacks)
💧 Syntax
Maps(gs_ax=...)has been re-named toMaps(ax=...)- ❗ Usage of the
m.figure.<...>accessor is depreciated!- Objects are now directly accessible via
m.f,m.ax,m.collandm.colorbar.ax_cbm.colorbar.ax_cb_plot
- Objects are now directly accessible via
💧 Updates for keypress callbacks
keypresscallbacks are now triggered irrespective of the mouse-position (as long as the figure is active)- It is now also possible to create callbacks that trigger on any key by using
key=None.
(the actually used key is passed to the callback via thekeykwarg)
💧 Updates for layer sliders
- There's a new function
slider.set_layers()to updates the layers targeted by an existing slider - The slider-label now shows the currently visible layer-name in red if the active layer is not targeted by the slider
💧 Updates for logos
- It is now possible to fix the logo-position relative to the map with
m.add_logo(fix_position=True)
(the default is False so that logos can be re-positioned with the layout-editor!) - Checkout the new 👽 logos section in the docs for more details!
🔨 Fixes
- fix issues when adding Maps-objects to existing figures
- fix issues when setting the map-extent to the data-extent
- speed up opening datasets with the companion widget (avoid scaling to retrieve info)
- allow adding MapsGrid objects to existing figures
- make "switch_layer" keypress callbacks accept only strings as layer-names
- update github actions to address depreciation warnings
- fix registering of transparent colormaps
- fix issues with boundary-pixels for "raster" shape
- fix using layer-names that contain double-underscores
- make sure the figure is closed if Maps is used as context-manager
- fix handling of long layer-names in companion-widget
- assign n for shapes based on dataset-size (if not specified explicitly)
- remove cached background layers of deleted layers
- adjust shading pipeline on figure resize
- adjust shading pipeline on m.savefig if dpi is changed
- fix re-fetching of xyz webmap services if axis size changed
- fix issues when adding new webmap layers via the companion widget
- avoid keeping companion-widget "always-on-top"
- fix logos reset position at next draw event
EOmaps v5.1
A first minor release for EOmaps v5.x with a lot of bugfixes, some improvements for speed and memory-management and new functionalities for the colorbar!
Make sure to check the new features introduced in EOmaps v5.0 as well!
🌳 New
- new WebMap service:
m.add_wms.DLR_basemaps - improved speed and memory-management for very large datasets
🌈 Updates for the colorbar
New convenience function m.colorbar.set_bin_labels() to simplify labeling individual bins of the colorbar with custom names.
Check the 📖 documentation for more details!
- ... ordinary colorbar (for classified data):

- ... the colorbar after using
m.colorbar.set_bin_labels()to set custom labels at the center of the specified bins

🔨 Fixes
- allow using (equal-length) 1D datasets for
m.set_shape.raster - fix close button callback for companion-widget popups
- fix utility widgets for multiple maps in one figure
- fix layer assignment for WebMap legends
- fix providing custom colorbar ticks for classified data
- fix issues with colorbar tick formatter
- avoid memory-intense index-creations for very large datasets
- avoid re-shaping for very large 2D datasets with 1D coordinates
- add some basic unittests for plotting from files
- fix colormap usage for classified datasets
EOmaps v5.0
A new major release that brings a lot of very nice features and updates 🥳
❗ (possibly) breaking changes to v4.x ❗
New layer-name convention:
-
All layer-names are now parsed as
string!
(any non-string object passed as layer-name will be converted to string and a warning is shown) -
The
"|"character is used as a separator for multi-layers (see new ⧉ Multi Layers feature below)
(a layer-name such as"first|second"now represents the combined artists for the layers"first"and"second")
Changes for the colorbar
The implementation of the colorbar has been re-worked and several changes have been introduced:
- Colorbars are now accessible via
m.colorbar- Some arguments of
m.add_colorbar(...)have changed! Check the docstring for details! - The individual colorbar-axes are accessible via
m.colorbar.ax_cbandm.colorbar.ax_cb_plot - To set the size of the colorbar, use
m.colorbar.set_position(...) - To remove a colorbar, use
m.colorbar.remove()
- Some arguments of
🌳 New
🧰 Companion widget
Starting with v5.0, EOmaps provides an awesome companion-widget to speed up data-comparisons and analysis.
NOTE: Using the widget is only possible if you use matplotlibs
"PyQt5"backend!
- To open the widget, simply press
won the keyboard while the mouse-pointer is hoovering the map. - The
?button on the top left can be used to activate showing help-tooltips if you hoover over the controls explain their functionalities.
📖 Checkout the corresponding section in the docs for more details! 🧰 Companion Widget
✏️ Draw shapes on the map
There is a new functionality to draw simple (geo-coded) shapes on the map!
📖 Checkout the corresponding section in the docs for more details! ✏️ Draw shapes on the map
⧉ Multi Layers
It is now possible to create "multi-layers" which inherit their artists from existing layers.
The layer-name hereby consists of existing layer-names separated by "|".
To show the layers "first" and "second" at the same time, use:
m.show_layer("first|second")- If you view a multi-layer, ALL artists from the constituting layers will be shown!
- E.g.:
"first|second|third"will show all artists of the layers"first","second"and"third"
- E.g.:
- The "vertical stacking order" for plotting is still exclusively determined by the
zorderproperty of the artists!- (artists at the same zorder are ordered with respect to the creation-time)
- It is possible (however rarely useful) to create a
Mapsobject representing multi-layers- Its artists will then only be shown if all constituting layers are visible
📖 Checkout the corresponding section in the docs for more details! 🚀 Basics/Layers
🏗️ Updates for the Layout Editor
- Select (and edit) multiple axes by holding
shiftwhile clicking on the axes - Scaling the axes-size (with the scroll-wheel or the
+/-buttons) now preserves the center of the axis - If you hold down
controlwhile a colorbar is selected, the scroll wheel (or the+/-buttons) will adjust
the relative size between the colorbar and the histogram - If you hold down
h(orv) the scroll-wheel adjusts only the horizontal (or vertical) size of the axes
📖 Checkout the corresponding section in the docs for more details! 🏗️ Layout Editor
🗺️ Set map-extent via OpenStreetMap Nominatim query
- There is now a method to set the extent of the map via a OSM query.
m = Maps() m.set_extent_to_location("Austria") m.add_wms.OpenStreetMap.add_layer.default()
📷 Snapshots for JupyterNotebooks
- The new
m.shapshot()functionality allows you to plot static snapshots of a map
in Jupyter Notebooks (or in the IPython console) irrespective of the used backend.
👓 Updates for peek-layer callbacks:
- It is now possible to use transparency when peeking on a layer!
m.cb.click.attach.peek_layer(layer="some layer", alpha=.5) - There's a new option
how="full"to overlay another layer on the whole axis - The size of the square used for peeking (e.g.
how=0.5) is now always with respect to the smallest axis-dimension
... additional new features ...
- Equi7Grid projections can now be accessed via explicit names (e.g.:
Equi7_EU,Equi7_AF...) - Any colormap created by EOmaps during runtime is now always registered as a matplotlib colormap
- It is now possible to add logos to specific layers by using:
m.add_logo(layer=...) - 🛰️ New WebMap services
m.add_wms.OpenStreetMap.OSM_wmsm.add_wms.OpenStreetMap.OSM_landuse
Dynamic artists are now layer-sensitive!
- annotations and markers can now be added to specific layers:
m.add_annotation(layer=...)andm.add_marker(layer=...) - To add dynamic artists on specific layers, simply use
m.BM.add_artist(<artist>, layer=...)
(to make the artist visible on all layers, simply uselayer="all")
🌦️ (non-breaking) Changes
- obsolete arguments
radiusandradius_crshave been removed fromm.set_shape.raster() - the default radius for
m.set_shape.geod_circleshas been set to 1km
🔨 Fixes
- fix default style kwarg for wms layers
- remove obsolete shape arguments
- fix custom args for feature presets
- fix _on_layer_change actions
- fix fetching wmts services
- fix passing kwargs to wms and wmts services added to the active layer
- fix updating background layers on add/remove of artists
- fix handling of encoded NetCDF data
EOmaps v4.4.3
Just a hotfix release
🔨 fixes
- fix
ImportErrorforTriMeshwhen usingmatpltolib >= 3.6
EOmaps v4.4.2
Another bugfix release.
🌳 New
- Make sure to also have a look at the new features added in EOmaps v4.4!
- There is now an option to draw a an "outline" on top of the colorbar-histogram with:
m.add_colorbar(show_outline=True)(for a black outline with linewidth 1)m.add_colorbar(show_outline=dict(color="b", linewidth=2))(for a custom outline)
🔨 Fixes
- fix using
m.cb.pickcallbacks with datasets assigned to the"all"layer - raise error if undefined objects are passed to NetCDF and GeoTIFF readers
- fix using the LayoutEditor to move colorbars with "arrow-keys"
- fix default styles must be provided as list for wms and wmts services!
EOmaps v4.4.1
A quick bugfix release
🔨 Fixes
- fix providing kwargs to WebMap services (time, styles etc.)
EOmaps v4.4
A release that introduces 2 new functionalities: m.add_line, m.cb.move and the ability to use keypress-modifiers for callbacks!
🌳 New
🚲 A new method to quickly draw paths on a map!
- ⭐
m.add_line(): connect points via geodesic (or straight) lines!- specify number of intermediate points per line-segment
- (alternatively) specify distance between intermediate points for each line-segment
- checkout the new 🚲 example and the corresponding section in the 📖 documentation!
- specify number of intermediate points per line-segment
🛸 New features for callbacks!
👾 Keypress-modifiers
It is now possible to assign multiple callbacks to the same mouse-button and use keyboard-shortcuts
to switch between the assigned callbacks!
(e.g. the callback will only be executed if the corresponding button is pressed on the keyboard)
-
🌟 simply provide the modifier of choice with the
modifier=...argument!- e.g.:
m.cb.click.attach.annotate(modifier="a"): this callback will only be executed if the"a"key is pressed
- e.g.:
-
🌟 You can make modifiers "sticky" (e.g. to keep them activated after the button is released) by using:
m.cb.click.set_sticky_modifiers("a", "b", "c")- "sticky modifiers" are assigned separately for
click,pickandmovecallbacks - to release a "sticky modifier" press
ctrl + <modifier key>orescape
-
checkout the corresponding section in the 📖 documentation!
⭐ move callbacks
There's now an explicit container to attach callbacks that are executed
on mouse movement if NO button is clicked
- NOTE: use
m.cb.click.attach...to execute callbacks on mouse-movement if a button is clicked!- and set
on_motion=Falseto avoid executing the click-callback on mouse-movements
- and set
m = Maps()
m.add_feature.preset.coastline()
m.cb.move.attach.annotate()
m.cb.move.attach.mark(modifier=1, radius=2, radius_crs=4326, fc="none", ec="r")🌦️ Changes
-
❗
m.cb.click.attach.mark()now usespermanent=Falseby default -
🏞️ NaturalEarth features have been updated
click for a list of new features
{ 10m_cultural: {'admin_0_countries_iso', 'parks_and_protected_lands', 'admin_0_countries_tlc'} 10m_physical: {'bathymetry_G_4000', 'graticules_20', 'bathymetry_K_200', 'bathymetry_E_6000', 'graticules_1', 'bathymetry_A_10000', 'bathymetry_F_5000', 'bathymetry_C_8000', 'bathymetry_B_9000', 'bathymetry_L_0', 'bathymetry_H_3000', 'bathymetry_I_2000', 'wgs84_bounding_box', 'bathymetry_J_1000', 'graticules_5', 'bathymetry_D_7000', 'graticules_30', 'graticules_10', 'graticules_15'} 110m_physical: {'graticules_15', 'graticules_20', 'graticules_1', 'wgs84_bounding_box', 'graticules_5', 'graticules_30', 'graticules_10'} 50m_physical: {'graticules_20', 'graticules_1', 'wgs84_bounding_box', 'graticules_5', 'graticules_30', 'graticules_10', 'graticules_15'} }
🔨 Fixes
- fix sharing boundary and inset-marker properties for inset-maps
- fix issues with invalid clipping shapes
- fix issues with geometries that cannot be exploded
- make sure temporary artists are cleared prior to executing callbacks
- fix issues with dynamically updated legends and temporary artists
- fix error when trying to update colorbar-arrows without a colorbar
- avoid re-fetching WebMap tiles if extent remains the same
- fix unnecessary re-draws of artists after overlay-actions
EOmaps v4.4
A release that introduces 2 new functionalities: m.add_line, m.cb.move and the ability to use keypress-modifiers for callbacks!
🌳 New
🚲 A new method to quickly draw paths on a map!
- ⭐
m.add_line(): connect points via geodesic (or straight) lines!- specify number of intermediate points per line-segment
- (alternatively) specify distance between intermediate points for each line-segment
- checkout the new 🚲 example and the corresponding section in the 📖 documentation!
- specify number of intermediate points per line-segment
🛸 New features for callbacks!
👾 Keypress-modifiers
It is now possible to assign multiple callbacks to the same mouse-button and use keyboard-shortcuts
to switch between the assigned callbacks!
(e.g. the callback will only be executed if the corresponding button is pressed on the keyboard)
-
🌟 simply provide the modifier of choice with the
modifier=...argument!- e.g.:
m.cb.click.attach.annotate(modifier="a"): this callback will only be executed if the"a"key is pressed
- e.g.:
-
🌟 You can make modifiers "sticky" (e.g. to keep them activated after the button is released) by using:
m.cb.click.set_sticky_modifiers("a", "b", "c")- "sticky modifiers" are assigned separately for
click,pickandmovecallbacks - to release a "sticky modifier" press
ctrl + <modifier key>orescape
-
checkout the corresponding section in the 📖 documentation!
⭐ move callbacks
There's now an explicit container to attach callbacks that are executed
on mouse movement if NO button is clicked
- NOTE: use
m.cb.click.attach...to execute callbacks on mouse-movement if a button is clicked!- and set
on_motion=Falseto avoid executing the click-callback on mouse-movements
- and set
m = Maps()
m.add_feature.preset.coastline()
m.cb.move.attach.annotate()
m.cb.move.attach.mark(modifier=1, radius=2, radius_crs=4326, fc="none", ec="r")🌦️ Changes
-
❗
m.cb.click.attach.mark()now usespermanent=Falseby default -
🏞️ NaturalEarth features have been updated
click for a list of new features
{ 10m_cultural: {'admin_0_countries_iso', 'parks_and_protected_lands', 'admin_0_countries_tlc'} 10m_physical: {'bathymetry_G_4000', 'graticules_20', 'bathymetry_K_200', 'bathymetry_E_6000', 'graticules_1', 'bathymetry_A_10000', 'bathymetry_F_5000', 'bathymetry_C_8000', 'bathymetry_B_9000', 'bathymetry_L_0', 'bathymetry_H_3000', 'bathymetry_I_2000', 'wgs84_bounding_box', 'bathymetry_J_1000', 'graticules_5', 'bathymetry_D_7000', 'graticules_30', 'graticules_10', 'graticules_15'} 110m_physical: {'graticules_15', 'graticules_20', 'graticules_1', 'wgs84_bounding_box', 'graticules_5', 'graticules_30', 'graticules_10'} 50m_physical: {'graticules_20', 'graticules_1', 'wgs84_bounding_box', 'graticules_5', 'graticules_30', 'graticules_10', 'graticules_15'} }
🔨 Fixes
- fix sharing boundary and inset-marker properties for inset-maps
- fix issues with invalid clipping shapes
- fix issues with geometries that cannot be exploded
- make sure temporary artists are cleared prior to executing callbacks
- fix issues with dynamically updated legends and temporary artists
- fix error when trying to update colorbar-arrows without a colorbar
- avoid re-fetching WebMap tiles if extent remains the same
- fix unnecessary re-draws of artists after overlay-actions
EOmaps v4.3
A new release that brings some nice updates and an awesome new Layout-Editor!
🌦️ Changes
- 🍃 utility-widgets now auto-update themselves if new layers are added to the map!
- to show only a subset of the available layers, use
m.util.layer_selector(layers=["layer1", ...])
- to show only a subset of the available layers, use
- 🍃 coastlines are no longer added by default when creating new layers from files (e.g. NetCDF, GeoTIFF etc.)
- (use
coastlines=Trueor explicitly callm.add_feature.preset.coastline()to add coastlines!)
- (use
- 🍃
m.add_gdfnow allows using apathto a file that can be read withgeopandas.read_fileinstead of providing thegeopandas.GeoDataFramedirectly - ❗ keyword-arguments for
m.new_inset_maphave changed!edgecolorandlinewidthare depreciated and will be removed in next major versions!- to set the properties of the boundary-polygon, use
m.new_inset_map(boundary=dict(fc="r", lw=1)instead
- ❗
m.cb.dynamichas been removed
🌳 New
⭐ New accessor for classification schemes
The new classification-schemes accessor 🌟 m.set_classify provides autocompletion and proper docstrings!
(you can use it just as you would use m.set_classify_specs)
Just select the scheme you want to use and call it with the relevant parameters:
m = Maps()
m.set_data(...)
m.set_classify.Quantiles(k=5)
m.plot_map(...)
# alternative (old) way to set the classification:
# m.set_classify_specs(scheme="Quantiles", k=5)⭐ There's a new 🏗️ Layout Editor to quickly re-arrange the subplots of a figure!
The Layout Editor can be used to quickly re-arrange the position of all axes in the figure.
(works for maps, colorbars, inset-maps, ordinary matplotlib plots etc.)
- You can save and re-apply a layout with:
- 🌟
m.get_layout(): get the current layout (or dump the layout as a json-file) - 🌟
m.apply_layout(): apply a given layout (or load and apply the layout from a json-file) - 🌟
m.edit_layout(filepath=...): enter LayoutEditor and (optionally) save layout as a json-file on exit
- 🌟
To quickly enter/exit Layout Editor, simply use the assigned keyboard-shortcuts:
- press
ALT + Lto enter the LayoutEditor mode - press
ALT + Lagain orescapeto exit the LayoutEditor
Have a look at the new section in the 📖 documentation for more details!
🔨 Fixes
- fix recognizing the parent layer when initializing utility-widgets from the parent Maps object
- fix layer-selectors should indicate no active layer if the active layer is not part of the widget
- updates for inset-maps
- add fix for reprojection issues with certain projections
- fix reprojection sometimes masks certain shapes
EOmaps v4.2.3
A minor bugfix release.
🌳 new
-
there is now an option to completely disable extension arrows when adding a colorbar
(e.g. withm.add_colorbar(add_extend_arrows=False)) -
it is now possible to set the "layer" of an inset-map on initialization (e.g.
m.new_inset_map(layer="adsf")
(by default, the"all"layer is used for inset-maps!)
🔨 fixes
- fix using alpha-transparency with wms and wmts services (e.g.
m.add_wms.<service>.add_layer.<layer>(alpha=0.5)) - fix colors of histogram-bins if the bins extend over more than one colorbar-split
- fix position of colorbar extension-arrows after using
m.subplots_adjust - fix appearance of "vertical" colorbar extension arrows
EOmaps v4.2.2
A minor bugfix release.
🌳 new
- To address issues when plotting 2D raster-data with unsorted coordinates, there is now an option
to force sorting the data by coordinates prior to plotting withm.plot_map(assume_sorted=False)- only works if coordinates are provided as 1D arrays and the data is provided as a 2D array
- sorting is only relevant for
rasterandshade_rastershapes (other shapes don't require sorting) - by default no sorting is performed!
🌦️ changes
- The pick-radius used to identify clicked pixels can now be set in 2 ways
m.plot_map(pick_distance=...):- if a number is provided, it is used as a multiplier for the dataset-radius
e.g.pick-radius = pick_distance * radius_in_plot_crs) - if a string is provided, it is directly used as the pick-radius in units of the plot_crs
e.g.pick-radius = float(pick_distance)
- if a number is provided, it is used as a multiplier for the dataset-radius
🔨 fixes
- ❗ fix using "pick" callbacks with
m.set_shape.raster()and 2D input-coordinates - make radius-estimation more robust (fallback to nearest-neighbor if 2D estimation fails)
- fallback to
np.inffor pick_distance if radius estimation fails - fix delaunay_triangulation does not need to estimate the radius if masked=False
- fix issues with registering pandas






