2012-07-20 37 views
7

與我的previous question類似,我想控制使用matplotlib繪製的線條的capstyle。但是,我有非常多的線條,並且使用線條集合以外的任何東西繪製都會花費太長時間。是否有任何解決方法來以一種通用的方式控制線條集合中的線條樣式(或者是繪製大量線條的超快速方法)。例如,我嘗試過使用matplotlib rc設置:matplotlib - 線條集合的控制capstyle /大量行

import matplotlib as mpl 
mpl.rcParams['lines.solid_capstyle'] = 'round' 
mpl.rcParams['lines.solid_joinstyle'] = 'round' 

但是這看起來沒有任何影響。從文檔字符串爲collections.py

的類並不意味着是它們的單一元素的同行一樣靈活(例如,你可能無法選擇所有線型),但他們註定要快於常見的使用情況(如大集實線segemnts)

這就解釋了爲什麼似乎無法控制各種參數,但是我還是要做到這一點!我看了一下AGG後端的代碼(_backend_agg.cpp:我真的不明白它),看起來line_cap和line_join由gc.capgc.join控制,其中gc來自GCAgg類。有誰知道如何從Python控制這個?我在這裏問正確的問題嗎?也許這是更簡單的方法來控制這些參數?

任何幫助非常感謝...我非常渴望得到這個工作,所以即使是瘋狂的黑客也歡迎!

感謝,

卡森

回答

3

既然你在你的問題中提到你不介意「髒」的解決方案,一個選項如下。

特定LineCollection的「拉拔處理」是通過在Collection類(的LineCollection基部)中定義的draw方法處理。此方法通過語句gc = renderer.new_gc()創建GraphicsContextBase(在backend_bases.py中定義)的實例。似乎正是這個對象控制着capstyle(財產_capstyle)控制其他物業。因此,人們可以繼承GraphicsContextBase,覆蓋_capstyle財產,並注入了新的new_gc方法爲RendererBase類,以便後續調用new_gc回報定製實例:

通過@florisvb中借鑑了答案的例子(假設Python3) :

#!/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') 

這將產生: enter image description here

+0

尼斯。那看起來很華麗!謝謝@ewcz! – 2017-05-14 19:50:53

+0

@ewcz此解決方案對基於agg的輸出非常有用,謝謝!我一直在尋找其他後端的源代碼,因爲我也想用PDF來獲得這個效果。我似乎無法讓'ps'或'pdf'後端接受你寫的補丁,但有趣的是'svg'後端可以處理它。關於如何調整這個補丁的pdf輸出的想法? – aorr 2017-07-09 16:42:22

1

我用同樣的問題掙扎。我最終在我的線集合上繪製了散點圖。這並不完美,但它可能適用於您的應用程序。有一些微妙之處 - 下面是一個工作示例。

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())