ENH: plot with single colors

This commit is contained in:
Joris Van den Bossche
2015-10-31 01:45:20 +01:00
parent 3489dcee24
commit 9c2d84c894
2 changed files with 92 additions and 20 deletions
+30 -15
View File
@@ -49,10 +49,9 @@ def plot_multilinestring(ax, geom, color='red', linewidth=1.0):
plot_linestring(ax, line, color=color, linewidth=linewidth)
def plot_point(ax, pt, marker='o', markersize=2, color="black"):
def plot_point(ax, pt, marker='o', markersize=2, color='black'):
""" Plot a single Point geometry """
ax.plot(pt.x, pt.y, marker=marker, markersize=markersize, linewidth=0,
color=color)
ax.plot(pt.x, pt.y, marker=marker, markersize=markersize, color=color)
def gencolor(N, colormap='Set1'):
@@ -75,7 +74,8 @@ def gencolor(N, colormap='Set1'):
yield colors[i % n_colors]
def plot_series(s, cmap='Set1', ax=None, linewidth=1.0, figsize=None, **color_kwds):
def plot_series(s, cmap='Set1', color=None, ax=None, linewidth=1.0,
figsize=None, **color_kwds):
""" Plot a GeoSeries
Generate a plot of a GeoSeries geometry with matplotlib.
@@ -96,6 +96,9 @@ def plot_series(s, cmap='Set1', ax=None, linewidth=1.0, figsize=None, **color_kw
Accent, Dark2, Paired, Pastel1, Pastel2, Set1, Set2, Set3
color : str (default None)
If specified, all objects will be colored uniformly.
ax : matplotlib.pyplot.Artist (default None)
axes on which to draw the plot
@@ -127,23 +130,26 @@ def plot_series(s, cmap='Set1', ax=None, linewidth=1.0, figsize=None, **color_kw
if ax is None:
fig, ax = plt.subplots(figsize=figsize)
ax.set_aspect('equal')
color = gencolor(len(s), colormap=cmap)
color_generator = gencolor(len(s), colormap=cmap)
for geom in s:
if color is None:
col = next(color_generator)
else:
col = color
if geom.type == 'Polygon' or geom.type == 'MultiPolygon':
plot_multipolygon(ax, geom, facecolor=next(color), linewidth=linewidth, **color_kwds)
plot_multipolygon(ax, geom, facecolor=col, linewidth=linewidth, **color_kwds)
elif geom.type == 'LineString' or geom.type == 'MultiLineString':
plot_multilinestring(ax, geom, color=next(color), linewidth=linewidth)
plot_multilinestring(ax, geom, color=col, linewidth=linewidth)
elif geom.type == 'Point':
plot_point(ax, geom, color=next(color))
plot_point(ax, geom, color=col)
plt.draw()
return ax
def plot_dataframe(s, column=None, cmap=None, linewidth=1.0,
def plot_dataframe(s, column=None, cmap=None, color=None, linewidth=1.0,
categorical=False, legend=False, ax=None,
scheme=None, k=5, vmin=None, vmax=None, figsize=None,
**color_kwds
):
**color_kwds):
""" Plot a GeoDataFrame
Generate a plot of a GeoDataFrame with matplotlib. If a
@@ -170,6 +176,9 @@ def plot_dataframe(s, column=None, cmap=None, linewidth=1.0,
cmap : str (default 'Set1')
The name of a colormap recognized by matplotlib.
color : str (default None)
If specified, all objects will be colored uniformly.
linewidth : float (default 1.0)
Line width for geometries.
@@ -229,7 +238,9 @@ def plot_dataframe(s, column=None, cmap=None, linewidth=1.0,
from matplotlib import cm
if column is None:
return plot_series(s.geometry, cmap=cmap, ax=ax, linewidth=linewidth, figsize=figsize, **color_kwds)
return plot_series(s.geometry, cmap=cmap, color=color,
ax=ax, linewidth=linewidth, figsize=figsize,
**color_kwds)
else:
if s[column].dtype is np.dtype('O'):
categorical = True
@@ -255,12 +266,16 @@ def plot_dataframe(s, column=None, cmap=None, linewidth=1.0,
fig, ax = plt.subplots(figsize=figsize)
ax.set_aspect('equal')
for geom, value in zip(s.geometry, values):
if color is None:
col = cmap.to_rgba(value)
else:
col = color
if geom.type == 'Polygon' or geom.type == 'MultiPolygon':
plot_multipolygon(ax, geom, facecolor=cmap.to_rgba(value), linewidth=linewidth, **color_kwds)
plot_multipolygon(ax, geom, facecolor=col, linewidth=linewidth, **color_kwds)
elif geom.type == 'LineString' or geom.type == 'MultiLineString':
plot_multilinestring(ax, geom, color=cmap.to_rgba(value), linewidth=linewidth)
plot_multilinestring(ax, geom, color=col, linewidth=linewidth)
elif geom.type == 'Point':
plot_point(ax, geom, color=cmap.to_rgba(value))
plot_point(ax, geom, color=col)
if legend:
if categorical:
patches = []
+62 -5
View File
@@ -26,7 +26,7 @@ BASELINE_DIR = os.path.join(os.path.dirname(__file__), 'baseline_images', 'test_
TRAVIS = bool(os.environ.get('TRAVIS', False))
class PlotTests(unittest.TestCase):
class TestImageComparisons(unittest.TestCase):
def setUp(self):
self.tempdir = tempfile.mkdtemp()
@@ -107,6 +107,7 @@ class PlotTests(unittest.TestCase):
self._compare_images(ax=ax, filename=filename)
class TestPointPlotting(unittest.TestCase):
def setUp(self):
@@ -159,9 +160,59 @@ class TestPointPlotting(unittest.TestCase):
ax = self.df.plot(column='values', cmap='RdYlGn')
cmap = get_cmap('RdYlGn')
expected_colors = cmap(np.arange(self.N)/(self.N-1))
_check_colors(ax.get_lines(), expected_colors)
def test_single_color(self):
ax = self.points.plot(color='green')
_check_colors(ax.get_lines(), ['green']*self.N)
ax = self.df.plot(color='green')
_check_colors(ax.get_lines(), ['green']*self.N)
ax = self.df.plot(column='values', color='green')
_check_colors(ax.get_lines(), ['green']*self.N)
class TestLineStringPlotting(unittest.TestCase):
def setUp(self):
self.N = 10
values = np.arange(self.N)
self.lines = GeoSeries([LineString([(0, i), (9, i)]) for i in xrange(self.N)])
self.df = GeoDataFrame({'geometry': self.lines, 'values': values})
def test_single_color(self):
ax = self.lines.plot(color='green')
_check_colors(ax.get_lines(), ['green']*self.N)
ax = self.df.plot(color='green')
_check_colors(ax.get_lines(), ['green']*self.N)
ax = self.df.plot(column='values', color='green')
_check_colors(ax.get_lines(), ['green']*self.N)
class TestPolygonPlotting(unittest.TestCase):
def test_single_color(self):
t1 = Polygon([(0, 0), (1, 0), (1, 1)])
t2 = Polygon([(1, 0), (2, 0), (2, 1)])
polys = GeoSeries([t1, t2])
df = GeoDataFrame({'geometry': polys, 'values': [0, 1]})
ax = polys.plot(color='green')
_check_colors(ax.patches, ['green']*2, alpha=0.5)
ax = df.plot(color='green')
_check_colors(ax.patches, ['green']*2, alpha=0.5)
ax = df.plot(column='values', color='green')
_check_colors(ax.patches, ['green']*2, alpha=0.5)
class TestPySALPlotting(unittest.TestCase):
@@ -184,14 +235,20 @@ class TestPySALPlotting(unittest.TestCase):
self.assertEqual(labels, expected)
def _check_colors(collection, expected_colors):
def _check_colors(collection, expected_colors, alpha=None):
from matplotlib.lines import Line2D
import matplotlib.colors as colors
conv = colors.colorConverter
for patch, color in zip(collection, expected_colors):
result = patch.get_color()
assert conv.to_rgba(result) == conv.to_rgba(color)
if isinstance(patch, Line2D):
# points/lines
result = patch.get_color()
else:
# polygons
result = patch.get_facecolor()
assert conv.to_rgba(result) == conv.to_rgba(color, alpha=alpha)
if __name__ == '__main__':