Releases: raphaelquast/EOmaps
EOmaps v4.2.1
A bugfix release that greatly reduces import time!
🌦️ changes
- 🕐 greatly reduced "plain" import-time
- "heavy" modules such as 'datashader', 'xarray' etc. are now lazily imported only when needed
- this reduces runtime of
from eomaps import Mapsin a fresh terminal from ~5sec to ~1sec
- 🍃
m.add_marker(...)now supports the "layer" kwarg - 🍃
m.show()now automatically callsplt.show()to actually draw the figure if matplotlib is in non-interactive mode
🔨 fixes
- legends for WebMap services are now updated based on the visible layer
m.add_markernow only draws newly added markers (instead of updating all dynamic artists)- avoid using
pkg_resourcesto identify package-version (use explicit_version.pyinstead)
EOmaps v4.2
🌳 New
- ⭐ there's a new function
m.fetch_layers()- ...to fetch (and cache) all layers of a map so that switching layers (with buttons & sliders) is fast
- a associated callback
m.cb.keypress.attach.fetch_layers()is also available
- ⭐ there's a new pre-defined WebMap service for the "Copernicus Atmosphere Monitoring Service"
- accessible via
m.add_wms.CAMS(see ECMWF CAMS for details )
- accessible via
- 📃 docs on WebMap services have been updated with examples on how to
- use custom service-urls
- pass arguments (time, style etc.) to the service
🌦️ Changes
- 🍃
m.set_shape.raster()can now be used with 1Dpandas.DataFramesas well!
(DataFrames will be re-structured internally based on unique values of the coordinate-columns) - 🍃
.add_legend()for WebMap services can now properly recognizes the used map-style
m.add_wms.<SERVICE>.....add_layer.<LAYER>.add_legend()
🔨 Fixes
- ❗ fix pixel centers shifted by half pixel-size with
m.set_shape.raster() - speedup
m.set_shape.raster()(remove unnecessary calculations) - fix identification of picked ID if
pandas.Seriesobjects are used as coordinates - allow setting shade-aggregator via strings (e.g. "mean", "min", "max" etc.) for
m.shade_points - fix colorbar kwargs assertions should intercept before axes are created
- add fix for QuadMesh performance issues for older matplotlib versions (e.g. < v3.5.2)
- fix issues with updating WebMaps when using
m.util.layer_slider() - fix re-using WebMap objects with different kwargs
- fix fetching WebMap legends for different styles
EOmaps v4.1.1
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-arrowsadd_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
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
🔨 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
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 underlyingMaps-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_rasterare:- the whole dataset is always plotted (so for very very large datasets
shade_rasteris much faster!) - it supports manual color specifications (
shade_rasterdoes not)
- the whole dataset is always plotted (so for very very large datasets
- the differences between
rectanglesandrasterare:rasterdoes not take the curvature of the edges into accountrasterdetermines the pixel-size based on neighboring pixels,rectanglesallows 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_crsfor themarkcallback is now determined based on theradius_crsassigned in the plot-shape
... this definition allows usingm.cb.pick.attach.mark(buffer=3)directly without having to worry about the crs
(previouslyin, 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 viam.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
🚀 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_fileorm.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)
- (if you really want to immediately convert all data-values, use
- The encoding information can be get/set via
m.data_specs.encodingorm.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 withm.set_shape.shade_raster()orm.set_shape.shade_points())
- it is dynamically updated based on the distribution of shaded pixels in the current field of view.
-
⭐ There is now a way to use
pickcallbacks on datasets without plotting the data first.- To make a "pick-only" dataset, use
m.set_data(...)to assign the dataset and then
callm.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
- To make a "pick-only" dataset, use
⚙️ 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()
- <500k datapoints:
Maps.from_fileandm.new_layer_from_filenow 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
[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 aMapsobject on the"all"layer) -
Note:
pickcallbacks 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 fromMaps(...)
(it set the colorbar-orientation which is now specified viam.add_colorbar(orientation=...)
🌳 NEW
- ⭐
m.show()can be used to make the associated layer visible. (a shortcut form.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_fileorm.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
Mapsobjects (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"inm.add_scalebar - Maps objects are now properly garbage-collected
- Fix auto-scaling of scalebars for very small scales
Maps.from_filenow properly handlespathlib.Pathobjects- 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
layerkwarg fromm.add_logo - Fix incorrect color-normalization for
shade_rasterorshade_pointsifvmin/vmaxoutside 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.allfor 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 aMapsobject on the"all"layer) -
Note:
pickcallbacks 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 fromMaps(...)
(it set the colorbar-orientation which is now specified viam.add_colorbar(orientation=...)
🌳 NEW
- ⭐
m.show()can be used to make the associated layer visible. (a shortcut form.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_fileorm.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
Mapsobjects (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"inm.add_scalebar - Maps objects are now properly garbage-collected
- Fix auto-scaling of scalebars for very small scales
Maps.from_filenow properly handlespathlib.Pathobjects- 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
layerkwarg fromm.add_logo - Fix incorrect color-normalization for
shade_rasterorshade_pointsifvmin/vmaxoutside the data-range are used
(thanks to @maxhollmann)
EOmaps v3.3.2
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_crsis now gone for good 🥳
- The previous limitation
🔨 fixes
- fix issues for
m.util.layer_sliderwhen 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
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()forMapsandMapsGridobjects 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)
(these are just shortcuts formg = MapsGrid() mg.subplots_adjust(left=0.2, right=0.8, top=0.9, bottom=0.1, hspace=0.05, wspace=0.15)
m.figure.gridspec.update()+m.redraw()) - 🍃
m.add_colorbarnow has an additional kwarglog=True/Falseto make the y-axis of the histogram logarithmic. - 🍃
m.add_scalebarnow provides style-presets viapreset="<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.savefigwith different dpi-settings requres a re-draw - fix
m.plot_mapwithdynamic=Truedoes 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)
