Skip to content

Commit

Permalink
added a convenience function for creating logarithmic colormaps
Browse files Browse the repository at this point in the history
  • Loading branch information
dlohmeier committed Apr 15, 2019
1 parent a426531 commit eca084b
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 11 deletions.
6 changes: 5 additions & 1 deletion doc/plotting/matplotlib/create_colormaps.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,8 @@ Discrete

Continous
==============================
.. autofunction:: pandapower.plotting.cmap_continous
.. autofunction:: pandapower.plotting.cmap_continous

Logarithmic
==============================
.. autofunction:: pandapower.plotting.cmap_logarithmic
77 changes: 67 additions & 10 deletions pandapower/plotting/colormaps.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,32 @@
# and Energy System Technology (IEE), Kassel. All rights reserved.


from matplotlib.colors import ListedColormap, BoundaryNorm, LinearSegmentedColormap, Normalize
from matplotlib.colors import ListedColormap, BoundaryNorm, LinearSegmentedColormap, Normalize, \
LogNorm
import numpy as np


def cmap_discrete(cmap_list):
"""
Can be used to create a discrete colormap.
INPUT:
- cmap_list (list) - list of tuples, where each tuple represents one range. Each tuple has the form of ((from, to), color).
- cmap_list (list) - list of tuples, where each tuple represents one range. Each tuple has
the form of ((from, to), color).
OUTPUT:
- cmap - matplotlib colormap
- norm - matplotlib norm object
EXAMPLE:
>>> from pandapower.plotting import cmap_discrete, create_line_trace, draw_traces
>>> cmap_list = [((20, 50), "green"), ((50, 70), "yellow"), ((70, 100), "red")]
>>> from pandapower.plotting import cmap_discrete, create_line_collection, draw_collections
>>> from pandapower.networks import mv_oberrhein
>>> net = mv_oberrhein("generation")
>>> cmap_list = [((0, 10), "green"), ((10, 30), "yellow"), ((30, 100), "red")]
>>> cmap, norm = cmap_discrete(cmap_list)
>>> lc = create_line_trace(net, cmap=cmap, norm=norm)
>>> draw_traces([lc])
>>> lc = create_line_collection(net, cmap=cmap, norm=norm)
>>> draw_collections([lc])
"""
cmap_colors = []
boundaries = []
Expand All @@ -46,19 +51,23 @@ def cmap_continous(cmap_list):
Can be used to create a continous colormap.
INPUT:
- cmap_list (list) - list of tuples, where each tuple represents one color. Each tuple has the form of (center, color). The colorbar is a linear segmentation of the colors between the centers.
- cmap_list (list) - list of tuples, where each tuple represents one color. Each tuple has
the form of (center, color). The colorbar is a linear segmentation of
the colors between the centers.
OUTPUT:
- cmap - matplotlib colormap
- norm - matplotlib norm object
EXAMPLE:
>>> from pandapower.plotting import cmap_continous, create_bus_trace, draw_traces
>>> from pandapower.plotting import cmap_continous, create_bus_collection, draw_collections
>>> from pandapower.networks import mv_oberrhein
>>> net = mv_oberrhein("generation")
>>> cmap_list = [(0.97, "blue"), (1.0, "green"), (1.03, "red")]
>>> cmap, norm = cmap_continous(cmap_list)
>>> bc = create_bus_trace(net, cmap=cmap, norm=norm)
>>> draw_traces([bc])
>>> bc = create_bus_collection(net, size=70, cmap=cmap, norm=norm)
>>> draw_collections([bc])
"""
min_loading = cmap_list[0][0]
max_loading = cmap_list[-1][0]
Expand All @@ -67,3 +76,51 @@ def cmap_continous(cmap_list):
cmap = LinearSegmentedColormap.from_list('name', cmap_colors)
norm = Normalize(min_loading, max_loading)
return cmap, norm


def cmap_logarithmic(min_value, max_value, colors):
"""
Can be used to create a logarithmic colormap. The colormap itself has a linear segmentation of
the given colors. The values however will be matched to the colors based on a logarithmic
normalization (c.f. matplotlib.colors.LogNorm for more information on how the logarithmic
normalization works).\nPlease note: There are numerous ways of how a logarithmic scale might
be created, the intermediate values on the scale are created automatically based on the minimum
and maximum given values in analogy to the LogNorm. Also, the logarithmic colormap can only be
used with at least 3 colors and increasing values which all have to be above 0.
INPUT:
- min_value (float) - the minimum value of the colorbar
- max_value (float) - the maximum value for the colorbar
- colors (list) - list of colors to be used for the colormap
OUTPUT:
- cmap - matplotlib colormap
- norm - matplotlib norm object
EXAMPLE:
>>> from pandapower.plotting import cmap_logarithmic, create_bus_collection, draw_collections
>>> from pandapower.networks import mv_oberrhein
>>> net = mv_oberrhein("generation")
>>> min_value, max_value = 1.0, 1.03
>>> colors = ["blue", "green", "red"]
>>> cmap, norm = cmap_logarithmic(min_value, max_value, colors)
>>> bc = create_bus_collection(net, size=70, cmap=cmap, norm=norm)
>>> draw_collections([bc])
"""
num_values = len(colors)
if num_values < 2:
raise UserWarning("Cannot create a logarithmic colormap less than 2 colors.")
if min_value <= 0:
raise UserWarning("The minimum value must be above 0.")
if max_value <= min_value:
raise UserWarning("The upper bound must be larger than the lower bound.")
values = np.arange(num_values + 1)
diff = (max_value - min_value) / (num_values - 1)
values = (np.log(min_value + values * diff) - np.log(min_value)) \
/ (np.log(max_value) - np.log(min_value))
cmap = LinearSegmentedColormap.from_list("name", list(zip(values, colors)))
norm = LogNorm(min_value, max_value)
return cmap, norm
49 changes: 49 additions & 0 deletions pandapower/test/plotting/test_create_colormaps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# -*- coding: utf-8 -*-

# Copyright (c) 2016-2019 by University of Kassel and Fraunhofer Institute for Energy Economics
# and Energy System Technology (IEE), Kassel. All rights reserved.


import numpy as np
import pandapower.plotting as plot
import pytest


def test_cmap_discrete():
cmap_list = [((0, 10), "green"), ((10, 30), "yellow"), ((30, 100), "red")]
cmap, norm = plot.cmap_discrete(cmap_list)
assert cmap.N == 3
assert norm.N == 4
assert norm(0) == 0
assert norm(9.999) == 0
assert norm(10.01) == 1
assert norm(29.999) == 1
assert norm(30.01) == 2
assert norm(99.999) == 2


def test_cmap_continuous():
cmap_list = [(0.97, "blue"), (1.0, "green"), (1.03, "red")]
cmap, norm = plot.cmap_continous(cmap_list)

assert np.allclose(cmap(0.99), (0.984313725490196, 0.007873894655901603, 0.0, 1.0))
assert np.allclose(cmap(1.02), (1.0, 0.0, 0.0, 1.0))
assert np.allclose([norm(0.97 + 0.01 * n) for n in range(7)],
[0.16666666666666666 * n for n in range(7)])


def test_cmap_logarithmic():
min_value, max_value = 1.0, 1.03
colors = ["blue", "green", "red"]
cmap, norm = plot.cmap_logarithmic(min_value, max_value, colors)
assert np.allclose(cmap(0.1), (0.0, 0.09770172300400634, 0.8053598487029561, 1.0))
assert np.allclose(cmap(0.5), (0.0, 0.5002328217805124, 0.003442425359135415, 1.0))
assert np.allclose(cmap(0.8), (0.5970222233016451, 0.20227904085250753, 0.0, 1.0))
assert norm(1.) == 0
assert norm(1.03) == 1
assert np.isclose(norm(1.01), 0.3366283509006011)
assert np.isclose(norm(1.02), 0.669940112402371)


if __name__ == "__main__":
pytest.main(["test_create_colormaps.py"])
2 changes: 2 additions & 0 deletions pandapower/test/plotting/test_to_html.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@
import pandapower.plotting as plot
from pandapower.test.toolbox import assert_net_equal, create_test_network, tempdir, net_in


def test_html(net_in, tempdir):
filename = os.path.join(tempdir, "testfile.html")
plot.to_html(net_in, filename)


if __name__ == "__main__":
pytest.main(["test_to_html.py"])

0 comments on commit eca084b

Please sign in to comment.