예제 #1
0
class SelectFromCollection(object):
    """Select indices from a matplotlib collection using `PolygonSelector`.

    Selected indices are saved in the `ind` attribute. This tool fades out the
    points that are not part of the selection (i.e., reduces their alpha
    values). If your collection has alpha < 1, this tool will permanently
    alter the alpha values.

    Note that this tool selects collection objects based on their *origins*
    (i.e., `offsets`).

    Parameters
    ----------
    ax : :class:`~matplotlib.axes.Axes`
        Axes to interact with.

    collection : :class:`matplotlib.collections.Collection` subclass
        Collection you want to select from.

    alpha_other : 0 <= float <= 1
        To highlight a selection, this tool sets all selected points to an
        alpha value of 1 and non-selected points to `alpha_other`.
    """

    def __init__(self, ax, collection, alpha_other=0.3):
        self.canvas = ax.figure.canvas
        self.collection = collection
        self.alpha_other = alpha_other

        self.xys = collection.get_offsets()
        self.Npts = len(self.xys)

        # Ensure that we have separate colors for each object
        self.fc = collection.get_facecolors()
        if len(self.fc) == 0:
            raise ValueError('Collection must have a facecolor')
        elif len(self.fc) == 1:
            self.fc = np.tile(self.fc, (self.Npts, 1))

        self.poly = PolygonSelector(ax, self.onselect)
        self.ind = []

    def onselect(self, verts):
        path = Path(verts)
        self.ind = np.nonzero(path.contains_points(self.xys))[0]
        self.fc[:, -1] = self.alpha_other
        self.fc[self.ind, -1] = 1
        self.collection.set_facecolors(self.fc)
        self.canvas.draw_idle()

    def disconnect(self):
        self.poly.disconnect_events()
        self.fc[:, -1] = 1
        self.collection.set_facecolors(self.fc)
        self.canvas.draw_idle()
예제 #2
0
class ChartSelector(object):
    def __init__(self, ax, chart_center, chart_size):
        self.canvas = ax.figure.canvas
        chart_height, chart_width = chart_size
        vertices = np.array([[
            chart_center[0] - chart_width / 2,
            chart_center[1] + chart_height / 2
        ],
                             [
                                 chart_center[0] + chart_width / 2,
                                 chart_center[1] + chart_height / 2
                             ],
                             [
                                 chart_center[0] + chart_width / 2,
                                 chart_center[1] - chart_height / 2
                             ],
                             [
                                 chart_center[0] - chart_width / 2,
                                 chart_center[1] - chart_height / 2
                             ],
                             [
                                 chart_center[0] - chart_width / 2,
                                 chart_center[1] + chart_height / 2
                             ]])

        self.poly = PolygonSelector(ax,
                                    self.onselect,
                                    lineprops=dict(color='g',
                                                   linewidth=5,
                                                   alpha=1),
                                    markerprops=dict(mfc='r',
                                                     markersize=10,
                                                     alpha=1))
        self.poly._xs = vertices[:, 0]
        self.poly._ys = vertices[:, 1]
        self.poly._polygon_completed = True
        self.poly._draw_polygon()
        self.vertices = vertices[:-1, :]

    def onselect(self, vertices):
        self.vertices = vertices
        self.canvas.draw_idle()

    def disconnect(self):
        self.poly.disconnect_events()
        self.canvas.draw_idle()
    def __init__(self, ax, collection, alpha_other=0.3):
        self.canvas = ax.figure.canvas
        self.collection = collection
        self.alpha_other = alpha_other

        self.xys = collection.get_offsets()
        self.Npts = len(self.xys)

        # Ensure that we have separate colors for each object
        self.fc = collection.get_facecolors()
        if len(self.fc) == 0:
            raise ValueError('Collection must have a facecolor')
        elif len(self.fc) == 1:
            self.fc = np.tile(self.fc, (self.Npts, 1))

        self.poly = PolygonSelector(ax, self.onselect)
        self.ind = []
 def __init__(self, ax, grid, csv, image):
     self.canvas = ax.figure.canvas
     self.grid = grid
     self.csv = csv
     self.ax = ax
     self.image = image
     self.tool = LassoSelector(ax, onselect=self.onselect)
     self.ind = []
     self.selection = []
예제 #5
0
    def drawPolygon(self, click):
        print(
            "Click somewhere on the screen to start drawing the polygon.\n\n")

        self.rs = PolygonSelector(self.ax,
                                  self._drawPolygonEvent,
                                  markerprops=dict(markersize=1),
                                  lineprops=dict(linewidth=1,
                                                 alpha=0.6,
                                                 color='k'))
예제 #6
0
파일: plotting.py 프로젝트: xy2259/arpys
    def enter_draw_mode(self) :
        """ 
        Ensure that the next click after this fcn call will start drawing 
        the polygon. 
        """
        # Remove the previous polygon
        if self.poly and self.poly._polygon_completed :
            self.remove_polygon()

        # Reset the flag indicating the first completion of a new polygon
        #self.first_time_complete = True

        # Create a PolygonSelector object and attach the draw lock to 
        # it 
        self.poly = PolygonSelector(self, self._on_polygon_complete, 
                                    lineprops=self.polylineprops, 
                                    markerprops=self.polymarkerprops,
                                    useblit=self.useblit)
        self.figure.canvas.widgetlock(self.poly)
예제 #7
0
class SelectFromArray(object):
    """Select indices from a matplotlib collection using `PolygonSelector`.

    Selected indices are saved in the `ind` attribute. This tool fades out the
    points that are not part of the selection (i.e., reduces their alpha
    values). If your collection has alpha < 1, this tool will permanently
    alter the alpha values.

    Note that this tool selects collection objects based on their *origins*
    (i.e., `offsets`).

    Parameters
    ----------
    ax : :class:`~matplotlib.axes.Axes`
        Axes to interact with.

    collection : :class:`matplotlib.collections.Collection` subclass
        Collection you want to select from.

    alpha_other : 0 <= float <= 1
        To highlight a selection, this tool sets all selected points to an
        alpha value of 1 and non-selected points to `alpha_other`.
    """
    def __init__(self, ax, x, y, alpha_other=0.3):
        self.canvas = ax.figure.canvas
        self.x, self.y = x, y
        self.xys = np.vstack((x, y))
        self.Npts = len(self.xys)

        # Ensure that we have separate colors for each object

        self.poly = PolygonSelector(ax, self.onselect)
        self.ind = []

    def onselect(self, verts):
        path = Path(verts)
        self.poly_mask = poly2mask(self.x, self.y, path)
        self.canvas.draw_idle()

    def disconnect(self):
        self.poly.disconnect_events()
        self.canvas.draw_idle()
