-
-
Notifications
You must be signed in to change notification settings - Fork 8k
Description
so my plot is,
- drawing regular scatterplot
- drawing a network overlay using
LineCollection
with each edge to be blurred using a trick calledagg_filter
, which is a hidden feature not listed in the documentation of matplotlib.
the problem is this plot used to be fine before perhaps in version 1.4, but now after upgrade to 1.5.0 there is a offset of line collection and scatterplot. the plot is now look like this:
the 2D coordinate for scatterplot and line collection should be correct otherwise the old version should not draw it correctly.
I found there is no explanation in the official documentation of matplotlib of the Collection. set_agg_filter(filter_func)
nor did I found the explanation of what is filter_fun
is like and how it should be defined.
please tell me whether agg_filter
is still working in Matplotlib, many thanks.
so basically I extract the relevant code to present:
## for drawing the overlay graph
# this line draw the network
pclt = LineCollection(segments = arwPair, linewidths = sizeArr, linestyles = markerArr)
from agg_filter import AggFilterHelper # a helper class wrapping the Gaussian filter
afh = AggFilterHelper("Blur")
pclt.set_agg_filter(afh.get_aggFilter()) # this LineCollection api to set filter
pclt.set_rasterized(True)
axx.add_collection(pclt) # add collection to axes object
# go on drawing
the agg_filter
code is found in MailList of matplotlib which is never listed in Documentation but mentioned to be implemented but never actually implemented. so I guess it is a hidden feature, perhaps the code is outdated, but I really need to blur these lines in my plot in the new version of Matplotlib.
def smooth1d(x, window_len):
# copied from http://www.scipy.org/Cookbook/SignalSmooth
s=np.r_[2*x[0]-x[window_len:1:-1],x,2*x[-1]-x[-1:-window_len:-1]]
w = np.hanning(window_len)
y=np.convolve(w/w.sum(),s,mode='same')
return y[window_len-1:-window_len+1]
def smooth2d(A, sigma=3):
window_len = max(int(sigma), 3)*2+1
A1 = np.array([smooth1d(x, window_len) for x in np.asarray(A)])
A2 = np.transpose(A1)
A3 = np.array([smooth1d(x, window_len) for x in A2])
A4 = np.transpose(A3)
return A4
class BaseFilter(object):
def prepare_image(self, src_image, dpi, pad):
ny, nx, depth = src_image.shape
padded_src = np.zeros([pad*2+ny, pad*2+nx, depth], dtype="d")
padded_src[pad:-pad, pad:-pad,:] = src_image[:,:,:]
return padded_src
def get_pad(self, dpi):
return 0
def __call__(self, im, dpi):
pad = self.get_pad(dpi)
padded_src = self.prepare_image(im, dpi, pad)
tgt_image = self.process_image(padded_src, dpi)
return tgt_image, -pad, -pad
class GaussianFilter(BaseFilter):
"simple gauss filter"
# Only this one I test and used in the application
def __init__(self, sigma):
self.sigma = sigma
def get_pad(self, dpi):
return int(self.sigma*3/72.*dpi)
def process_image(self, padded_src, dpi):
tgt_image = np.zeros_like(padded_src)
# original
# aa = smooth2d(padded_src[:,:,-1]*self.alpha, self.sigma/72.*dpi)
# tgt_image[:,:,-1] = aa
# tgt_image[:,:,:-1] = self.color
# My Try: hell yeah it works
for i in range(4):
aa = smooth2d(padded_src[:,:,i], self.sigma/72.*dpi)
tgt_image[:,:,i] = aa
return tgt_image