2012-07-20 18 views
7

Tương tự như một số previous question của tôi, tôi muốn kiểm soát kiểu dòng được vẽ bằng cách sử dụng matplotlib. Tuy nhiên, tôi có một số lượng cực lớn các dòng và vẽ với bất kỳ thứ gì ngoài bộ sưu tập đường mất quá nhiều thời gian. Có cách giải quyết nào để kiểm soát kiểu dáng của đường kẻ trong bộ sưu tập đường theo cách chung hay không (hoặc cách khác, cách siêu nhanh để vẽ một số lượng lớn các dòng Line2D). Ví dụ: tôi đã thử sử dụng cài đặt rc matplotlib qua:matplotlib - mẫu điều khiển của bộ sưu tập đường/số lượng lớn các dòng

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

Nhưng điều này dường như không có bất kỳ ảnh hưởng nào. Từ docstring cho collections.py:

Các lớp này không có nghĩa là đối tác đơn lẻ (ví dụ: bạn không thể chọn tất cả kiểu đường) nhưng chúng có nghĩa là nhanh (ví dụ như một tập hợp lớn các dòng rắn segemnts)

nào giải thích tại sao tôi dường như không thể kiểm soát các thông số khác nhau, nhưng tôi vẫn muốn làm điều đó! Tôi đã xem mã cho phần phụ trợ AGG (_backend_agg.cpp: không phải là tôi thực sự hiểu nó), và có vẻ như line_cap và line_join được kiểm soát bởi gc.capgc.join, trong đó gc xuất phát từ lớp GCAgg. Có ai biết làm thế nào người ta có thể kiểm soát này từ Python? Tôi có hỏi câu hỏi đúng ở đây không? Có lẽ đó là cách dễ dàng hơn để kiểm soát các thông số này?

Bất kỳ trợ giúp nào được đánh giá rất cao ... Tôi đang tuyệt vọng để làm việc này, vì vậy ngay cả những cú đánh điên cũng được chào đón!

Cảm ơn,

Carson

Trả lời

3

Vì bạn đề cập đến câu hỏi của mình rằng bạn không quan tâm đến giải pháp "bẩn", một tùy chọn như sau.

"Quá trình vẽ" của một số LineCollection cụ thể được xử lý theo phương pháp draw được xác định trong lớp Collection (cơ sở của LineCollection). Phương pháp này tạo ra một thể hiện của GraphicsContextBase (được xác định trong backend_bases.py) thông qua tuyên bố gc = renderer.new_gc(). Nó có vẻ là chính xác đối tượng này chi phối trong số những thứ khác các tài sản kiểm soát các capstyle (tài sản _capstyle). Do đó, người ta có thể phân lớp GraphicsContextBase, ghi đè lên _capstyle bất động sản, và tiêm một phương pháp mới new_gc vào lớp RendererBase để gọi quả để new_gc trở lại trường hợp tùy chỉnh:

Vay ví dụ từ câu trả lời của @florisvb (giả sử 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') 

này tạo ra: enter image description here

+0

Nice. Trông thật tuyệt! Cảm ơn @ewcz! –

+0

@ewcz Giải pháp này hoạt động tốt cho sản lượng dựa trên agg, cảm ơn!Tôi đã xem xét các nguồn cho backends khác bởi vì tôi muốn có được hiệu ứng này trong một pdf quá. Tôi không thể có vẻ để có được 'ps' hoặc 'pdf' backends để chấp nhận các bản vá mà bạn đã viết, nhưng thú vị là 'svg' phụ trợ có thể xử lý nó. Bất kỳ suy nghĩ về cách tinh chỉnh bản vá này cho đầu ra pdf? – aorr

1

tôi đã phải vật lộn với vấn đề tương tự. Tôi đã kết thúc một âm mưu phân tán trên đầu trang của bộ sưu tập của tôi. Nó không hoàn hảo, nhưng nó có thể làm việc cho ứng dụng của bạn. Có một vài sự tinh tế - dưới đây là một ví dụ làm việc.

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()) 
Các vấn đề liên quan