예제 #8
0
    def get_mask(self):

        data = self.resized
        fig = plt.figure()
        ax1 = fig.add_subplot(121)
        ax1.imshow(data)
        ax2 = fig.add_subplot(122)
        ax2.imshow(np.zeros_like(data))
        plt.subplots_adjust()
        self.fig = fig

        self.poly = PolygonSelector(ax1, self.onselect)
예제 #9
0
def show_filtered_image(event):
    '''
    shows the filtered image or the original image. If you press the button once, the
    respectively other option appears on the button.
    :param event:
    :return:
    '''

    global sfi_button, im_f, im, im_mask, lasso2

    # disconnects and stops the lassoselecto
    lasso2.disconnect_events()
    # showing the filtered image
    if sfi_button.label.get_text(
    ) == "show filtered\nimage":  # checks the text displayed on the button
        im.remove()  # removing unfiltered image
        im_f = ax.imshow(image_f)  # showning filterd image
        lasso2 = PolygonSelector(ax, select_mask)  # reinitalizing the selector
        if isinstance(mask_show,
                      np.ndarray):  # showing mask if already selected
            im_mask = ax.imshow(mask_show, alpha=0.2)
        sfi_button.label.set_text("show unfiltered\nimage")
        fig.canvas.draw_idle()  # plot update
        return

    # showing the unfilterd image
    if sfi_button.label.get_text(
    ) == "show unfiltered\nimage":  # checks the text displayed on the button
        im_f.remove()  # removing unfiltered image
        im = ax.imshow(image)  # showing filterd image
        lasso2 = PolygonSelector(ax, select_mask)  # reinitalizing the selector
        if isinstance(mask_show,
                      np.ndarray):  # showing mask if alaready selected
            im_mask = ax.imshow(mask_show, alpha=0.2)
        sfi_button.label.set_text("show filtered\nimage")
        fig.canvas.draw_idle()  # plot update
        return
def selectROI(region): 
    
    import pylab
    from matplotlib.widgets import PolygonSelector

    fig, ax = plt.subplots()
    ax.imshow(frame)
    plt.title(region)

    def onselect(verts):
        np.savetxt(direc + '\\coordinates\\' + region, verts)

    polygon = PolygonSelector(ax, onselect)

    plt.show()
def selectROI(region, frame, main_dir): 

	## function that allows us to display a matplotlib interactive polygon selector to annotate the frame for each region (which is one of the arguments) ##

	fig, ax = plt.subplots()
	ax.imshow(frame)
	plt.title(region + ' - Press Q to move to the next location')

	## this is the function that is fed to the polygon selector tool. All I am doing here is saving the coordinates for every polygon drawn to a text file of numpy coordinates ##
	## this allows me to save them outside of the python kernel, and they can be pulled in later at any point ##
	def onselect(verts):
		np.savetxt(os.path.join(os.path.join(main_dir, 'coordinates'), region), verts)

	polygon = PolygonSelector(ax, onselect)

	plt.show()
예제 #12
0
    def __init__(self, ax, collection, alpha_other=0.3):
        self.canvas = ax.figure.canvas
        self.collection = collection
        self.alpha_other = alpha_other

        self.xys = collection.get_offsets()
        self.Npts = len(self.xys)

        # Ensure that we have separate colors for each object
        self.fc = collection.get_facecolors()
        if len(self.fc) == 0:
            raise ValueError('Collection must have a facecolor')
        elif len(self.fc) == 1:
            self.fc = np.tile(self.fc, (self.Npts, 1))

        self.poly = PolygonSelector(ax, self.onselect)
        self.ind = []
예제 #13
0
    def __init__(self, ax, grid, csv, image, regions=[], labels=[], fracs=[]):
        self.canvas = ax.figure.canvas
        self.grid = grid
        self.csv = csv
        self.ax = ax
        self.image = image
        self.tool = LassoSelector(ax, onselect=self.onselect)
        self.ind = []
        self.selection = []
        self.region = []

        self.saved_regions = regions
        self.saved_labels = labels
        self.saved_fractions = fracs
        self.saved_max = []
        self.saved_min = []
        self.saved_avg = []
        self.saved_maxavg = []
예제 #14
0
	def getTargets(self, image, method, **kwargs):
		print("Add targets...\n")
		
		if method in ['poly', 'point']:
			figure = plt.figure()
			ax = plt.gca()
			plt.imshow(image)

		radius = kwargs['radius'] if 'radius' in kwargs else 2
		n = kwargs['n'] if 'n' in kwargs else 100

		if method == 'poly':
			ps = PolygonSelector(ax, lambda verts: self.computePolygon(verts, n = n) )
			plt.show()
		elif method =='point':
			figure.canvas.mpl_connect('button_press_event', lambda event: self.computeCircle(event, radius = radius, n = n) )
			plt.show()
		else:
			self.getTargetsFromImage( kwargs['L'], n )
예제 #15
0
    def __init__(self, image, atom_positions, invert_selection=False):
        """Get a subset of atom positions using interactive tool.

        Access the selected atom positions in the
        atom_positions_selected attribute.

        Parameters
        ----------
        image : 2D HyperSpy signal or 2D NumPy array
        atom_positions : list of lists, NumPy array
            In the form [[x0, y0]. [x1, y1], ...]
        invert_selection : bool, optional
            Get the atom positions outside the region, instead of the
            ones inside it. Default False

        Attributes
        ----------
        atom_positions_selected : NumPy array

        """
        self.image = image
        self.atom_positions = np.array(atom_positions)
        self.invert_selection = invert_selection
        self.atom_positions_selected = []
        self.fig, self.ax = plt.subplots(figsize=(6, 6))
        self.ax.set_title("Use the left mouse button to make the polygon.\n"
                          "Click the first position to finish the polygon.\n"
                          "Press ESC to reset the polygon, and hold SHIFT to\n"
                          "move the polygon.")
        self.cax = self.ax.imshow(self.image)
        self.line_non_selected = self.ax.plot(self.atom_positions[:, 0],
                                              self.atom_positions[:, 1],
                                              'o',
                                              color='red')[0]
        self.line_selected = None
        markerprops = dict(color='blue')
        lineprops = dict(color='blue')
        self.poly = PolygonSelector(self.ax,
                                    self.onselect,
                                    markerprops=markerprops,
                                    lineprops=lineprops)
        self.fig.tight_layout()
