Python matplotlib-控制行集合的样式/大量行

Python matplotlib-控制行集合的样式/大量行,python,matplotlib,lines,Python,Matplotlib,Lines,与我的类似,我想控制使用matplotlib绘制的线的capstyle。然而,我有非常多的线条,用线条集合以外的任何东西绘制都会花费很长时间。是否有任何变通方法可以以通用方式(或者以超快速方式绘制大量Line2D线)控制线集合中的线样式。例如,我尝试通过以下方式使用matplotlib rc设置: import matplotlib as mpl mpl.rcParams['lines.solid_capstyle'] = 'round' mpl.rcParams['lines.solid_jo

与我的类似,我想控制使用matplotlib绘制的线的capstyle。然而,我有非常多的线条,用线条集合以外的任何东西绘制都会花费很长时间。是否有任何变通方法可以以通用方式(或者以超快速方式绘制大量
Line2D
线)控制线集合中的线样式。例如,我尝试通过以下方式使用matplotlib rc设置:

import matplotlib as mpl
mpl.rcParams['lines.solid_capstyle'] = 'round'
mpl.rcParams['lines.solid_joinstyle'] = 'round'
但这似乎没有任何影响。从
collections.py的docstring中:

这些类并不意味着像它们的单元素对应物那样灵活(例如,您可能无法选择所有线条样式),但它们意味着对于常见用例(例如,一大组实线分段)来说是快速的

这解释了为什么我似乎无法控制各种参数,但我仍然想这样做!我已经看了AGG后端的代码(
\u backend\u AGG.cpp
:我不是很了解它),似乎line\u cap和line\u join由
gc.cap
gc.join
控制,其中gc来自
GCAgg
类。有人知道如何从Python控制它吗?我问的问题对吗?也许这是控制这些参数的更简单的方法

非常感谢您的帮助。。。我非常想让它工作,所以即使是疯狂的黑客也欢迎

谢谢


卡森

我也在为同样的问题而挣扎。最后,我在我的线集合上绘制了一个散点图。它并不完美,但可能适合您的应用程序。这里有一些微妙之处——下面是一个有效的例子

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.collections import LineCollection

x = np.random.random(10)
y = np.random.random(10)
z = np.arange(0,10)

points = np.array([x, y]).T.reshape(-1, 1, 2)
segments = np.concatenate([points[:-1], points[1:]], axis=1)

fig = plt.figure()
ax = fig.add_subplot(111)

linewidth = 10
cmap = plt.get_cmap('jet')
norm = plt.Normalize(np.min(z), np.max(z))
color = cmap(norm(z))

lc = LineCollection(segments, linewidths=linewidth, cmap=cmap, norm=norm)
lc.set_array(z)
lc.set_zorder(z.tolist())
ax.add_collection(lc)

ax.scatter(x,y,color=color,s=linewidth**2,edgecolor='none', zorder=(z+2).tolist())

既然您在问题中提到您不介意“肮脏”的解决方案,那么有一个选项如下

特定
LineCollection
的“绘图过程”由
Collection
类(LineCollection
的基础)中定义的
draw
方法处理。此方法通过语句
gc=renderer.new\u gc()
创建
GraphicsContextBase
(在
backend\u base.py
中定义)的实例。似乎正是这个对象控制着控制
capstyle
(property
\u capstyle
)的属性。因此,可以将
GraphicsContextBase
子类化,重写
\u capstyle
属性,并将新的
new\u gc
方法注入
RenderBase
类,以便对
new\u gc
的后续调用返回自定义实例:

借用@florisvb的答案(假设是Python3)的例子:

这将产生:

更新@ewcz的答案,因为搜索结果中仍会出现此线程。
现在可以使用
path\u effects
而不是定义自己的GraphicsContextBase

e、 g


而且它似乎也能很好地处理pdf输出。看起来真漂亮!谢谢@ewcz@ewcz此解决方案非常适合基于agg的输出,谢谢!我一直在寻找其他后端的源代码,因为我也想在pdf中获得这种效果。我似乎无法让“ps”或“pdf”后端接受您编写的补丁,但有趣的是,“svg”后端可以处理它。关于如何调整此补丁以获得pdf输出有何想法?谢谢您的回答,但导出为pdf不起作用,我使用此答案使其起作用
#!/usr/bin/env python
import types

import numpy as np
from matplotlib.backend_bases import GraphicsContextBase, RendererBase
import matplotlib.pyplot as plt
from matplotlib.collections import LineCollection

class GC(GraphicsContextBase):
    def __init__(self):
        super().__init__()
        self._capstyle = 'round'

def custom_new_gc(self):
    return GC()

RendererBase.new_gc = types.MethodType(custom_new_gc, RendererBase)
#----------------------------------------------------------------------
np.random.seed(42)

x = np.random.random(10)
y = np.random.random(10)

points = np.array([x, y]).T.reshape((-1, 1, 2))
segments = np.concatenate([points[:-1], points[1:]], axis=1)

fig = plt.figure()
ax = fig.add_subplot(111)

linewidth = 10
lc = LineCollection(segments, linewidths=linewidth)
ax.add_collection(lc)

fig.savefig('fig.png')
import numpy as np
import matplotlib.patheffects as path_effects
from matplotlib.collections import LineCollection

np.random.seed(42)

x = np.random.random(10)
y = np.random.random(10)

points = np.array([x, y]).T.reshape((-1, 1, 2))
segments = np.concatenate([points[:-1], points[1:]], axis=1)

fig = plt.figure()
ax = fig.add_subplot(111)

linewidth = 10

### Stroke redraws the segment passing kwargs down to the GC renderer
lc = LineCollection(segments, linewidths=linewidth, 
    path_effects=[path_effects.Stroke(capstyle="round")])

ax.add_collection(lc)

fig.show()