class ChooseDifficultyView:
    def __init__(self, update_slider_range: Callable[[Event], None],
                 draw_field: Callable[[Event], None]) -> None:
        # programs can only have one window, but can
        # create multiple "Toplevel"s (effectively new windows)
        self.window = Toplevel()
        self.window.title('HexSweeper - Choose Difficulty')
        self.window.geometry('400x473')
        self.window.bind('<Configure>', draw_field)

        # these statements allow the hexgrid (in col 1, row 3)
        # to stretch as the window is resized

        # stretch the second column horizontally:
        Grid.columnconfigure(self.window, 1, weight=1)
        # stretch the fourth row vertically:
        Grid.rowconfigure(self.window, 3, weight=1)

        Label(self.window, text='Board Size:').grid(row=0, column=0, sticky=W)

        # TkInter "Scale" objects are sliders
        # Default slider resolution/accuracy is 1
        self.game_size_slider = Scale(
            self.window,
            # from_ because from is a Python keyword
            from_=2,
            to=15,
            orient=HORIZONTAL,
            command=update_slider_range)
        self.game_size_slider.grid(row=0, column=1, sticky=E + W)

        Label(self.window, text='Number of mines:') \
            .grid(row=1, column=0, sticky=W)
        self.mine_count_slider = Scale(self.window,
                                       from_=1,
                                       to=315,
                                       orient=HORIZONTAL,
                                       command=draw_field)
        self.mine_count_slider.grid(row=1, column=1, sticky=E + W)

        self.canvas = Canvas(self.window, bg='white')
        self.canvas.grid(
            row=3,
            column=0,
            # span columns 0 and 1
            columnspan=2,
            # resize with the window
            sticky=E + N + W + S)

    def close_window(self):
        self.window.destroy()

    def set_mine_count_slider_upper_bound(self, upper_bound):
        self.mine_count_slider.config(to=upper_bound)
Exemple #2
0
class Slider(ScheduleMixin, DestroyMixin, EnableMixin, FocusMixin,
             DisplayMixin, ReprMixin):
    def __init__(self,
                 master,
                 start=0,
                 end=100,
                 horizontal=True,
                 command=None,
                 grid=None,
                 align=None):

        # If you specify a command to the slider, it must take one argument as it will be given
        # the slider's current value

        # Description of this object (for friendly error messages)
        self.description = "[Slider] object from " + str(start) + " to " + str(
            end)

        # Set the direction
        orient = HORIZONTAL if horizontal else VERTICAL

        # Create a tk Scale object within this object
        self.tk = Scale(master.tk,
                        from_=start,
                        to=end,
                        orient=orient,
                        command=command)

        # Pack this object
        try:
            utils.auto_pack(self, master, grid, align)
        except AttributeError:
            utils.error_format(
                self.description + "\n" +
                "Could not add to interface - check first argument is [App] or [Box]"
            )

    # PROPERTIES
    # ----------------
    # Get/set the value
    @property
    def value(self):
        return (self.tk.get())

    @value.setter
    def value(self, value):
        self.tk.set(value)

    # METHODS
    # ----------------
    # Calls the given function when the slider value is changed
    def add_command(self, command):
        self.tk.config(command=command)
Exemple #3
0
def demo():
    root = tkinter.Tk()
    root.title("Motion Planning")
    universal_height = 1000

    nb = ttk.Notebook(root)
    page1 = ttk.Frame(nb, width= 1080,height = universal_height)
    page2 = ttk.Frame(nb,width = 1080,height = universal_height)

    nb.add(page1, text='Workspace')
    nb.add(page2, text='Configspace')
    nb.grid(column=0)
 
    workspace = Workspace("./resources/robot_BW_small.bmp", "./resources/Room_BW_small.bmp", page1)
    configspace = Configspace(page2)
    controller = Controller(workspace,configspace)


    workspace.drawAll(workspace.currentPos[0],workspace.currentPos[1])
    def callback(event):
        # print ("clicked at", event.x, event.y)
        controller.drawMouseOffSet(event.x, event.y)
        if controller.isInCollision(): setBackgroundColor(page1,"red")
        else: setBackgroundColor(page1,"green")

    workspace.label.bind("<Button-1>", callback)

    def moveRobotOnPath(val):
        if controller.isAllInitialized():
            controller.setSolutionPathOnCurrentPos(int(val))
            controller.drawCurrentPos()
            if controller.isInCollision(): setBackgroundColor(page1,"red")
            else: setBackgroundColor(page1,"green")

    slider = Scale(page1, from_=0, to=200, orient=HORIZONTAL, command=moveRobotOnPath)
    slider.config(length=600)
    
    def set_goal():
        controller.setCurrentPosAsGoal()
        slider['from_'] = 0
        slider['to_'] = len(configspace.solutionPath)-1

    setGoalButton = ttk.Button(page1, text = 'Set Goal',command = set_goal)
    setGoalButton.pack(side=tkinter.RIGHT)

    def set_init():
        controller.setCurrentPosAsInit()
    setInitButton = ttk.Button(page1, text = 'Set Init',command = set_init)
    setInitButton.pack(side=tkinter.RIGHT)

    slider.pack()

    root.mainloop()
Exemple #4
0
def Slider(root, style="", horizontal=False, **options):

    props = {'troughcolor': load_color(style)['bgColor']}

    scale = Scale(root)

    props.update(**options)

    scale.config(props)

    if horizontal:
        scale.config(orient=HORIZONTAL)

    scale.pack()
Exemple #5
0
class Slider:
    def __init__(self, parent, label, valueCarrier, groupLabel=""):
        self.instance = Scale(parent,
                              from_=2,
                              to=0,
                              resolution=0.02,
                              length=100,
                              showvalue=0,
                              command=valueCarrier.saveVal)
        self.valueCarrier = valueCarrier
        self.groupLabel = groupLabel
        self._label = None
        if isinstance(label, str):
            self._label = Label(parent, text=label)
        elif isinstance(label, PhotoImage):
            self._label = Label(parent, image=label)
        else:
            raise TypeError(
                'Wrong Type. Label must be of type String or PhotoImage!')

    @property
    def label(self):
        return self._label.cget('text')

    # set pos for slider with label/icon
    def pos(self, row, column):
        self.instance.grid(row=row, column=column, padx=(21, 21), pady=5)
        self._label.grid(row=row + 1, column=column)

    # activate or deactivate slider
    def changeState(self, state):
        if state == DISABLED:
            self.instance.config(state=DISABLED, fg="#808080")
            self._label.config(fg="#808080")
        elif state == NORMAL:
            self.instance.config(state=NORMAL, fg="#000000")
            self._label.config(fg="#000000")
        else:
            raise ValueError(
                'Wrong State. State can be either DISABLED or NORMAL!')
class Visualiser(object):
    '''
    Generic Offline Visualiser. Subclasses need to be used that specify
    how to handle a data source.
    '''
    
    ### Public functions ###

    def __init__(self,
                 title="Visualisation",
                 width=400,
                 height=400,
                 recording=False,
                 recordPattern=None,
                 paused=False,
                 source=None):
        '''
        Constructor.

        Params:
        title: string - Title of the visualisation window
        width: int - Width of the visualisation window
        height: int - Height of the visualisation window
        recording: boolean - Start with recording enabled?
        recordPattern: string - Pattern for recorded images,
          e.g., cylinders%05g.png
        paused: boolean - Start with playback paused?
        source:- The data source to read.
          What is required here varies by visualiser.
        '''

        # Visualisation options
        self.vis_features = []
        self.vis_frame = 0
        self.vis_frameStep = 1
        self.vis_jumping = False
        self.vis_recording = recording
        self.vis_recordPattern = recordPattern
        self.vis_paused = paused
        self.vis_source = source

        # VTK structures
        self.vtk_cells = vtkCellArray()
        self.vtk_renderer = vtkRenderer()

        # Tk structures
        self.tk_root = Tk()
        self.tk_root.title(title)
        self.tk_root.grid_rowconfigure(0, weight=1)
        self.tk_root.grid_columnconfigure(0, weight=3)
        self.tk_root.bind('<Destroy>', self.destroyed)
        if not self.vis_paused: self.tk_root.after(100, self.animate)            

        self.tk_renderWidget = vtkTkRenderWidget(self.tk_root,
                                                 width=width,
                                                 height=height)
        self.tk_renderWidget.grid(row=0, column=0, sticky=N+S+E+W)
        self.tk_renderWidget.GetRenderWindow().AddRenderer(self.vtk_renderer)

        self.tk_featureFrame = Frame(self.tk_root)
        self.tk_featureFrame.grid(row=0, column=1, rowspan=2)
        Label(self.tk_featureFrame, text='Features:').grid(row=0, column=0)

        self.tk_controlFrame = Frame(self.tk_root)
        self.tk_controlFrame.grid(row=1, column=0)

        self.tk_quit = Button(self.tk_controlFrame, text="Quit",
                              command=self.shutdown)
        self.tk_quit.grid(row=0, column=0, columnspan=2)

        def pause():
            if self.vis_paused:
                self.tk_pause.config(text='Pause')
                self.tk_root.after(100, self.animate)
            else:
                self.tk_pause.config(text='Resume')
            self.vis_paused ^= True
        self.tk_pause = Button(self.tk_controlFrame, text="Pause", command=pause)
        self.tk_pause.grid(row=0, column=2, columnspan=2)

        if self.vis_recordPattern is not None:
            def record():
                if self.vis_recording:
                    self.tk_record.config(text='Start Recording')
                else:
                    self.tk_record.config(text='Stop Recording')
                self.vis_recording ^= True
            self.tk_record = Button(self.tk_controlFrame, text="Start Recording", command=record)
            self.tk_record.grid(row=0, column=4, columnspan=2)
            if self.vis_recording:
                self.tk_record.config(text="Stop Recording")

        def make_seek_button(label, column, frame):
            def jump():
                self.jumpTo(frame)
            b = Button(self.tk_controlFrame,
                       text=label,
                       command=jump)
            b.grid(row=1, column=column, sticky=W+E)
            return b
        self.tk_seek_start = make_seek_button("|<", 0, 0)
        self.tk_seek_back10 = make_seek_button("<<", 1,
                                               lambda: self.vis_frame - 10)
        self.tk_seek_back1 = make_seek_button("<", 2,
                                              lambda: self.vis_frame - 1)
        self.tk_seek_forward1 = make_seek_button(">", 3,
                                                 lambda: self.vis_frame + 1)
        self.tk_seek_forward10 = make_seek_button(">>", 4,
                                                  lambda: self.vis_frame + 10)
        self.tk_seek_end = make_seek_button(">|", 5,
                                            self.getMaxFrameNumber)

        Label(self.tk_controlFrame, text='Frame').grid(row=2, column=0,
                                                       sticky=W+E)
        def changeFrame(frame):
            if not self.vis_jumping:
                self.vis_jumping = True
                self.jumpTo(self.tk_frame.get())
                self.vis_jumping = False
        self.tk_frame = Scale(self.tk_controlFrame, command=changeFrame,
                              from_=0, to=0, orient=HORIZONTAL)
        self.tk_frame.grid(row=2, column=1, columnspan=2, sticky=W+E)

        Label(self.tk_controlFrame, text='Step').grid(row=2, column=3,
                                                     sticky=W+E)
        def changeFrameStep(step):
            self.vis_frameStep = int(step)
        self.tk_frameStep = Scale(self.tk_controlFrame, command=changeFrameStep,
                                  from_=1, to=1, orient=HORIZONTAL)
        self.tk_frameStep.grid(row=2, column=4, columnspan=2, sticky=W+E)

        self.setupGrid()

    def add_feature(self, feature):
        '''Add a feature to this visualiser'''
        self.vis_features.append(feature)
        feature.button(self.tk_featureFrame).grid(row=len(self.vis_features),
                                                  column=0, sticky=W+E)
        feature.visualiser = self

    def run(self):
        '''Start the visualiser'''
        self.redraw()
        self.tk_root.mainloop()

    ### Private funcitions ###

    def resetSliders(self):
        '''
        Recalculate the upper bound on the frame and frameStep
        sliders.
        '''
        maxFrame = self.getMaxFrameNumber()
        self.tk_frame.config(to=maxFrame)
        self.tk_frameStep.config(to=maxFrame)

    def jumpTo(self, frame):
        '''
        Jump to a given frame. If frame is a function, jump to the
        return value of frame().
        '''
        oldFrame = self.vis_frame
        if hasattr(frame, '__call__'):
            self.vis_frame = frame()
        else:
            self.vis_frame = frame

        maxFrame = self.getMaxFrameNumber()

        if self.vis_frame < 0:
            self.vis_frame = 0
        elif self.vis_frame > maxFrame:
            self.vis_frame = maxFrame
            self.vis_paused = True
            self.tk_pause.config(text='Resume')

        self.tk_frame.set(self.vis_frame)
        self.redraw(oldFrame != self.vis_frame)

    def redraw(self, update=False):
        self.resetSliders()
        for feature in [ f for f in self.vis_features if not f.dynamic ]:
            feature.draw(self.vtk_renderer)
        if update:
            for feature in [ f for f in self.vis_features if f.dynamic]:
                f.redraw(self.vtk_renderer)
        self.tk_renderWidget.GetRenderWindow().Render()
        self.tk_root.update_idletasks()

    ### Gui events ###

    def destroyed(self, event):
        if event.widget == self.tk_root:
            self.shutdown()

    def shutdown(self):
        self.tk_root.withdraw()
        self.tk_root.destroy()

    def animate(self):
        if not self.vis_paused:
            self.jumpTo(self.vis_frame + self.vis_frameStep)
            if self.vis_recording and self.vis_recordPattern is not None:
                self.save_image()
            self.tk_root.after(100, self.animate)

    def save_image(self):
        extmap = {'.jpg' : vtkJPEGWriter,
                  '.jpeg' : vtkJPEGWriter,
                  '.png' : vtkPNGWriter,
                  '.pnm' : vtkPNMWriter}
        _, ext = splitext(self.vis_recordPattern)
        try: writer = extmap[ext.lower()]()
        except KeyError:
            print('ERROR: Can\'t handle %s extension. Recording disabled.' % ext)
            self.vis_recordPattern = None
            return

        win = self.vtk_renderer.GetRenderWindow()
        w2i = vtkWindowToImageFilter()
        w2i.SetInput(win)
        w2i.Update()
        writer.SetInput(w2i.GetOutput())
        writer.SetFileName(self.vis_recordPattern % self.vis_frame)
        win.Render()
        writer.Write()

    ### Things subclasses need to override ###

    def setupGrid(self):
        '''
        Populate the vtkCellArray instance at
        self.vtk_cells. Subclasses are required to override this
        function to read from their source as appropriate.
        '''
        raise NotImplementedError('Subclass needs to override Visualiser::setupGrid!')

    def getMaxFrameNumber(self):
        '''
        Return the maximum frame number. This will need to be defined
        by a subclass.
        '''
        raise NotImplementedError('Subclass needs to override Visualiser::getMaxFrameNumber!')

    def getQuantityPoints(self, quantityName, dynamic=True, frameNumber=0):
        '''
        Return the points of a quantity at a given frame as a list
        [float]. Subclasses need to override this.
        '''
        raise NotImplementedError('Subclass needs to override Visualiser::getQuantityPoints!')

    def getQuantityDict(self):
        '''
        Return the values of all quantities at a given time as a
        dictionary. Sublclasses need to override this.
        '''
        raise NotImplementedError('Subclass needs to override Visualiser::getQuantityDict!')
Exemple #7
0
class Report(Frame):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.root = self.winfo_toplevel()
        self.root.title(" ".join((APPNAME, VERSION, "| Report")))
        self.root.resizable(0, 0)
        self.items = None
        headers = ('Page', 'Rank', 'PageRank Value', 'Incoming')
        self.t = Scale(self,
                       from_=0,
                       to=1,
                       label='n-th iteration',
                       bd=1,
                       width=7,
                       orient='horizontal',
                       command=self.__set_t)
        self.t.pack(fill='x')
        self.label = Label(self, anchor='e')
        self.label.pack(fill='x')
        self.tree = Treeview(self,
                             columns=headers,
                             show="headings",
                             height=REPORT_HEIGHT)
        self.tree.column(0, anchor='center', width=55)
        self.tree.column(1, anchor='center', width=55)
        self.tree.column(2, width=175)
        self.tree.column(3, anchor='center', width=55)
        self.scroll = Scrollbar(self, command=self.tree.yview)
        self.scroll.pack(side='right', fill='y')
        self.tree.config(yscrollcommand=self.scroll.set)
        for col in headers:
            self.tree.heading(col, text=col.title())
        self.root.master.focus_force()
        self.root.bind('<Key>', self.__keys)

    def __keys(self, event):
        if event.char == 'i':
            self.t.set(self.t.get() - 1)
        elif event.char == 'I':
            self.t.set(0)
        elif event.char == 'o':
            self.t.set(self.t.get() + 1)
        elif event.char == 'O':
            self.t.set(self.pagerank[1])

    def __set_t(self, t=None):
        self.render(self.pagerank, self.edge_counts, self.d, self.e, t=int(t))

    def render(self, pagerank, edge_counts, d, e, t=None):
        self.d, self.e = d, e
        self.edge_counts = edge_counts
        self.pagerank = pagerank
        if t is not None:
            pr = pagerank[0][t]
        else:
            self.t.config(command=None)
            self.t.config(to=self.pagerank[1])
            self.t.set(self.pagerank[1])
            self.t.config(command=self.__set_t)
            pr = pagerank[0][-1]
        label_text = '# of ranks:{0:>3}     # of iterations:{1:>3}'.format(
            len(set(pr.values())), self.pagerank[1])
        self.label.config(text=label_text)
        in_map = {k: 0 for k in pr.keys()}  # incoming edges by nodes
        for (tail, head), n in edge_counts.items():
            if tail is not head:
                in_map[head] += n

        get_rank = lambda k: sorted(pr.values())[::-1].index(pr[k]) + 1
        data = tuple(
            (k, get_rank(k), pr[k], in_map[k]) for k in sorted(pr.keys()))
        if self.items: self.tree.delete(*self.items)
        self.items = [
            self.tree.insert('', 'end', values=line) for line in data
        ]
        self.tree.pack(side='left', fill='y')
        #self.root.master.focus_force()

    def destroy(self):
        super().destroy()
        self.root.master.r_win = False
        self.root.master.windowsmenu.entryconfig(0, label='[ ] Report window')
        self.root.destroy()
Exemple #8
0
class MainWindow:

    def __init__(self, master):
        self.FORMAT = {0: '.pdf', 1: '.jpg'}
        self.SETTINGS_DPI = {0: 72, 1: 100, 2: 150}
        self.SETTINGS_COLOR = {0: '1', 1: 'RGB'}
        self.list_files = ''
        self.filename = ''
        self.lenght_list_files = ''
        ####################################################################################################
        # A1 # 1      # 2       # 3       # 4       # 5       # 6       # 7       # 8       # 9       # 10 #
        # A2 # BUTTON # TEXT    # TEXT    # TEXT    # TEXT    # TEXT    # TEXT    # TEXT    # VSCROLL # 10 #
        # A3 # BUTTON # TEXT    # TEXT    # TEXT    # TEXT    # TEXT    # TEXT    # TEXT    # VSCROLL # 10 #
        # A4 # BUTTON # TEXT    # TEXT    # TEXT    # TEXT    # TEXT    # TEXT    # TEXT    # VSCROLL # 10 #
        # A5 # BUTTON # TEXT    # TEXT    # TEXT    # TEXT    # TEXT    # TEXT    # TEXT    # VSCROLL # 10 #
        # A6 # 1      # HSCROLL # HSCROLL # HSCROLL # HSCROLL # HSCROLL # HSCROLL # HSCROLL # HSCROLL # 10 #
        # A7 # FORMAT # SPLIT   # SPLIT   # DPI     # DPI     # COLOR   # COLOR   # QUALITY # QUALITY # 10 #
        # A8 # FORMAT # SPLIT   # SPLIT   # DPI     # DPI     # COLOR   # COLOR   # QUALITY # QUALITY # 10 #
        # A9 # FORMAT # SPLIT   # SPLIT   # DPI     # DPI     # COLOR   # COLOR   # QUALITY # QUALITY # 10 #
        # A10# P_BAR  # P_BAR   # P_BAR   # P_BAR   # P_BAR   # P_BAR   # P_BAR   # P_BAR   # P_BAR   # 10 #
        ####################################################################################################
        self.text_box = Text(master, wrap='char', width=80, height=16)
        self.vscroll_text_box = Scrollbar(
            master, orient='vertical', command=self.text_box.yview())
        self.hscroll_text_box = Scrollbar(
            master, orient='horizontal', command=self.text_box.xview())
        self.text_box.config(yscrollcommand=self.vscroll_text_box.set,
                             xscrollcommand=self.hscroll_text_box.set)
        self.text_box.grid(row=2, column=2, rowspan=4, columnspan=7)
        self.vscroll_text_box.grid(
            row=2, column=9, rowspan=4, sticky=('se', 'ne'))
        self.hscroll_text_box.grid(
            row=6, column=2, columnspan=8, sticky=('we', 'ne'))
        #
        #
        # Настройки формата файла
        self.labelframe_format = LabelFrame(
            master, text="Формат файла")
        self.labelframe_format.grid(
            row=7, column=1, columnspan=1, rowspan=3, sticky='wens')
        self.format_output_file = IntVar()
        self.format_output_file.set(0)
        self.radiobutton_pdf = Radiobutton(self.labelframe_format, text='Формат PDF',
                                           variable=self.format_output_file, value=0, command=self.shutdown_button)
        self.radiobutton_jpg = Radiobutton(self.labelframe_format, text='Формат JPEG',
                                           variable=self.format_output_file, value=1, command=self.shutdown_button)
        self.radiobutton_pdf.pack(fill='x')
        self.radiobutton_jpg.pack(fill='x')
        #
        #
        # Задаём фрейм в котором будем размещать настройки разделения
        self.labelframe_split = LabelFrame(master, text="Развибка на страницы")
        self.labelframe_split.grid(
            row=7, column=2, columnspan=2, rowspan=3, sticky='wens')
        self.scale_split = Scale(self.labelframe_split, from_=0, to=100,
                                 resolution=5, orient="horizontal")
        self.scale_split.pack(fill='both')
        #
        #
        # Задаём фрейм в котором будем размещать настройки качества файла
        self.labelframe_dpi = LabelFrame(master, text="Настройки качества")
        self.labelframe_dpi.grid(
            row=7, column=4, columnspan=2, rowspan=3, sticky='wens')
        self.dpi = IntVar()
        self.dpi.set(2)
        self.radiobutton_dpi_72 = Radiobutton(self.labelframe_dpi, text='Среднее',
                                              variable=self.dpi, value=0)
        self.radiobutton_dpi_100 = Radiobutton(self.labelframe_dpi, text='Хорошее',
                                               variable=self.dpi, value=1)
        self.radiobutton_dpi_150 = Radiobutton(self.labelframe_dpi, text='Отличное',
                                               variable=self.dpi, value=2)
        self.radiobutton_dpi_72.pack(fill='both')
        self.radiobutton_dpi_100.pack(fill='both')
        self.radiobutton_dpi_150.pack(fill='both')
        #
        #
        # Фрейм с настройками выбора цветное или ч/б
        self.labelframe_color = LabelFrame(master, text="Настройки цвета")
        self.labelframe_color.grid(
            row=7, column=6, columnspan=2, rowspan=3, sticky='wens')
        self.color = IntVar()
        self.color.set(0)
        self.radiobutton_bw = Radiobutton(self.labelframe_color, text='Чёрно/белое',
                                          variable=self.color, value=0)
        self.radiobutton_color = Radiobutton(self.labelframe_color, text='Цветное',
                                             variable=self.color, value=1)
        self.radiobutton_bw.pack(fill='both')
        self.radiobutton_color.pack(fill='both')
        #
        #
        # Фрейм с настройками качества сжатия JPEG
        self.labelframe_quality = LabelFrame(
            master, text="Настройка сжатия файла")
        self.labelframe_quality.grid(
            row=7, column=8, columnspan=2, rowspan=3, sticky='nw ne')
        self.scale_quality = Scale(self.labelframe_quality, label='Хуже                   Лучше', from_=1, to=100,
                                   resolution=1, orient="horizontal", state='active')
        self.scale_quality.set(100)
        self.scale_quality.pack(fill='both')
        #
        #
        # Чекбокс настройки оптимизации качества
        self.optimize_image = BooleanVar()
        self.optimize_image.set(False)
        self.checkbutton_optimize = Checkbutton(
            self.labelframe_quality, text='Автоматически', variable=self.optimize_image, onvalue=True, offvalue=False)
        self.checkbutton_optimize.pack()
        self.checkbutton_optimize.bind(
            '<Button>', lambda event: self.change_state(event))
        #
        #
        # Задаем фрейм в котором будем размещать основные кнопки команд
        self.button_frame = Frame(master)
        self.button_frame.grid(row=2, column=1, rowspan=4)
        self.button_open = Button(self.button_frame, text="Добавить файлы",
                                  command=self.listFiles, state='active', pady=5, padx=8)
        self.button_open.pack()
        self.button_save = Button(self.button_frame, text="Сохранить файл",
                                  command=self.savefileName, state='active', pady=5, padx=9)
        self.button_save.pack()
        self.button_run = Button(self.button_frame, text="Запустить",
                                 command=lambda x=True: ConvertFile().process(
                                     input_file=self.list_files, output_file=self.filename,
                                     format_file=self.FORMAT[self.format_output_file.get(
                                     )], dpi=self.SETTINGS_DPI[self.dpi.get()], color=self.SETTINGS_COLOR[self.color.get()],
                                     optimize=self.optimize_image.get(),
                                     quality=self.scale_quality.get(), split_step=self.scale_split.get()),
                                 state='active', pady=5, padx=26)
        self.button_run.pack()
        #
        #
        # Progressbar
        self.pbar = ttk.Progressbar(
            master, orient='horizontal', mode='determinate', length=100, maximum=100)
        self.pbar.grid(row=10, column=1, columnspan=9, sticky='wens')
        #
        #
        # Меню программы
        self.menu = Menu(master)
        master.config(menu=self.menu)
        self.sub_menu1 = Menu(self.menu)
        self.menu.add_cascade(label='Файл', menu=self.sub_menu1)
        self.sub_menu1.add_command(label='Выход', command=self.closed_window)
        self.sub_menu2 = Menu(self.menu)
        self.menu.add_cascade(label='Информация', menu=self.sub_menu2)
        self.sub_menu2.add_command(
            label='О программе', command=self.show_about)

    def frange(self, start, stop, step):
        while start < stop:
            yield start
            start += step

    def change_state(self, event):
        if self.optimize_image.get() is False:
            self.scale_quality.config(state='disable')
        else:
            self.scale_quality.config(state='active')

    def shutdown_button(self):
        if self.format_output_file.get() == 1:
            self.button_save.config(state='disable')
        else:
            self.button_save.config(state='active')

    def update_progressbar(self, page):
        step = 100 / self.lenght_list_files
        step_range = list(self.frange(0, 100, step))
        self.pbar['value'] = step_range[page] + step
        root.update()

    def show_about(self):
        messagebox.showinfo(
            title='О программе', message=ABOUT)

    def show_error(self, message):
        messagebox.showerror(title='ОШИБКА', message=message)

    def closed_window(self):
        root.quit()

    def listFiles(self):
        """ Функция привязана к кнопке "Добавить файлы". Результат работы функции - список файлов, который отображается в поле text_box """
        self.list_files = filedialog.askopenfilenames()
        self.lenght_list_files = len(self.list_files)
        self.text_box.delete(1.0, END)
        for i in self.list_files:
            self.text_box.insert(END, i)
            self.text_box.insert(END, '\n')
        return self.list_files

    def savefileName(self):
        """ Функция привязана к кнопке "Сохранить файл". Результат работы функции - полный путь к выходному файлу """
        default = self.FORMAT[0]
        setting_format = self.FORMAT[self.format_output_file.get()]
        self.filename = filedialog.asksaveasfilename(filetypes=[(f"Формат файла *{setting_format}",
                                                                 f"*{setting_format}")],
                                                     defaultextension=default)
        return self.filename
Exemple #9
0
class ControlAppGUI:
    def __init__(self, master):
        self.master = master
        # GUI layout setup
        self.menu = Menu(self.master)

        self.master.config(menu=self.menu)
        master.grid_rowconfigure(0, weight=1)
        master.grid_columnconfigure(0, weight=1)
        filemenu = Menu(self.menu)
        self.menu.add_cascade(label="File", menu=filemenu)
        filemenu.add_command(label="New", command=self.NewFile)
        openmenu = Menu(self.menu)
        openmenu.add_command(label="Gcode", command=self.OpenGcodeFile)
        openmenu.add_command(label="CSV", command=self.OpenCsvFile)
        savemenu = Menu(self.menu)
        savemenu.add_command(label="Gcode", command=self.SaveGcodeFile)
        savemenu.add_command(label="CSV", command=self.SaveCsvFile)
        filemenu.add_cascade(label='Open...', menu=openmenu, underline=0)
        filemenu.add_cascade(label="Save...", menu=savemenu, underline=0)
        #filemenu.add_command(label="Reload current file", command=None)
        filemenu.add_command(label="Set color", command=self.AskColor)
        filemenu.add_separator()

        def updatePortList():
            ports = serial.serial_ports()
            self.portCombo['values'] = ports
            if len(ports) > 0:
                self.portCombo.current(0)

        filemenu.add_command(label="Refresh port list", command=updatePortList)
        filemenu.add_command(label="Exit", command=self.Quit)

        editmenu = Menu(self.menu)
        self.menu.add_cascade(label="Edit", menu=editmenu)
        editmenu.add_command(label="Settings", command=self.Settings)

        helpmenu = Menu(self.menu)
        self.menu.add_cascade(label="Help", menu=helpmenu)
        helpmenu.add_command(label="About...", command=self.About)
        master.title("Embroiderino frontend")

        self.controls = ttk.Notebook(master)
        tab1 = Frame(self.controls)
        tab2 = Frame(self.controls)
        self.controls.add(tab1, text="Machine control")
        self.controls.add(tab2, text="Path manipulation")
        self.controls.grid(row=0, column=1, sticky=N)
        self.controls.grid_rowconfigure(0, weight=1)
        self.controls.grid_columnconfigure(0, weight=1)

        # MACHINE TAB
        ports = serial.serial_ports()
        self.portCombo = ttk.Combobox(tab1, values=ports)
        if len(ports) > 0:
            self.portCombo.current(0)
        self.portCombo.grid(row=1, column=0)
        self.baudCombo = ttk.Combobox(tab1,
                                      state='readonly',
                                      values=("115200", "9600"),
                                      width=10)
        self.baudCombo.current(0)
        self.baudCombo.grid(row=1, column=1)
        self.connectButton = Button(tab1,
                                    text="Connect",
                                    command=self.ToggleConnect,
                                    width=10)
        self.connectButton.grid(row=1, column=2)

        self.startButton = Button(tab1,
                                  text="Start job",
                                  command=self.ToggleStart,
                                  state=DISABLED)
        self.startButton.grid(row=2, column=1)
        self.homeButton = Button(tab1,
                                 text="Home machine",
                                 command=lambda: serial.queue_command("G28\n"),
                                 state=DISABLED)
        self.homeButton.grid(row=2, column=0)

        testNavigation = Frame(tab1)
        leftButton = Button(
            testNavigation,
            text="<",
            command=lambda: serial.queue_command("G91\nG0 X-2\nG90\n"),
            state=DISABLED)
        leftButton.grid(row=1, column=0)
        rightButton = Button(
            testNavigation,
            text=">",
            command=lambda: serial.queue_command("G91\nG0 X2\nG90\n"),
            state=DISABLED)
        rightButton.grid(row=1, column=2)
        upButton = Button(
            testNavigation,
            text="/\\",
            command=lambda: serial.queue_command("G91\nG0 Y2\nG90\n"),
            state=DISABLED)
        upButton.grid(row=0, column=1)
        downButton = Button(
            testNavigation,
            text="\\/",
            command=lambda: serial.queue_command("G91\nG0 Y-2\nG90\n"),
            state=DISABLED)
        downButton.grid(row=2, column=1)
        testNavigation.grid(row=3, column=0)
        self.navigationButtons = [
            leftButton, rightButton, upButton, downButton
        ]

        self.testButton = Button(tab1,
                                 text="Test border path",
                                 command=self.TestBorder,
                                 state=DISABLED)
        self.testButton.grid(row=3, column=1)

        self.gotoButton = Button(tab1,
                                 text="Go to",
                                 command=self.GoTo,
                                 state=DISABLED,
                                 relief=RAISED)
        self.gotoButton.grid(row=3, column=2)

        self.stopButton = Button(tab1,
                                 text="STOP",
                                 command=self.StopAll,
                                 state=DISABLED)
        self.stopButton.grid(row=4, column=0)

        self.pauseOnToolChange = IntVar()
        self.pauseOnTrim = IntVar()
        self.toolChangeCheck = Checkbutton(tab1,
                                           variable=self.pauseOnToolChange,
                                           onvalue=1,
                                           offvalue=0,
                                           text="Pause on tool change")
        self.toolChangeCheck.grid(row=4, column=1)
        self.toolChangeCheck.select()
        self.trimCheck = Checkbutton(tab1,
                                     variable=self.pauseOnTrim,
                                     onvalue=1,
                                     offvalue=0,
                                     text="Pause on trim")
        self.trimCheck.grid(row=4, column=2)
        self.trimCheck.select()

        progressFrame = Frame(tab1)
        Label(progressFrame, text="Tool changes: ", bd=1).grid(row=0,
                                                               column=0,
                                                               pady=(10, 1))
        self.toolChangesLabel = Label(progressFrame,
                                      text="0/0",
                                      bd=1,
                                      relief=SUNKEN)
        self.toolChangesLabel.grid(row=1, column=0)

        Label(progressFrame, text="Tool points: ", bd=1).grid(row=0,
                                                              column=2,
                                                              pady=(10, 1))
        self.toolPointsLabel = Label(progressFrame,
                                     text="0/0",
                                     bd=1,
                                     relief=SUNKEN)
        self.toolPointsLabel.grid(row=1, column=2)

        Label(progressFrame, text="Estimated endtime: ",
              bd=1).grid(row=0, column=4, pady=(10, 1))
        self.timeLabel = Label(progressFrame, text="0/0", bd=1, relief=SUNKEN)
        self.timeLabel.grid(row=1, column=4)
        progressFrame.grid(row=5, column=0, columnspan=3)

        colorsFrame = Frame(tab1, bd=1)
        colorsFrame.grid(row=6, column=0, columnspan=3, pady=(10, 1))
        Label(colorsFrame, text="Current color: ", bd=1).pack(side=LEFT)
        self.currentColorIndicator = Label(colorsFrame,
                                           text="    ",
                                           relief=RAISED,
                                           bd=1)
        self.currentColorIndicator.pack(side=LEFT, padx=(1, 40))
        Label(colorsFrame, text="Next color: ", bd=1).pack(side=LEFT, padx=2)
        self.nextColorIndicator = Label(colorsFrame,
                                        text="    ",
                                        relief=RAISED,
                                        bd=1)
        self.nextColorIndicator.pack(side=LEFT)

        Label(tab1, text="SPM speed limit: ", bd=1).grid(row=7, column=0)
        self.speedSlider = Scale(tab1,
                                 from_=80,
                                 to=800,
                                 command=None,
                                 orient=HORIZONTAL,
                                 length=200)
        self.speedSlider.set(400)
        self.speedSlider.bind(
            "<ButtonRelease-1>", lambda _: serial.queue_command(
                "M222 S%d\n" % self.speedSlider.get(), priority=-1))
        self.speedSlider.grid(row=7, column=1, columnspan=2)

        # PATH TAB
        tab2.grid_columnconfigure(0, weight=1)
        Label(tab2, text="Display progress: ", bd=1).grid(row=0)
        self.slider = Scale(tab2,
                            from_=0,
                            to=0,
                            command=self.UpdatePath,
                            orient=HORIZONTAL,
                            length=300)
        self.slider.grid(row=1)

        toolbar = Frame(tab2, bd=1, relief=RAISED)
        toolbar.grid(row=2)
        self.panButton = Button(toolbar,
                                relief=RAISED,
                                command=self.TogglePan,
                                text="Move path")
        self.panButton.pack(side=LEFT, padx=2, pady=2)

        self.rotateButton = Button(toolbar,
                                   relief=RAISED,
                                   command=self.ToggleRotate,
                                   text="Rotate path")
        self.rotateButton.pack(side=LEFT, padx=2, pady=2)

        self.mirrorButton = Button(toolbar,
                                   relief=RAISED,
                                   command=self.ToggleMirror,
                                   text="Mirror path")
        self.mirrorButton.pack(side=LEFT, padx=2, pady=2)

        self.scaleButton = Button(toolbar,
                                  relief=RAISED,
                                  command=self.ToggleScale,
                                  text="Scale path")
        self.scaleButton.pack(side=LEFT, padx=2, pady=2)

        # CANVAS
        canvasFrame = Frame(master)
        canvasFrame.grid(row=0, column=0, sticky='NWES')
        self.canvas = ResizingCanvas(canvasFrame,
                                     width=400,
                                     height=400,
                                     bg="white",
                                     highlightthickness=0)
        self.canvas.bind("<B1-Motion>", self.CanvasDrag)
        self.canvas.bind("<Button-1>", self.CanvasClick)
        self.canvas.bind("<ButtonRelease-1>", self.CanvasRelease)
        self.canvas.pack(expand=YES, anchor=N + W)

        #STATUS BAR
        self.status = Label(master,
                            text="Not connected",
                            bd=1,
                            relief=SUNKEN,
                            anchor=W)
        self.status.grid(row=2, columnspan=2, sticky='WE')

        # PROGRAM VARIABLES
        self.SETTINGSFNAME = "settings.pickle"
        self.commands = []
        self.transform = (0, 0)
        self.isConnected = False
        self.isJobRunning = False
        self.isJobPaused = False
        self.lastSendCommandIndex = -1
        self.lastMove = None
        self.currentColor = 'black'
        self.currentToolChange = 0
        self.toolChangesTotal = 0
        self.currentToolPoint = 0
        self.toolPointsTotal = 0
        self.distancesList = []
        self.distanceTraveled = 0
        self.positionResponseRegex = re.compile(
            "X:(\-?\d+\.\d+),Y:(\-?\d+\.\d+)")
        self.machineSetups = {}
        self.currentSetupName = None
        self.workAreaSize = [100, 100]
        self.workAreaOrigin = [0, 0]

        # LOAD SOME SETTIGS
        self.loadSettings()
        self.canvas.setArea(self.workAreaSize[0], self.workAreaSize[1])
        self.canvas.setOrigin(self.workAreaOrigin[0], self.workAreaOrigin[1])

    # UI LOGIC
    def Quit(self):
        if messagebox.askyesno('Confirm', 'Really quit?'):
            self.master.quit()
            return True
        return False

    def AskColor(self):
        color = colorchooser.askcolor(title="Colour Chooser")

    def NewFile(self):
        if self.isJobRunning:
            return
        self.toolChangesTotal = 0
        self.toolPointsTotal = 0
        self.distancesList = []
        self.lastSendCommandIndex = -1
        self.lastMove = None
        self.commands = []
        self.canvas.clear()
        self.slider.config(to=0)

    def OpenGcodeFile(self):
        if self.isJobRunning:
            return
        with filedialog.askopenfile(filetypes=(("Machine G-code",
                                                "*.gcode"), )) as f:
            self.commands = load_gcode_file(f)
            self.FinishLoading()

    def SaveGcodeFile(self):
        if not self.commands:
            return
        with filedialog.asksaveasfile(filetypes=(("Machine G-code",
                                                  "*.gcode"), ),
                                      defaultextension='.gcode') as f:
            save_gcode_file(f, self.commands)

    def OpenCsvFile(self):
        if self.isJobRunning:
            return
        with filedialog.askopenfile(filetypes=(("Comma separated values",
                                                "*.csv"), )) as f:
            self.commands = load_csv_file(f)
            self.FinishLoading()

    def SaveCsvFile(self):
        pass

    def FinishLoading(self):
        points_count = len(self.commands)
        # file loaded
        if points_count > 2:
            self.testButton.config(state=NORMAL)
            self.startButton.config(state=NORMAL)
            # prepare color indicators
            self.currentColorIndicator.configure(background=self.currentColor)
            self.currentColorIndicator.configure(background=None)
            # center loaded path
            rectangle = toolpath_border_points(self.commands)
            rwidth = rectangle[2][0] - rectangle[0][0]
            rheight = rectangle[2][1] - rectangle[0][1]
            center = (rectangle[2][0] - (rwidth) / 2,
                      rectangle[2][1] - (rheight) / 2)
            transform = (self.workAreaSize[0] / 2 - center[0] +
                         self.workAreaOrigin[0], self.workAreaSize[1] / 2 -
                         center[1] + self.workAreaOrigin[1])
            self.commands = translate_toolpath(self.commands, transform)
            # check if  design is bigger than available workarea
            if (rwidth > self.workAreaSize[0]
                    or rheight > self.workAreaSize[1]):
                messagebox.showinfo(
                    'Size Warning!',
                    "Looks like this design is bigger than available work area."
                )

        self.slider.config(to=points_count)
        self.slider.set(points_count)
        self.toolPointsTotal, self.toolChangesTotal, self.distancesList = toolpath_info(
            self.commands)
        self.toolPointsLabel.config(
            text="%d/%d" % (self.currentToolPoint, self.toolPointsTotal))
        self.toolChangesLabel.config(
            text="%d/%d" % (self.currentToolChange, self.toolChangesTotal))
        self.UpdateTimeEstLabel()
        self.canvas.draw_toolpath(self.commands)

    def About(self):
        #self.PausePopup()
        messagebox.showinfo(
            'About this software',
            'This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or any later version.\n\nThis program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nWritten in 2018 by markol.'
        )

    def Settings(self):
        tl = Toplevel(root)
        tl.title("Global settings")

        frame = Frame(tl)
        frame.grid()

        machineFrame = LabelFrame(frame,
                                  text="Machine hoop workarea (mm)",
                                  relief=RIDGE)
        machineFrame.grid()
        Label(machineFrame, text="width ").grid(row=0, column=0, sticky=N)
        workareaWidth = Entry(machineFrame, text="1")
        workareaWidth.grid(row=0, column=1)
        Label(machineFrame, text="height ").grid(row=2, column=0, sticky=N)
        workareaHeight = Entry(machineFrame, text="2")
        workareaHeight.grid(row=2, column=1)
        hoopFrame = LabelFrame(frame,
                               text="Machine hoop origin (mm)",
                               relief=RIDGE)
        hoopFrame.grid()
        Label(hoopFrame, text="X ").grid(row=0, column=0, sticky=N)
        workareaOriginX = Entry(hoopFrame, text="3")
        workareaOriginX.grid(row=0, column=1)
        Label(hoopFrame, text="Y ").grid(row=2, column=0, sticky=N)
        workareaOriginY = Entry(hoopFrame, text="4")
        workareaOriginY.grid(row=2, column=1)
        Label(hoopFrame, text="Setup name ").grid(row=3, column=0, sticky=N)
        setupName = Entry(hoopFrame, text="Setup1")
        setupName.grid(row=3, column=1)

        def setupSelected(event=None):
            if event:
                selectedSetupName = setupsCombo.get()
            else:
                selectedSetupName = self.currentSetupName

            workareaWidth.delete(0, END)
            workareaWidth.insert(
                0,
                str(self.machineSetups[selectedSetupName]["workAreaSize"][0]))
            workareaHeight.delete(0, END)
            workareaHeight.insert(
                0,
                str(self.machineSetups[selectedSetupName]["workAreaSize"][1]))
            workareaOriginX.delete(0, END)
            workareaOriginX.insert(
                0,
                str(self.machineSetups[selectedSetupName]["workAreaOrigin"]
                    [0]))
            workareaOriginY.delete(0, END)
            workareaOriginY.insert(
                0,
                str(self.machineSetups[selectedSetupName]["workAreaOrigin"]
                    [1]))
            setupName.delete(0, END)
            setupName.insert(0, selectedSetupName)

        setupSelected()

        setupsCombo = ttk.Combobox(frame,
                                   values=list(self.machineSetups.keys()),
                                   state="readonly")
        setupsCombo.grid(row=2, column=0)
        setupsCombo.current(setupsCombo['values'].index(self.currentSetupName))
        setupsCombo.bind("<<ComboboxSelected>>", setupSelected)

        def addSettings():
            newSetupName = setupName.get()

            if newSetupName in self.machineSetups.keys():
                if not messagebox.askyesno(
                        "Machine setup exists",
                        "Machine setup with this name exists. Overwrite?"):
                    return
            newSetup = {
                "workAreaSize":
                (int(workareaWidth.get()), int(workareaHeight.get())),
                "workAreaOrigin":
                (int(workareaOriginX.get()), int(workareaOriginY.get()))
            }
            self.machineSetups[newSetupName] = newSetup
            setupsCombo['values'] = list(self.machineSetups.keys())

        Button(frame, relief=RAISED, command=addSettings,
               text="Add setup").grid(row=2, column=1)

        def removeSetup():
            self.machineSetups.pop(setupsCombo.get(), None)
            options = list(self.machineSetups.keys())
            setupsCombo['values'] = options
            if len(options) > 0:
                self.currentSetupName = list(self.machineSetups.keys())[0]
                setupsCombo.current(0)
                setupSelected(1)

        Button(frame, relief=RAISED, command=removeSetup,
               text="Remove setup").grid(row=2, column=2)

        def saveSettings():
            try:
                if len(setupsCombo.get()) > 0:
                    self.workAreaSize = (int(workareaWidth.get()),
                                         int(workareaHeight.get()))
                    self.workAreaOrigin = (int(workareaOriginX.get()),
                                           int(workareaOriginY.get()))
                    self.currentSetupName = setupsCombo.get()
            except:
                messagebox.showerror(
                    "Invalid numeric values",
                    "Please provide correct workarea values!")
                return

            self.canvas.setArea(self.workAreaSize[0], self.workAreaSize[1])
            self.canvas.setOrigin(self.workAreaOrigin[0],
                                  self.workAreaOrigin[1])
            self.storeSettings()
            TmpDim = namedtuple('TmpDim', 'width height')
            tmp = TmpDim(self.canvas.width, self.canvas.height)
            self.canvas.on_resize(tmp)

        Button(frame, text="Save", command=saveSettings,
               width=10).grid(row=3, column=3)
        Button(frame, text="Close", command=lambda: tl.destroy(),
               width=10).grid(row=3, column=2)

    def loadSettings(self):
        try:
            with open(self.SETTINGSFNAME, "rb") as f:
                data = pickle.load(f)
            self.machineSetups = data["machineSetups"]
            self.currentSetupName = data["currentSetupName"]
            self.workAreaSize = self.machineSetups[
                self.currentSetupName]["workAreaSize"]
            self.workAreaOrigin = self.machineSetups[
                self.currentSetupName]["workAreaOrigin"]
        except Exception as e:
            print("Unable to restore program settings:", str(e))

    def storeSettings(self):
        with open(self.SETTINGSFNAME, "wb") as f:
            try:
                data = {
                    "machineSetups": self.machineSetups,
                    "currentSetupName": self.currentSetupName
                }
                pickle.dump(data, f)
            except Exception as e:
                print("Error while saving settings:", str(e))

    def ToggleConnect(self):
        if self.isConnected:
            serial.close_serial()
            self.connectButton.config(text="Connect")
            self.status.config(text="Not connected")
            self.homeButton.config(state=DISABLED)
            self.stopButton.config(state=DISABLED)
            self.gotoButton.config(state=DISABLED)
            self.SetNavButtonsState(False)
            self.isConnected = False
        else:
            if serial.open_serial(self.portCombo.get(), self.baudCombo.get()):
                self.connectButton.config(text="Disconnect")
                self.status.config(text="Connected")
                self.homeButton.config(state=NORMAL)
                self.stopButton.config(state=NORMAL)
                self.gotoButton.config(state=NORMAL)
                self.SetNavButtonsState(True)
                self.isConnected = True
                self.GetPositionTimerTaks()

    def TestBorder(self):
        rectangle = toolpath_border_points(self.commands)
        for point in rectangle:
            serial.queue_command("G0 X%f Y%f F5000\n" % point)

    def ToggleStart(self):
        if self.isJobPaused:
            serial.queue.clear()
            self.startButton.config(text="Resume job")
            self.status.config(text="Job paused")
        else:
            self.startButton.config(text="Pause job")
            self.status.config(text="Job in progress")
            startInstructionIndex = self.lastSendCommandIndex + 1
            # job launch
            if not self.isJobRunning:
                self.canvas.clear()
                startInstructionIndex = 0
                self.start = time.time()
                serial.queue_command("G0 F15000\n")

            self.isJobRunning = True
            self.QueueCommandsBlock(startInstructionIndex)

        self.isJobPaused = not self.isJobPaused

    def QueueCommandsBlock(self, startInstructionIndex):
        commandsCount = len(self.commands)

        def progressCallback(instruction_index):
            ''' after every move G0 or G1 or G28 command being sent, this callback is executed '''
            point = self.commands[instruction_index]
            if self.lastMove:
                coord = (self.lastMove[1], self.lastMove[2], point[1],
                         point[2])
                color = self.currentColor
                # set color for jump move
                if "G0" == point[0] or "G28" == point[0]:
                    color = "snow2"
                else:
                    self.currentToolPoint += 1
                    self.toolPointsLabel.config(
                        text="%d/%d" %
                        (self.currentToolPoint, self.toolPointsTotal))
                    # calculate distance for material usage
                    self.distanceTraveled += math.hypot(
                        coord[0] - coord[2], coord[1] - coord[3])
                # draw new line on canvas
                line = self.canvas.create_line(self.canvas.calc_coords(coord),
                                               fill=color)
                self.canvas.lift(self.canvas.pointer, line)
                self.UpdateTimeEstLabel()
            # store next start point and instruction index
            self.lastSendCommandIndex = instruction_index
            self.lastMove = point

            # update status bar
            if self.currentToolPoint % 10 == 0:
                progress = instruction_index / commandsCount * 100
                self.status.config(text="Job in progress %.1f%%" % progress)

        def progressPauseCallback(instruction_index, trim=False):
            ''' this callback pauses the job '''
            point = self.commands[instruction_index]
            self.lastSendCommandIndex = instruction_index
            # pause on color change
            if not trim:
                self.currentColor = _from_rgb((point[1], point[2], point[3]))
                self.currentToolChange += 1
                self.currentColorIndicator.configure(
                    background=self.currentColor)
                self.toolChangesLabel.config(
                    text="%d/%d" %
                    (self.currentToolChange, self.toolChangesTotal))
                # pause enabled or not
                if self.pauseOnToolChange.get() == 1:
                    self.ToggleStart()
                    self.PausePopup(self.currentColor)
                else:
                    self.QueueCommandsBlock(self.lastSendCommandIndex + 1)
            # pause on trim
            else:
                # pause enabled or not
                if self.pauseOnTrim.get() == 1:
                    self.ToggleStart()
                    self.PausePopup(self.currentColor, trim)
                else:
                    self.QueueCommandsBlock(self.lastSendCommandIndex + 1)

        # all the commands until next tool change command, are queued at once
        # unsupported commands are ignored
        for i in range(startInstructionIndex, commandsCount):
            point = self.commands[i]
            # pause on color change
            if "M6" == point[0]:
                serial.queue_command(
                    "M6\n", lambda _, index=i: progressPauseCallback(index))
                self.nextColorIndicator.configure(
                    background=_from_rgb((point[1], point[2], point[3])))
                break
            # pause on trim
            elif "G12" == point[0]:
                # if next command is a color change, there is no need to pause now
                if i < commandsCount + 1 and self.commands[
                        i +
                        1][0] == "M6" and self.pauseOnToolChange.get() == 1:
                    serial.queue_command("G12\n")
                else:
                    serial.queue_command(
                        "G12\n",
                        lambda _, index=i: progressPauseCallback(index,
                                                                 trim=True))
                    break
            elif "G1" == point[0] or "G0" == point[0] or "G28" == point[0]:
                serial.queue_command(
                    "%s X%f Y%f\n" % (point[0], point[1], point[2]),
                    lambda _, index=i: progressCallback(index))
        # queue job finish callback
        if i + 1 >= commandsCount:
            serial.queue_command("M114\n", self.JobFinished)

    def SetNavButtonsState(self, enabled=False):
        newState = NORMAL if enabled else DISABLED
        for b in self.navigationButtons:
            b.config(state=newState)

    def TogglePan(self):
        self.rotateButton.config(relief=RAISED)
        self.scaleButton.config(relief=RAISED)
        if self.isJobRunning:
            return
        if self.panButton.config('relief')[-1] == SUNKEN:
            self.panButton.config(relief=RAISED)
        else:
            self.panButton.config(relief=SUNKEN)

    def ToggleRotate(self):
        self.panButton.config(relief=RAISED)
        self.scaleButton.config(relief=RAISED)
        if self.isJobRunning:
            return
        if self.rotateButton.config('relief')[-1] == SUNKEN:
            self.rotateButton.config(relief=RAISED)
        else:
            self.rotateButton.config(relief=SUNKEN)

    def ToggleMirror(self):
        self.panButton.config(relief=RAISED)
        self.rotateButton.config(relief=RAISED)
        self.scaleButton.config(relief=RAISED)
        if self.isJobRunning:
            return
        self.commands = reflect_toolpath(
            self.commands, self.workAreaSize[0] / 2 + self.workAreaOrigin[0])
        self.canvas.draw_toolpath(self.commands[0:int(self.slider.get())])

    def ToggleScale(self):
        self.panButton.config(relief=RAISED)
        self.rotateButton.config(relief=RAISED)
        self.mirrorButton.config(relief=RAISED)
        if self.isJobRunning:
            return
        if self.scaleButton.config('relief')[-1] == SUNKEN:
            self.scaleButton.config(relief=RAISED)
        else:
            self.scaleButton.config(relief=SUNKEN)

    def GoTo(self):
        if self.isJobRunning:
            return
        if self.gotoButton.config('relief')[-1] == SUNKEN:
            self.gotoButton.config(relief=RAISED)
        else:
            self.gotoButton.config(relief=SUNKEN)

    def StopAll(self):
        serial.queue.clear()
        self.JobFinished(False)
        self.status.config(text="Job stopped on user demand")

    def JobFinished(self, messagePopup=True):
        self.isJobRunning = False
        self.isJobPaused = False
        self.lastSendCommandIndex = -1
        self.lastMove = None
        self.distanceTraveled = 0
        self.currentToolChange = 0
        self.currentToolPoint = 0
        self.currentColor = 'black'
        self.toolPointsLabel.config(
            text="%d/%d" % (self.currentToolPoint, self.toolPointsTotal))
        self.toolChangesLabel.config(
            text="%d/%d" % (self.currentToolChange, self.toolChangesTotal))
        self.UpdateTimeEstLabel()
        self.startButton.config(text="Start job")
        self.status.config(text="Job finished")
        timeTaken = time.time() - self.start
        # non blocking popup messagebox
        if messagePopup:
            tl = Toplevel(root)
            # this pop-up is always on top and other windows are deactivated
            tl.attributes('-topmost', 'true')
            tl.title("Job finished")
            tl.grab_set()
            frame = Frame(tl)
            frame.grid()
            Label(frame,
                  text='Current job is finished and took %s.' %
                  time.strftime("%H hours, %M minutes, %S seconds",
                                time.gmtime(timeTaken))).grid(row=0,
                                                              column=0,
                                                              sticky=N)
            Button(frame, text="OK", command=lambda: tl.destroy(),
                   width=10).grid(row=1, column=0)

    def CanvasClick(self, event):
        if self.isJobRunning:
            return
        self.dragStart = [event.x, event.y]
        #self.transform = math.atan2(event.x, event.y)
        self.transform = 0
        # go to
        if self.gotoButton.config('relief')[-1] == SUNKEN:
            point = self.canvas.canvas_point_to_machine(self.dragStart)
            serial.queue_command("G0 X%f Y%f\n" % point)
        #print("Clicked at: ", self.dragStart)
    def CanvasRelease(self, event):
        if self.isJobRunning:
            return

        print("Applied transform", self.transform)

    def CanvasDrag(self, event):
        if self.isJobRunning:
            return
        vect = (self.dragStart[0] - event.x, self.dragStart[1] - event.y)
        # move event
        if self.panButton.config('relief')[-1] == SUNKEN:
            self.transform = self.canvas.canvas_vector_to_machine(vect)
            self.commands = translate_toolpath(self.commands, self.transform)
            self.canvas.draw_toolpath(self.commands[0:int(self.slider.get())])
            self.dragStart[0] = event.x
            self.dragStart[1] = event.y
        # rotate event
        if self.rotateButton.config('relief')[-1] == SUNKEN:
            angle = math.atan2(vect[0],
                               vect[1])  # atan2(y, x) or atan2(sin, cos)
            self.commands = rotate_toolpath(
                self.commands,
                (self.workAreaSize[0] / 2 + self.workAreaOrigin[0],
                 self.workAreaSize[1] / 2 + self.workAreaOrigin[1]),
                -(self.transform - angle))
            self.canvas.draw_toolpath(self.commands[0:int(self.slider.get())])
            self.transform = angle
        # scale event
        if self.scaleButton.config('relief')[-1] == SUNKEN:
            factor = math.sqrt((vect[0])**2 + (vect[1])**2) / 500
            f = factor - self.transform
            if vect[0] < 0:
                f = -f
            self.commands = scale_toolpath(self.commands, f)
            self.canvas.draw_toolpath(self.commands[0:int(self.slider.get())])
            self.transform = factor

    def UpdatePath(self, val):
        if self.isJobRunning:
            return
        self.canvas.draw_toolpath(self.commands[0:int(val)])

    def UpdateTimeEstLabel(self):
        # avg milimeters per second factor
        factor = 11.0
        time_to_toolchange = (self.distancesList[self.currentToolChange] -
                              self.distanceTraveled) / factor
        time_total = (self.distancesList[-1] - self.distanceTraveled) / factor
        self.timeLabel.config(text="%d m %d s/%d m %d s" %
                              (time_to_toolchange / 60, time_to_toolchange %
                               60, time_total / 60, time_total % 60))

    def GetPositionTimerTaks(self):
        if self.isConnected:

            def TimerCallback(response):
                response = self.positionResponseRegex.search(response)
                if response:
                    pos = (float(response.group(1)), float(response.group(2)))
                    self.canvas.move_pointer(pos)

            serial.queue_command("M114\n", TimerCallback, priority=-1)
            self.master.after(2000, self.GetPositionTimerTaks)

    def CleanUp(self):
        serial.close_serial()

    def PausePopup(self, newColor="black", trim=False):
        tl = Toplevel(root)
        tl.attributes('-topmost', 'true')
        tl.grab_set()

        tl.title("Tool change")
        msg = "change the tool for a next color"
        if trim:
            tl.title("Thread trim")
            msg = "cut the thread"

        frame = Frame(tl)
        frame.grid()

        canvas = Canvas(frame, width=64, height=64)
        canvas.grid(row=2, column=0)
        canvas.create_rectangle(0, 0, 65, 65, fill=newColor)
        msgbody = Label(
            frame,
            text=
            "There is the moment to %s. Resume the current job after change." %
            msg)
        msgbody.grid(row=1, column=0, sticky=N)

        okbttn = Button(frame,
                        text="OK",
                        command=lambda: tl.destroy(),
                        width=10)
        okbttn.grid(row=2, column=2)
Exemple #10
0
class ParametersWindow(Frame):
    def __init__(self, master=None, name=None, param_dict=None):
        Frame.__init__(self, master=master, name=name)
        self._master = master
        self._param_dict = param_dict
        self._name = name

        # Variable for keeping track regarding whether the body() was called before or not
        self._body_pack_checker = False

        self.misc_dir_path = "../bin/misc"
        self.config_file_path = self.misc_dir_path + "/sampling_config.yml"

        self.win_width = 1500
        self.win_height = 750
        self.sampling_width = 450
        self.padding_x = 160
        self.separator_pad = 50
        self.param_width = self.win_width - self.sampling_width - self.separator_pad
        self.x_offset = int((self.winfo_screenwidth() - self.win_width) / 2)
        self.y_offset = int(
            (self.winfo_screenheight() - self.win_height - 50) / 2)
        self._geometry = "{:d}x{:d}+{:d}+{:d}".format(self.win_width,
                                                      self.win_height,
                                                      self.x_offset,
                                                      self.y_offset)

        self.frame_width = self.param_width - self.padding_x
        self.frame_height = self.win_height / 13

        self.config(width=self.win_width - self.padding_x,
                    height=self.win_height - self.frame_height)
        self.pack_propagate(False)

        # For establishing which sample image will be affected by a parameter there will be three states as follows:
        # which = -1    - for parameters that affect only minimum
        # which = 0     - for parameters that affect both
        # which = 1     - for parameters that affect only maximum
        self.sampling_dict = {
            'Template path': '',
            'Output path': self.misc_dir_path,
            'Which': 0,
            'Counter': 0
        }

        # Configuring sampling frame
        self.apply_filters = ApplyFiltersFrame(master=self,
                                               width=self.sampling_width,
                                               height=self.win_height)

        # Configuring title frame
        self.title_font = ('Segoe UI', 12)
        self.title_frame = Frame(self,
                                 width=self.frame_width,
                                 height=self.frame_height)
        self.title = "Parameters"

        self.W_geometry = {'orient': 'horizontal', 'length': 200}

        # Configuring main frame
        self.param_set_frame = Frame(self,
                                     name='param_set',
                                     width=self.frame_width,
                                     height=self.frame_height * 11)
        self.param_set_frame.pack_propagate(False)

        # Configuring radial distortion and halo frame
        self.distortion_n_halo_frame = Frame(self.param_set_frame,
                                             width=self.frame_width,
                                             height=self.frame_height)
        self.distortion_n_halo_frame.pack_propagate(False)
        self.radial_distortion_scale = Scale(
            self.distortion_n_halo_frame,
            self.W_geometry,
            name='dist',
            from_=0,
            to=0.0001,
            resolution=0.00001,
            command=lambda x: self.both_callback())
        self.distortion_center_x = 0
        self.distortion_center_y = 0
        self.halo_scale = Scale(self.distortion_n_halo_frame,
                                self.W_geometry,
                                name='halo',
                                from_=0,
                                to=15,
                                resolution=1,
                                command=lambda x: self.both_callback())

        # Configuring vertical perspective frame
        self.V_perspective_frame = Frame(self.param_set_frame,
                                         name='frame v_persp',
                                         width=self.frame_width,
                                         height=self.frame_height)
        self.V_perspective_frame.pack_propagate(False)
        self.min_V_perspective_scale = Scale(
            self.V_perspective_frame,
            self.W_geometry,
            name='min v_persp',
            from_=-0.5,
            to=0.5,
            resolution=0.1,
            command=lambda value: self.min_callback(value, 'min v_persp'))
        self.max_V_perspective_scale = Scale(
            self.V_perspective_frame,
            self.W_geometry,
            name='max v_persp',
            from_=-0.5,
            to=0.5,
            resolution=0.1,
            command=lambda value: self.max_callback(value, 'max v_persp'))

        # Configuring horizontal perspective frame
        self.H_perspective_frame = Frame(self.param_set_frame,
                                         name='frame h_persp',
                                         width=self.frame_width,
                                         height=self.frame_height)
        self.H_perspective_frame.pack_propagate(False)
        self.min_H_perspective_scale = Scale(
            self.H_perspective_frame,
            self.W_geometry,
            name='min h_persp',
            from_=-0.5,
            to=0.5,
            resolution=0.1,
            command=lambda value: self.min_callback(value, 'min h_persp'))
        self.max_H_perspective_scale = Scale(
            self.H_perspective_frame,
            self.W_geometry,
            name='max h_persp',
            from_=-0.5,
            to=0.5,
            resolution=0.1,
            command=lambda value: self.max_callback(value, 'max h_persp'))

        # Configuring brightness frame
        self.brightness_frame = Frame(self.param_set_frame,
                                      name='frame bright',
                                      width=self.frame_width,
                                      height=self.frame_height)
        self.brightness_frame.pack_propagate(False)
        self.min_brightness_scale = Scale(
            self.brightness_frame,
            self.W_geometry,
            name='min bright',
            from_=0,
            to=60,
            resolution=1,
            command=lambda value: self.min_callback(value, 'min bright'))
        self.max_brightness_scale = Scale(
            self.brightness_frame,
            self.W_geometry,
            name='max bright',
            from_=0,
            to=60,
            resolution=1,
            command=lambda value: self.max_callback(value, 'max bright'))

        # Configuring noise frame
        self.noise_frame = Frame(self.param_set_frame,
                                 name='frame noise',
                                 width=self.frame_width,
                                 height=self.frame_height)
        self.noise_frame.pack_propagate(False)
        self.min_noise_scale = Scale(
            self.noise_frame,
            self.W_geometry,
            name='min noise',
            from_=0,
            to=20,
            resolution=1,
            command=lambda value: self.min_callback(value, 'min noise'))
        self.max_noise_scale = Scale(
            self.noise_frame,
            self.W_geometry,
            name='max noise',
            from_=0,
            to=20,
            resolution=1,
            command=lambda value: self.max_callback(value, 'max noise'))

        # Configuring blur frame
        self.blur_frame = Frame(self.param_set_frame,
                                name='frame blur',
                                width=self.frame_width,
                                height=self.frame_height)
        self.blur_frame.pack_propagate(False)
        self.min_blur_scale = Scale(
            self.blur_frame,
            self.W_geometry,
            name='min blur',
            from_=0,
            to=20,
            resolution=1,
            command=lambda value: self.min_callback(value, 'min blur'))
        self.max_blur_scale = Scale(
            self.blur_frame,
            self.W_geometry,
            name='max blur',
            from_=0,
            to=20,
            resolution=1,
            command=lambda value: self.max_callback(value, 'max blur'))

        # Configuring aberration frame
        self.aberration_frame = Frame(self.param_set_frame,
                                      width=self.frame_width,
                                      height=self.frame_height)
        self.aberration_frame.pack_propagate(False)
        self.V_aberration_scale = Scale(self.aberration_frame,
                                        self.W_geometry,
                                        name='v_aberration',
                                        from_=0,
                                        to=10,
                                        resolution=1,
                                        command=lambda x: self.both_callback())
        self.H_aberration_scale = Scale(self.aberration_frame,
                                        self.W_geometry,
                                        name='h_aberration',
                                        from_=0,
                                        to=10,
                                        resolution=1,
                                        command=lambda x: self.both_callback())

        # Configuring resize frame
        self.resize_frame = Frame(self.param_set_frame,
                                  name='frame resize',
                                  width=self.frame_width,
                                  height=self.frame_height)
        self.resize_frame.pack_propagate(False)
        self.min_resize_scale = Scale(
            self.resize_frame,
            self.W_geometry,
            name='min resize',
            from_=0,
            to=150,
            resolution=1,
            command=lambda value: self.min_callback(value, 'min resize'))
        self.max_resize_scale = Scale(
            self.resize_frame,
            self.W_geometry,
            name='max resize',
            from_=0,
            to=500,
            resolution=1,
            command=lambda value: self.max_callback(value, 'max resize'))

        # Configuring background enlargement frame
        self.enlarge_bg_frame = Frame(self.param_set_frame,
                                      width=self.frame_width,
                                      height=self.frame_height)
        self.enlarge_bg_frame.pack_propagate(False)
        self.V_max_enlargement_scale = Scale(
            self.enlarge_bg_frame,
            self.W_geometry,
            name='v_bg',
            from_=0,
            to=50,
            resolution=1,
            command=lambda x: self.calc_nr_of_samples_generated())
        self.H_max_enlargement_scale = Scale(
            self.enlarge_bg_frame,
            self.W_geometry,
            name='h_bg',
            from_=0,
            to=50,
            resolution=1,
            command=lambda x: self.calc_nr_of_samples_generated())

        # Configuring notes frame
        self.notes_frame = Frame(self.param_set_frame,
                                 width=self.frame_width,
                                 height=self.frame_height)
        self.notes_frame.pack_propagate(False)
        self.notes = "Note: Parameters that are set to 0 (at both minimum and maximum, where applicable) will not be " \
                     "applied."

        # Configuring buttons frame (SET DEFAULT, RESET and samples scale)
        self.buttons_frame = Frame(self.param_set_frame,
                                   width=self.frame_width,
                                   height=self.frame_height)
        self.buttons_frame.pack_propagate(False)
        self.generated_samples = 0
        self.nr_of_samples_scale = Scale(self.buttons_frame, self.W_geometry)
        self.reset_button = Button(self.buttons_frame,
                                   text="Reset",
                                   width=10,
                                   command=self.reset_callback)
        self.default_button = Button(self.buttons_frame,
                                     text="Set default",
                                     width=15,
                                     command=self.default_callback)

    # Function sets geometry of master
    def set_geometry(self):
        self._master.geometry(self._geometry)

    # Function sets the body of the window
    def body(self):
        template_path = glob.glob(self._param_dict["Path to templates"] +
                                  '/*.png')[0].replace('\\', '/')
        self.sampling_dict["Template path"] = template_path

        # Setting title of the frame
        Label(self.title_frame, text=self.title,
              font=self.title_font).pack(side=TOP, anchor=CENTER)
        self.title_frame.pack(side=TOP, pady=10)

        # Setting sampling frame
        self.apply_filters.body_pack(
            side=LEFT, image_path=self.sampling_dict['Template path'])

        Separator(self, orient=VERTICAL).pack(side=LEFT,
                                              fill=Y,
                                              padx=self.separator_pad / 2)

        # Setting radial distortion and halo frame
        Label(self.distortion_n_halo_frame,
              text="Radial distortion:",
              width=13,
              anchor=W).pack(side=LEFT, anchor=S)
        self.radial_distortion_scale.pack(side=LEFT, anchor=S)
        self.halo_scale.pack(side=RIGHT, anchor=S)
        Label(self.distortion_n_halo_frame, text="Halo:", width=5,
              anchor=W).pack(side=RIGHT, anchor=S)
        self.distortion_n_halo_frame.pack(side=TOP)

        # Setting vertical perspective frame
        Label(self.V_perspective_frame,
              text="Vertical perspective:",
              width=30,
              anchor=W).pack(side=LEFT, anchor=S)
        Label(self.V_perspective_frame, text="Minimum:", width=10,
              anchor=W).pack(side=LEFT, anchor=S)
        self.min_V_perspective_scale.pack(side=LEFT, anchor=S)
        self.max_V_perspective_scale.pack(side=RIGHT, anchor=S)
        Label(self.V_perspective_frame, text="Maximum:", width=10,
              anchor=W).pack(side=RIGHT, anchor=S)
        self.V_perspective_frame.pack(side=TOP)

        # Setting horizontal perspective frame
        Label(self.H_perspective_frame,
              text="Horizontal perspective:",
              width=30,
              anchor=W).pack(side=LEFT, anchor=S)
        Label(self.H_perspective_frame, text="Minimum:", width=10,
              anchor=W).pack(side=LEFT, anchor=S)
        self.min_H_perspective_scale.pack(side=LEFT, anchor=S)
        self.max_H_perspective_scale.pack(side=RIGHT, anchor=S)
        Label(self.H_perspective_frame, text="Maximum:", width=10,
              anchor=W).pack(side=RIGHT, anchor=S)
        self.H_perspective_frame.pack(side=TOP)

        # Setting brightness frame
        Label(self.brightness_frame, text="Brightness:", width=30,
              anchor=W).pack(side=LEFT, anchor=S)
        Label(self.brightness_frame, text="Minimum:", width=10,
              anchor=W).pack(side=LEFT, anchor=S)
        self.min_brightness_scale.pack(side=LEFT, anchor=S)
        self.max_brightness_scale.pack(side=RIGHT, anchor=S)
        Label(self.brightness_frame, text="Maximum:", width=10,
              anchor=W).pack(side=RIGHT, anchor=S)
        self.brightness_frame.pack(side=TOP)

        # Setting noise frame
        Label(self.noise_frame, text="Noise:", width=30,
              anchor=W).pack(side=LEFT, anchor=S)
        Label(self.noise_frame, text="Minimum:", width=10,
              anchor=W).pack(side=LEFT, anchor=S)
        self.min_noise_scale.pack(side=LEFT, anchor=S)
        self.max_noise_scale.pack(side=RIGHT, anchor=S)
        Label(self.noise_frame, text="Maximum:", width=10,
              anchor=W).pack(side=RIGHT, anchor=S)
        self.noise_frame.pack(side=TOP)

        # setting blur frame
        Label(self.blur_frame, text="Blur:", width=30,
              anchor=W).pack(side=LEFT, anchor=S)
        Label(self.blur_frame, text="Minimum:", width=10,
              anchor=W).pack(side=LEFT, anchor=S)
        self.min_blur_scale.pack(side=LEFT, anchor=S)
        self.max_blur_scale.pack(side=RIGHT, anchor=S)
        Label(self.blur_frame, text="Maximum:", width=10,
              anchor=W).pack(side=RIGHT, anchor=S)
        self.blur_frame.pack(side=TOP)

        # Setting aberration frame
        Label(self.aberration_frame, text="Aberration:", width=30,
              anchor=W).pack(side=LEFT, anchor=S)
        Label(self.aberration_frame, text="Vertical:", width=10,
              anchor=W).pack(side=LEFT, anchor=S)
        self.V_aberration_scale.pack(side=LEFT, anchor=S)
        self.H_aberration_scale.pack(side=RIGHT, anchor=S)
        Label(self.aberration_frame, text="Horizontal:", width=10,
              anchor=W).pack(side=RIGHT, anchor=S)
        self.aberration_frame.pack(side=TOP)

        # Setting resize frame
        Label(self.resize_frame, text="Resize:", width=30,
              anchor=W).pack(side=LEFT, anchor=S)
        Label(self.resize_frame, text="Minimum:", width=10,
              anchor=W).pack(side=LEFT, anchor=S)
        self.min_resize_scale.pack(side=LEFT, anchor=S)
        self.max_resize_scale.pack(side=RIGHT, anchor=S)
        Label(self.resize_frame, text="Maximum", width=10,
              anchor=W).pack(side=RIGHT, anchor=S)
        self.resize_frame.pack(side=TOP)

        # Setting background enlargement frame
        Label(self.enlarge_bg_frame,
              text="Maximum background enlargement:",
              width=30,
              anchor=W).pack(side=LEFT, anchor=S)
        Label(self.enlarge_bg_frame, text="Vertical:", width=10,
              anchor=W).pack(side=LEFT, anchor=S)
        self.V_max_enlargement_scale.pack(side=LEFT, anchor=S)
        self.H_max_enlargement_scale.pack(side=RIGHT, anchor=S)
        Label(self.enlarge_bg_frame, text="Horizontal:", width=10,
              anchor=W).pack(side=RIGHT, anchor=S)
        self.enlarge_bg_frame.pack(side=TOP)

        # Setting notes frame
        Label(self.notes_frame, text=self.notes, fg='gray').pack(side=BOTTOM,
                                                                 anchor=W)
        self.notes_frame.pack(side=TOP)

        # Setting SET DEFAULT, RESET and samples scale buttons frame
        self.default_button.pack(side=LEFT, anchor=S)
        self.reset_button.pack(side=LEFT, anchor=S, padx=35)
        self.calc_nr_of_samples_generated()
        self.nr_of_samples_scale.pack(side=RIGHT, anchor=S)
        Label(self.buttons_frame,
              text="Samples generated per class:",
              anchor=W).pack(side=RIGHT, anchor=S)
        self.buttons_frame.pack(side=TOP)

        self.param_set_frame.pack(side=LEFT, fill=Y)

        self._body_pack_checker = True

    # Function verifies if body() was called before and packs up the frame
    def body_pack(self):
        self.set_geometry()

        if self._body_pack_checker is False:
            self.body()

        self.pack(side=TOP)

    # Callback function for the RESET button, setting all scales to 0(zero)
    def reset_callback(self):
        self.min_resize_scale.set(0)
        self.max_resize_scale.set(0)
        self.min_V_perspective_scale.set(0)
        self.max_V_perspective_scale.set(0)
        self.min_H_perspective_scale.set(0)
        self.max_H_perspective_scale.set(0)
        self.min_brightness_scale.set(0)
        self.max_brightness_scale.set(0)
        self.min_noise_scale.set(0)
        self.max_noise_scale.set(0)
        self.min_blur_scale.set(0)
        self.max_blur_scale.set(0)
        self.V_aberration_scale.set(0)
        self.H_aberration_scale.set(0)
        self.V_max_enlargement_scale.set(0)
        self.H_max_enlargement_scale.set(0)
        self.radial_distortion_scale.set(0.0)
        self.halo_scale.set(0)

    # Callback function for the SET DEFAULT button, setting all scales to values defined in default configuration file
    def default_callback(self):
        if self._param_dict:
            self.min_resize_scale.set(self._param_dict["Min resize"])
            self.max_resize_scale.set(self._param_dict["Max resize"])
            self.min_V_perspective_scale.set(
                self._param_dict["Min V perspective"])
            self.max_V_perspective_scale.set(
                self._param_dict["Max V perspective"])
            self.min_H_perspective_scale.set(
                self._param_dict["Min H perspective"])
            self.max_H_perspective_scale.set(
                self._param_dict["Max H perspective"])
            self.min_brightness_scale.set(self._param_dict["Min light"])
            self.max_brightness_scale.set(self._param_dict["Max light"])
            self.min_noise_scale.set(self._param_dict["Min noise value"])
            self.max_noise_scale.set(self._param_dict["Max noise value"])
            self.min_blur_scale.set(self._param_dict["Min blur amplitude"])
            self.max_blur_scale.set(self._param_dict["Max blur amplitude"])
            self.V_aberration_scale.set(
                self._param_dict["Vertical max aberration"])
            self.H_aberration_scale.set(
                self._param_dict["Horizontal max aberration"])
            self.radial_distortion_scale.set(
                self._param_dict["Radial distortion"])
            self.halo_scale.set(self._param_dict["Halo amount"])
            self.V_max_enlargement_scale.set(
                self._param_dict["Max enlarge background vertical"])
            self.H_max_enlargement_scale.set(
                self._param_dict["Max enlarge background horizontal"])

    # Function returns the distortion center used for the fish eye effect. Based on dims of template images
    def calc_distortion_center(self):
        # List containing template images
        images_path_list = glob.glob(self._param_dict["Path to templates"] +
                                     '/*.png')

        # Lists to collect dims of the images
        widths = []
        heights = []
        for image_path in images_path_list:
            image = Image.open(image_path)
            widths.append(image.size[0])
            heights.append(image.size[1])

        x_center_distortion = random.randint(1, min(widths))
        y_center_distortion = random.randint(1, min(heights))
        return x_center_distortion, y_center_distortion

    # Callback function for parameters that apply only to minimum sampling images
    def min_callback(self, value=None, name=None):
        self.correlate_buttons_by_min(value=value, name=name)
        self.sampling_dict['Which'] = -1
        self.write_sampling_configuration()
        self.apply_filters.sampling_filters(self.config_file_path)
        self.calc_nr_of_samples_generated()

    # Function correlates a max button to a min value when min is higher than max
    def correlate_buttons_by_min(self, value=None, name=None):
        max_button_name = name.replace('min', 'max')
        frame_name = name.replace('min', 'frame')
        path_to_button = '.' + self.winfo_name(
        ) + '.param_set.' + frame_name + '.' + max_button_name

        if value.find('.'):
            value = float(value)
        else:
            value = int(value)

        if value > self.nametowidget(path_to_button).get():
            self.nametowidget(path_to_button).set(value)

    # Callback function for parameters that apply only to maximum images
    def max_callback(self, value=None, name=None):
        self.correlate_buttons_by_max(value=value, name=name)
        self.sampling_dict['Which'] = 1
        self.write_sampling_configuration()
        self.apply_filters.sampling_filters(self.config_file_path)
        self.calc_nr_of_samples_generated()

    # Function correlates a min button to a max value when max is lower than min
    def correlate_buttons_by_max(self, value=None, name=None):
        max_button_name = name.replace('max', 'min')
        frame_name = name.replace('max', 'frame')
        path_to_button = '.' + self.winfo_name(
        ) + '.param_set.' + frame_name + '.' + max_button_name

        if value.find('.'):
            value = float(value)
        else:
            value = int(value)

        if value < self.nametowidget(path_to_button).get():
            self.nametowidget(path_to_button).set(value)

    # Callback function for parameters that apply to both sampling images
    def both_callback(self):
        self.sampling_dict['Which'] = 0
        self.write_sampling_configuration()
        self.apply_filters.sampling_filters(self.config_file_path)
        self.calc_nr_of_samples_generated()

    # Function overwrites the sampling configuration file
    def write_sampling_configuration(self):
        import os

        if not os.path.exists(self.misc_dir_path):
            os.makedirs(self.misc_dir_path)

        yaml_file = open(self.config_file_path, 'w')

        yaml_file.write("%YAML 1.0\n")
        yaml_file.write("---")

        yaml_file.write("\nPaths:\n")
        yaml_file.write("    Template path: \"{:}\"\n".format(
            self.sampling_dict["Template path"]))
        yaml_file.write("    Output path: \"{:}\"\n".format(
            self.sampling_dict["Output path"]))

        yaml_file.write("\nWhich: {:}\n".format(self.sampling_dict["Which"]))
        self.sampling_dict["Counter"] = self.sampling_dict["Counter"] + 1
        yaml_file.write("\nCounter: {:}\n".format(
            self.sampling_dict["Counter"]))

        yaml_file.write("\nMinimum:\n")
        yaml_file.write("    Resize: {:}\n".format(
            self.min_resize_scale.get()))
        yaml_file.write("    V perspective: {:}\n".format(
            self.min_V_perspective_scale.get()))
        yaml_file.write("    H perspective: {:}\n".format(
            self.min_H_perspective_scale.get()))
        yaml_file.write("    Brightness: {:}\n".format(
            self.min_brightness_scale.get()))
        yaml_file.write("    Noise: {:}\n".format(self.min_noise_scale.get()))
        yaml_file.write("    Blur: {:}\n".format(self.min_blur_scale.get()))

        yaml_file.write("\nMaximum:\n")
        yaml_file.write("    Resize: {:}\n".format(
            self.max_resize_scale.get()))
        yaml_file.write("    V perspective: {:}\n".format(
            self.max_V_perspective_scale.get()))
        yaml_file.write("    H perspective: {:}\n".format(
            self.max_H_perspective_scale.get()))
        yaml_file.write("    Brightness: {:}\n".format(
            self.max_brightness_scale.get()))
        yaml_file.write("    Noise: {:}\n".format(self.max_noise_scale.get()))
        yaml_file.write("    Blur: {:}\n".format(self.max_blur_scale.get()))

        if self.radial_distortion_scale.get() is not 0:
            if self.distortion_center_y is 0 and self.distortion_center_y is 0:
                self.distortion_center_x, self.distortion_center_y = self.calc_distortion_center(
                )
        else:
            self.distortion_center_x = 0
            self.distortion_center_y = 0
        yaml_file.write("\nOther:\n")
        yaml_file.write("    V aberration: {:}\n".format(
            self.V_aberration_scale.get()))
        yaml_file.write("    H aberration: {:}\n".format(
            self.H_aberration_scale.get()))
        yaml_file.write("    Radial distortion: {:}\n".format(
            self.radial_distortion_scale.get()))
        yaml_file.write("    X center distortion: {:}\n".format(
            self.distortion_center_x))
        yaml_file.write("    Y center distortion: {:}\n".format(
            self.distortion_center_y))
        yaml_file.write("    Halo: {:}\n".format(self.halo_scale.get()))

        yaml_file.close()

    # Function calculates the number of samples that will be generated
    def calc_nr_of_samples_generated(self):
        if self.min_H_perspective_scale.get(
        ) == 0.0 and self.max_H_perspective_scale.get() == 0.0:
            h_perspective_cycles = 1
        else:
            h_perspective_cycles = NUMBER_OF_PERSPECTIVES

        if self.min_V_perspective_scale.get(
        ) == 0.0 and self.max_V_perspective_scale.get() == 0.0:
            v_perspective_cycles = 1
        else:
            v_perspective_cycles = NUMBER_OF_PERSPECTIVES

        if self.min_blur_scale.get() == 0 and self.max_blur_scale.get() == 0:
            blur_cycles = 1
        else:
            blur_cycles = self.max_blur_scale.get() - self.min_blur_scale.get(
            ) + 1

        self.generated_samples = NUMBER_OF_ILLUMINATIONS * h_perspective_cycles * v_perspective_cycles * blur_cycles

        if self.generated_samples < 0:
            self.nr_of_samples_scale.config(label='N/A', from_=0, to=0)

        else:
            self.nr_of_samples_scale.config(from_=self.generated_samples,
                                            to=(self.generated_samples * 5),
                                            label='',
                                            resolution=self.generated_samples)
            self.nr_of_samples_scale.set(self.generated_samples)

    # Functions passes configuration into parameter _dict
    def get_parameters(self, _dict):
        _dict["Min resize"] = self.min_resize_scale.get()
        _dict["Max resize"] = self.max_resize_scale.get()
        _dict["Min H perspective"] = self.min_H_perspective_scale.get()
        _dict["Max H perspective"] = self.max_H_perspective_scale.get()
        _dict["Min V perspective"] = self.min_V_perspective_scale.get()
        _dict["Max V perspective"] = self.max_V_perspective_scale.get()
        _dict["Min light"] = self.min_brightness_scale.get()
        _dict["Max light"] = self.max_brightness_scale.get()
        _dict["Min noise value"] = self.min_noise_scale.get()
        _dict["Max noise value"] = self.max_noise_scale.get()
        _dict["Min blur amplitude"] = self.min_blur_scale.get()
        _dict["Max blur amplitude"] = self.max_blur_scale.get()
        _dict["Vertical max aberration"] = self.V_aberration_scale.get()
        _dict["Horizontal max aberration"] = self.H_aberration_scale.get()
        _dict["Radial distortion"] = self.radial_distortion_scale.get()
        if _dict["Radial distortion"] == 0:
            _dict["X center distortion"] = 0
            _dict["Y center distortion"] = 0
        else:
            _dict["X center distortion"], _dict[
                "Y center distortion"] = self.calc_distortion_center()
        _dict["Halo amount"] = self.halo_scale.get()
        _dict[
            "Max enlarge background vertical"] = self.V_max_enlargement_scale.get(
            )
        _dict[
            "Max enlarge background horizontal"] = self.H_max_enlargement_scale.get(
            )
        _dict["Number of samples per class"] = self.generated_samples
        _dict["Number of generations"] = self.nr_of_samples_scale.get(
        ) / self.generated_samples

    # Function calls Apply_filters_frame 'delete_misc_content' function, passing its on files to delete
    def delete_misc(self):
        self.apply_filters.delete_misc_content(
            other_files=self.config_file_path)
Exemple #11
0
class Main(Frame):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.root = self.winfo_toplevel()
        self.root.option_add("*Font", "serif 10 bold")
        self.root.title(" ".join((APPNAME, VERSION, "| Main")))
        self.root.resizable(0,0)
        self.root.bind('<Key>', self.__keys) 

        # Menu
        menubar = Menu(self.root)
        self.windowsmenu = Menu(menubar, tearoff=0)
        self.windowsmenu.add_command(label="[ ] Report window", command=self.__toggle_report)
        self.windowsmenu.add_command(label="Plot current model", command=self.__plot)
        self.windowsmenu.add_separator()
        self.windowsmenu.add_command(label="Quit", command=self.destroy)
        menubar.add_cascade(label="Windows", menu=self.windowsmenu)
        settingsmenu = Menu(menubar, tearoff=0)
        settingsmenu.add_command(label="Spectrum range")
        settingsmenu.add_command(label="Color scheme")
        menubar.add_cascade(label="Settings", menu=settingsmenu)
        helpmenu = Menu(menubar, tearoff=0)
        helpmenu.add_command(label="Help", command=self.__help)
        helpmenu.add_separator()
        helpmenu.add_command(label="About", command=self.__about)
        menubar.add_cascade(label="Help", menu=helpmenu)
        self.root.config(menu=menubar)
        # disabled menu items
        settingsmenu.entryconfig(0, state='disabled')
        settingsmenu.entryconfig(1, state='disabled')
        helpmenu.entryconfig(0, state='disabled')

        # Scale
        ctrls = Labelframe(self, text='Control', relief='ridge')
        self.e = Scale(ctrls, from_=E_MIN, to=E_MAX, label='Links',
                bd=1, width=7, length=150, orient='horizontal')
        self.d = Scale(ctrls, from_=D_MIN, to=D_MAX, label='Pages',
                bd=1, width=7, length=150, orient='horizontal')
        self.e.set(E)
        self.d.set(D)
        self.e.config(command=self.__refresh)
        self.d.config(command=self.__refresh)
        self.e.pack(side='left')
        self.d.pack(side='right')
        self.r_win = False
        ctrls.pack(side='top', anchor='e', padx=7, pady=5)

        # initialize model
        self.generate_model()
        self.c = GraphViewer(self, D, self.edge_counts, self.pagerank)
        self.c.pack()

        # open windows
        self.__toggle_report()

    def generate_model(self):
        edges, self.edge_counts = randEdges(self.d.get(), self.e.get())
        self.pagerank = pagerank(edges)

    def render(self):
        self.generate_model()
        self.c.render(self.d.get(), self.edge_counts, self.pagerank)
        try: self.r.render(self.pagerank, self.edge_counts, self.d.get(), self.e.get())
        except: pass

    def __refresh(self, value=None):
        self.generate_model()
        self.render()

    def __toggle_report(self):
        if self.r_win:
            try: self.r.destroy()
            except: pass
            self.r_win = False
            self.windowsmenu.entryconfig(0, label='[ ] Report window')
            return 
        self.r = Report(Toplevel(self))
        self.r.pack()
        self.r.render(self.pagerank, self.edge_counts, self.d.get(), self.e.get())
        self.r_win = True
        self.windowsmenu.entryconfig(0, label='[•] Report window ')

    def __plot(self):
        try: self.plot_root.destroy()
        except: pass
        self.plot_root = Toplevel(self)
        self.plot_root.title(" ".join((APPNAME, VERSION, "| Plot")))
        self.plot_root.resizable(0,0)
        draw_figure(self.plot_root, self.pagerank)
        self.root.after(1, lambda : self.root.focus_force())

    def __keys(self, event):
        if event.char == 'q':
            self.destroy()

        elif event.char == 'r':
            self.__toggle_report()
        elif event.char == 'p':
            self.__plot()
        elif event.char == 'x':
            try: self.plot_root.destroy()
            except: pass

        elif event.char == 'n':
            self.__refresh()

        elif event.char == 'j':
            self.d.set(self.d.get()-1)
        elif event.char == 'J':
            self.d.set(self.d.get()-5)
        elif event.char == 'k':
            self.d.set(self.d.get()+1)
        elif event.char == 'K':
            self.d.set(self.d.get()+5)

        elif event.char == 'h':
            self.e.set(self.e.get()-1)
        elif event.char == 'H':
            self.e.set(self.e.get()-40)
        elif event.char == 'l':
            self.e.set(self.e.get()+1)
        elif event.char == 'L':
            self.e.set(self.e.get()+40)
    
    def __help(self):
        pass
    
    def __about(self):
        try: self.a.destroy()
        except: pass
        about_text = "{} {}\n\nUW MATH308(Linear Algebra) Winter 2018".format(APPNAME, VERSION)
        self.a = Toplevel(self)
        self.a.title(" ".join((APPNAME, VERSION, "| About")))
        f = Frame(self.a)
        l = Label(f, text=about_text)
        b = Button(f, text='Close', command=self.a.destroy)
        l.pack(padx=5)
        b.pack(pady=10)
        f.pack(padx=50, pady=20)
            
    def destroy(self):
        super().destroy()
        self.root.destroy()
        exit(1)
Exemple #12
0
class UI(tk.Tk):
    def __init__(self):
        super().__init__()

        __width_label_lc = 16

        self.result_type_dict = [('mass', 'mass'),
                                 ('mass density', 'mass_density'),
                                 ('stiffness', 'stf'),
                                 ('shear capacity', 's_c'), ('drift', 'drift')]

        self.result_type_dict_right = [('displacement ratio', 'dsp_r'),
                                       ('drift ratio', 'dft_r'),
                                       ('spectrum of time history curve',
                                        'thc'),
                                       ('base shear of time history', 'sth'),
                                       ('drift of time history', 'dth')]

        self.result_type_dict_added = [('period', 'period'),
                                       ('seismic shear coefficient', 's_s_c'),
                                       ('seismic shear adjust factor', 's_a_f')
                                       ]

        # variables of app
        self.file_path = FilePath()
        self.yjk_dir = tk.StringVar()
        self.etabs_name = tk.StringVar()
        self.result_type = tk.StringVar()
        self.result_type.set('drift')
        self.cur_tower_number = tk.StringVar()
        self.cur_merge_df = None
        self.tower_number = None
        self.position = None
        self.cur_result_type = None
        self.font = dict(family='KaiTi',
                         color='black',
                         weight='normal',
                         size=10.5)

        # variables of YJK
        self.cur_yjk_class = None
        self.cur_yjk_dic = None
        self.cur_yjk_df = None
        self.df_yjk_export = None
        self.cur_yjk_lc = tk.StringVar()
        self.cur_yjk_tow_num_name = tk.StringVar()
        self.cur_yjk_flr_num_name = tk.StringVar()
        self.cur_yjk_content_name = tk.StringVar()
        self.lbl_yjk_tree_content = tk.StringVar()

        # variables of ETABS
        self.cur_etabs_dic = None
        self.cur_etabs_df = None
        self.df_etabs_export = None
        self.cur_etabs_lc = tk.StringVar()
        self.cur_etabs_tow_num_name = tk.StringVar()
        self.cur_etabs_flr_num_name = tk.StringVar()
        self.cur_etabs_content_name = tk.StringVar()
        self.lbl_etabs_tree_content = tk.StringVar()

        self.yjk_disp = None

        # GUI
        self.minsize(1280, 800)
        self.title('ARP_AnalysisResultProcessing')

        # start widget in frame_yjk_path
        self.frame_yjk_path = Frame(self)
        self.entry_yjk_path = Entry(self.frame_yjk_path,
                                    textvariable=self.yjk_dir)
        self.entry_yjk_path.pack(side=tk.LEFT,
                                 padx=5,
                                 pady=5,
                                 expand=tk.YES,
                                 fill=tk.X)
        self.btn_yjk_path = Button(self.frame_yjk_path,
                                   text='YJK',
                                   width=16,
                                   command=self.get_path)
        self.btn_yjk_path.pack(side=tk.LEFT, padx=5, pady=5)
        self.frame_yjk_path.pack(side=tk.TOP, fill=tk.X)
        # end widget in frame_yjk_path

        # start widget in frame_etabs_name
        self.frame_etabs_name = Frame(self)
        self.entry_etabs_name = Entry(self.frame_etabs_name,
                                      textvariable=self.etabs_name)
        self.entry_etabs_name.pack(side=tk.LEFT,
                                   padx=5,
                                   pady=5,
                                   expand=tk.YES,
                                   fill=tk.X)
        self.btn_etabs_path = Button(self.frame_etabs_name,
                                     text='ETABS',
                                     width=16,
                                     command=self.get_file_name)
        self.btn_etabs_path.pack(side=tk.LEFT, padx=5, pady=5)
        self.frame_etabs_name.pack(side=tk.TOP, fill=tk.X)
        # end widget in frame_etabs_name

        # start widget in frame_result_list
        self.frame_result_list = Frame(self)

        # option buttons of results
        self.lf_result_name = tk.LabelFrame(self.frame_result_list,
                                            text='Result to processing')

        self.frame_result_name_left = Frame(self.lf_result_name)
        for name, value in self.result_type_dict:
            _ = tk.Radiobutton(self.frame_result_name_left,
                               text=name,
                               value=value,
                               anchor=tk.W,
                               command=self.get_type,
                               variable=self.result_type)
            _.pack(side=tk.TOP, fill=tk.X, padx=5)
        self.frame_result_name_left.pack(side=tk.LEFT,
                                         expand=tk.YES,
                                         fill=tk.X)

        self.frame_result_name_right = Frame(self.lf_result_name)
        for name, value in self.result_type_dict_right:
            _ = tk.Radiobutton(self.frame_result_name_right,
                               text=name,
                               value=value,
                               anchor=tk.W,
                               command=self.get_type,
                               variable=self.result_type)
            _.pack(side=tk.TOP, fill=tk.X, padx=5)
        self.frame_result_name_right.pack(side=tk.LEFT,
                                          expand=tk.YES,
                                          fill=tk.X)

        self.frame_result_name_added = Frame(self.lf_result_name)
        for name, value in self.result_type_dict_added:
            _ = tk.Radiobutton(self.frame_result_name_added,
                               text=name,
                               value=value,
                               anchor=tk.NW,
                               command=self.get_type,
                               variable=self.result_type)
            _.pack(side=tk.TOP, fill=tk.X, padx=5)
        self.frame_result_name_added.pack(side=tk.LEFT,
                                          expand=tk.YES,
                                          fill=tk.X,
                                          anchor=tk.N)

        self.lf_result_name.pack(side=tk.TOP, fill=tk.X)

        # labelframe of yjk results
        self.lf_yjk = tk.LabelFrame(self.frame_result_list, text='YJK')

        # load combination cmb
        self.frame_yjk_lc = tk.Frame(self.lf_yjk)
        self.lbl_yjk_lc = tk.Label(self.frame_yjk_lc,
                                   width=__width_label_lc,
                                   text='Load Combination',
                                   anchor=tk.W)
        self.lbl_yjk_lc.pack(side=tk.LEFT, fill=tk.X)
        self.cmb_yjk_lc = ttk.Combobox(self.frame_yjk_lc,
                                       state="readonly",
                                       height=1,
                                       textvariable=self.cur_yjk_lc)
        self.cmb_yjk_lc.pack(side=tk.LEFT,
                             expand=tk.YES,
                             fill=tk.X,
                             padx=5,
                             pady=5)
        self.frame_yjk_lc.pack(side=tk.TOP, fill=tk.X)

        # tower number cmb
        self.frame_yjk_tower = tk.Frame(self.lf_yjk)
        self.lbl_yjk_tower = tk.Label(self.frame_yjk_tower,
                                      width=__width_label_lc,
                                      text='Tower Number',
                                      anchor=tk.W)
        self.lbl_yjk_tower.pack(side=tk.LEFT, fill=tk.X)
        self.cmb_yjk_tower = ttk.Combobox(
            self.frame_yjk_tower,
            state="readonly",
            height=1,
            textvariable=self.cur_yjk_tow_num_name)
        self.cmb_yjk_tower.pack(side=tk.LEFT,
                                expand=tk.YES,
                                fill=tk.X,
                                padx=5,
                                pady=5)
        self.frame_yjk_tower.pack(side=tk.TOP, fill=tk.X)

        # floor number cmb
        self.frame_yjk_floor = tk.Frame(self.lf_yjk)
        self.lbl_yjk_floor = tk.Label(self.frame_yjk_floor,
                                      width=__width_label_lc,
                                      text='Floor Number',
                                      anchor=tk.W)
        self.lbl_yjk_floor.pack(side=tk.LEFT, fill=tk.X)
        self.cmb_yjk_floor = ttk.Combobox(
            self.frame_yjk_floor,
            state="readonly",
            height=1,
            textvariable=self.cur_yjk_flr_num_name)
        self.cmb_yjk_floor.pack(side=tk.LEFT,
                                expand=tk.YES,
                                fill=tk.X,
                                padx=5,
                                pady=5)
        self.frame_yjk_floor.pack(side=tk.TOP, fill=tk.X)

        # result content cmb
        self.frame_yjk_content = tk.Frame(self.lf_yjk)
        self.lbl_yjk_content = tk.Label(self.frame_yjk_content,
                                        width=__width_label_lc,
                                        text='Content',
                                        anchor=tk.W)
        self.lbl_yjk_content.pack(side=tk.LEFT, fill=tk.X)
        self.cmb_yjk_content = ttk.Combobox(
            self.frame_yjk_content,
            state="readonly",
            height=1,
            textvariable=self.cur_yjk_content_name)
        self.cmb_yjk_content.pack(side=tk.LEFT,
                                  expand=tk.YES,
                                  fill=tk.X,
                                  padx=5,
                                  pady=5)
        self.frame_yjk_content.pack(side=tk.TOP, fill=tk.X)

        # self.yjk_tree
        self.yjk_tree = ttk.Treeview(self.lf_yjk, show='headings')
        self.yjk_tree['column'] = ['a', 'b', 'c']
        self.yjk_tree.column('a', width=18)
        self.yjk_tree.column('b', width=18)
        self.yjk_tree.column('c', width=18)
        self.yjk_tree.heading('a', text='Tower No.')
        self.yjk_tree.heading('b', text='Floor No.')
        self.yjk_tree.heading('c', text='content')
        self.yjk_tree.pack(side=tk.TOP, expand=tk.YES, fill=tk.BOTH)

        self.scr_yjk_tree = tk.Scrollbar(self.yjk_tree)
        self.scr_yjk_tree.pack(side=tk.RIGHT, fill=tk.Y)

        self.yjk_tree.config(yscrollcommand=self.scr_yjk_tree.set)
        self.scr_yjk_tree.config(command=self.yjk_tree.yview)

        # self.lbl_yjk_tree
        self.lbl_yjk_tree = tk.Label(self.lf_yjk,
                                     anchor=tk.W,
                                     textvariable=self.lbl_yjk_tree_content)
        self.lbl_yjk_tree.pack(side=tk.TOP, fill=tk.X)

        self.lf_yjk.pack(side=tk.TOP, expand=tk.YES, fill=tk.BOTH)
        # end of labelframe yjk results

        # labelframe of etabs results
        self.lf_etabs = tk.LabelFrame(self.frame_result_list, text='ETABS')

        # load combination cmb
        self.frame_etabs_lc = tk.Frame(self.lf_etabs)
        self.lbl_etabs_lc = tk.Label(self.frame_etabs_lc,
                                     width=__width_label_lc,
                                     text='Load Combination',
                                     anchor=tk.W)
        self.lbl_etabs_lc.pack(side=tk.LEFT, fill=tk.X)
        self.cmb_etabs_lc = ttk.Combobox(self.frame_etabs_lc,
                                         state="readonly",
                                         height=1,
                                         textvariable=self.cur_etabs_lc)
        self.cmb_etabs_lc.pack(side=tk.LEFT,
                               expand=tk.YES,
                               fill=tk.X,
                               padx=5,
                               pady=5)
        self.frame_etabs_lc.pack(side=tk.TOP, fill=tk.X)

        # tower number cmb
        self.frame_etabs_tower = tk.Frame(self.lf_etabs)
        self.lbl_etabs_tower = tk.Label(self.frame_etabs_tower,
                                        width=__width_label_lc,
                                        text='Tower Number',
                                        anchor=tk.W)
        self.lbl_etabs_tower.pack(side=tk.LEFT, fill=tk.X)
        self.cmb_etabs_tower = ttk.Combobox(
            self.frame_etabs_tower,
            state="readonly",
            height=1,
            textvariable=self.cur_etabs_tow_num_name)
        self.cmb_etabs_tower.pack(side=tk.LEFT,
                                  expand=tk.YES,
                                  fill=tk.X,
                                  padx=5,
                                  pady=5)
        self.frame_etabs_tower.pack(side=tk.TOP, fill=tk.X)

        # floor number cmb
        self.frame_etabs_floor = tk.Frame(self.lf_etabs)
        self.lbl_etabs_floor = tk.Label(self.frame_etabs_floor,
                                        width=__width_label_lc,
                                        text='Floor Number',
                                        anchor=tk.W)
        self.lbl_etabs_floor.pack(side=tk.LEFT, fill=tk.X)
        self.cmb_etabs_floor = ttk.Combobox(
            self.frame_etabs_floor,
            state="readonly",
            height=1,
            textvariable=self.cur_etabs_flr_num_name)
        self.cmb_etabs_floor.pack(side=tk.LEFT,
                                  expand=tk.YES,
                                  fill=tk.X,
                                  padx=5,
                                  pady=5)
        self.frame_etabs_floor.pack(side=tk.TOP, fill=tk.X)

        # result content cmb
        self.frame_etabs_content = tk.Frame(self.lf_etabs)
        self.lbl_etabs_content = tk.Label(self.frame_etabs_content,
                                          width=__width_label_lc,
                                          text='Content',
                                          anchor=tk.W)
        self.lbl_etabs_content.pack(side=tk.LEFT, fill=tk.X)
        self.cmb_etabs_content = ttk.Combobox(
            self.frame_etabs_content,
            state="readonly",
            height=1,
            textvariable=self.cur_etabs_content_name)
        self.cmb_etabs_content.pack(side=tk.LEFT,
                                    expand=tk.YES,
                                    fill=tk.X,
                                    padx=5,
                                    pady=5)
        self.frame_etabs_content.pack(side=tk.TOP, fill=tk.X)

        # self.etabs_tree
        self.etabs_tree = ttk.Treeview(self.lf_etabs, show='headings')
        self.etabs_tree['column'] = ['a', 'b', 'c']
        self.etabs_tree.column('a', width=18)
        self.etabs_tree.column('b', width=18)
        self.etabs_tree.column('c', width=18)
        self.etabs_tree.heading('a', text='Tower No.')
        self.etabs_tree.heading('b', text='Floor No.')
        self.etabs_tree.heading('c', text='content')
        self.etabs_tree.pack(side=tk.TOP, expand=tk.YES, fill=tk.BOTH)

        self.scr_etabs_tree = tk.Scrollbar(self.etabs_tree)
        self.scr_etabs_tree.pack(side=tk.RIGHT, fill=tk.Y)

        self.etabs_tree.config(yscrollcommand=self.scr_etabs_tree.set)
        self.scr_etabs_tree.config(command=self.etabs_tree.yview)

        # self.lbl_etabs_tree
        self.lbl_etabs_tree = tk.Label(
            self.lf_etabs,
            anchor=tk.W,
            textvariable=self.lbl_etabs_tree_content)
        self.lbl_etabs_tree.pack(side=tk.TOP, fill=tk.X)

        self.lf_etabs.pack(side=tk.TOP, expand=tk.YES, fill=tk.BOTH)

        # self.lf_data_import
        self.lf_data_import = tk.LabelFrame(self.frame_result_list,
                                            text='action')

        # button yjk import
        self.btn_yjk_import = Button(self.lf_data_import,
                                     text='add YJK data',
                                     width=18,
                                     command=self.import_yjk)
        self.btn_yjk_import.pack(side=tk.LEFT, anchor=tk.W, padx=36)

        # button etabs import
        self.btn_etabs_import = Button(self.lf_data_import,
                                       text='add ETABS data',
                                       width=18,
                                       command=self.import_etabs)
        self.btn_etabs_import.pack(side=tk.LEFT, anchor=tk.CENTER, padx=36)

        # button merge and import
        self.btn_merge = Button(self.lf_data_import,
                                text='merge and add',
                                width=18,
                                command=self.merge_import)
        self.btn_merge.pack(side=tk.LEFT, anchor=tk.E, padx=36)

        self.lf_data_import.pack(side=tk.TOP, fill=tk.X)

        self.frame_result_list.pack(side=tk.LEFT,
                                    expand=tk.YES,
                                    fill=tk.BOTH,
                                    padx=5,
                                    pady=5)
        # end widget in frame_result_list

        # start widget in frame_data_table
        self.frame_data_table = Frame(self)
        self.frame_table = Frame(self.frame_data_table)
        self.data_table = Table(self.frame_table,
                                rows=50,
                                cols=10,
                                showstatusbar=True)
        self.data_table.show()
        self.frame_table.pack(side=tk.TOP, expand=tk.YES, fill=tk.BOTH)
        self.frame_tower = Frame(self.frame_data_table)
        self.lbl_tower = Label(self.frame_data_table,
                               text='tower No.').pack(side=tk.BOTTOM)
        self.tower_scale = Scale(self.frame_data_table,
                                 orient=tk.HORIZONTAL,
                                 length=300,
                                 width=16,
                                 sliderlength=10,
                                 from_=0,
                                 to=10,
                                 tickinterval=1,
                                 variable=self.cur_tower_number,
                                 command=self.tower_select)
        self.tower_scale.pack(side=tk.BOTTOM, fill=tk.BOTH)
        self.frame_tower.pack(side=tk.TOP, fill=tk.X)
        self.frame_data_table.pack(side=tk.LEFT, expand=tk.YES, fill=tk.BOTH)
        # end widget in frame_data_table

        # start widget in frame_image
        self.frame_image = Frame(self)
        self.fig = Figure(figsize=(3.378, 4.331), dpi=150)
        self.ax = self.fig.add_subplot(111)
        self.canvas = FigureCanvasTkAgg(self.fig, master=self.frame_image)
        self.canvas.get_tk_widget().pack(side=tk.TOP)
        self.canvas.draw()
        toolbar = NavigationToolbar2Tk(self.canvas, self.frame_image)
        toolbar.update()
        self.canvas.get_tk_widget().pack(side=tk.TOP)

        self.lf_plot_control = tk.LabelFrame(self.frame_image, text='plot')

        self.lbl = Label(self.lf_plot_control, text='none').pack(side=tk.LEFT,
                                                                 fill=tk.X)
        self.btn_batch_plot = Button(self.lf_plot_control,
                                     text='batch plot',
                                     command=self.batch_plot)
        self.btn_batch_plot.pack(side=tk.RIGHT)

        self.lf_plot_control.pack(side=tk.BOTTOM, fill=tk.X)

        self.frame_image.pack(side=tk.LEFT, expand=tk.YES, fill=tk.BOTH)
        # end widget in frame_image

        self.data_table.zoomOut()
        self.data_table.zoomOut()

        self.action_bind()

    def action_bind(self):
        # action when yjk cmb selected
        self.cmb_yjk_lc.bind("<<ComboboxSelected>>", self.update_yjk_cmb)
        self.cmb_yjk_tower.bind("<<ComboboxSelected>>", self.update_yjk_tree)
        self.cmb_yjk_floor.bind("<<ComboboxSelected>>", self.update_yjk_tree)
        self.cmb_yjk_content.bind("<<ComboboxSelected>>", self.update_yjk_tree)

        # action when etabs cmb selected
        self.cmb_etabs_lc.bind("<<ComboboxSelected>>", self.update_etabs_cmb)
        self.cmb_etabs_tower.bind("<<ComboboxSelected>>",
                                  self.update_etabs_tree)
        self.cmb_etabs_floor.bind("<<ComboboxSelected>>",
                                  self.update_etabs_tree)
        self.cmb_etabs_content.bind("<<ComboboxSelected>>",
                                    self.update_etabs_tree)

    def get_path(self):
        """
        get path of yjk result by FilePath class.
        update yjk widgets.
        :return:
        """
        self.file_path.get_path()
        self.entry_yjk_path.delete(0, tk.END)
        self.entry_yjk_path.insert(tk.END, self.file_path.yjk_path)
        self.yjk_update()

    def get_file_name(self):
        """
        get filename of etabs result in excel format by FilePath class.
        update etabs widgets.
        :return:
        """
        self.file_path.get_path(openfile=True)
        self.entry_etabs_name.delete(0, tk.END)
        self.entry_etabs_name.insert(tk.END, self.file_path.etabs_name)
        if self.file_path.etabs_name is not None and self.file_path.etabs_name != '':
            self.etabs_update()

    def get_type(self):
        self.yjk_update()
        self.etabs_update()

    def yjk_update(self):
        if self.file_path.yjk_path is not None and os.path.exists(
                self.file_path.yjk_path) is True:
            self.cur_result_type = self.result_type.get()
            if self.cur_result_type == 'drift':
                with open(self.file_path.full_name('Wdisp.out'), 'r') as f:
                    self.cur_yjk_class = Wdisp.Wdisp(f.read())
                    self.cmb_yjk_lc['values'] = self.cur_yjk_class.cqc
                    self.cmb_yjk_lc.current(0)
                    self.cmb_yjk_lc.configure(
                        height=len(self.cur_yjk_class.cqc))
            elif self.cur_result_type == 'dsp_r' or self.result_type.get(
            ) == 'dft_r':
                with open(self.file_path.full_name('Wdisp.out'), 'r') as f:
                    self.cur_yjk_class = Wdisp.Wdisp(f.read())
                    self.cmb_yjk_lc['values'] = self.cur_yjk_class.spc_lateral
                    self.cmb_yjk_lc.current(0)
                    self.cmb_yjk_lc.configure(
                        height=len(self.cur_yjk_class.spc_lateral))
            elif self.cur_result_type == 'mass':
                with open(self.file_path.full_name('wmass.out'), 'r') as f:
                    self.cur_yjk_class = Wmass.Wmass(f.read())
                    self.cmb_yjk_lc['values'] = ['mass_info']
                    self.cmb_yjk_lc.current(0)
            elif self.cur_result_type == 'mass_density':
                with open(self.file_path.full_name('wmass.out'), 'r') as f:
                    self.cur_yjk_class = Wmass.Wmass(f.read())
                    self.cmb_yjk_lc['values'] = ['mass_density_detail']
                    self.cmb_yjk_lc.current(0)
            elif self.cur_result_type == 'stf':
                with open(self.file_path.full_name('wmass.out'), 'r') as f:
                    self.cur_yjk_class = Wmass.Wmass(f.read())
                    self.cmb_yjk_lc['values'] = ['stiffness_detail']
                    self.cmb_yjk_lc.current(0)
            elif self.cur_result_type == 's_c':
                with open(self.file_path.full_name('wmass.out'), 'r') as f:
                    self.cur_yjk_class = Wmass.Wmass(f.read())
                    self.cmb_yjk_lc['values'] = ['storey_shear_capacity_info']
                    self.cmb_yjk_lc.current(0)
            elif self.cur_result_type == 'period':
                with open(self.file_path.full_name('wzq.out'), 'r') as f:
                    self.cur_yjk_class = Wzq.Wzq(f.read())
                    self.cmb_yjk_lc['values'] = ['period']
                    self.cmb_yjk_lc.current(0)
            elif self.cur_result_type == 's_a_f':
                with open(self.file_path.full_name('wzq.out'), 'r') as f:
                    self.cur_yjk_class = Wzq.Wzq(f.read())
                    self.cmb_yjk_lc['values'] = ['shear_adjust_factor']
                    self.cmb_yjk_lc.current(0)
            elif self.cur_result_type == 's_s_c':
                with open(self.file_path.full_name('wzq.out'), 'r') as f:
                    self.cur_yjk_class = Wzq.Wzq(f.read())
                    self.cmb_yjk_lc['values'] = self.cur_yjk_class.s_s_c
                    self.cmb_yjk_lc.current(0)

            self.read_yjk_df()
            self.update_yjk_cmb(None)

    def read_yjk_df(self):
        if len(self.cmb_yjk_lc['values']) != 0:
            self.cur_yjk_df = getattr(self.cur_yjk_class,
                                      self.cur_yjk_lc.get())

    def update_yjk_cmb(self, event):
        self.read_yjk_df()
        _columns = self.cur_yjk_df.columns.tolist()
        if self.result_type.get() == 'drift':
            self.position = (1, 0, len(_columns) - 3)
        elif self.result_type.get() == 'dsp_r':
            self.position = (1, 0, len(_columns) - 1)
        elif self.result_type.get() == 'dft_r':
            self.position = (1, 0, 5)
        elif self.result_type.get() == 'mass':
            self.position = (1, 0, 5)
        elif self.result_type.get() == 'mass_density':
            self.position = (1, 0, 3)
        elif self.result_type.get() == 'stf':
            self.position = (1, 0, len(_columns) - 3)
        elif self.result_type.get() == 's_c':
            self.position = (1, 0, len(_columns) - 2)
        elif self.cur_result_type == 'period':
            self.position = (0, 1, 3)
        elif self.cur_result_type == 's_a_f':
            self.position = (1, 0, 2)
        elif self.cur_result_type == 's_s_c':
            self.position = (1, 0, 4)
        self.cmb_yjk_tower['values'] = _columns
        self.cmb_yjk_tower.configure(height=len(_columns))
        self.cmb_yjk_tower.current(self.position[0])
        self.cmb_yjk_floor['values'] = _columns
        self.cmb_yjk_floor.configure(height=len(_columns))
        self.cmb_yjk_floor.current(self.position[1])
        self.cmb_yjk_content['values'] = _columns
        self.cmb_yjk_content.configure(height=len(_columns))
        self.cmb_yjk_content.current(self.position[2])
        self.update_yjk_tree(None)

    def update_yjk_tree(self, event):
        if self.cur_yjk_tow_num_name.get() is not None and\
                self.cur_yjk_flr_num_name.get() is not None and \
                self.cmb_yjk_content.get() is not None:
            self.df_yjk_export = self.cur_yjk_df[[
                self.cur_yjk_tow_num_name.get(),
                self.cur_yjk_flr_num_name.get(),
                self.cur_yjk_content_name.get()
            ]]

            _content = self.yjk_tree.get_children()
            for _ in _content:
                self.yjk_tree.delete(_)

            for _ in range(len(self.df_yjk_export) - 1, -1, -1):
                self.yjk_tree.insert(
                    '', 0, values=self.df_yjk_export.iloc[_].tolist())

            self.lbl_yjk_tree_content.set(
                '%d row, %d columns' %
                (self.df_yjk_export.shape[0], self.df_yjk_export.shape[1]))

    def etabs_update(self):
        pass

    def update_etabs_cmb(self, event):
        pass

    def update_etabs_tree(self, event):
        pass

    def import_yjk(self):
        self.data_table.model.df = self.df_yjk_export
        number_groups = self.df_yjk_export.groupby(
            self.df_yjk_export.columns.tolist()[0]).ngroups
        self.tower_scale.config(to=number_groups)
        self.cur_tower_number.set(0)
        self.data_table.redraw()
        self.plot()

    def import_etabs(self):
        self.plot()
        pass

    def merge_import(self):
        self.plot()
        pass

    def tower_select(self, tower_number):
        group_by_tower = self.df_yjk_export.groupby(
            self.df_yjk_export.columns.tolist()[0])
        tower_number = int(tower_number)
        if tower_number == 0:
            self.data_table.model.df = self.df_yjk_export
        else:
            self.data_table.model.df = group_by_tower.get_group(tower_number)
        self.data_table.redraw()
        self.plot()

    def plot(self):
        self.ax.clear()
        tower_number = int(self.cur_tower_number.get())
        if tower_number == 0 and tower_number > 1:
            pass
        elif tower_number > 0:
            if self.result_type.get() == 'drift':
                self.ax.plot(1 / self.data_table.model.df.iloc[:, 2] * 1000,
                             self.data_table.model.df.iloc[:, 1],
                             marker='o')
                self.ax.grid(alpha=0.5, linestyle="-.", linewidth=0.3)
                self.ax.set_xlabel('位移角(1/1000)', fontdict=self.font)
                self.ax.set_ylabel('楼层', fontdict=self.font)
                self.fig.tight_layout(pad=0.3)
            elif self.result_type.get() == 'dsp_r':
                self.ax.plot(self.data_table.model.df.iloc[:, 2],
                             self.data_table.model.df.iloc[:, 1],
                             marker='o')
                self.ax.grid(alpha=0.5, linestyle="-.", linewidth=0.3)
                self.ax.set_xlabel('位移比', fontdict=self.font)
                self.ax.set_ylabel('楼层', fontdict=self.font)
                self.fig.tight_layout(pad=0.3)
            elif self.result_type.get() == 'dft_r':
                self.ax.plot(self.data_table.model.df.iloc[:, 2],
                             self.data_table.model.df.iloc[:, 1],
                             marker='o')
                self.ax.grid(alpha=0.5, linestyle="-.", linewidth=0.3)
                self.ax.set_xlabel('层间位移比', fontdict=self.font)
                self.ax.set_ylabel('楼层', fontdict=self.font)
                self.fig.tight_layout(pad=0.3)
            elif self.result_type.get() == 'mass':
                self.ax.plot(self.data_table.model.df.iloc[:, 2],
                             self.data_table.model.df.iloc[:, 1],
                             marker='o')
                self.ax.grid(alpha=0.5, linestyle="-.", linewidth=0.3)
                self.ax.set_xlabel('楼层质量', fontdict=self.font)
                self.ax.set_ylabel('楼层', fontdict=self.font)
                self.fig.tight_layout(pad=0.3)
            elif self.result_type.get() == 'mass_density':
                self.ax.plot(self.data_table.model.df.iloc[:, 2],
                             self.data_table.model.df.iloc[:, 1],
                             marker='o')
                self.ax.grid(alpha=0.5, linestyle="-.", linewidth=0.3)
                self.ax.set_xlabel('单位面积楼层质量', fontdict=self.font)
                self.ax.set_ylabel('楼层', fontdict=self.font)
                self.fig.tight_layout(pad=0.3)
            elif self.result_type.get() == 'stf':
                self.ax.plot(self.data_table.model.df.iloc[:, 2],
                             self.data_table.model.df.iloc[:, 1],
                             marker='o')
                self.ax.grid(alpha=0.5, linestyle="-.", linewidth=0.3)
                self.ax.set_xlabel('抗侧刚度(v/d)', fontdict=self.font)
                self.ax.set_ylabel('楼层', fontdict=self.font)
                self.fig.tight_layout(pad=0.3)
            elif self.result_type.get() == 's_c':
                self.ax.plot(self.data_table.model.df.iloc[:, 2],
                             self.data_table.model.df.iloc[:, 1],
                             marker='o')
                self.ax.grid(alpha=0.5, linestyle="-.", linewidth=0.3)
                self.ax.set_xlabel('楼层受剪承载力', fontdict=self.font)
                self.ax.set_ylabel('楼层', fontdict=self.font)
                self.fig.tight_layout(pad=0.3)
            elif self.cur_result_type == 'period':
                pass
            elif self.cur_result_type == 's_a_f':
                self.ax.plot(self.data_table.model.df.iloc[:, 2],
                             self.data_table.model.df.iloc[:, 1],
                             marker='o')
                self.ax.grid(alpha=0.5, linestyle="-.", linewidth=0.3)
                self.ax.set_xlabel('地震剪力放大系数', fontdict=self.font)
                self.ax.set_ylabel('楼层', fontdict=self.font)
                self.fig.tight_layout(pad=0.3)
            elif self.cur_result_type == 's_s_c':
                self.ax.plot(self.data_table.model.df.iloc[:, 2],
                             self.data_table.model.df.iloc[:, 1],
                             marker='o')
                self.ax.grid(alpha=0.5, linestyle="-.", linewidth=0.3)
                self.ax.set_xlabel('剪重比(%)', fontdict=self.font)
                self.ax.set_ylabel('楼层', fontdict=self.font)
                self.fig.tight_layout(pad=0.3)
            self.canvas.draw()
            pass

    def figure_save(self, fig_name=None):
        if fig_name is None:
            fig_name = '%s.png' % self.cur_yjk_lc.get()
        self.fig.savefig(self.file_path.result_name(fig_name),
                         transparent=True,
                         dpi=300,
                         format='png')

    def batch_plot(self):
        result_type_dict = self.result_type_dict + self.result_type_dict_right + self.result_type_dict_added
        if self.yjk_dir.get() != '' or self.etabs_name.get() != '':
            for name, result_type in result_type_dict:
                self.result_type.set(result_type)
                self.yjk_update()
                for ct, lc_name in enumerate(self.cmb_yjk_lc['values']):
                    self.cur_yjk_lc.set(lc_name)
                    self.update_yjk_cmb(None)
                    self.import_yjk()
                    self.cur_tower_number.set(1)
                    self.tower_select(1)
                    f_name = '%s-%d-%s.png' % (name, ct, lc_name)
                    self.figure_save(f_name)
Exemple #13
0
class Sierpinski:
    def __init__(self, master):
        self.master = master

        # Window dimensions and fields
        self.depth = 1
        self.index = 0
        self.colors = ["white", "#444444"]
        self.width = 600
        self.height = int(round(self.width * math.sqrt(3) / 2))
        self.margin = 10

        # Setup Tk
        Tk.config(master, bg=self.colors[self.index])
        master.title("Sierpinski")
        master.iconbitmap('tri.ico')
        master.bind("<space>", self.invert)
        master.bind("<Key-Up>", self.updatedepth)
        master.bind("<Key-Down>", self.updatedepth)
        master.bind("<Key-Right>", self.updatedepth)
        master.bind("<Key-Left>", self.updatedepth)

        # setup window
        self.canvas = Canvas(master,
                             width=self.width + (2 * self.margin),
                             height=self.height + (2 * self.margin))
        self.canvas.config(bg=self.colors[self.index], highlightthickness=0)
        self.canvas.bind("<Button-1>", self.invert)
        self.canvas.pack()

        # slider to set triangle depth
        self.level = Scale(master,
                           from_=1,
                           to=8,
                           orient=HORIZONTAL,
                           command=self.updatedepth)
        self.level.config(bg=self.colors[self.index], highlightthickness=0)
        self.level.pack()

        self.draw(self.level.get())

    def updatedepth(self, event):
        try:
            if event.keysym in ("Up", "Right"):
                self.depth = 8 if self.depth == 8 else self.depth + 1
            elif event.keysym in ("Down", "Left"):
                self.depth = 1 if self.depth == 1 else self.depth - 1
            self.level.set(self.depth)
        except AttributeError:
            self.depth = self.level.get()

        self.draw(self.depth)

    def invert(self, event):
        self.index = 1 if self.index == 0 else 0
        self.draw(self.depth)

    def draw(self, level):
        # clear canvas
        self.canvas.delete("all")

        x1 = self.margin
        y1 = self.margin + self.height
        x2 = self.margin + self.width / 2
        y2 = self.margin
        x3 = self.margin + self.width
        y3 = self.margin + self.height

        self.canvas.create_polygon(x1,
                                   y1,
                                   x2,
                                   y2,
                                   x3,
                                   y3,
                                   fill=self.colors[self.index],
                                   outline=self.colors[self.index - 1])
        self.recursion(int(level), x1, y1, x2, y2, x3, y3)

    def recursion(self, level, x1, y1, x2, y2, x3, y3):
        color = self.colors[self.index - 1]
        if level <= 1:
            self.canvas.create_polygon(x1, y1, x2, y2, x3, y3, fill=color)
        else:
            left_x = (x1 + x2) / 2
            left_y = (y1 + y2) / 2

            right_x = (x2 + x3) / 2
            right_y = (y2 + y3) / 2

            bottom_x = (x3 + x1) / 2
            bottom_y = (y3 + y1) / 2

            self.recursion(level - 1, x1, y1, left_x, left_y, bottom_x,
                           bottom_y)
            self.recursion(level - 1, left_x, left_y, x2, y2, right_x, right_y)
            self.recursion(level - 1, bottom_x, bottom_y, right_x, right_y, x3,
                           y3)
Exemple #14
0
class EulerQuatGUI:
    def __init__(self, window):
        self.window = window
        self.window.title('Final Project')

        scalelength = 180
        scalewidth = 18
        scalefontsize = 16
        # slider
        self.rollslider = Scale(window,
                                from_=-90,
                                to=90,
                                orient=HORIZONTAL,
                                resolution=5,
                                label='Roll',
                                command=self.updateRoll)
        self.rollslider.grid(column=0, row=1)
        self.rollslider.config(length=scalelength,
                               width=scalewidth,
                               font=("Helvetica", scalefontsize))
        self.rollslider.set(0)  # set the default position

        # slider
        self.pitchSlider = Scale(window,
                                 from_=-90,
                                 to=90,
                                 orient=HORIZONTAL,
                                 resolution=5,
                                 label='Pitch',
                                 command=self.updatePitch)
        self.pitchSlider.grid(column=0, row=2)
        self.pitchSlider.config(length=scalelength,
                                width=scalewidth,
                                font=("Helvetica", scalefontsize))
        self.pitchSlider.set(0)  # set the default angle

        # slider
        self.yawSlider = Scale(window,
                               from_=-180,
                               to=180,
                               orient=HORIZONTAL,
                               resolution=5,
                               label='Yaw',
                               command=self.updateYaw)
        self.yawSlider.grid(column=0, row=3)
        self.yawSlider.config(length=scalelength,
                              width=scalewidth,
                              font=("Helvetica", scalefontsize))
        self.yawSlider.set(0)  # set the default wind power

        # show me button
        self.buttonEuler = Button(window,
                                  text='Show me Euler',
                                  command=self.showMeEuler)
        self.buttonEuler.grid(column=0, row=4)
        self.buttonEuler.config(width=scalewidth,
                                font=("Helvetica", scalefontsize))

        # show me button
        self.buttonQuat = Button(window,
                                 text='Show me Quaternion',
                                 command=self.showMeQuat)
        self.buttonQuat.grid(column=0, row=5)
        self.buttonQuat.config(width=scalewidth,
                               font=("Helvetica", scalefontsize))

        self.e0box = Text(window, width=16, height=5)
        self.e0box.config(width=scalewidth - 4,
                          font=("Helvetica", scalefontsize))
        self.e0box.grid(column=2, row=1)

        self.ThetaBox = Text(window, width=16, height=2)
        self.ThetaBox.config(width=scalewidth - 4,
                             font=("Helvetica", scalefontsize))
        self.ThetaBox.grid(column=2, row=2)

        self.VectorBox = Text(window, width=16, height=4)
        self.VectorBox.config(width=scalewidth - 4,
                              font=("Helvetica", scalefontsize))
        self.VectorBox.grid(column=2, row=3)

        self.v0, self.v1, self.v2, self.meshColors = self.getAircraftPoints()
        self.allpoints = np.hstack((self.v0, self.v1, self.v2))

        self.initial = 0
        self.initial2 = 0
        self.phi = 0.0
        self.theta = 0.0
        self.psi = 0.0
        self.poly3d = None
        self.poly3d_num2 = None
        self.convert()

        #end of init function

    def updateRoll(self, value):
        self.phi = np.radians(float(value))
        self.convert()

    def updatePitch(self, value):
        self.theta = np.radians(float(value))
        self.convert()

    def updateYaw(self, value):
        self.psi = np.radians(float(value))
        self.convert()

    def showMeEuler(self):
        dt = [0.04] * 3
        if self.psi < 0:
            dt[0] *= -1
        if self.theta < 0:
            dt[1] *= -1
        if self.phi < 0:
            dt[2] *= -1

        for i in np.arange(0.0, self.psi, dt[0]):
            self.plot2(0.0, 0.0, i)  # roll, pitch, yaw

        for i in np.arange(0.0, self.theta, dt[1]):
            self.plot2(0.0, i, self.psi)  # roll, pitch, yaw

        for i in np.arange(0.0, self.phi, dt[2]):
            self.plot2(i, self.theta, self.psi)  # roll, pitch, yaw

        self.plot2(self.phi, self.theta, self.psi)

    def showMeQuat(self):
        beginquat = np.array([[1, 0, 0, 0]]).T
        endquat = Euler2Quaternion(self.phi, self.theta, self.psi)
        dist = np.linalg.norm(beginquat - endquat)
        howmany = int(dist * 100 / 1.2)
        e0 = np.linspace(beginquat.item(0), endquat.item(0), num=howmany)
        e1 = np.linspace(beginquat.item(1), endquat.item(1), num=howmany)
        e2 = np.linspace(beginquat.item(2), endquat.item(2), num=howmany)
        e3 = np.linspace(beginquat.item(3), endquat.item(3), num=howmany)

        for i in range(howmany):
            quat = np.array([[e0[i], e1[i], e2[i], e3[i]]]).T
            phi, theta, psi = Quaternion2Euler(quat)
            self.plot2(phi, theta, psi)

        self.plot2(self.phi, self.theta, self.psi)

    def convert(self):
        quat = Euler2Quaternion(self.phi, self.theta, self.psi)
        e0 = quat.item(0)
        e1 = quat.item(1)
        e2 = quat.item(2)
        e3 = quat.item(3)

        # put the quaternion on the GUI
        self.e0box.delete(0.0, 20.20)
        self.e0box.insert(0.0, 'quaternion = \n' + str(quat))

        self.THETA = np.arccos(e0) * 2.0
        # put the number on the GUI
        self.ThetaBox.delete(0.0, 20.20)
        self.ThetaBox.insert(
            0.0, 'theta = \n' + str(round(np.degrees(self.THETA), 5)) + ' deg')

        self.vector_v = quat[1:, :] * np.sin(self.THETA / 2)
        # put the number on the GUI
        self.VectorBox.delete(0.0, 20.20)
        showv = np.copy(self.vector_v)
        showv[2] = -showv[2]
        self.VectorBox.insert(0.0,
                              'v = \n' + str(showv / np.linalg.norm(showv)))

        # make the vector_v big for plotting purposes
        test = 8 * self.vector_v / np.linalg.norm(self.vector_v)
        if not np.isnan(self.vector_v.item(0)):
            R = np.array([[0, 1, 0], [1, 0, 0], [0, 0, -1]])
            self.vector_v = R @ test

        self.plot()

    def rotatePoints(self, points, R):
        "Rotate points by the rotation matrix R"
        rotated_points = R @ points
        return rotated_points

    def getAircraftPoints(self):
        """"
            Define the points on the aircraft following diagram in Figure C.3
        """
        # m = mesh.Mesh.from_file('basic plane.stl')
        m = mesh.Mesh.from_file('./betterPlane.stl')
        v0 = m.v0.T
        v1 = m.v1.T
        v2 = m.v2.T
        N = v0.shape[1]
        # print('number of mesh nodes is: ',N)

        #   define the colors for each face of triangular mesh
        red = np.array([153., 0., 51., 255.]) / 255
        green = np.array([34., 204., 0., 255.]) / 255
        blue = np.array([77., 136., 255., 255.]) / 255
        yellow = np.array([230., 230., 0., 255.]) / 255
        white = np.array([255., 255., 255., 255.]) / 255

        meshColors = np.empty((N, 3, 4), dtype=np.float32)
        for i in range(N):
            # meshColors[i] = random.choice([red, green, blue, yellow])
            meshColors[i] = red
            if m.areas.item(i) > 0.2:
                # print(i)
                meshColors[i] = yellow

        # return points, meshColors
        return v0, v1, v2, meshColors

    def pointsToMesh(self, points):
        """"
        Converts points to triangular mesh
        Each mesh face is defined by three 3D points
        (a rectangle requires two triangular mesh faces)
        """
        N = int(points.shape[1] / 3)
        translatedv0 = points[:, 0:N].T
        translatedv1 = points[:, N:2 * N].T
        translatedv2 = points[:, 2 * N:3 * N].T
        my_mesh = np.zeros((N, 3, 3))
        for i in range(N):
            my_mesh[i] = np.array(
                [translatedv0[i], translatedv1[i], translatedv2[i]])

        return my_mesh

    def plot(self):

        if self.initial == 0:
            fig = Figure(figsize=(9, 12))
            self.ax0 = fig.add_subplot(211, projection='3d')
            self.ax1 = fig.add_subplot(212, projection='3d')
            self.canvas = FigureCanvasTkAgg(fig, master=self.window)
            self.canvas.get_tk_widget().grid(column=1, row=0, rowspan=14)
            self.ax0.set_ylim(-8, 8)
            self.ax0.set_xlim(-8, 8)
            self.ax0.set_zlim(-8, 8)
            self.ax0.set_xlabel('j')
            self.ax0.set_ylabel('i')
            self.ax0.set_zlabel('k')

            self.ax1.set_ylim(-8, 8)
            self.ax1.set_xlim(-8, 8)
            self.ax1.set_zlim(-8, 8)
            self.ax1.set_xlabel('j')
            self.ax1.set_ylabel('i')
            self.ax1.set_zlabel('k')

            self.ax0.grid(True)
            self.ax0.set_title('')
            self.ax1.grid(True)
            self.ax1.set_title('')

            self.initial = 1
            self.ax0.mouse_init()
            self.ax1.mouse_init()

            v = self.allpoints

            # convert North-East Down to East-North-Up for rendering
            R = np.array([[0, 1, 0], [1, 0, 0], [0, 0, -1]])
            v = R @ v

            verts = self.pointsToMesh(v)

            # plot sides
            self.poly3d = Poly3DCollection(verts, alpha=.35)
            self.poly3d.set_facecolor(['blue', 'red'])
            self.ax0.add_collection3d(self.poly3d)

            X = [0, self.vector_v.item(0)]
            Y = [0, self.vector_v.item(1)]
            Z = [0, self.vector_v.item(2)]
            self.ELine, = self.ax0.plot(X, Y, Z, lw=4)

            self.canvas.draw()

        else:

            R = Euler2Rotation(self.phi, self.theta, self.psi)
            v = R @ self.allpoints

            # convert North-East Down to East-North-Up for rendering
            R = np.array([[0, 1, 0], [1, 0, 0], [0, 0, -1]])
            v = R @ v

            verts = self.pointsToMesh(v)
            # plot sides
            self.poly3d.set_verts(verts)

            X = [0, self.vector_v.item(0)]
            Y = [0, self.vector_v.item(1)]
            Z = [0, self.vector_v.item(2)]
            self.ELine._verts3d = (X, Y, Z)

            self.canvas.draw()

    def plot2(self, phi, theta, psi):

        if self.initial2 == 0:
            # self.ax1.cla()
            self.initial2 = 1

            v = self.allpoints
            # self.ax0.scatter3D(v[:, 0], v[:, 1], v[:, 2])
            # convert North-East Down to East-North-Up for rendering
            R = np.array([[0, 1, 0], [1, 0, 0], [0, 0, -1]])
            v = R @ v
            # generate list of sides' polygons of our pyramid
            verts = self.pointsToMesh(v)

            # plot sides
            self.poly3d_num2 = Poly3DCollection(verts, alpha=.35)
            self.poly3d_num2.set_facecolor('blue')
            self.ax1.add_collection3d(self.poly3d_num2)

            self.canvas.draw()

        else:

            R = Euler2Rotation(phi, theta, psi)
            v = R @ self.allpoints

            # convert North-East Down to East-North-Up for rendering
            R = np.array([[0, 1, 0], [1, 0, 0], [0, 0, -1]])
            v = R @ v
            # self.ax0.scatter3D(v[:, 0], v[:, 1], v[:, 2])

            # generate list of sides' polygons of our pyramid
            verts = self.pointsToMesh(v)

            # plot sides
            self.poly3d_num2.set_verts(verts)

            self.canvas.draw()
Exemple #15
0
class Interface:
    """ GUI class """
    def __init__(self, master):
        # colour swatches
        self.gray1 = "#f6f6f6"
        self.gray2 = "#eaeaea"
        self.gray3 = "#d9d9d9"
        # key parameters
        self.running = False
        self.sect_width = 360
        self.rb_choice = StringVar()
        self.dob1_val = StringVar()
        self.dob2_val = StringVar()
        self.df_records = StringVar()

        master.geometry("800x600+200+200")
        master.title("Red Snapper")
        master.resizable(False, False)
        master.configure(background=self.gray1)

        # LEFT SECTION LAYER
        # --------------------------------------------------------------------
        self.sect_left = Frame(master)
        self.sect_left.place(x=15, y=15, width=self.sect_width, height=570)
        self.sect_left.config(relief=RIDGE)
        self.sect_left.config(background=self.gray2)

        # RIGHT SECTION LAYER
        # --------------------------------------------------------------------
        self.sect_right = Frame(master)
        self.sect_right.place(x=-15, y=200, width=self.sect_width, height=385)
        self.sect_right.place(relx=1.0, anchor="ne")
        self.sect_right.config(relief=RIDGE)
        self.sect_right.config(background=self.gray2)

        # Sliders layer
        self.layer_sliders = Frame(self.sect_left)
        self.layer_sliders.place(y=0, width=self.sect_width, height=320)
        self.layer_sliders.config(**self.layer_props(self.gray2))
        self.lab_sliders = Label(self.layer_sliders)
        self.lab_sliders.config(**self.title_props("Parameters"))
        self.lab_sliders.pack()

        # DOB layer
        self.layer_dob = Frame(self.sect_left)
        self.layer_dob.place(y=320, width=self.sect_width, height=80)
        self.layer_dob.config(**self.layer_props(self.gray2))
        self.lab_dob = Label(self.layer_dob)
        self.lab_dob.config(**self.title_props("Birthdays range"))
        self.lab_dob.pack()

        # Export layer
        self.layer_export = Frame(self.sect_left)
        self.layer_export.place(y=400, width=self.sect_width, height=80)
        self.layer_export.config(**self.layer_props(self.gray2))
        self.lab_export = Label(self.layer_export)
        self.lab_export.config(**self.title_props("Export format"))
        self.lab_export.pack()

        # Run layer
        self.layer_run = Frame(self.sect_left)
        self.layer_run.place(y=480, width=self.sect_width, height=100)
        self.layer_run.config(**self.layer_props(self.gray2))
        self.lab_run = Label(self.layer_run)
        self.lab_run.config(**self.title_props("Run"))
        self.lab_run.pack()

        # About layer
        self.layer_about = Frame(self.sect_right)
        self.layer_about.place(width=self.sect_width, height=385)
        self.layer_about.config(**self.layer_props(self.gray2))
        self.lab_about = Label(self.layer_about)
        self.lab_about.config(**self.title_props("About Red Snapper"))
        self.lab_about.pack()

        # sliders
        self.sli_wom = Scale(self.layer_sliders, from_=0, to=100)
        self.sli_wom.config(**self.sli_props())
        self.sli_wom.config(label="Percentage of women in dataset.")
        self.sli_wom.pack(padx=20, pady=10)
        self.sli_wom.set(50)

        self.sli_nam = Scale(self.layer_sliders, from_=0, to=100)
        self.sli_nam.config(**self.sli_props())
        self.sli_nam.config(label="Percentage of people with double name")
        self.sli_nam.pack(padx=20, pady=0)
        self.sli_nam.set(25)

        self.sli_sur = Scale(self.layer_sliders, from_=0, to=100)
        self.sli_sur.config(**self.sli_props())
        self.sli_sur.config(label="Percentage of people with double surname")
        self.sli_sur.pack(padx=20, pady=10)
        self.sli_sur.set(15)

        # DOB Layer - From Date
        self.dob1_val.set("1945")
        self.lab_dob1 = Label(self.layer_dob, text="From date")
        self.lab_dob1.config(**self.label_props())
        self.lab_dob1.pack(side=LEFT, padx=5)
        self.box_dob1 = Spinbox(self.layer_dob)
        self.box_dob1.config(from_=1945, to=1996, textvariable=self.dob1_val)
        self.box_dob1.config(**self.date_props())
        self.box_dob1.pack(side=LEFT)

        # DOB Layer - To Date
        self.dob2_val.set("1997")
        self.lab_dob2 = Label(self.layer_dob, text="To date")
        self.lab_dob2.config(**self.label_props())
        self.lab_dob2.pack(side=LEFT, padx=17)
        self.box_dob2 = Spinbox(self.layer_dob)
        self.box_dob2.config(from_=1946, to=1997, textvariable=self.dob2_val)
        self.box_dob2.config(**self.date_props())
        self.box_dob2.pack(side=LEFT)

        # Export layer - JSON / CSV radio buttons
        self.rb_choice.set("CSV")
        self.rb1 = Radiobutton(self.layer_export,
                               text="Save as CSV",
                               variable=self.rb_choice,
                               value="CSV")
        self.rb1.config(**self.radio_props())
        self.rb1.place(y=35, x=50)
        self.rb2 = Radiobutton(self.layer_export,
                               text="Save as JSON",
                               variable=self.rb_choice,
                               value="JSON")
        self.rb2.config(**self.radio_props())
        self.rb2.place(y=35, x=200)

        # Run layer - no of records spinbox
        self.df_records.set("100")
        self.box_gen = Spinbox(self.layer_run)
        self.box_gen.config(from_=1, to=999999, textvariable=self.df_records)
        self.box_gen.config(increment=1000, width=19)
        self.box_gen.place(x=70, y=53)
        self.lab_gen = Label(self.layer_run, text="Number of records")
        self.lab_gen.config(**self.label_props())
        self.lab_gen.place(x=70, y=30)

        # Run layer - generate button
        self.btn_run = ttk.Button(self.layer_run)
        self.btn_run.place(x=225, y=35, height=40)
        self.btn_run_reset()

        # header & logo section
        self.sect_logo = Frame(master)
        self.sect_logo.place(x=-15, y=30, width=350, height=120)
        self.sect_logo.place(relx=1.0, anchor="ne")
        self.logo = PhotoImage(file="./redsnapper/interface/logo.png")
        self.lab_logo = Label(self.sect_logo, image=self.logo)
        self.lab_logo.config(background=self.gray1)
        self.lab_logo.pack()

        # About
        box_about = Text(self.layer_about)
        box_about.config(**self.text_props())
        box_about.pack(pady=10, padx=10)
        txt = """This program allows generating thousands of rows filled with pseudo-random data. """ \
              + """\nThe generated records (like name,  """ \
              + """ surname, date of birth, e-mail address) can be used to provide sample data to:
        - test query performance of your database 
        - practice data operations with BI tools.""" \
              + """ \nThe application uses 4 processes to generate data simultaneously. """ \
              + """ It takes about 25 seconds to create 1 million rows of data.\n"""

        box_about.insert(END, txt)

    # styling wrapped into functions for reusability
    def sli_props(self):
        """
        bundle popular attributes of TK control so they can be reused
        :return: dict of bundled props
        """
        return {
            "length": 300,
            "orient": HORIZONTAL,
            "sliderrelief": FLAT,
            "showvalue": 1,
            "resolution": 1,
            "sliderlength": 25,
            "tickinterval": 100,
            "font": ("Arial", 8),
            "activebackground": "#333333",
            "background": "#666666",
            "troughcolor": "#d0d4d2",
            "foreground": "#eeeeee",
            "highlightthickness": 8,
            "highlightcolor": "#ffffff",
            "highlightbackground": self.gray3,
            "borderwidth": 1
        }

    @staticmethod
    def layer_props(bgcolor):
        """
        bundle popular attributes of TK control so they can be reused
        :return: dict of bundled props
        """
        return {"relief": RIDGE, "background": bgcolor}

    def title_props(self, title):
        """
        bundle popular attributes of TK control so they can be reused
        :return: dict of bundled props
        """
        return {
            "text": title,
            "background": self.gray3,
            "width": self.sect_width,
            "borderwidth": 1,
            "relief": RIDGE
        }

    def radio_props(self):
        """
        bundle popular attributes of TK control so they can be reused
        :return: dict of bundled props
        """
        return {
            "background": self.gray2,
            "activebackground": self.gray2,
        }

    def date_props(self):
        """
        bundle popular attributes of TK control so they can be reused
        :return: dict of bundled props
        """
        return {
            "width": 8,
            "increment": 1,
            "font": ("Arial", 8),
            "background": "#666666",
            "buttonbackground": "#666666",
            "foreground": "#eeeeee",
            "highlightthickness": 8,
            "highlightcolor": "#ffffff",
            "highlightbackground": self.gray2,
            "borderwidth": 1
        }

    def label_props(self):
        """
        bundle popular attributes of TK control so they can be reused
        :return: dict of bundled props
        """
        return {
            "background": self.gray2,
            "highlightcolor": "#ffffff",
            "highlightbackground": self.gray2,
            "borderwidth": 1
        }

    def text_props(self):
        """
        bundle popular attributes of TK control so they can be reused
        :return: dict of bundled props
        """
        return {
            "font": ("Arial", 11),
            "background": self.gray1,
            "foreground": "#212121",
            "highlightthickness": 8,
            "highlightbackground": self.gray1,
            "highlightcolor": self.gray1,
            "borderwidth": 0,
            "wrap": "word",
            "spacing1": 11,
            "spacing2": 7,
        }

    def produce_props(self):
        """
        produce dict of key GUI parameters selected by user
        :return: no return parameters
        """
        rows = int(self.box_gen.get())
        props = {
            "pgender": self.sli_wom.get(),
            "pdname": self.sli_nam.get(),
            "pdsurname": self.sli_sur.get(),
            "dob1": self.box_dob1.get(),
            "dob2": self.box_dob2.get(),
        }
        dataset = Dataset().run_workload(rows, **props)
        exp_format = self.rb_choice.get()
        if exp_format == "CSV":
            Export().to_csv(dataset)
        else:
            Export().to_json(dataset)
        self.btn_run_reset()
        return

    def btn_run_reset(self):
        """
        abort button (when generating)
        :return: no return parameters
        """
        self.running = False
        self.btn_run.config(text="Generate", command=self.btn_run_start)
        return

    def btn_run_start(self):
        """
        handle the run button
        :return: no return parameters
        """
        self.running = True
        newthread = threading.Thread(target=self.produce_props)
        newthread.start()
        self.btn_run.config(text="Abort", command=self.btn_run_reset)
        return