예제 #16
0
    def __init__(self, image, dataType='image', xlim=None, ylim=None):

        self.x1 = 0.0
        self.x2 = 0.0
        self.y1 = 0.0
        self.y2 = 0.0
        self.verts = []

        # Print instructions for the user
        self.instructions = "\nINSTRUCTIONS TO DRAW THE POLYGON\n\n"+\
           "Select points in the figure by enclosing them within a polygon.\n"+\
           "Press the 'esc' key to start a new polygon.\n"+\
           "Try holding the 'shift' key to move all of the vertices.\n"+\
           "Try holding the 'ctrl' key to move a single vertex."

        lineprops = dict(color='r', linestyle='-', linewidth=2, alpha=0.5)
        markerprops = dict(marker='o',
                           markersize=7,
                           mec='r',
                           mfc='r',
                           alpha=0.5)

        # Create the figure and plot the image
        fig = plt.figure(1)
        self.ax1 = fig.add_subplot(111)
        if dataType == 'image':
            self.ax1.imshow(image.T)
        elif dataType == 'points':
            self.ax1.plot(*image.T[0:2], 'ob', markersize=3)

        if xlim is not None:
            self.ax1.set_xlim(xlim[0], xlim[1])
        if ylim is not None:
            self.ax1.set_ylim(ylim[0], ylim[1])

        self.ps = PolygonSelector(self.ax1,
                                  self.onselect,
                                  lineprops=lineprops,
                                  markerprops=markerprops)

        plt.show()
예제 #17
0
 def _select_roi(self):
     if self._active == 'roi':
         self._active=None
         self._actions['roi'].setChecked(False)
         self.lasso=None
     else:
         self._active='roi'
         self._actions['roi'].setChecked(True)
         # lasso disappears if window closed and reopened. Must check super
         if not self.unsorted:#self.fig is None:
             ax=self.figure.gca()
             h=self.histo
             if h.dims==2:
                 #from polygonlasso import MyLassoSelector
                 #self.lasso=MyLassoSelector(ax,self.select2dGate,useblit=False)
                 self.lasso=PolygonSelector(ax,self.select2dGate,useblit=False,
                         lineprops=dict(color='c', linestyle='-',
                                        linewidth=2, alpha=0.5))
             else:
                 self.lasso=SpanSelector(ax,self.select1dregion,"horizontal",
                         rectprops = dict(facecolor='blue', alpha=0.5))
예제 #18
0
def ask_file(event):
    '''
    opens a tk inter file browser. The selected file is loaded as an image to the window.
    Additionally the filtered image is calculated immediately.
    :param event:
    :return:
    '''

    # opens dialog box for image selection
    global fig, ax, image, pix, image_f, im, lasso2
    root = tk.Tk()
    root.withdraw()  #
    file_path = filedialog.askopenfile()
    # loading the image
    image = plt.imread(file_path.name)
    # grey scale conversion, one could use some wights here
    if len(image.shape) == 3:
        #image=image[:,:,0]
        image = np.mean(image, axis=2)

    # filtering image
    image_f = normalize(image, lb=0.1,
                        ub=99.9)  # normalization to a range  from 0 to 1
    image_f = gaussian(image_f, sigma=s1) - gaussian(
        image_f, sigma=s2)  # difference of gaussian filtering

    # displaying unfiltered image first
    im = ax.imshow(image)  # you can choose a diffrent color map here
    fig.canvas.draw_idle()  #plot update

    # coordinate of the image, later needed for selction
    pixx = np.arange(image.shape[0])
    pixy = np.arange(image.shape[1])
    xv, yv = np.meshgrid(pixy, pixx)
    pix = np.vstack((xv.flatten(), yv.flatten())).T

    # (re)initialize polygon selector
    #lasso2.disconnect_events() seems to have some kind of bug...
    lasso2 = PolygonSelector(ax, select_mask)  # selector on bf image
예제 #19
0
파일: plotting.py 프로젝트: kuadrat/arpys
class cursorpolyax(cursorax):
    """ 
    A cursorax that allows drawing of a draggable polygon-ROI. 

    By clicking on the plot, a cursor appears which behaves and can be 
    accessed the same way as in :class:`cursorax 
    <arpys.utilities.plotting.cursorax>`.
    Additionally, hitting the `draw_key` (`d` by default) puts user in 
    `polygon-draw mode` where each subsequent click on the plot adds another 
    corner to a polygon until it is completed by clicking on the starting
    point again. 
    Once finished, each click just moves the cursor, as before. Hitting the 
    `remove_key` (`e` by default) removes the polygon from the plot.
    At the moment of the polygon's completion, the function 
    :meth:`on_polygon_complete 
    <arpys.utilities.plotting.cursorpolyax.on_polygon_complete>` 
    is executed. This function is a stub in the class definition and can be 
    overwritten/reassigned by the user to perform any action desired on 
    polygon completion.
    The vertices of the last completed polygon are present as an argument to 
    :meth:`on_polygon_complete 
    <kustom.plotting.cursorpolyax.on_polygon_complete>` and can also be 
    accessed by :attr:`vertices` at any time.

    The actual magic here is done by :class:`PolygonSelector 
    <matplotlib.widgets.PolygonSelector>` which this class mostly just 
    provides a simple interface for ...

    :Known bugs:
        * Using :class:`PolygonSelector 
          <matplotlib.widgets.PolygonSelector>`'s default 'remove' key (Esc) 
          messes up reaction to :class:`cursorpolyax 
          <arpys.utilities.plotting.cursorpolyax>`' keybinds.
        * Shift-dragging polygon makes the cursor jump.
    """
    # The name under which this class of axes will be accessible from matplotlib
    name = 'cursorpoly'

    poly = None
    vertices = None
    polylineprops = dict(color='r', lw='1')
    polymarkerprops = dict(marker='None')

    draw_key = 'd'
    remove_key = 'e'

    # Blitting leads to weird behaviour
    useblit = False

    #first_time_complete = True

    def __init__(self, *args, **kwargs):
        """ 
        The super-class's __init__ method connects the event handling but is 
        going to use the definitions for :func: `on_click 
        <kustom.plotting.cursorpolyax.on_click>` and :func: `on_press 
        <kustom.plotting.cursorpolyas.on_press>` from this class. 
        """
        #cid = self.figure.canvas.mpl_connect('button_press_event', self.on_click)
        #pid = self.figure.canvas.mpl_connect('key_press_event', on_press)
        super().__init__(*args, **kwargs)

    def on_press(self, event):
        """ 
        Handle keyboard press events. If the pressed key matches :attr: 
        `draw_key <cursorax.draw_key>` or :attr: `remove_key 
        <cursorpolyax.remove_key>` and the figure is not draw-locked, carry 
        out the respective operations.
        """
        # Don't do anything if someone else is drawing
        if not self.figure.canvas.widgetlock.available(self.poly):
            return

        if event.key == self.remove_key:
            # Remove the polygon and release the lock
            self.remove_polygon()
            return

        elif event.key == self.draw_key:
            self.enter_draw_mode()

    def enter_draw_mode(self):
        """ 
        Ensure that the next click after this fcn call will start drawing 
        the polygon. 
        """
        # Remove the previous polygon
        if self.poly and self.poly._polygon_completed:
            self.remove_polygon()

        # Reset the flag indicating the first completion of a new polygon
        #self.first_time_complete = True

        # Create a PolygonSelector object and attach the draw lock to
        # it
        self.poly = PolygonSelector(self,
                                    self._on_polygon_complete,
                                    lineprops=self.polylineprops,
                                    markerprops=self.polymarkerprops,
                                    useblit=self.useblit)
        self.figure.canvas.widgetlock(self.poly)

    def on_click(self, event):
        """ 
        Handle mouse-click events. Just call the superclass' on_click 
        method, which positions the cursor at the clicked location. That 
        method check's itself whether the draw lock is free, so we don't get 
        cursor jumps while we're drawing a polygon. 
        """
        # Release the draw lock if the polygon has been completed. Otherwise,
        # the cursor can't be repositioned.
        if self.poly and self.poly._polygon_completed:
            self.figure.canvas.widgetlock.release(self.poly)
        super().on_click(event)

    def remove_polygon(self):
        """ 
        Make the polygon invisible, remove the reference to it (which 
        should cause the underlying :class: `PolygonSelector 
        <matplotlib.widgets.PolygonSelector>` object to be garbage collected) 
        and release the draw lock.
        """
        if not self.poly: return
        try:
            self.figure.canvas.widgetlock.release(self.poly)
        except:
            pass
        self.poly.set_visible(False)
        self.poly = None
        self.figure.canvas.draw()

    def _on_polygon_complete(self, vertices):
        """ 
        Get a handle on the polygon's vertices and call the user-supplied 
        :func: `on_polygon_complete 
        <kustom.plotting.cursorpolyas.on_polygon_complete>`. 
        """
        self.vertices = vertices
        # Only do this the first time the polygon is completed NOTE If we
        # only do this the first time the polygon is completed, the function
        # wont be called when user moves the polygon with shift+drag. The
        # drawback of the way it is now is that this function gets called
        # every time the user clicks on the plot once the polygin has been
        # created....
        #if self.first_time_complete :
        self.on_polygon_complete(vertices)
        #self.first_time_complete = False
        #self.figure.canvas.draw_idle()

    def on_polygon_complete(self, vertices):
        """ This method should be overridden/redefined by user. """
        print(vertices)
예제 #20
0
 def lasso_select(self, event):
     self.disconnect()
     self.tool = LassoSelector(self.ax, onselect=self.onselect)
     self.canvas.draw_idle()
예제 #21
0
 def poly_select(self, event):
     self.disconnect()
     self.tool = PolygonSelector(self.ax,
                                 onselect=self.onselect,
                                 markerprops={'markersize': 3})
     self.canvas.draw_idle()
예제 #22
0
class SelectFromCollection(object):
    """Select indices from a matplotlib collection using `PolygonSelector`.
    
    Selected pixels within the polygon is marked as True and saved in the 
    member variable self.mask, in the same size as input AxesImage object
    with all the other pixels marked as False.

    Parameters
    ----------
    ax : :class:`~matplotlib.axes.Axes`
        Axes to interact with.

    collection : :class:`matplotlib.collections.Collection` subclass
        Collection you want to select from.

    Examples
    --------
    import matplotlib.pyplot as plt
    from mintpy.utils import readfile, plot as pp
    
    fig, ax = plt.subplots()
    data = readfile.read('velocity.h5', datasetName='velocity')[0]
    im = ax.imshow(data)

    selector = pp.SelectFromCollection(ax, im)
    plt.show()
    selector.disconnect()
    
    plt.figure()
    plt.imshow(selector.mask)
    plt.show()
    """
    def __init__(self, ax, collection, alpha_other=0.3):
        self.canvas = ax.figure.canvas
        self.collection = collection
        self.prepare_coordinates()

        self.poly = PolygonSelector(ax, self.onselect)

        msg = "\nSelect points in the figure by enclosing them within a polygon.\n"
        msg += "Press the 'esc' key to start a new polygon.\n"
        msg += "Try hold to left key to move a single vertex.\n"
        msg += "After complete the selection, close the figure/window to continue.\n"
        print(msg)

    def prepare_coordinates(self):
        imgExt = self.collection.get_extent()
        self.length = int(imgExt[2] - imgExt[3])
        self.width = int(imgExt[1] - imgExt[0])
        yy, xx = np.mgrid[:self.length, :self.width]
        self.coords = np.hstack((xx.reshape(-1, 1), yy.reshape(-1, 1)))

    def onselect(self, verts):
        self.poly_path = Path(verts)
        self.mask = self.poly_path.contains_points(self.coords).reshape(
            self.length, self.width)
        self.canvas.draw_idle()

    def disconnect(self):
        self.poly.disconnect_events()
        self.canvas.draw_idle()
