Skip to content

urgent bug after 1.5.0: offset of LineCollection when apply agg_filter #5969

@Hualin

Description

@Hualin

so my plot is,

  1. drawing regular scatterplot
  2. drawing a network overlay using LineCollection with each edge to be blurred using a trick called agg_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:

tsne_d_delaunay_plot pdf 1 page preview today at 6 43 26 pm

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions