예제 #1
0
class SidePanel(WidgetPanel):
    _widget_list = ("buttons", "info_panel")
    buttons = widget_descriptors.PanelDescriptor(
        "buttons", ButtonPanel, default_text="")  # type: ButtonPanel
    info_panel = widget_descriptors.PanelDescriptor(
        "info_panel", InfoPanel, default_text="")  # type: InfoPanel

    def __init__(self, parent):
        WidgetPanel.__init__(self, parent)
        self.init_w_vertical_layout()
예제 #2
0
class Panel1(WidgetPanel):
    _widget_list = (
        'button', 'combobox', 'scale', 'label', 'label_frame', 'entry',
        # 'text',  # omit this one for now, because it's broken
        'spinbox', 'radio_button_panel', 'update_radio_selection', 'check_button')
    button = widget_descriptors.ButtonDescriptor("button")  # type: basic_widgets.Button
    combobox = widget_descriptors.ComboboxDescriptor("combobox")  # type: basic_widgets.Combobox
    scale = widget_descriptors.ScaleDescriptor("scale")  # type: basic_widgets.Scale
    label = widget_descriptors.LabelDescriptor("label")  # type: basic_widgets.Label
    label_frame = widget_descriptors.LabelFrameDescriptor("label_frame")  # type: basic_widgets.LabelFrame
    entry = widget_descriptors.EntryDescriptor("entry", default_text="")  # type: basic_widgets.Entry
    text = widget_descriptors.TextDescriptor("text")  # type: basic_widgets.Text
    spinbox = widget_descriptors.SpinboxDescriptor("spinbox", default_text="")  # type: basic_widgets.Spinbox
    radio_button_panel = widget_descriptors.PanelDescriptor("radio_button_panel", RadioPanel)   # type: RadioPanel
    update_radio_selection = widget_descriptors.ButtonDescriptor("update_radio_selection")  # type: basic_widgets.Button
    check_button = widget_descriptors.CheckButtonDescriptor("check_button")  # type: basic_widgets.CheckButton

    def __init__(self, parent):
        WidgetPanel.__init__(self, parent)
        self.parent = parent
        self.init_w_vertical_layout()

        # callbacks
        self.update_radio_selection.on_left_mouse_click(self.callback_update_radio_selection)

    def callback_update_radio_selection(self, event):
        selection = self.radio_button_panel.selection()
        if selection == self.radio_button_panel.button_1:
            self.radio_button_panel.set_text("button 1")
        elif selection == self.radio_button_panel.button_2:
            self.radio_button_panel.set_text("button 2")
        elif selection == self.radio_button_panel.button_3:
            self.radio_button_panel.set_text("button 3")
예제 #3
0
class ImageCanvasPanel(WidgetPanel):
    _widget_list = ("image_canvas",)

    image_canvas = widget_descriptors.PanelDescriptor("image_canvas", AxesImageCanvas)

    def __init__(self,
                 parent,
                 ):
        WidgetPanel.__init__(self, parent)
        self.init_w_vertical_layout()
        self.pack(fill=tkinter.BOTH, expand=1)
예제 #4
0
class PrimaryPanel(WidgetPanel):
    _widget_list = ('button_1', 'panel_1')
    button_1 = widget_descriptors.ButtonDescriptor("button_1", default_text="asdf")  # type: basic_widgets.Button
    button_2 = widget_descriptors.ButtonDescriptor("button_2")   # type: basic_widgets.Button
    panel_1 = widget_descriptors.PanelDescriptor("panel_1", Panel1)     # type: Panel1

    def __init__(self, primary):
        primary_frame = tkinter.Frame(primary)
        WidgetPanel.__init__(self, primary_frame)

        self.init_w_horizontal_layout()

        primary_frame.pack()
예제 #5
0
class ImageViewer(WidgetPanel, WidgetWithMetadata):
    _widget_list = ("image_panel", "pyplot_panel")
    image_panel = widget_descriptors.ImagePanelDescriptor(
        "image_panel")  # type: ImagePanel
    pyplot_panel = widget_descriptors.PanelDescriptor(
        "pyplot_panel", PyplotImagePanel)  # type: PyplotImagePanel

    def __init__(self, primary):
        """

        Parameters
        ----------
        primary : tkinter.Toplevel|tkinter.Tk
        """

        self.root = primary
        self.primary_frame = basic_widgets.Frame(primary)
        WidgetPanel.__init__(self, self.primary_frame)
        WidgetWithMetadata.__init__(self, primary)
        self.variables = AppVariables()

        self.init_w_horizontal_layout()
        self.set_title()

        # define menus
        menubar = tkinter.Menu()
        # file menu
        filemenu = tkinter.Menu(menubar, tearoff=0)
        filemenu.add_command(label="Open Image",
                             command=self.callback_select_files)
        filemenu.add_command(label="Open Directory",
                             command=self.callback_select_directory)
        filemenu.add_separator()
        filemenu.add_command(label="Exit", command=self.exit)
        # menus for informational popups
        popups_menu = tkinter.Menu(menubar, tearoff=0)
        popups_menu.add_command(label="Metaicon", command=self.metaicon_popup)
        popups_menu.add_command(label="Metaviewer",
                                command=self.metaviewer_popup)
        # ensure menus cascade
        menubar.add_cascade(label="File", menu=filemenu)
        menubar.add_cascade(label="Metadata", menu=popups_menu)

        # handle packing
        self.primary_frame.pack(fill=tkinter.BOTH, expand=tkinter.YES)
        primary.config(menu=menubar)

        # hide extraneous tool elements
        self.image_panel.hide_tools('shape_drawing')
        self.image_panel.hide_shapes()

        # bind canvas events for proper functionality
        # this makes for bad performance on a larger image - do not activate
        # self.image_panel.canvas.bind('<<SelectionChanged>>', self.handle_selection_change)
        self.image_panel.canvas.bind('<<SelectionFinalized>>',
                                     self.handle_selection_change)
        self.image_panel.canvas.bind('<<RemapChanged>>',
                                     self.handle_remap_change)
        self.image_panel.canvas.bind('<<ImageIndexChanged>>',
                                     self.handle_image_index_changed)

    def set_title(self):
        """
        Sets the window title.
        """

        file_name = None if self.variables.image_reader is None else self.variables.image_reader.file_name
        if file_name is None:
            the_title = "Image Viewer"
        elif isinstance(file_name, (list, tuple)):
            the_title = "Image Viewer, Multiple Files"
        else:
            the_title = "Image Viewer for {}".format(
                os.path.split(file_name)[1])
        self.winfo_toplevel().title(the_title)

    def exit(self):
        self.root.destroy()

    # noinspection PyUnusedLocal
    def handle_selection_change(self, event):
        """
        Handle a change in the selection area.

        Parameters
        ----------
        event
        """

        if self.variables.image_reader is None:
            return

        full_image_width = self.image_panel.canvas.variables.state.canvas_width
        fill_image_height = self.image_panel.canvas.variables.state.canvas_height
        self.image_panel.canvas.zoom_to_canvas_selection(
            (0, 0, full_image_width, fill_image_height))
        self.display_canvas_rect_selection_in_pyplot_frame()

    # noinspection PyUnusedLocal
    def handle_remap_change(self, event):
        """
        Handle that the remap for the image canvas has changed.

        Parameters
        ----------
        event
        """
        if self.variables.image_reader is not None:
            self.display_canvas_rect_selection_in_pyplot_frame()

    #noinspection PyUnusedLocal
    def handle_image_index_changed(self, event):
        """
        Handle that the image index has changed.

        Parameters
        ----------
        event
        """

        self.my_populate_metaicon()

    def update_reader(self, the_reader):
        """
        Update the reader.

        Parameters
        ----------
        the_reader : ImageReader
        """

        # change the tool to view
        self.image_panel.canvas.set_current_tool_to_view()
        self.image_panel.canvas.set_current_tool_to_view()
        # update the reader
        self.variables.image_reader = the_reader
        self.image_panel.set_image_reader(the_reader)
        self.set_title()
        # refresh appropriate GUI elements
        self.pyplot_panel.make_blank()
        self.my_populate_metaicon()
        self.my_populate_metaviewer()

    def callback_select_files(self):
        fnames = askopenfilenames(initialdir=self.variables.browse_directory,
                                  filetypes=common_use_collection)
        if fnames is None or fnames in ['', ()]:
            return
        # update the default directory for browsing
        self.variables.browse_directory = os.path.split(fnames[0])[0]

        the_reader = None
        if len(fnames) > 1:
            the_reader = ComplexImageReader(fnames)
        if the_reader is None:
            try:
                the_reader = ComplexImageReader(fnames[0])
            except IOError:
                the_reader = None
        if the_reader is None:
            the_reader = DerivedImageReader(fnames[0])
        if the_reader is None:
            showinfo(
                'Opener not found',
                message='File {} was not successfully opened as a SICD type '
                'or SIDD type file.'.format(fnames))
            return
        self.update_reader(the_reader)

    def callback_select_directory(self):
        dirname = askdirectory(initialdir=self.variables.browse_directory,
                               mustexist=True)
        if dirname is None or dirname in [(), '']:
            return
        # update the default directory for browsing
        self.variables.browse_directory = os.path.split(dirname)[0]
        # TODO: handle non-complex data possibilities here?
        the_reader = ComplexImageReader(dirname)
        self.update_reader(the_reader)

    def display_canvas_rect_selection_in_pyplot_frame(self):
        def get_extent(coords):
            left = min(coords[1::2])
            right = max(coords[1::2])
            top = max(coords[0::2])
            bottom = min(coords[0::2])
            return left, right, top, bottom

        threshold = self.image_panel.canvas.variables.config.select_size_threshold

        select_id = self.image_panel.canvas.variables.select_rect.uid
        rect_coords = self.image_panel.canvas.get_shape_image_coords(select_id)
        extent = get_extent(rect_coords)

        if abs(extent[1] -
               extent[0]) < threshold or abs(extent[2] -
                                             extent[3]) < threshold:
            self.pyplot_panel.make_blank()
        else:
            image_data = self.image_panel.canvas.get_image_data_in_canvas_rect_by_id(
                select_id)
            if image_data is not None:
                self.pyplot_panel.update_image(image_data, extent=extent)
            else:
                self.pyplot_panel.make_blank()

    def my_populate_metaicon(self):
        """
        Populate the metaicon.
        """

        if self.image_panel.canvas.variables.canvas_image_object is None or \
                self.image_panel.canvas.variables.canvas_image_object.image_reader is None:
            image_reader = None
            the_index = 0
        else:
            image_reader = self.image_panel.canvas.variables.canvas_image_object.image_reader
            the_index = self.image_panel.canvas.get_image_index()
        self.populate_metaicon(image_reader, the_index)

    def my_populate_metaviewer(self):
        """
        Populate the metaviewer.
        """

        if self.image_panel.canvas.variables.canvas_image_object is None:
            image_reader = None
        else:
            image_reader = self.image_panel.canvas.variables.canvas_image_object.image_reader
        self.populate_metaviewer(image_reader)
예제 #6
0
class GeotiffViewer(WidgetPanel):
    """
    A geotiff viewer prototype.
    """
    _widget_list = ("band_selection_panel", "controls_panel",
                    "geotiff_image_panel", "zoom_image_panel")
    geotiff_image_panel = widget_descriptors.AxesImageCanvasDescriptor(
        "geotiff_image_panel")  # type: AxesImageCanvas
    zoom_image_panel = widget_descriptors.AxesImageCanvasDescriptor(
        "zoom_image_panel")  # type: AxesImageCanvas
    band_selection_panel = widget_descriptors.PanelDescriptor(
        "band_selection_panel", BandSelection)  # type: BandSelection
    controls_panel = widget_descriptors.PanelDescriptor(
        "controls_panel", Controls)  # type: Controls
    image_reader = None  # type: GeotiffImageReader

    def __init__(self, primary):
        """

        Parameters
        ----------
        primary
            The primary widget.
        """

        self.primary = primary

        primary_frame = tkinter.Frame(primary)
        WidgetPanel.__init__(self, primary_frame)

        self.init_w_horizontal_layout()

        self.geotiff_image_panel.set_canvas_size(800, 1080)
        self.geotiff_image_panel.canvas.set_current_tool_to_pan()

        menubar = Menu()

        filemenu = Menu(menubar, tearoff=0)
        filemenu.add_command(label="Open", command=self.select_file)
        filemenu.add_separator()
        filemenu.add_command(label="Exit", command=self.exit)

        # create more pulldown menus
        popups_menu = Menu(menubar, tearoff=0)
        popups_menu.add_command(label="Main Controls", command=self.exit)

        menubar.add_cascade(label="File", menu=filemenu)
        menubar.add_cascade(label="Popups", menu=popups_menu)

        primary.config(menu=menubar)

        primary_frame.pack()

        self.band_selection_panel.red_selection.on_selection(
            self.callback_update_red_band)
        self.band_selection_panel.green_selection.on_selection(
            self.callback_update_green_band)
        self.band_selection_panel.blue_selection.on_selection(
            self.callback_update_blue_band)
        self.band_selection_panel.alpha_selection.on_selection(
            self.callback_update_alpha_band)

        self.controls_panel.pan.on_left_mouse_click(self.callback_set_to_pan)
        self.controls_panel.select.on_left_mouse_click(
            self.callback_set_to_select)
        self.geotiff_image_panel.canvas.on_left_mouse_release(
            self.callback_select)

    def exit(self):
        """
        Exits/destroys the widget.

        Returns
        -------
        None
        """

        self.quit()

    def select_file(self, fname=None):
        """
        File selector action. Will open a file selector dialog if `None`.

        Parameters
        ----------
        fname : str|None

        Returns
        -------
        None
        """

        if fname is None:
            fname = filedialog.askopenfilename(
                initialdir=os.path.expanduser("~"),
                title="Select file",
                filetypes=(("tiff files", ("*.tif", "*.tiff", "*.TIF",
                                           "*.TIFF")), ("all files", "*.*")))
        self.image_reader = GeotiffImageReader(fname)
        self.geotiff_image_panel.set_image_reader(self.image_reader)
        self.populate_band_selections()

    def populate_band_selections(self):
        """
        Helper method for populating the band selection.

        Returns
        -------
        None
        """

        bands = self.image_reader.n_bands
        band_selections = [str(band) for band in range(bands)]
        band_selections.append("None")
        self.band_selection_panel.red_selection.update_combobox_values(
            band_selections)
        self.band_selection_panel.green_selection.update_combobox_values(
            band_selections)
        self.band_selection_panel.blue_selection.update_combobox_values(
            band_selections)
        self.band_selection_panel.alpha_selection.update_combobox_values(
            band_selections)

        self.band_selection_panel.red_selection.set(
            str(self.image_reader.display_bands[0]))
        self.band_selection_panel.green_selection.set(
            str(self.image_reader.display_bands[1]))
        self.band_selection_panel.blue_selection.set(
            str(self.image_reader.display_bands[2]))
        if len(self.image_reader.display_bands) > 3:
            self.band_selection_panel.alpha_selection.set(
                str(self.image_reader.display_bands[3]))
        else:
            self.band_selection_panel.alpha_selection.set("None")

    def callback_update_red_band(self, event):
        """
        Update the read band.

        Parameters
        ----------
        event

        Returns
        -------
        None
        """

        red_band = self.band_selection_panel.red_selection.get()
        band_num = 0
        if red_band == "None":
            if band_num not in self.geotiff_image_panel.canvas.variables.canvas_image_object.drop_bands:
                self.geotiff_image_panel.canvas.variables.canvas_image_object.drop_bands.append(
                    band_num)
        else:
            if band_num in self.geotiff_image_panel.canvas.variables.canvas_image_object.drop_bands:
                self.geotiff_image_panel.canvas.variables.canvas_image_object.drop_bands.remove(
                    band_num)
            self.image_reader.display_bands[band_num] = int(red_band)
        self.geotiff_image_panel.canvas.update_current_image()

    def callback_update_green_band(self, event):
        """
        Update the green band.

        Parameters
        ----------
        event

        Returns
        -------
        None
        """

        green_band = self.band_selection_panel.green_selection.get()
        band_num = 1
        if green_band == "None":
            if band_num not in self.geotiff_image_panel.canvas.variables.canvas_image_object.drop_bands:
                self.geotiff_image_panel.canvas.variables.canvas_image_object.drop_bands.append(
                    1)
        else:
            if band_num in self.geotiff_image_panel.canvas.variables.canvas_image_object.drop_bands:
                self.geotiff_image_panel.canvas.variables.canvas_image_object.drop_bands.remove(
                    1)
            self.image_reader.display_bands[1] = int(green_band)
        self.geotiff_image_panel.canvas.update_current_image()

    def callback_update_blue_band(self, event):
        """
        Update the blue band.

        Parameters
        ----------
        event

        Returns
        -------
        None
        """

        band_num = 2
        blue_band = self.band_selection_panel.blue_selection.get()
        if blue_band == "None":
            if band_num not in self.geotiff_image_panel.canvas.variables.canvas_image_object.drop_bands:
                self.geotiff_image_panel.canvas.variables.canvas_image_object.drop_bands.append(
                    band_num)
        else:
            if band_num in self.geotiff_image_panel.canvas.variables.canvas_image_object.drop_bands:
                self.geotiff_image_panel.canvas.variables.canvas_image_object.drop_bands.remove(
                    band_num)
            self.image_reader.display_bands[band_num] = int(blue_band)
        self.geotiff_image_panel.canvas.update_current_image()

    def callback_update_alpha_band(self, event):
        """
        Update the alpha channel.

        Parameters
        ----------
        event

        Returns
        -------
        None
        """

        alpha_band = self.band_selection_panel.alpha_selection.get()
        band_num = 3
        if len(self.image_reader.display_bands) == 3:
            self.image_reader.display_bands.append(band_num)
        if alpha_band == "None":
            self.image_reader.display_bands = self.image_reader.display_bands[
                0:3]
        else:
            if band_num in self.geotiff_image_panel.canvas.variables.canvas_image_object.drop_bands:
                self.geotiff_image_panel.canvas.variables.canvas_image_object.drop_bands.remove(
                    band_num)
            self.image_reader.display_bands[band_num] = int(alpha_band)
        self.geotiff_image_panel.canvas.update_current_image()

    def callback_set_to_pan(self, event):
        self.geotiff_image_panel.canvas.set_current_tool_to_pan()

    def callback_set_to_select(self, event):
        self.geotiff_image_panel.canvas.set_current_tool_to_selection_tool()

    def callback_select(self, event):
        data = self.geotiff_image_panel.canvas.get_image_data_in_canvas_rect_by_id(
            self.geotiff_image_panel.canvas.variables.select_rect_id,
            decimation=1)
        data = data[:, :, 0]
        reader = NumpyImageReader(data)
        self.zoom_image_panel.set_image_reader(reader)
        self.zoom_image_panel.canvas.update_current_image()
예제 #7
0
class PyplotPanel(WidgetPanel):
    """
    Panel that displays pyplot plots and plot animations.
    """
    _widget_list = (
        "pyplot_canvas",
        "control_panel",
    )
    pyplot_canvas = widget_descriptors.PyplotCanvasDescriptor(
        "pyplot_canvas")  # type: PyplotCanvas
    control_panel = widget_descriptors.PanelDescriptor(
        "control_panel", PyplotControlPanel)  # type: PyplotControlPanel

    def __init__(self, primary):
        WidgetPanel.__init__(self, primary)
        self.variables = AppVariables()
        self.pyplot_utils = PlotStyleUtils()
        self.init_w_vertical_layout()

        canvas_size_pixels = self.pyplot_canvas.canvas.figure.get_size_inches(
        ) * self.pyplot_canvas.canvas.figure.dpi

        self.control_panel.scale.config(length=canvas_size_pixels[0] * 0.75)
        self.variables.animation_related_controls = [
            self.control_panel.scale,
            self.control_panel.rescale_y_axis_per_frame,
            self.control_panel.animate, self.control_panel.fps_entry,
            self.control_panel.fps_label
        ]

        self.control_panel.n_colors_label.set_text("n colors")
        self.control_panel.n_colors.set_text(self.pyplot_utils.n_color_bins)

        # set listeners
        self.control_panel.scale.on_left_mouse_motion(
            self._callback_update_from_slider)
        self.control_panel.rescale_y_axis_per_frame.on_selection(
            self._callback_set_y_rescale)
        self.control_panel.animate.config(command=self.animate)
        self.control_panel.color_palette.on_selection(
            self.callback_update_plot_colors)
        self.control_panel.n_colors.on_enter_or_return_key(
            self.callback_update_n_colors)
        self.control_panel.n_colors.config(command=self.update_n_colors)

        self.hide_control_panel()

    @property
    def title(self):
        return self.variables.title

    @title.setter
    def title(self, val):
        """
        sets the plot's title

        Parameters
        ----------
        val: str

        Returns
        -------
        """

        self.variables.title = val
        self.pyplot_canvas.axes.set_title(val)
        self.update_plot()

    @property
    def y_label(self):
        return self.variables.y_label

    @y_label.setter
    def y_label(self, val):
        """
        sets the plot's y label

        Parameters
        ----------
        val: str

        Returns
        -------
        """
        self.variables.y_label = val
        self.pyplot_canvas.axes.set_ylabel(val)
        self.update_plot()

    @property
    def x_label(self):
        return self.variables.y_label

    @x_label.setter
    def x_label(self, val):
        """
        sets the plot's x label

        Parameters
        ----------
        val: str

        Returns
        -------
        """
        self.variables.x_label = val
        self.pyplot_canvas.axes.set_xlabel(val)
        self.update_plot()

    def hide_control_panel(self):
        """
        hides the control panel
        """
        self.control_panel.pack_forget()

    def show_control_panel(self):
        """
        shows / unhides the control panel
        """
        self.control_panel.pack()

    def hide_animation_related_controls(self):
        """
        hides all controls related to animation settings.  Used by default when non time-series data is displayed.
        """
        for widget in self.variables.animation_related_controls:
            widget.pack_forget()

    def show_animation_related_controls(self):
        """
        shows / unhides animation related controls.  Used by default when time-series data is displayed.
        """
        for widget in self.variables.animation_related_controls:
            widget.pack()

    def set_y_margin_percent(
            self,
            percent_0_to_100=5  # type: float
    ):
        """
        sets the y margin
        """
        self.variables.y_margin = percent_0_to_100 * 0.01

    def set_data(self, plot_data, x_axis=None):
        """

        sets the data to be displayed.  Data can be in following formats:
        1d: single plot to be displayed
        2d: several plots to be displayed as overplots.  The length of first dimension is the total length of each plot
        The length of the second dimension is the total number of plots to be displayed
        3d: time series of overplots.  Ex1: data of shape [100, 1, 50] would represent a single plot of length 100 with
        50 time series steps.  Ex2: data of shape[100, 10, 50] would represent 10 overplots, each of length 100, with
        50 times series steps.

        Parameters
        ----------
        plot_data : numpy.ndarray
        x_axis : numpy.ndarray

        Returns
        -------

        """
        x = x_axis
        n_frames = 1
        if len(plot_data.shape) == 1:
            self.hide_animation_related_controls()
            nx = len(plot_data)
            segments = numpy.zeros((1, nx, 2))
            segments[0, :, 1] = plot_data
        elif len(plot_data.shape) == 2:
            self.hide_animation_related_controls()
            nx = len(plot_data[:, 0])
            n_overplots = len(plot_data[0])
            segments = numpy.zeros((n_overplots, nx, 2))
            for i in range(n_overplots):
                segments[i, :, 1] = plot_data[:, i]
        elif len(plot_data.shape) == 3:
            self.show_animation_related_controls()
            nx = numpy.shape(plot_data)[0]
            n_overplots = numpy.shape(plot_data)[1]
            n_frames = numpy.shape(plot_data)[2]
            segments = numpy.zeros((n_overplots, nx, 2))
            for i in range(n_overplots):
                segments[i, :, 1] = plot_data[:, i, 0]
        if x is None:
            x = numpy.arange(nx)
        segments[:, :, 0] = x

        self.variables.xmin = x.min()
        self.variables.xmax = x.max()

        y_range = plot_data.max() - plot_data.min()

        self.variables.ymin = plot_data.min(
        ) - y_range * self.variables.y_margin
        self.variables.ymax = plot_data.max(
        ) + y_range * self.variables.y_margin

        self.variables.x_axis = x
        self.variables.plot_data = plot_data
        self.variables.segments = segments
        self.variables.n_frames = n_frames

        self.control_panel.scale.config(to=n_frames - 1)

        if len(plot_data.shape) == 3:
            self.update_plot_animation(0)

        else:
            self.pyplot_canvas.axes.clear()
            self.pyplot_canvas.axes.plot(self.variables.plot_data)
            self.pyplot_canvas.axes.set_ylim(self.variables.ymin,
                                             self.variables.ymax)
            self.pyplot_canvas.canvas.draw()

    def update_plot_animation(self, animation_index):
        """
        Updates the plot based on the time series / animation index

        Parameters
        ----------
        animation_index: int

        Returns
        -------
        str
        """
        self.control_panel.scale.set(animation_index)
        self.variables.animation_index = animation_index
        self.update_plot()

    def _callback_update_from_slider(self, event):
        self.variables.animation_index = int(
            numpy.round(self.control_panel.scale.get()))
        self.update_plot()

    # define custom callbacks here
    def _callback_set_y_rescale(self, event):
        selection = self.control_panel.rescale_y_axis_per_frame.get()
        if selection == SCALE_Y_AXIS_PER_FRAME_TRUE:
            self.variables.set_y_margins_per_frame = True
        else:
            self.variables.set_y_margins_per_frame = False
            y_range = self.variables.plot_data.max(
            ) - self.variables.plot_data.min()
            self.variables.ymin = self.variables.plot_data.min(
            ) - y_range * self.variables.y_margin
            self.variables.ymax = self.variables.plot_data.max(
            ) + y_range * self.variables.y_margin
        self.update_plot()

    def animate(self):
        """
        Animates the plot based on the plot data's time series. and other inputs supplied in the control panel,
        such as fps
        """
        start_frame = 0
        stop_frame = self.variables.n_frames
        fps = float(self.control_panel.fps_entry.get())

        time_between_frames = 1 / fps

        for i in range(start_frame, stop_frame):
            tic = time.time()
            self.update_plot_animation(i)
            toc = time.time()
            time_to_update_plot = toc - tic
            if time_between_frames > time_to_update_plot:
                time.sleep(time_between_frames - time_to_update_plot)
            else:
                pass

    def callback_update_plot_colors(self, event):
        """
        Updates the plot colors based on the color palette selected in the control panel
        """
        color_palette_text = self.control_panel.color_palette.get()
        self.pyplot_utils.set_palette_by_name(color_palette_text)
        self.update_plot()

    def callback_update_n_colors(self, event):
        """
        Updates the number of colors to cycle through based on the selection in the control panel
        """
        n_colors = int(self.control_panel.n_colors.get())
        self.pyplot_utils.set_n_colors(n_colors)
        self.update_plot()

    def update_n_colors(self):
        """
        sets number of colors to run through in the pyplot color cycler.
        """
        n_colors = int(self.control_panel.n_colors.get())
        self.pyplot_utils.set_n_colors(n_colors)
        self.update_plot()

    def update_plot(self):
        """
        clears canvas and updates plot based on the animation index
        """
        if len(self.variables.plot_data.shape) < 3:
            self.pyplot_canvas.canvas.draw()
        elif self.variables.plot_data is not None:
            n_overplots = numpy.shape(self.variables.segments)[0]
            animation_index = int(self.control_panel.scale.get())

            for i in range(n_overplots):
                self.variables.segments[
                    i, :, 1] = self.variables.plot_data[:, i, animation_index]

            self.pyplot_canvas.axes.clear()

            self.pyplot_canvas.axes.set_xlim(self.variables.xmin,
                                             self.variables.xmax)
            line_segments = LineCollection(
                self.variables.segments,
                self.pyplot_utils.linewidths,
                linestyle=self.pyplot_utils.linestyle)
            line_segments.set_color(self.pyplot_utils.rgb_array_full_palette)
            if self.variables.set_y_margins_per_frame:
                plot_data = self.variables.segments[:, :, 1]
                y_range = plot_data.max() - plot_data.min()
                self.variables.ymin = plot_data.min(
                ) - y_range * self.variables.y_margin
                self.variables.ymax = plot_data.max(
                ) + y_range * self.variables.y_margin
            self.pyplot_canvas.axes.set_ylim(self.variables.ymin,
                                             self.variables.ymax)

            self.pyplot_canvas.axes.add_collection(line_segments)
            self.pyplot_canvas.canvas.draw()
        else:
            pass
예제 #8
0
class CanvasResize(WidgetPanel):
    _widget_list = ("image_panel", "button_panel")

    image_panel = widget_descriptors.ImagePanelDescriptor(
        "image_panel")  # type: ImagePanel
    button_panel = widget_descriptors.PanelDescriptor("button_panel",
                                                      Buttons)  # type: Buttons

    def __init__(self, primary):
        self._shape_ids = {}

        self.primary = primary

        primary_frame = tkinter.Frame(primary)
        WidgetPanel.__init__(self, primary_frame)

        self.init_w_horizontal_layout()

        image_npix_x = 2000
        image_npix_y = 1500

        self.image_panel.set_max_canvas_size(image_npix_x, image_npix_y)

        image_data = numpy.linspace(0, 255, image_npix_x * image_npix_y)
        image_data = numpy.reshape(image_data, (image_npix_y, image_npix_x))
        image_reader = NumpyImageReader(image_data)
        self.image_panel.set_image_reader(image_reader)

        self.drag_xlim_1 = image_npix_x * 0.1
        self.drag_xlim_2 = image_npix_x * 0.9
        self.drag_ylim_1 = image_npix_y * 0.1
        self.drag_ylim_2 = image_npix_y * 0.9

        self.image_panel.current_tool = ToolConstants.PAN

        self.image_panel.set_min_canvas_size(100, 100)

        primary_frame.pack(fill=tkinter.BOTH, expand=tkinter.YES)

        self.button_panel.draw_rect.config(command=self.callback_draw_rect)
        self.button_panel.draw_line.config(command=self.callback_draw_line)
        self.button_panel.draw_arrow.config(command=self.callback_draw_arrow)
        self.button_panel.draw_point.config(command=self.callback_draw_point)
        self.button_panel.draw_ellipse.config(
            command=self.callback_draw_ellipse)
        self.button_panel.draw_polygon.config(
            command=self.callback_draw_polygon)

        # handle the image creation event
        self.image_panel.canvas.bind('<<ShapeCreate>>', self.handle_new_shape)

    @property
    def point_id(self):
        """
        None|int: The point id.
        """

        return self._shape_ids.get(ShapeTypeConstants.POINT, None)

    @property
    def line_id(self):
        """
        None|int: The line id.
        """

        return self._shape_ids.get(ShapeTypeConstants.LINE, None)

    @property
    def arrow_id(self):
        """
        None|int: The arrow id.
        """

        return self._shape_ids.get(ShapeTypeConstants.ARROW, None)

    @property
    def rect_id(self):
        """
        None|int: The rectangle id.
        """

        return self._shape_ids.get(ShapeTypeConstants.RECT, None)

    @property
    def ellipse_id(self):
        """
        None|int: The ellipse id.
        """

        return self._shape_ids.get(ShapeTypeConstants.ELLIPSE, None)

    @property
    def polygon_id(self):
        """
        None|int: polygon id.
        """

        return self._shape_ids.get(ShapeTypeConstants.POLYGON, None)

    def callback_draw_point(self):
        self.image_panel.canvas.set_current_tool_to_draw_point(self.point_id)

    def callback_draw_line(self):
        self.image_panel.canvas.set_current_tool_to_draw_line(self.line_id)

    def callback_draw_arrow(self):
        self.image_panel.canvas.set_current_tool_to_draw_arrow(self.arrow_id)

    def callback_draw_rect(self):
        self.image_panel.canvas.set_current_tool_to_draw_rect(self.rect_id)

    def callback_draw_ellipse(self):
        self.image_panel.canvas.set_current_tool_to_draw_ellipse(
            self.ellipse_id)

    def callback_draw_polygon(self):
        self.image_panel.canvas.set_current_tool_to_draw_polygon(
            self.polygon_id)

    def handle_new_shape(self, event):
        """
        Handle the creation of a new shape.

        Parameters
        ----------
        event
        """

        # we'll be tracking the most recently created
        self._shape_ids[event.y] = event.x

    def exit(self):
        self.quit()
예제 #9
0
class PyplotPanel(WidgetPanel):
    _widget_list = (
        "pyplot_canvas",
        "control_panel",
    )
    pyplot_canvas = widget_descriptors.PyplotCanvasDescriptor(
        "pyplot_canvas")  # type: PyplotCanvas
    control_panel = widget_descriptors.PanelDescriptor(
        "control_panel", PyplotControlPanel)  # type: PyplotControlPanel

    def __init__(self, primary):
        WidgetPanel.__init__(self, primary)

        self.variables = AppVariables()
        self.pyplot_utils = PlotStyleUtils()
        self.init_w_vertical_layout()

        canvas_size_pixels = self.pyplot_canvas.canvas.figure.get_size_inches(
        ) * self.pyplot_canvas.canvas.figure.dpi

        self.control_panel.scale.config(length=canvas_size_pixels[0] * 0.75)
        self.variables.animation_related_controls = [
            self.control_panel.scale,
            self.control_panel.rescale_y_axis_per_frame,
            self.control_panel.animate, self.control_panel.fps_entry,
            self.control_panel.fps_label
        ]

        self.control_panel.n_colors_label.set_text("n colors")
        self.control_panel.n_colors.set_text(self.pyplot_utils.n_color_bins)

        # set listeners
        self.control_panel.scale.on_left_mouse_motion(
            self.callback_update_from_slider)
        self.control_panel.rescale_y_axis_per_frame.on_selection(
            self.callback_set_y_rescale)
        self.control_panel.animate.config(command=self.animate)
        self.control_panel.color_palette.on_selection(
            self.callback_update_plot_colors)
        self.control_panel.n_colors.on_enter_or_return_key(
            self.callback_update_n_colors)
        self.control_panel.n_colors.config(command=self.update_n_colors)

        # self.hide_animation_related_controls()
        self.hide_control_panel()

    @property
    def title(self):
        return self.variables.title

    @title.setter
    def title(self, val):
        self.variables.title = val
        self.pyplot_canvas.axes.set_title(val)
        self.update_plot()

    @property
    def y_label(self):
        return self.variables.y_label

    @y_label.setter
    def y_label(self, val):
        self.variables.y_label = val
        self.pyplot_canvas.axes.set_ylabel(val)
        self.update_plot()

    @property
    def x_label(self):
        return self.variables.y_label

    @x_label.setter
    def x_label(self, val):
        self.variables.x_label = val
        self.pyplot_canvas.axes.set_xlabel(val)
        self.update_plot()

    def hide_control_panel(self):
        self.control_panel.pack_forget()

    def show_control_panel(self):
        self.control_panel.pack()

    def hide_animation_related_controls(self):
        for widget in self.variables.animation_related_controls:
            widget.pack_forget()

    def show_animation_related_controls(self):
        for widget in self.variables.animation_related_controls:
            widget.pack()

    def set_y_margin_percent(
            self,
            percent_0_to_100=5  # type: float
    ):
        self.variables.y_margin = percent_0_to_100 * 0.01

    def set_data(self, plot_data, x_axis=None):
        """


        Parameters
        ----------
        plot_data : numpy.ndarray
        x_axis : numpy.ndarray

        Returns
        -------

        """
        x = x_axis
        n_frames = 1
        if len(plot_data.shape) == 1:
            self.hide_animation_related_controls()
            nx = len(plot_data)
            segments = numpy.zeros((1, nx, 2))
            segments[0, :, 1] = plot_data
        elif len(plot_data.shape) == 2:
            self.hide_animation_related_controls()
            nx = len(plot_data[:, 0])
            n_overplots = len(plot_data[0])
            segments = numpy.zeros((n_overplots, nx, 2))
            for i in range(n_overplots):
                segments[i, :, 1] = plot_data[:, i]
        elif len(plot_data.shape) == 3:
            self.show_animation_related_controls()
            nx = numpy.shape(plot_data)[0]
            n_overplots = numpy.shape(plot_data)[1]
            n_frames = numpy.shape(plot_data)[2]
            segments = numpy.zeros((n_overplots, nx, 2))
            for i in range(n_overplots):
                segments[i, :, 1] = plot_data[:, i, 0]
        if x is None:
            x = numpy.arange(nx)
        segments[:, :, 0] = x

        self.variables.xmin = x.min()
        self.variables.xmax = x.max()

        y_range = plot_data.max() - plot_data.min()

        self.variables.ymin = plot_data.min(
        ) - y_range * self.variables.y_margin
        self.variables.ymax = plot_data.max(
        ) + y_range * self.variables.y_margin

        self.variables.x_axis = x
        self.variables.plot_data = plot_data
        self.variables.segments = segments
        self.variables.n_frames = n_frames

        self.control_panel.scale.config(to=n_frames - 1)

        if len(plot_data.shape) == 3:
            self.update_plot_animation(0)

        else:
            self.pyplot_canvas.axes.clear()
            self.pyplot_canvas.axes.plot(self.variables.plot_data)
            self.pyplot_canvas.axes.set_ylim(self.variables.ymin,
                                             self.variables.ymax)
            self.pyplot_canvas.canvas.draw()

    def update_plot_animation(self, animation_index):
        self.update_animation_index(animation_index)
        self.update_plot()

    def update_animation_index(self, animation_index):
        self.control_panel.scale.set(animation_index)
        self.variables.animation_index = animation_index

    def callback_update_from_slider(self, event):
        self.variables.animation_index = int(
            numpy.round(self.control_panel.scale.get()))
        self.update_plot()

    # define custom callbacks here
    def callback_set_y_rescale(self, event):
        selection = self.control_panel.rescale_y_axis_per_frame.get()
        if selection == SCALE_Y_AXIS_PER_FRAME_TRUE:
            self.variables.set_y_margins_per_frame = True
        else:
            self.variables.set_y_margins_per_frame = False
            y_range = self.variables.plot_data.max(
            ) - self.variables.plot_data.min()
            self.variables.ymin = self.variables.plot_data.min(
            ) - y_range * self.variables.y_margin
            self.variables.ymax = self.variables.plot_data.max(
            ) + y_range * self.variables.y_margin
        self.update_plot()

    def animate(self):
        start_frame = 0
        stop_frame = self.variables.n_frames
        fps = float(self.control_panel.fps_entry.get())

        time_between_frames = 1 / fps

        for i in range(start_frame, stop_frame):
            tic = time.time()
            self.update_animation_index(i)
            self.update_plot()
            toc = time.time()
            time_to_update_plot = toc - tic
            if time_between_frames > time_to_update_plot:
                time.sleep(time_between_frames - time_to_update_plot)
            else:
                pass

    def callback_update_plot_colors(self, event):
        color_palette_text = self.control_panel.color_palette.get()
        self.pyplot_utils.set_palette_by_name(color_palette_text)
        self.update_plot()

    def callback_update_n_colors(self, event):
        n_colors = int(self.control_panel.n_colors.get())
        self.pyplot_utils.set_n_colors(n_colors)
        self.update_plot()

    def update_n_colors(self):
        n_colors = int(self.control_panel.n_colors.get())
        self.pyplot_utils.set_n_colors(n_colors)
        self.update_plot()

    def update_plot(self):
        if len(self.variables.plot_data.shape) < 3:
            self.pyplot_canvas.canvas.draw()
        elif self.variables.plot_data is not None:
            n_overplots = numpy.shape(self.variables.segments)[0]
            animation_index = int(self.control_panel.scale.get())

            for i in range(n_overplots):
                self.variables.segments[
                    i, :, 1] = self.variables.plot_data[:, i, animation_index]

            self.pyplot_canvas.axes.clear()

            self.pyplot_canvas.axes.set_xlim(self.variables.xmin,
                                             self.variables.xmax)
            line_segments = LineCollection(
                self.variables.segments,
                self.pyplot_utils.linewidths,
                linestyle=self.pyplot_utils.linestyle)
            line_segments.set_color(self.pyplot_utils.rgb_array_full_palette)
            if self.variables.set_y_margins_per_frame:
                plot_data = self.variables.segments[:, :, 1]
                y_range = plot_data.max() - plot_data.min()
                self.variables.ymin = plot_data.min(
                ) - y_range * self.variables.y_margin
                self.variables.ymax = plot_data.max(
                ) + y_range * self.variables.y_margin
            self.pyplot_canvas.axes.set_ylim(self.variables.ymin,
                                             self.variables.ymax)

            self.pyplot_canvas.axes.add_collection(line_segments)
            self.pyplot_canvas.canvas.draw()
        else:
            pass
예제 #10
0
class CanvasResize(WidgetPanel):
    _widget_list = ("image_panel", "button_panel")

    image_panel = widget_descriptors.ImagePanelDescriptor("image_panel")         # type: ImagePanel
    button_panel = widget_descriptors.PanelDescriptor("button_panel", Buttons)  # type: Buttons

    def __init__(self, primary):
        self.rect_id = None
        self.line_id = None
        self.arrow_id = None
        self.point_id = None
        self.polygon_id = None
        self.n_shapes = 0

        self.primary = primary

        primary_frame = tkinter.Frame(primary)
        WidgetPanel.__init__(self, primary_frame)

        self.init_w_horizontal_layout()

        self.image_panel.image_frame.set_canvas_size(800, 600)
        self.image_panel.resizeable = True

        image_npix_x = 1200
        image_npix_y = 500

        image_data = numpy.random.random((image_npix_y, image_npix_x))
        image_data = image_data * 255
        image_reader = NumpyImageReader(image_data)
        self.image_panel.set_image_reader(image_reader)

        self.drag_xlim_1 = image_npix_x * 0.25
        self.drag_xlim_2 = image_npix_x * 0.75
        self.drag_ylim_1 = image_npix_y * 0.1
        self.drag_ylim_2 = image_npix_y * 0.9

        self.image_panel.current_tool = ToolConstants.PAN_TOOL

        self.image_panel.axes_canvas.image_x_min_val = 500
        self.image_panel.axes_canvas.image_x_max_val = 1200

        self.image_panel.axes_canvas.image_y_min_val = 5000
        self.image_panel.axes_canvas.image_y_max_val = 2000

        primary_frame.pack(fill=tkinter.BOTH, expand=tkinter.YES)
        self.image_panel.canvas.set_canvas_size(800, 800)

        self.button_panel.draw_rect.on_left_mouse_click(self.callback_draw_rect)
        self.button_panel.draw_line.on_left_mouse_click(self.callback_draw_line)
        self.button_panel.draw_arrow.on_left_mouse_click(self.callback_draw_arrow)
        self.button_panel.draw_point.on_left_mouse_click(self.callback_draw_point)
        self.button_panel.draw_polygon.on_left_mouse_click(self.callback_draw_polygon)
        self.button_panel.edit_shape.on_left_mouse_click(self.callback_edit_shape)
        self.image_panel.canvas.on_left_mouse_release(self.callback_on_left_mouse_release)

    def callback_draw_rect(self, event):
        self.image_panel.canvas.set_current_tool_to_draw_rect(self.rect_id)

    def callback_draw_line(self, event):
        self.image_panel.canvas.set_current_tool_to_draw_line_by_dragging(self.line_id)

    def callback_draw_arrow(self, event):
        self.image_panel.canvas.set_current_tool_to_draw_arrow_by_dragging(self.arrow_id)

    def callback_draw_point(self, event):
        self.image_panel.canvas.set_current_tool_to_draw_point(self.point_id)

    def callback_draw_polygon(self, event):
        self.image_panel.canvas.set_current_tool_to_draw_polygon_by_clicking(self.polygon_id)

    def callback_edit_shape(self, event):
        self.image_panel.canvas.set_current_tool_to_edit_shape()

    def callback_on_left_mouse_release(self, event):
        self.image_panel.canvas.callback_handle_left_mouse_release(event)
        n_shapes = len(self.image_panel.canvas.get_non_tool_shape_ids())
        if n_shapes > self.n_shapes:
            if self.image_panel.current_tool == ToolConstants.DRAW_RECT_BY_DRAGGING:
                self.rect_id = self.image_panel.canvas.variables.current_shape_id
            elif self.image_panel.current_tool == ToolConstants.DRAW_LINE_BY_DRAGGING:
                self.line_id = self.image_panel.canvas.variables.current_shape_id
            elif self.image_panel.current_tool == ToolConstants.DRAW_ARROW_BY_DRAGGING:
                self.arrow_id = self.image_panel.canvas.variables.current_shape_id
            elif self.image_panel.current_tool == ToolConstants.DRAW_POINT_BY_CLICKING:
                self.point_id = self.image_panel.canvas.variables.current_shape_id
            elif self.image_panel.current_tool == ToolConstants.DRAW_POLYGON_BY_CLICKING:
                self.polygon_id = self.image_panel.canvas.variables.current_shape_id
            self.image_panel.canvas.get_vector_object(
                self.image_panel.canvas.variables.current_shape_id).image_drag_limits = (self.drag_ylim_1,
                                                                                         self.drag_xlim_1,
                                                                                         self.drag_ylim_2,
                                                                                         self.drag_xlim_2)

    def exit(self):
        self.quit()
예제 #11
0
class PlotDemo(WidgetPanel):
    """
    Basic plot demo gui.
    """
    _widget_list = ("button_panel", "pyplot_panel")
    button_panel = widget_descriptors.PanelDescriptor(
        "button_panel", ButtonPanel,
        default_text="plot buttons")  # type: ButtonPanel
    pyplot_panel = widget_descriptors.PyplotPanelDescriptor(
        "pyplot_panel")  # type: PyplotPanel

    def __init__(self, primary):
        """

        Parameters
        ----------
        primary
            The primary widget.
        """

        # set the primary frame
        primary_frame = tkinter.Frame(primary)
        WidgetPanel.__init__(self, primary_frame)
        self.init_w_vertical_layout()

        # need to pack both primary frame and self, since this is the main app window.
        primary_frame.pack()

        # set up event listeners
        self.button_panel.single_plot.config(command=self.single_plot)
        self.button_panel.multi_plot.config(command=self.multi_plot)
        self.button_panel.animated_plot.config(command=self.animated_plot)

        self.pyplot_panel.set_y_margin_percent(5)
        self.pyplot_panel.variables.set_y_margins_per_frame = True

        self.single_plot()

        self.pyplot_panel.show_control_panel()

    def single_plot(self):
        """
        A single plot callback.

        Returns
        -------
        None
        """

        plot_data = self.mockup_animation_data_1()
        self.pyplot_panel.set_data(plot_data)
        self.pyplot_panel.title = "single plot"

    def multi_plot(self):
        """
        A multiplot callback.

        Returns
        -------
        None
        """

        plot_data = self.mockup_animation_data_2()
        data_shape = numpy.shape(plot_data)
        x_axis_points = data_shape[0]
        n_overplots = data_shape[1]
        print("plot data has dimensions of: " + str(data_shape))
        print("with " + str(x_axis_points) + " data points along the x axis")
        print("and " + str(n_overplots) + " overplots")
        self.pyplot_panel.set_data(plot_data)

    def animated_plot(self):
        """
        Animated callback plot.

        Returns
        -------
        None
        """

        plot_data = self.mockup_animation_data_3()
        data_shape = numpy.shape(plot_data)
        x_axis_points = data_shape[0]
        n_overplots = data_shape[1]
        n_animation_frames = data_shape[2]
        print("plot data has dimensions of: " + str(data_shape))
        print("with " + str(x_axis_points) + " data points along the x axis")
        print("and " + str(n_overplots) + " overplots")
        print("and " + str(n_animation_frames) + " animation frames")
        self.pyplot_panel.set_data(plot_data)

    @staticmethod
    def mockup_animation_data_3():
        """
        Mock annimation.

        Returns
        -------
        numpy.ndarray
        """

        n_overplots = 10
        nx = 200
        n_times = 100

        x_axis = numpy.linspace(0, numpy.pi, nx)
        y_data_1 = numpy.sin(x_axis)
        y_data_2 = numpy.zeros((len(x_axis), n_overplots))
        y_data_3 = numpy.zeros((len(x_axis), n_overplots, n_times))

        scaling_factors = numpy.linspace(0.7, 1, n_overplots)

        for i in range(n_overplots):
            y_data_2[:, i] = y_data_1 * scaling_factors[i]

        x_over_time = numpy.zeros((nx, n_times))
        x_over_time_start = numpy.linspace(0, numpy.pi, n_times)
        for i in range(n_times):
            x_start = x_over_time_start[i]
            x = numpy.linspace(x_start, numpy.pi + x_start, nx)
            x_over_time[:, i] = x
            y = numpy.sin(x)
            for j in range(n_overplots):
                y_data_3[:, j, i] = y * scaling_factors[j]
        return y_data_3

    @staticmethod
    def mockup_animation_data_2():
        """
        Mock animation.

        Returns
        -------
        numpy.ndarray
        """

        n_overplots = 10
        nx = 200

        x_axis = numpy.linspace(0, 2 * numpy.pi, nx)
        y_data_1 = x_axis
        y_data_2 = numpy.zeros((len(x_axis), n_overplots))

        scaling_factors = numpy.linspace(0.7, 1, n_overplots)

        for i in range(n_overplots):
            y_data_2[:, i] = y_data_1 * scaling_factors[i]

        return y_data_2

    @staticmethod
    def mockup_animation_data_1():
        """
        Mock animation.

        Returns
        -------
        numpy.ndarray
        """

        x = numpy.linspace(-5, 5, 200)
        y = numpy.sinc(x)
        return y
예제 #12
0
class MetaIconDemo(WidgetPanel):
    # The metaicon will be a popup, so leave the widget list unpopulated
    _widget_list = ()

    metaicon = widget_descriptors.PanelDescriptor("metaicon", MetaIcon)  # type: MetaIcon

    def __init__(self, primary):
        self.primary = primary

        primary_frame = basic_widgets.Frame(primary)
        WidgetPanel.__init__(self, primary_frame)

        self.init_w_horizontal_layout()

        lat = 35.05452800184999
        lon = -106.59258099877832
        collect_start = numpy.datetime64('2016-09-21T16:41:07.000000')
        collect_duration = 14.47132
        collector_name = 'Sandia FARAD X-band'
        core_name = '0508C01_PS0009_CC000000_N03_M1_PC054036_HH_wfcc_sv'
        azimuth = 241.15240495122976
        graze = 28.403774480669846
        layover = 263.96070589564016
        shadow = -90.0
        multipath = 66.5880303387554
        side_of_track = 'R'
        col_impulse_response_width = 0.1903215223097113
        row_impulse_response_width = 0.1606955380577428
        grid_column_sample_spacing = 0.04462
        grid_row_sample_spacing = 0.03767
        image_plane = 'SLANT'
        tx_rf_bandwidth = 2843.7592056795997
        rniirs = None
        polarization = 'H:H'

        data_container = MetaIconDataContainer(lat=lat,
                                               lon=lon,
                                               collect_start=collect_start,
                                               collect_duration=collect_duration,
                                               collector_name=collector_name,
                                               core_name=core_name,
                                               azimuth=azimuth,
                                               graze=graze,
                                               layover=layover,
                                               shadow=shadow,
                                               multipath=multipath,
                                               side_of_track=side_of_track,
                                               col_impulse_response_width=col_impulse_response_width,
                                               row_impulse_response_width=row_impulse_response_width,
                                               grid_column_sample_spacing=grid_column_sample_spacing,
                                               grid_row_sample_spacing=grid_row_sample_spacing,
                                               image_plane=image_plane,
                                               tx_rf_bandwidth=tx_rf_bandwidth,
                                               rniirs=rniirs,
                                               polarization=polarization,
                                               )
        self.metaicon_popup_panel = tkinter.Toplevel(self.primary)
        self.metaicon = MetaIcon(self.metaicon_popup_panel)
        self.metaicon.create_from_metaicon_data_container(data_container)
        # hide the main window so just the metaicon popup is showing
        self.primary.withdraw()

        # quit the program when the user closes the metaicon popup
        self.metaicon_popup_panel.protocol("WM_DELETE_WINDOW", self.primary.quit)
예제 #13
0
class ImagePanel(WidgetPanel):
    _widget_list = (
        "toolbar",
        "image_frame",
    )
    image_frame = widget_descriptors.PanelDescriptor(
        "image_frame", ImageFrame)  # type: ImageFrame
    toolbar = widget_descriptors.PanelDescriptor("toolbar",
                                                 Toolbar)  # type: Toolbar
    canvas = widget_descriptors.ImageCanvasDescriptor(
        "canvas")  # type: ImageCanvas
    axes_canvas = widget_descriptors.AxesImageCanvasDescriptor(
        "axes_canvas")  # type: AxesImageCanvas

    def __init__(self, parent):
        WidgetPanel.__init__(self, parent)
        self.variables = AppVariables()
        self.init_w_vertical_layout()
        self.pack(fill=tkinter.BOTH, expand=tkinter.YES)
        self.toolbar.left_margin.config(width=5)
        self.toolbar.right_margin.config(width=5)
        self.toolbar.top_margin.config(width=5)
        self.toolbar.bottom_margin.config(width=5)

        self.toolbar.left_margin_label.master.forget()
        self.toolbar.title_label.master.forget()

        # set up callbacks
        self.toolbar.save_canvas.on_left_mouse_click(self.callback_save_canvas)
        self.toolbar.save_image.on_left_mouse_click(self.callback_save_image)

        self.toolbar.left_margin.on_enter_or_return_key(
            self.callback_update_axes)
        self.toolbar.right_margin.on_enter_or_return_key(
            self.callback_update_axes)
        self.toolbar.top_margin.on_enter_or_return_key(
            self.callback_update_axes)
        self.toolbar.bottom_margin.on_enter_or_return_key(
            self.callback_update_axes)

        self.toolbar.title.on_enter_or_return_key(self.callback_update_axes)
        self.toolbar.x.on_enter_or_return_key(self.callback_update_axes)
        self.toolbar.y.on_enter_or_return_key(self.callback_update_axes)

        self.toolbar.zoom_in.on_left_mouse_click(self.callback_set_to_zoom_in)
        self.toolbar.zoom_out.on_left_mouse_click(
            self.callback_set_to_zoom_out)
        self.toolbar.pan.on_left_mouse_click(self.callback_set_to_pan)

        self.toolbar.margins_checkbox.config(
            command=self.callback_hide_show_margins)
        self.toolbar.axes_labels_checkbox.config(
            command=self.callback_hide_show_axes_controls)

        self.toolbar.pack(expand=tkinter.YES, fill=tkinter.X)

        self.canvas = self.image_frame.outer_canvas.canvas
        self.axes_canvas = self.image_frame.outer_canvas

    def callback_set_to_zoom_in(self, event):
        self.current_tool = ToolConstants.ZOOM_IN_TOOL

    def callback_set_to_zoom_out(self, event):
        self.current_tool = ToolConstants.ZOOM_OUT_TOOL

    def callback_set_to_pan(self, event):
        self.current_tool = ToolConstants.PAN_TOOL

    def callback_save_canvas(self, event):
        save_fname = asksaveasfilename()
        if "." not in os.path.basename(save_fname):
            save_fname = save_fname + ".png"
        self.axes_canvas.save_full_canvas_as_png(save_fname)

    def callback_save_image(self, event):
        save_fname = asksaveasfilename()
        if "." not in os.path.basename(save_fname):
            save_fname = save_fname + ".png"
        self.canvas.save_full_canvas_as_png(save_fname)

    def callback_hide_show_margins(self):
        show_margins = self.toolbar.margins_checkbox.is_selected()
        if show_margins is False:
            self.toolbar.left_margin_label.master.forget()
        else:
            self.toolbar.left_margin_label.master.pack()

    def callback_hide_show_axes_controls(self):
        show_axes_controls = self.toolbar.axes_labels_checkbox.is_selected()
        if show_axes_controls is False:
            self.toolbar.title_label.master.forget()
        else:
            self.toolbar.title_label.master.pack()

    def callback_update_axes(self, event):
        self.image_frame.outer_canvas.title = self.toolbar.title.get()
        self.image_frame.outer_canvas.x_label = self.toolbar.x.get()
        self.image_frame.outer_canvas.y_label = self.toolbar.y.get()

        if self.toolbar.top_margin.get() == "0":
            self.toolbar.top_margin.set_text(
                str(self.image_frame.outer_canvas.top_margin_pixels))
        if self.toolbar.bottom_margin.get() == "0":
            self.toolbar.bottom_margin.set_text(
                str(self.image_frame.outer_canvas.bottom_margin_pixels))
        if self.toolbar.left_margin.get() == "0":
            self.toolbar.left_margin.set_text(
                str(self.image_frame.outer_canvas.left_margin_pixels))
        if self.toolbar.right_margin.get() == "0":
            self.toolbar.right_margin.set_text(
                str(self.image_frame.outer_canvas.right_margin_pixels))

        self.image_frame.outer_canvas.left_margin_pixels = int(
            self.toolbar.left_margin.get())
        self.image_frame.outer_canvas.right_margin_pixels = int(
            self.toolbar.right_margin.get())
        self.image_frame.outer_canvas.top_margin_pixels = int(
            self.toolbar.top_margin.get())
        self.image_frame.outer_canvas.bottom_margin_pixels = int(
            self.toolbar.bottom_margin.get())

        self.update_everything()

    def set_image_reader(self, image_reader):
        self.image_frame.outer_canvas.set_image_reader(image_reader)

    @property
    def resizeable(self):
        return self.variables.resizeable

    @resizeable.setter
    def resizeable(self, value):
        self.variables.resizeable = value
        if value is False:
            self.pack(expand=tkinter.NO)
        self.image_frame.resizeable = False

        if self.resizeable:
            self.on_resize(self.callback_resize)

    @property
    def current_tool(self):
        return self.image_frame.outer_canvas.canvas.variables.current_tool

    @current_tool.setter
    def current_tool(self, value):
        if value is None:
            self.canvas.set_current_tool_to_none()
        elif value == ToolConstants.EDIT_SHAPE_TOOL:
            self.canvas.set_current_tool_to_edit_shape()
        elif value == ToolConstants.PAN_TOOL:
            self.canvas.set_current_tool_to_pan()
        elif value == ToolConstants.SELECT_TOOL:
            self.canvas.set_current_tool_to_selection_tool()
        elif value == ToolConstants.ZOOM_IN_TOOL:
            self.canvas.set_current_tool_to_zoom_in()
        elif value == ToolConstants.ZOOM_OUT_TOOL:
            self.canvas.set_current_tool_to_zoom_out()
        elif value == ToolConstants.DRAW_ARROW_BY_DRAGGING:
            self.canvas.set_current_tool_to_draw_arrow_by_dragging()
        elif value == ToolConstants.DRAW_RECT_BY_DRAGGING:
            self.canvas.set_current_tool_to_draw_rect()

    def callback_resize(self, event):
        self.update_everything()

    def update_everything(self):
        self.image_frame.outer_canvas.delete("all")

        width = self.winfo_width()
        height = self.winfo_height()

        parent_geometry = self.image_frame.master.winfo_geometry()
        outer_canvas_geometry = self.image_frame.winfo_geometry()

        parent_geom_width = int(parent_geometry.split("x")[0])
        parent_geom_height = int(parent_geometry.split("x")[1].split("+")[0])
        parent_geom_pad_x = int(parent_geometry.split("+")[1])
        parent_geom_pad_y = int(parent_geometry.split("+")[2])

        outer_canvas_width = int(outer_canvas_geometry.split("x")[0])
        outer_canvas_height = int(
            outer_canvas_geometry.split("x")[1].split("+")[0])
        outer_canvas_pad_x = int(outer_canvas_geometry.split("+")[1])
        outer_canvas_pad_y = int(outer_canvas_geometry.split("+")[2])

        constant_offset_x = WidgetPanel.padx
        constant_offset_y = WidgetPanel.pady

        width_offset = parent_geom_width - outer_canvas_width + outer_canvas_pad_x + parent_geom_pad_x - constant_offset_x
        height_offset = parent_geom_height - outer_canvas_height + outer_canvas_pad_y + parent_geom_pad_y - constant_offset_y

        adjusted_canvas_width = width - width_offset
        adjusted_canvas_height = height - height_offset

        if parent_geom_width > 1 and outer_canvas_width > 1:
            self.image_frame.set_canvas_size(adjusted_canvas_width,
                                             adjusted_canvas_height)

            self.axes_canvas.set_canvas_size(adjusted_canvas_width,
                                             adjusted_canvas_height)
            self.canvas.set_canvas_size(
                self.axes_canvas.variables.canvas_width -
                self.axes_canvas.left_margin_pixels -
                self.axes_canvas.right_margin_pixels,
                self.axes_canvas.variables.canvas_height -
                self.axes_canvas.top_margin_pixels -
                self.axes_canvas.bottom_margin_pixels)

            self.canvas.update_current_image()

            display_image_dims = numpy.shape(
                self.canvas.variables.canvas_image_object.display_image)

            self.axes_canvas.set_canvas_size(
                display_image_dims[1] + self.axes_canvas.right_margin_pixels +
                self.axes_canvas.left_margin_pixels,
                display_image_dims[0] + self.axes_canvas.top_margin_pixels +
                self.axes_canvas.bottom_margin_pixels + 5)
            self.canvas.set_canvas_size(
                self.axes_canvas.variables.canvas_width -
                self.image_frame.outer_canvas.left_margin_pixels -
                self.image_frame.outer_canvas.right_margin_pixels,
                self.image_frame.outer_canvas.variables.canvas_height -
                self.image_frame.outer_canvas.top_margin_pixels -
                self.image_frame.outer_canvas.bottom_margin_pixels)
            self.canvas.update_current_image()
        self.axes_canvas.delete("all")

        self.image_frame.create_window(0,
                                       0,
                                       anchor=tkinter.NW,
                                       window=self.image_frame.outer_canvas)
        self.image_frame.outer_canvas.create_window(
            self.image_frame.outer_canvas.left_margin_pixels,
            self.image_frame.outer_canvas.top_margin_pixels,
            anchor=tkinter.NW,
            window=self.image_frame.outer_canvas.canvas)
        self.canvas.redraw_all_shapes()

        self.image_frame.outer_canvas._update_y_axis()
        self.image_frame.outer_canvas._update_y_label()
        self.image_frame.outer_canvas._update_title()
        self.image_frame.outer_canvas._update_x_axis()
        self.image_frame.outer_canvas._update_x_label()
예제 #14
0
class CanvasDemo(WidgetPanel):
    _widget_list = ("button_panel", "canvas_demo_image_panel", "pyplot_panel")
    button_panel = widget_descriptors.PanelDescriptor(
        "button_panel", CanvasDemoButtonPanel)  # type: CanvasDemoButtonPanel
    pyplot_panel = widget_descriptors.PyplotImagePanelDescriptor(
        "pyplot_panel")  # type: PyplotImagePanel
    canvas_demo_image_panel = widget_descriptors.ImagePanelDescriptor(
        "canvas_demo_image_panel")  # type: ImagePanel

    def __init__(self, primary):
        primary_frame = basic_widgets.Frame(primary)
        WidgetPanel.__init__(self, primary_frame)
        self.variables = AppVariables()

        self.init_w_horizontal_layout()
        primary_frame.pack(fill=tkinter.BOTH, expand=tkinter.YES)
        self.button_panel.pack(fill=tkinter.X, expand=tkinter.NO)
        self.pyplot_panel.pack(expand=tkinter.YES)
        self.canvas_demo_image_panel.pack(expand=tkinter.YES)

        # bind events to callbacks here
        self.button_panel.fname_select.config(
            command=self.callback_initialize_canvas_image)
        self.button_panel.rect_select.config(
            command=self.callback_set_to_select)

        self.button_panel.draw_line.config(command=self.callback_draw_line)
        self.button_panel.draw_arrow.config(command=self.callback_draw_arrow)
        self.button_panel.draw_rect.config(command=self.callback_draw_rect)
        self.button_panel.draw_polygon.config(
            command=self.callback_draw_polygon)
        self.button_panel.draw_point.config(command=self.callback_draw_point)
        self.button_panel.edit.config(command=self.callback_edit)
        self.button_panel.color_selector.config(
            command=self.callback_activate_color_selector)
        self.button_panel.remap_dropdown.on_selection(self.callback_remap)

        self.canvas_demo_image_panel.canvas.on_left_mouse_click(
            self.callback_handle_canvas_left_mouse_click)
        self.canvas_demo_image_panel.canvas.on_left_mouse_release(
            self.callback_handle_canvas_left_mouse_release)

    def callback_save_kml(self):
        kml_save_fname = asksaveasfilename(
            initialdir=os.path.expanduser("~/Downloads"))

        kml_util = KmlUtil()

        for shape_id in self.canvas_demo_image_panel.canvas.variables.shape_ids:
            image_coords = self.canvas_demo_image_panel.canvas.get_shape_image_coords(
                shape_id)
            shape_type = self.canvas_demo_image_panel.canvas.get_shape_type(
                shape_id)
            if image_coords:
                sicd_meta = self.canvas_demo_image_panel.canvas.variables.canvas_image_object.reader_object.sicdmeta
                image_points = numpy.zeros((int(len(image_coords) / 2), 2))
                image_points[:, 0] = image_coords[0::2]
                image_points[:, 1] = image_coords[1::2]

                ground_points_ecf = point_projection.image_to_ground(
                    image_points, sicd_meta)
                ground_points_latlon = geocoords.ecf_to_geodetic(
                    ground_points_ecf)

                world_y_coordinates = ground_points_latlon[:, 0]
                world_x_coordinates = ground_points_latlon[:, 1]

                xy_point_list = [
                    (x, y)
                    for x, y in zip(world_x_coordinates, world_y_coordinates)
                ]

                if shape_id == self.canvas_demo_image_panel.canvas.variables.zoom_rect.uid:
                    pass
                elif shape_type == self.canvas_demo_image_panel.canvas.variables.select_rect.uid:
                    pass
                elif shape_type == ShapeTypeConstants.POINT:
                    kml_util.add_point(str(shape_id), xy_point_list[0])
                elif shape_type == ShapeTypeConstants.LINE:
                    kml_util.add_linestring(str(shape_id), xy_point_list)
                elif shape_type == ShapeTypeConstants.POLYGON:
                    kml_util.add_polygon(str(shape_id), xy_point_list)
                elif shape_type == ShapeTypeConstants.RECT:
                    kml_util.add_polygon(str(shape_id), xy_point_list)
        kml_util.write_to_file(kml_save_fname)

    def callback_handle_canvas_left_mouse_click(self, event):
        self.canvas_demo_image_panel.canvas.callback_handle_left_mouse_click(
            event)
        current_shape = self.canvas_demo_image_panel.canvas.current_shape_id
        if current_shape:
            self.variables.shapes_in_selector.append(current_shape)
            self.variables.shapes_in_selector = sorted(
                list(set(self.variables.shapes_in_selector)))

    def callback_handle_canvas_left_mouse_release(self, event):
        self.canvas_demo_image_panel.canvas.callback_handle_left_mouse_release(
            event)
        if self.canvas_demo_image_panel.canvas.variables.select_rect.uid == self.canvas_demo_image_panel.canvas.current_shape_id:
            self.update_selection()

    def callback_edit(self):
        self.canvas_demo_image_panel.canvas.set_current_tool_to_edit_shape(
            select_closest_first=True)

    def callback_activate_color_selector(self):
        self.canvas_demo_image_panel.canvas.activate_color_selector()

    def callback_draw_line(self):
        self.canvas_demo_image_panel.canvas.set_current_tool_to_draw_line()

    def callback_draw_arrow(self):
        self.canvas_demo_image_panel.canvas.set_current_tool_to_draw_arrow()

    def callback_draw_rect(self):
        self.canvas_demo_image_panel.canvas.set_current_tool_to_draw_rect()

    def callback_draw_polygon(self):
        self.canvas_demo_image_panel.canvas.set_current_tool_to_draw_polygon()

    def callback_draw_point(self):
        self.canvas_demo_image_panel.canvas.set_current_tool_to_draw_point()

    def callback_set_to_select(self):
        self.canvas_demo_image_panel.canvas.set_current_tool_to_select()

    # define custom callbacks here
    def callback_remap(self):
        self.update_selection()

    def update_selection(self):
        remap_dict = {entry[0]: entry[1] for entry in remap.get_remap_list()}
        selection = self.button_panel.remap_dropdown.get()
        self.variables.image_reader.set_remap_type(remap_dict[selection])
        image_data = self.canvas_demo_image_panel.canvas.get_image_data_in_canvas_rect_by_id(
            self.canvas_demo_image_panel.canvas.variables.select_rect.uid)
        self.pyplot_panel.update_image(image_data)
        self.canvas_demo_image_panel.canvas.update_current_image()

    def callback_initialize_canvas_image(self):
        image_file_extensions = ['*.nitf', '*.NITF', '*.ntf', '*.NTF']
        ftypes = [
            ('NITF files', image_file_extensions),
            ('All files', '*'),
        ]
        new_fname = askopenfilename(initialdir=self.variables.browse_directory,
                                    filetypes=ftypes)
        if new_fname:
            self.variables.browse_directory = os.path.split(new_fname)[0]
            self.variables.image_reader = ComplexImageReader(new_fname)
            self.canvas_demo_image_panel.set_image_reader(
                self.variables.image_reader)