예제 #23
0
class SelectUtils(object):
    def __init__(self, ax, grid, csv, image, regions=[], labels=[], fracs=[]):
        self.canvas = ax.figure.canvas
        self.grid = grid
        self.csv = csv
        self.ax = ax
        self.image = image
        self.tool = LassoSelector(ax, onselect=self.onselect)
        self.ind = []
        self.selection = []
        self.region = []

        self.saved_regions = regions
        self.saved_labels = labels
        self.saved_fractions = fracs
        self.saved_max = []
        self.saved_min = []
        self.saved_avg = []
        self.saved_maxavg = []
        self.saved_pixcount = []

    def onselect(self, verts):
        print("selected!")
        reg = Path(verts)
        self.ind = reg.contains_points(self.grid, radius=1)
        mask = ~self.ind
        alpha = (
            0.6 +
            ma.masked_array(np.zeros_like(self.csv) + 0.4, mask=mask)).data
        self.selection = ma.masked_array(self.csv, mask=mask)
        self.region = reg
        self.image.set_alpha(alpha)
        self.canvas.draw_idle()

    def lasso_select(self, event):
        self.disconnect()
        self.tool = LassoSelector(self.ax, onselect=self.onselect)
        self.canvas.draw_idle()

    def poly_select(self, event):
        self.disconnect()
        self.tool = PolygonSelector(self.ax,
                                    onselect=self.onselect,
                                    markerprops={'markersize': 3})
        self.canvas.draw_idle()

    def disconnect(self):
        self.tool.disconnect_events()
        self.canvas.draw_idle()

    def reset(self, event):
        self.disconnect()
        self.image.set_alpha(np.ones_like(self.csv))
        self.canvas.draw_idle()

    def clear_polygons(self, event):
        self.disconnect()
        self.ax.clear()
        self.image = self.ax.imshow(self.csv,
                                    cmap='plasma',
                                    vmin=self.csv.min(),
                                    vmax=self.csv.max(),
                                    interpolation='none')
        self.ax.set_title("Press enter to accept selected points.")
        self.canvas.draw_idle()

    def save_selection(self, event):
        if event.key == "enter":
            label = input("Label for this region: ")
            frac = float(input("Area fraction: "))
            max = np.max(self.selection)
            min = np.min(self.selection)
            avg = np.average(self.selection)
            avg_10max = np.average(
                heapq.nlargest(10, self.selection.compressed()))

            self.saved_regions.append(self.region)
            self.saved_labels.append(label)
            self.saved_fractions.append(frac)
            self.saved_max.append(max)
            self.saved_min.append(min)
            self.saved_avg.append(avg)
            self.saved_maxavg.append(avg_10max)
            self.saved_pixcount.append(self.selection.compressed().size)

    def refresh_results(self):
        #Used when paths are imported from prior image and results need to be re-calculated for the new image
        for reg in self.saved_regions:
            self.ind = reg.contains_points(self.grid, radius=1)
            mask = ~self.ind
            self.selection = ma.masked_array(self.csv, mask=mask)

            max = np.max(self.selection)
            min = np.min(self.selection)
            avg = np.average(self.selection)
            avg_10max = np.average(
                heapq.nlargest(10, self.selection.compressed()))
            self.saved_max.append(max)
            self.saved_min.append(min)
            self.saved_avg.append(avg)
            self.saved_maxavg.append(avg_10max)
            self.saved_pixcount.append(self.selection.compressed().size)

    def write(self, fname, volt, curr):
        output = open(fname, "a")
        if os.stat(fname).st_size == 0:
            output.write(
                "Region,Max T,Avg Max T (10 largest),Min T,Avg T,Voltage,Current,Power,Area Fraction,Pixel Count\n"
            )
        for i, label in enumerate(self.saved_labels):
            output.write(
                "%s,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%i\n" %
                (label, self.saved_max[i], self.saved_maxavg[i],
                 self.saved_min[i], self.saved_avg[i], volt, curr, volt * curr,
                 self.saved_fractions[i], self.saved_pixcount[i]))
        output.close()
    polygonVertices = [(min(max(0, entry[0]), imageHandler.xMax),
                        min(max(0, entry[1]), imageHandler.yMax))
                       for entry in polygonVertices]
    xPoints, yPoints = np.meshgrid(np.arange(outAveraged.shape[2]),
                                   np.arange(outAveraged.shape[1]))
    xPoints, yPoints = xPoints.flatten(), yPoints.flatten()

    points = np.vstack((xPoints, yPoints)).T
    polyPath = Path(polygonVertices)
    imageMask = polyPath.contains_points(points)
    imageHandler.imageMask = imageMask.reshape(
        (outAveraged.shape[1], outAveraged.shape[2]))
    imageHandler.boundaryPoly = polyPath


poly = PolygonSelector(ax, PolySelection)

plt.show()
plt.close()
#
#
outAveraged = outAveraged * imageHandler.imageMask + 1

for centerSlice in range(len(wavelengths)):
    CLFrame = outAveraged[centerSlice, :, :]
    backgroundPoints = getBackgroundPoints(CLFrame, 0.01)
    backgroundAverage = np.mean(backgroundPoints)
    outAveragedBlurred[centerSlice, :, :] = gaussian_filter(
        CLFrame, sigma=gaussianSigma,
        truncate=truncateWindow) + backgroundAverage / 2
예제 #25
0
    def init_plot(self,
                  embedding,
                  weights,
                  on_selection,
                  on_close,
                  disable_select,
                  top_level=False,
                  labels=None,
                  color_norm=None):
        """ Set the initial embedding and point weights
            to create and display the plot at iteration step=0"""
        # pylint: disable=attribute-defined-outside-init
        self.top_level = top_level
        self.labels = labels
        self.color_norm = color_norm
        self.disable_select = disable_select
        self.selection_mask = np.full(weights.shape, False)

        # Plot and image definition
        # self.rect = None
        self.extent = 2.8
        self.cleanup = True
        self.rectangle_selector = None
        self.lasso_selector = None

        # Callbacks
        self.fig.canvas.mpl_connect('motion_notify_event', self.on_over)
        self.fig.canvas.mpl_connect('key_press_event', self.on_keypress)
        self.fig.canvas.mpl_connect('button_press_event', self.on_start_select)
        self.fig.canvas.mpl_connect('close_event', self.handle_close)

        # Brush support values
        self.in_selection = False
        self.in_paint = False
        self.dim_xy = (None, None)  # displacement
        self.rorg_xy = (None, None)  # The bottom left corner

        print("Show plot")
        plt.show(block=False)  # Need no block for cooperation with tkinter

        self.embedding = embedding
        self.on_selection = on_selection
        self.on_close = on_close
        # pylint: enable=attribute-defined-outside-init
        x = embedding[:, 0]
        y = embedding[:, 1]
        if self.labels is None:
            self.scatter = self.ax.scatter(x,
                                           y,
                                           s=weights * 8,
                                           c='b',
                                           alpha=0.4,
                                           picker=10)
        else:
            self.scatter = self.ax.scatter(
                x,
                y,
                s=weights * 8,
                c=self.labels,
                # TODO make color map user selectable pylint: disable=fixme
                cmap=plt.cm.rainbow_r,  # # pylint: disable=no-member
                norm=self.color_norm,
                alpha=0.4,
                picker=10)

        self.update_scatter_plot_limits(embedding)

        # Drawing selectors
        rectangle_selector = RectangleSelector(self.ax,
                                               self.on_end_rectangle_select,
                                               drawtype='box',
                                               useblit=True,
                                               button=[1, 3],
                                               rectprops=dict(
                                                   facecolor=(1, 0, 0, 0.1),
                                                   edgecolor=(1, 0, 0, 0.5),
                                                   fill=False),
                                               minspanx=5,
                                               minspany=5,
                                               spancoords='pixels')
        lasso_selector = LassoSelector(self.ax,
                                       onselect=self.on_end_lasso_select,
                                       lineprops=dict(color=(1, 0, 0, 0.5)))
        ellipse_selector = EllipseSelector(self.ax,
                                           onselect=self.on_end_ellipse_select,
                                           drawtype='line',
                                           lineprops=dict(color=(1, 0, 0,
                                                                 0.5)))
        polygon_selector = PolygonSelector(self.ax,
                                           onselect=self.on_end_lasso_select,
                                           lineprops=dict(color=(1, 0, 0,
                                                                 0.5)))

        self.selectors = {
            DrawingShape.Lasso: lasso_selector,
            DrawingShape.Ellipse: ellipse_selector,
            DrawingShape.Rectangle: rectangle_selector,
            DrawingShape.Polygon: polygon_selector
        }
        # pylint: disable=attribute-defined-outside-init
        self.set_selector()
        # force rendering of facecolors
        self.fig.canvas.draw()
        self.facecolors = self.scatter.get_facecolors()
예제 #26
0
class Map():
    """
    This class provides a GUI interface and map object that represents a
    robot's environment. This will be used to graph a robots movements in
    an environment
    """
    def __init__(self, height=100, width=100, points_per_side=1000):
        """
        This function creates and initializes the Map with the given parameters.

        Parameters
        ----------
        height:  Integer
            The height of the map
        width:  Integer
            The width of the map
        points_per_side:      Integer
            The number of points on the map grid per side (x and y)

        Returns
        -------
        Map object with the given parameters after the user has edited.
        """

        self._h = height
        self._w = width
        self._pps = points_per_side
        self._objects = []

        # Get figure objects and adjust for buttons
        self.setup()

        # Build map of points
        points_x = np.tile(np.linspace(0, self._w, self._pps), self._pps)
        points_y = np.repeat(np.linspace(0, self._h, self._pps), self._pps)
        self._pts = self._ax.scatter(points_x, points_y)
        self._coordinates = self._pts.get_offsets()

        #Make points invisible
        #self._pts.set_facecolors([0, 0, 0, 0])
        self._pts.remove()

        self._map = np.zeros((self._pps - 1, self._pps - 1))

    def edit(self):
        try:
            plt.close(self._fig)
        except:
            print("Exception")
            pass

        self.setup()
        plt.figure(self._fig.number)
        plt.show(block=True)

    def click_add_object(self, event):
        """
        Callback for the 'Add Object' button
        """
        self._poly_select.set_active(True)

    def click_clear(self, event):
        """
        Callback for the 'Clear Objects' button
        """
        for item in self._objects:
            item.remove()

        self._objects.clear()
        self._map = np.zeros((self._pps - 1, self._pps - 1))

    def click_finished(self, event):
        """
        Callback for the 'Finished' button
        """
        plt.close(self._fig)

    @property
    def height(self):
        """
        The height of the map (Max y value)
        """
        return self._h

    @property
    def width(self):
        """
        The width of the map (Max x value)
        """
        return self._w

    @property
    def map(self):
        """
        The map defined by the object. -1 indicates an obstacle.
        """
        return self._map

    @property
    def pps(self):
        """
        The number of points per side in the map. NOTE: The map property will be
        one point smaller in both directions as it is the gaps between the points.
        """
        return self._pps

    @map.setter
    def map(self, new_map):
        """
        This is a setter for the internal map object. This allows the user
        to manually edit a copy of the map and set it back in the object.

        """

        self._map = new_map

    def setup(self):
        # Get figure objects and adjust for buttons
        self._fig = plt.figure()
        self._ax = self._fig.add_subplot(1, 1, 1)
        self._ax.set_title("Map Editor")
        self._fig.canvas.set_window_title('RoboLib')
        self._ax.set_xlim([0, self._w])
        self._ax.set_ylim([0, self._h])
        plt.subplots_adjust(bottom=0.2)

        # Build buttons
        button_location = plt.axes([0.8, 0.05, 0.15, 0.075])
        self._add_object_button = Button(button_location, 'Add Object')
        self._add_object_button.on_clicked(self.click_add_object)

        button_location = plt.axes([0.6, 0.05, 0.18, 0.075])
        self._clear_axes_button = Button(button_location, "Clear Objects")
        self._clear_axes_button.on_clicked(self.click_clear)

        button_location = plt.axes([0.4, 0.05, 0.15, 0.075])
        self._finished_button = Button(button_location, 'Finished')
        self._finished_button.on_clicked(self.click_finished)

        # Clear from previous axis
        for patch in self._objects:
            patch.remove()

        for patch in self._objects:
            self._ax.add_patch(patch)

        self._poly_select = PolygonSelector(self._ax, self.on_poly_select)
        self._poly_select.set_active(False)

    def on_poly_select(self, verts):
        """
        This function is called by the polygon select when a polygon
        is closed by the user. It adds a patch to the figure and updates
        the grid map.
        """
        #Close and create patch TODO: Replace with Draggable
        verts.append(verts[0])
        path = Path(verts)

        patch = patches.PathPatch(path)
        self._ax.add_patch(patch)
        self._objects.append(patch)

        # Find points which the polygon contains
        self._intersections = np.nonzero(
            path.contains_points(self._coordinates))[0]

        # Update the grid
        for index in self._intersections:
            x = index % self._pps
            y = floor(index / self._pps)

            if x != self._w and y != self._h:
                self._map[x, y] = -1
            if x != 0 and y != 0:
                self._map[x - 1, y - 1] = -1
            if x != self._w and y != 0:
                self._map[x, y - 1] = -1
            if x != 0 and y != self._h:
                self._map[x - 1, y] = -1

        # Necessary Matplotlib internal functions on the PolygonSelector
        self._poly_select._clean_event(self._poly_select._prev_event)
        self._poly_select.set_visible(True)
        self._poly_select._xs, self._poly_select._ys = [0], [0]
        self._poly_select._polygon_completed = False
        self._poly_select.update()
        self._poly_select.set_active(False)
예제 #27
0
minsize = 0  # default value, you can change this

# custom color map for showing the mask of segmentation
cmap_mask = LinearSegmentedColormap.from_list('mycmap', ["red", "white"])

# initializing the interactive window
fig, ax = plt.subplots()
txt = plt.text(0.25, 0.15, str(""))  # text over sliding bar
plt.subplots_adjust(left=0.25, bottom=0.25)

# adding the open image button to the window
ax_file, file_select = set_button([0.02, 0.5, 0.17, 0.05], 'open image',
                                  ask_file)

# initialyzing the polygone selector
lasso2 = PolygonSelector(ax, select_mask)  #

## adds functionality to delete the mask of segemntation or the dish area on rioght mouse click
delete_mask_event = fig.canvas.mpl_connect('button_press_event', delete_mask)

# buttton so save the mask of the dish area
ax_save_changes, save_changes_button = set_button([0.02, 0.4, 0.17, 0.05],
                                                  'save mask', save_mask)

# buttton to swithc between the filtered and unfiltered images
ax_sfi, sfi_button = set_button([0.02, 0.15, 0.17, 0.1],
                                "show filtered\nimage", show_filtered_image)

# adding the slider for thresholding
ax_slider_tresh = plt.axes([0.25, 0.1, 0.65, 0.03])  # axis for the slider
slider1 = Slider(ax_slider_tresh,
예제 #28
0
Polygon Selector
================

Shows how to create a polygon programmatically or interactively
"""

import matplotlib.pyplot as plt
from matplotlib.widgets import PolygonSelector

###############################################################################
#
# To create the polygon programmatically
fig, ax = plt.subplots()
fig.show()

selector = PolygonSelector(ax, lambda *args: None)

# Add three vertices
selector.verts = [(0.1, 0.4), (0.5, 0.9), (0.3, 0.2)]

###############################################################################
#
# To create the polygon interactively

fig2, ax2 = plt.subplots()
fig2.show()

selector2 = PolygonSelector(ax2, lambda *args: None)

print("Click on the figure to create a polygon.")
print("Press the 'esc' key to start a new polygon.")
예제 #29
0
    def imshow(self,
               image,
               slider=False,
               normalize=True,
               roi_callback=None,
               roi_drawtype='box',
               **kwargs):
        '''
        Showing an image on the canvas, and optional sliders for colour adjustments.
        
        Redrawing image afterwards is quite fast because set_data is used
        instead imshow (matplotlib).

        INPUT ARGUMENTS
        slider          Whether to draw the sliders for setting image cap values
        roi_callback    A callable taking in x1,y1,x2,y2
        roi_drawtype    "box", "ellipse" "line" or "polygon"
        *kwargs     go to imshow

        Returns the object returned by matplotlib's axes.imshow.
        '''

        if image is None:
            image = self.imshow_image

        self.imshow_image = image

        # Slider
        if slider:
            # Check if the sliders exist. If not, create
            try:
                self.imshow_sliders
            except AttributeError:
                self.slider_axes = [
                    self.figure.add_axes(rect)
                    for rect in ([0.2, 0.05, 0.6, 0.05], [0.2, 0, 0.6, 0.05])
                ]

                self.imshow_sliders = []
                self.imshow_sliders.append(
                    matplotlib.widgets.Slider(self.slider_axes[0],
                                              'Upper %',
                                              0,
                                              100,
                                              valinit=90,
                                              valstep=1))
                self.imshow_sliders.append(
                    matplotlib.widgets.Slider(self.slider_axes[1],
                                              'Lower %',
                                              0,
                                              100,
                                              valinit=5,
                                              valstep=1))
                for slider in self.imshow_sliders:
                    slider.on_changed(lambda slider_val: self.imshow(
                        None, slider=slider, **kwargs))

            for ax in self.slider_axes:
                if ax.get_visible() == False:
                    ax.set_visible(True)

            # Normalize using the known clipping values
            #image = image - lower_clip
            #image = image / upper_clip
        else:
            # Hide the sliders if they exist
            if getattr(self, 'imshow_sliders', None):
                for ax in self.slider_axes:
                    if ax.get_visible() == True:
                        ax.set_visible(False)
                        print('axes not visible not')

        if getattr(self, 'imshow_sliders', None):
            # Check that the lower slider cannot go above the upper.
            if self.imshow_sliders[0].val < self.imshow_sliders[1].val:
                self.imshow_sliders[0].val = self.imshow_sliders[1].val

            upper_clip = np.percentile(image, self.imshow_sliders[0].val)
            lower_clip = np.percentile(image, self.imshow_sliders[1].val)
            image = np.clip(image, lower_clip, upper_clip)

        if normalize:
            image = image - np.min(image)
            image = image / np.max(image)

        # Just set the data or make an imshow plot
        if self._previous_shape == image.shape and (
                roi_callback is None
                or roi_drawtype == self._previous_roi_drawtype):
            self.imshow_obj.set_data(image)
        else:
            if hasattr(self, 'imshow_obj'):
                # Fixed here. Without removing the AxesImages object plotting
                # goes increacingly slow every time when visiting this else block
                # Not sure if this is the best fix (does it free all memory) but
                # it seems to work well
                self.imshow_obj.remove()

            self.imshow_obj = self.ax.imshow(image, **kwargs)
            self.figure.subplots_adjust(left=0,
                                        bottom=0,
                                        right=1,
                                        top=1,
                                        wspace=None,
                                        hspace=None)
            self.ax.xaxis.set_major_locator(matplotlib.ticker.NullLocator())
            self.ax.yaxis.set_major_locator(matplotlib.ticker.NullLocator())
            if callable(roi_callback):

                if getattr(self, "roi_rectangle", None):
                    if self._previous_roi_drawtype == 'line':
                        self.roi_rectangle.disconnect()
                    else:
                        self.roi_rectangle.disconnect_events()

                if roi_drawtype == 'box':
                    self.roi_rectangle = RectangleSelector(
                        self.ax, self.__onSelectRectangle, useblit=True)
                elif roi_drawtype == 'ellipse':
                    self.roi_rectangle = EllipseSelector(
                        self.ax, self.__onSelectRectangle, useblit=True)
                elif roi_drawtype == 'line':
                    self.roi_rectangle = ArrowSelector(
                        self.ax, self.__onSelectRectangle)
                elif roi_drawtype == 'polygon':
                    self.roi_rectangle = PolygonSelector(
                        self.ax, self.__onSelectPolygon, useblit=True)
                else:
                    raise ValueError(
                        'roi_drawtype either "box", "ellipse", "line", or "polygon", got {}'
                        .format(roi_drawtype))

                self.roi_callback = roi_callback
                self._previous_roi_drawtype = roi_drawtype

        self._previous_shape = image.shape
        self.canvas.draw()

        return self.imshow_obj
예제 #30
0
	def drawAOI(self):
		"""Function that allows speicification of area of interest (AOI) for analysis.

		"""

		with open(self.json_file, "r") as f:
			json_data = json.load(f)

		aoi_left_x = 0
		aoi_left_y = 0
		aoi_right_x = 0
		aoi_right_y = 0

		display_width = json_data["Analysis_Params"]["EyeTracker"]["Display_width"]
		display_height = json_data["Analysis_Params"]["EyeTracker"]["Display_height"]

		cnt = 0
		img = None

		if os.path.isdir(self.path + "/Stimuli/"):
			for f in os.listdir(self.path + "/Stimuli/"):
				if f.split(".")[-1] in ['jpg', 'jpeg', 'png']:
					img = plt.imread(self.path + "/Stimuli/" + f)
					cnt += 1
					break

		if cnt == 0:
			img = np.zeros((display_height, display_width, 3))

		fig, ax = plt.subplots()
		fig.canvas.set_window_title("Draw AOI")
		ax.imshow(img)

		if self.aoi == "p":

			def onselect(verts):
				nonlocal vertices, canvas
				print('\nSelected points:')
				x = []
				y = []
				for i, j in vertices:
					print(round(i, 3), ",", round(j, 3))
					x.append(i)
					y.append(j)

				vertices = verts
				canvas.draw_idle()

			canvas = ax.figure.canvas
			_ = PolygonSelector(ax, onselect, lineprops=dict(color='r', linestyle='-', linewidth=2, alpha=0.5), markerprops=dict(marker='o', markersize=7, mec='r', mfc='k', alpha=0.5))
			vertices = []

			print("1) 'esc' KEY: START A NEW POLYGON")
			print("2) 'shift' KEY: MOVE ALL VERTICES BY DRAGGING ANY EDGE")
			print("3) 'ctrl' KEY: MOVE A SINGLE VERTEX")

			plt.show()
			return vertices

		elif self.aoi == "r":
			def line_select_callback(eclick, erelease):
				nonlocal aoi_left_x, aoi_left_y, aoi_right_x, aoi_right_y
				aoi_left_x, aoi_left_y = round(eclick.xdata, 3), round(eclick.ydata, 3)
				aoi_right_x, aoi_right_y = round(erelease.xdata, 3), round(erelease.ydata, 3)
				print("Coordinates [(start_x, start_y), (end_x, end_y)]: ", "[(%6.2f, %6.2f), (%6.2f, %6.2f)]" % (aoi_left_x, aoi_left_y, aoi_right_x, aoi_right_y))

			RS = RectangleSelector(ax, line_select_callback, drawtype='box', useblit=False, interactive=True)
			RS.to_draw.set_visible(True)

			plt.show()
			return [aoi_left_x, aoi_left_y, aoi_right_x, aoi_right_y]

		elif self.aoi == "e":
			x_dia = 0
			y_dia = 0
			centre = (0,0)
			def onselect(eclick, erelease):
				nonlocal x_dia, y_dia, centre
				x_dia = (erelease.xdata - eclick.xdata)
				y_dia = (erelease.ydata - eclick.ydata)
				centre = [round(eclick.xdata + x_dia/2., 3), round(eclick.ydata + y_dia/2., 3)]
				print("Centre: ", centre)
				print("X Diameter: ", x_dia)
				print("Y Diameter: ", y_dia)
				print()

			ES = EllipseSelector(ax, onselect, drawtype='box', interactive=True, lineprops=dict(color='g', linestyle='-', linewidth=2, alpha=0.5), marker_props=dict(marker='o', markersize=7, mec='g', mfc='k', alpha=0.5))
			plt.show()

			return [centre, x_dia, y_dia]
예제 #31
0
    def __init__(self, ax):
        self.canvas = ax.figure.canvas

        self.poly = PolygonSelector(ax, self.onselect)
        self.ind = []
예제 #32
0
def show_mask(prod, mask: np.ndarray) -> None:

    filter = (abs(prod.vh_image.mean() - (prod.vh_image.std(
    ) if prod.vh_image.mean() > 0.005 else prod.vh_image.min())))
    min = 0.0
    max = (prod.vh_image.mean() if prod.vv_image.mean() < prod.vh_image.mean()
           else prod.vh_image.mean())

    # Update function for the PolygonSelector
    def onselect(verts):
        print("Creating Indices")

        # Path based on the verticies from the selection
        path = Path(verts)

        coords_pruned = prune(prod, verts)

        path_start = time.perf_counter()

        # Array of indices that are within the polygon
        ind = np.vstack(
            [[p[0] for p in coords_pruned if path.contains_point(p)],
             [p[1] for p in coords_pruned if path.contains_point(p)]])

        path_end = time.perf_counter()
        print("Point in Polygon Time: ", path_end - path_start)

        mask_start = time.perf_counter()
        mask_edited = edit_mask_from_selection(mask, 1, verts, ind)
        mask_end = time.perf_counter()
        print("Mask Editing Time: ", mask_end - mask_start)
        return show_mask(prod, mask_edited)

    def update(val):
        show_mask(prod, create_mask(prod.vv_image, prod.vh_image, val))

    mat = plt.matshow(mask)
    ax = plt.gca()

    # Calls onselect with an array of tuples defining the verticies of the polygon
    # Note: this is called any time the plot is clicked on!
    selector = PolygonSelector(plt.gca(), onselect)

    filter_slider = Slider(plt.axes([0.5, 0.025, 0.25, 0.04]),
                           'Filter',
                           min, (max - min) / 2,
                           valinit=filter,
                           valstep=max / 10000)
    filter_slider.on_changed(update)

    button = Button(plt.axes([0.1, 0.025, 0.1, 0.04]), 'Save GeoTiff')
    button.on_clicked(
        lambda _: write_mask_to_file(mask, f'mask-{prod.mask_number}.tif', prod
                                     .projection, prod.geo_transform))

    x = prod.vv_array
    y = prod.vh_array

    fig, axs = plt.subplots(1, 2, sharey=True, tight_layout=True)

    axs[0].hist(x, bins=50)
    axs[1].hist(y, bins=50)

    plt.show()