Example #1
0
class TimerDemo:
    """Controller"""
    def __init__(self):
        self.root = Tk()
        self.root.title('Timer')
        left = (self.root.winfo_screenwidth() - WIDTH) // 2
        top = (self.root.winfo_screenheight() - HEIGHT) // 2
        self.root.geometry(f'{WIDTH}x{HEIGHT}+{left}+{top}')
        self.root.resizable(False, False)

        # variables
        self.count_start = IntVar()
        self.count_start.trace_add('write', self.count_start_changed)
        self.count = IntVar()
        self.count.trace_add('write', self.count_changed)
        self.time = StringVar()
        self.timer_id = None

        self.ui = TimerUi(self)
        self.count_start.set(DEFAULT_COUNT)

    def run(self):
        self.root.mainloop()

    def count_changed(self, *args):
        self.draw_time()

    def count_start_changed(self, *args):
        # Countdown中には呼ばれないようにすること
        self.count.set(self.count_start.get())

    def draw_time(self):
        count = self.count.get()
        m, s = count // 60, count % 60
        self.time.set(f'{m:0>2}:{s:0>2}')

    def start_timer(self):
        if self.count.get() == 0:
            self.count_start_changed()
        self.ui.state_started()
        self.timer_id = self.root.after(1000, self.countdown)

    def stop_timer(self):
        if self.timer_id:
            self.root.after_cancel(self.timer_id)
        self.ui.state_stopped()

    def countdown(self):
        self.count.set(self.count.get() - 1)
        if self.count.get() > 0:
            self.timer_id = self.root.after(1000, self.countdown)  # recursive
        else:
            self.root.bell()
            self.ui.state_stopped()
Example #2
0
 def init_reformat_display(self):
     orientation_var = IntVar(0)
     orientation_var.trace_add('write', self.__reformat_callback)
     count = 0
     for text, value in self._ORIENTATIONS:
         b = Radiobutton(self,
                         text=text,
                         variable=orientation_var,
                         value=count)
         b.pack(side=tk.TOP, anchor='w')
         count += 1
     self._orientation = orientation_var
Example #3
0
class CheckBox(Widget):
    def __init__(self, master, **kwargs):
        self._value = IntVar()
        super().__init__(tk=ttk.Checkbutton(master=master,
                                            variable=self._value),
                         **kwargs)

        self._setter = self.connect_to_prop("value", self.on_changed_value)
        self._trace = self._value.trace_add(
            "write", lambda *_: self._setter(self._value.get()))

    def on_changed_value(self, value):
        self._value.set(value)

    def on_disposed(self):
        self._value.trace_remove("write", self._trace)
        self._value = None
        self._setter = None
Example #4
0
class Scale(Widget):
    def __init__(self, master, **kwargs):
        self._valuev = IntVar()
        super().__init__(tk=TkTickScale(master=master,
                                        orient=kwargs.get("node").get_attr(
                                            "orient", "horizontal"),
                                        variable=self._valuev),
                         **kwargs)
        self._setter = self.connect_to_prop("value", self.on_changed_value)
        self._trace = self._valuev.trace_add(
            "write", lambda *_: self._setter(self._valuev.get()))

    def on_changed_value(self, value):
        self._valuev.set(int(value))

    def on_disposed(self):
        self._valuev.trace_remove("write", self._trace)
        self._valuev = None
        self._setter = None
Example #5
0
class UBX_CFGVAL_Frame(Frame):
    """
    UBX CFG-VAL configuration command panel.
    """
    def __init__(self, app, container, *args, **kwargs):
        """
        Constructor.

        :param Frame app: reference to main tkinter application
        :param Frame container: reference to container frame (config-dialog)
        :param args: optional args to pass to Frame parent class
        :param kwargs: optional kwargs to pass to Frame parent class
        """

        self.__app = app  # Reference to main application class
        self.__master = self.__app.get_master()  # Reference to root class (Tk)
        self.__container = container

        Frame.__init__(self, self.__container.container, *args, **kwargs)

        self._img_send = ImageTk.PhotoImage(Image.open(ICON_SEND))
        self._img_pending = ImageTk.PhotoImage(Image.open(ICON_PENDING))
        self._img_confirmed = ImageTk.PhotoImage(Image.open(ICON_CONFIRMED))
        self._img_warn = ImageTk.PhotoImage(Image.open(ICON_WARNING))
        self._cfgval_cat = None
        self._cfgval_keyname = None
        self._cfgval_keyid = None
        self._cfgmode = IntVar()
        self._cfgatt = StringVar()
        self._cfgkeyid = StringVar()
        self._cfgval = StringVar()
        self._cfglayer = StringVar()

        self._body()
        self._do_layout()
        self._attach_events()
        self.reset()

    def _body(self):
        """
        Set up frame and widgets.
        """

        self._lbl_configdb = Label(
            self,
            text="CFG-VALSET/DEL/GET Configuration Interface",
            anchor="w")
        self._lbl_cat = Label(self, text="Category", anchor="w")
        self._lbx_cat = Listbox(
            self,
            border=2,
            relief="sunken",
            bg=ENTCOL,
            height=5,
            justify=LEFT,
            exportselection=False,
        )
        self._scr_catv = Scrollbar(self, orient=VERTICAL)
        self._scr_cath = Scrollbar(self, orient=HORIZONTAL)
        self._lbx_cat.config(yscrollcommand=self._scr_catv.set)
        self._lbx_cat.config(xscrollcommand=self._scr_cath.set)
        self._scr_catv.config(command=self._lbx_cat.yview)
        self._scr_cath.config(command=self._lbx_cat.xview)
        self._lbl_parm = Label(self, text="Keyname", anchor="w")
        self._lbx_parm = Listbox(
            self,
            border=2,
            relief="sunken",
            bg=ENTCOL,
            height=5,
            justify=LEFT,
            exportselection=False,
        )
        self._scr_parmv = Scrollbar(self, orient=VERTICAL)
        self._scr_parmh = Scrollbar(self, orient=HORIZONTAL)
        self._lbx_parm.config(yscrollcommand=self._scr_parmv.set)
        self._lbx_parm.config(xscrollcommand=self._scr_parmh.set)
        self._scr_parmv.config(command=self._lbx_parm.yview)
        self._scr_parmh.config(command=self._lbx_parm.xview)

        self._rad_cfgset = Radiobutton(self,
                                       text="CFG-VALSET",
                                       variable=self._cfgmode,
                                       value=0)
        self._rad_cfgdel = Radiobutton(self,
                                       text="CFG-VALDEL",
                                       variable=self._cfgmode,
                                       value=1)
        self._rad_cfgget = Radiobutton(self,
                                       text="CFG-VALGET",
                                       variable=self._cfgmode,
                                       value=2)
        self._lbl_key = Label(self, text="KeyID")
        self._lbl_keyid = Label(
            self,
            textvariable=self._cfgkeyid,
            bg=ENTCOL,
            width=10,
            fg=INFCOL,
            border=1,
            relief="sunken",
        )
        self._lbl_type = Label(self, text="Type")
        self._lbl_att = Label(
            self,
            textvariable=self._cfgatt,
            bg=ENTCOL,
            width=5,
            fg=INFCOL,
            border=1,
            relief="sunken",
        )
        self._lbl_layer = Label(self, text="Layer")
        self._spn_layer = Spinbox(
            self,
            textvariable=self._cfglayer,
            values=("RAM", "BBR", "FLASH", "DEFAULT"),
            bg=ENTCOL,
            wrap=True,
            width=8,
            state=READONLY,
            readonlybackground=ENTCOL,
        )
        self._lbl_val = Label(self, text="Value")
        self._ent_val = Entry(
            self,
            textvariable=self._cfgval,
            readonlybackground=ENTCOL,
            fg=INFCOL,
            state=READONLY,
            relief="sunken",
        )

        self._lbl_send_command = Label(self)
        self._btn_send_command = Button(
            self,
            image=self._img_send,
            width=50,
            command=self._on_send_config,
        )

    def _do_layout(self):
        """
        Layout widgets.
        """

        self._lbl_configdb.grid(column=0,
                                row=0,
                                columnspan=6,
                                padx=3,
                                sticky=(W, E))
        self._lbl_cat.grid(column=0, row=1, padx=3, sticky=(W, E))
        self._lbx_cat.grid(column=0,
                           row=2,
                           rowspan=5,
                           padx=3,
                           pady=3,
                           sticky=(W, E))
        self._scr_catv.grid(column=0, row=2, rowspan=5, sticky=(N, S, E))
        self._scr_cath.grid(column=0, row=7, sticky=(W, E))
        self._lbl_parm.grid(column=1,
                            row=1,
                            columnspan=4,
                            padx=3,
                            sticky=(W, E))
        self._lbx_parm.grid(column=1,
                            row=2,
                            columnspan=4,
                            rowspan=5,
                            padx=3,
                            pady=3,
                            sticky=(W, E))
        self._scr_parmv.grid(column=4, row=2, rowspan=5, sticky=(N, S, E))
        self._scr_parmh.grid(column=1, row=7, columnspan=4, sticky=(W, E))
        self._rad_cfgget.grid(column=0, row=8, padx=3, pady=0, sticky=(W))
        self._rad_cfgset.grid(column=0, row=9, padx=3, pady=0, sticky=(W))
        self._rad_cfgdel.grid(column=0, row=10, padx=3, pady=0, sticky=(W))
        self._lbl_key.grid(column=1, row=8, padx=3, pady=0, sticky=(E))
        self._lbl_keyid.grid(column=2, row=8, padx=3, pady=0, sticky=(W))
        self._lbl_type.grid(column=3, row=8, padx=3, pady=0, sticky=(E))
        self._lbl_att.grid(column=4, row=8, padx=3, pady=0, sticky=(W))
        self._lbl_layer.grid(column=1, row=9, padx=3, pady=0, sticky=(E))
        self._spn_layer.grid(column=2, row=9, padx=3, pady=0, sticky=(W))
        self._lbl_val.grid(column=1, row=10, padx=3, pady=0, sticky=(E))
        self._ent_val.grid(column=2,
                           row=10,
                           columnspan=3,
                           padx=3,
                           pady=0,
                           sticky=(W, E))

        self._btn_send_command.grid(column=3,
                                    row=12,
                                    rowspan=2,
                                    ipadx=3,
                                    ipady=3,
                                    sticky=(E))
        self._lbl_send_command.grid(column=4,
                                    row=13,
                                    rowspan=2,
                                    ipadx=3,
                                    ipady=3,
                                    sticky=(E))

        (cols, rows) = self.grid_size()
        for i in range(cols):
            self.grid_columnconfigure(i, weight=1)
        for i in range(rows):
            self.grid_rowconfigure(i, weight=1)
        self.option_add("*Font", self.__app.font_sm)

    def _attach_events(self):
        """
        Bind events to widgets.
        """

        self._lbx_cat.bind("<<ListboxSelect>>", self._on_select_cat)
        self._lbx_parm.bind("<<ListboxSelect>>", self._on_select_parm)
        self._cfgmode.trace_add("write", self._on_select_mode)

    def reset(self):
        """
        Reset panel.
        """

        for i, cat in enumerate(UBX_CONFIG_CATEGORIES):
            self._lbx_cat.insert(i, cat)
        self._cfgmode.set(2)

    def _on_select_mode(self, *args, **kwargs):  # pylint: disable=unused-argument
        """
        Mode has been selected.
        """

        if self._cfgmode.get() == VALSET:
            self._ent_val.config(state=NORMAL, bg=ENTCOL, fg="Black")
        else:
            self._ent_val.config(state=READONLY,
                                 readonlybackground=ENTCOL,
                                 fg=INFCOL)

    def _on_select_cat(self, *args, **kwargs):  # pylint: disable=unused-argument
        """
        Configuration category has been selected.
        """

        idx = self._lbx_cat.curselection()
        self._cfgval_cat = self._lbx_cat.get(idx)

        self._lbx_parm.delete(0, "end")
        self._cfgkeyid.set("")
        self._cfgatt.set("")
        idx = 0
        for keyname, (_, _) in UBX_CONFIG_DATABASE.items():
            if self._cfgval_cat in keyname:
                self._lbx_parm.insert(idx, keyname)
                idx += 1
        self._cfgval.set("")

    def _on_select_parm(self, *args, **kwargs):  # pylint: disable=unused-argument
        """
        Configuration parameter (keyname) has been selected.
        """

        idx = self._lbx_parm.curselection()
        self._cfgval_keyname = self._lbx_parm.get(idx)

        (keyid, att) = UBXMessage.cfgname2key(self._cfgval_keyname)
        self._cfgkeyid.set(hex(keyid))
        self._cfgatt.set(att)
        self._cfgval.set("")

    def _on_send_config(self, *args, **kwargs):  # pylint: disable=unused-argument
        """
        Config interface send button has been clicked.
        """

        if self._cfgval_keyname is not None:
            if self._cfgmode.get() == VALSET:
                self._do_valset()
            elif self._cfgmode.get() == VALDEL:
                self._do_valdel()
            else:
                self._do_valget()

    def _do_valset(self):
        """
        Send a CFG-VALSET message.

        :return: valid entry flag
        :rtype: bool
        """

        valid_entry = True
        att = atttyp(self._cfgatt.get())
        atts = attsiz(self._cfgatt.get())
        val = self._cfgval.get()
        layers = self._cfglayer.get()
        if layers == "BBR":
            layers = 2
        elif layers == "FLASH":
            layers = 4
        else:
            layers = 1
        try:
            if att in ("C", "X"):  # byte or char
                if len(val) == atts * 2:  # 2 hex chars per byte
                    val = bytearray.fromhex(val)
                else:
                    valid_entry = False
            elif att in ("E", "U"):  # unsigned integer
                val = int(val)
                if val < 0:
                    valid_entry = False
            elif att == "L":  # bool
                val = int(val)
                if val not in (0, 1):
                    valid_entry = False
            elif att == "I":  # signed integer
                val = int(val)
            elif att == "R":  # floating point
                val = float(val)
            transaction = 0
            cfgData = [
                (self._cfgval_keyname, val),
            ]
        except ValueError:
            valid_entry = False

        if valid_entry:
            msg = UBXMessage.config_set(layers, transaction, cfgData)
            self.__app.serial_handler.serial_write(msg.serialize())
            self._ent_val.configure(bg=ENTCOL)
            self._lbl_send_command.config(image=self._img_pending)
            self.__container.set_status("CFG-VALSET SET message sent", "blue")
            self.__container.set_pending(UBX_CFGVAL, ("ACK-ACK", "ACK-NAK"))
        else:
            self._ent_val.configure(bg=ERRCOL)
            self._lbl_send_command.config(image=self._img_warn)
            typ = ATTDICT[att]
            self.__container.set_status(
                ("INVALID ENTRY - must conform to parameter "
                 f"type {att} ({typ}) and size {atts} bytes"),
                "red",
            )

        return valid_entry

    def _do_valdel(self):
        """
        Send a CFG-VALDEL message.
        """

        layers = self._cfglayer.get()
        if layers == "BBR":
            layers = 2
        elif layers == "FLASH":
            layers = 4
        else:
            layers = 1
        transaction = 0
        key = [
            self._cfgval_keyname,
        ]
        msg = UBXMessage.config_del(layers, transaction, key)
        self.__app.serial_handler.serial_write(msg.serialize())
        self._ent_val.configure(bg=ENTCOL)
        self._lbl_send_command.config(image=self._img_pending)
        self.__container.set_status("CFG-VALDEL SET message sent", "blue")
        self.__container.set_pending(UBX_CFGVAL, ("ACK-ACK", "ACK-NAK"))

    def _do_valget(self):
        """
        Send a CFG-VALGET message.
        """

        layers = self._cfglayer.get()
        if layers == "BBR":
            layers = 1
        elif layers == "FLASH":
            layers = 2
        elif layers == "DEFAULT":
            layers = 7
        else:
            layers = 0
        transaction = 0
        keys = [
            self._cfgval_keyname,
        ]
        msg = UBXMessage.config_poll(layers, transaction, keys)
        self.__app.serial_handler.serial_write(msg.serialize())
        self._ent_val.configure(bg=ENTCOL)
        self._lbl_send_command.config(image=self._img_pending)
        self.__container.set_status("CFG-VALGET POLL message sent", "blue")
        self.__container.set_pending(UBX_CFGVAL,
                                     ("CFG-VALGET", "ACK-ACK", "ACK-NAK"))

    def update_status(self, cfgtype, **kwargs):  # pylint: disable=unused-argument
        """
        Update pending confirmation status.

        :param str cfgtype: identity of UBX message containing config info
        :param kwargs: status keywords and values from UBX config message
        """

        if cfgtype == "CFG-VALGET":
            self._lbl_send_command.config(image=self._img_confirmed)
            data = kwargs.get("data", None)
            if data is not None:
                val = getattr(data, self._cfgval_keyname, None)
                if val is not None:
                    if isinstance(val, bytes):
                        val = val.hex()
                    self._cfgval.set(val)
            self.__container.set_status(f"{cfgtype} GET message received",
                                        "green")
        elif cfgtype == "ACK-ACK":
            self._lbl_send_command.config(image=self._img_confirmed)
            self.__container.set_status(f"{cfgtype} GET message received",
                                        "green")
        elif cfgtype == "ACK-NAK":
            self._lbl_send_command.config(image=self._img_warn)
            self.__container.set_status("CFG-VAL message rejected", "red")
Example #6
0
class Meter(Frame):
    """A radial meter that can be used to show progress of long running operations or the amount of work completed;
    can also be used as a `Dial` when set to ``interactive=True``.

    This widget is very flexible. There are two primary meter types which can be set with the ``metertype`` parameter:
    'full' and 'semi', which show the arc of the meter in a full or semi-circle. You can also customize the arc of the
    circle with the ``arcrange`` and ``arcoffset`` parameters.

    The progress bar indicator can be displayed as a solid color or with stripes using the ``stripethickness``
    parameter. By default, the ``stripethickness`` is 0, which results in a solid progress bar. A higher
    ``stripethickness`` results in larger wedges around the arc of the meter.

    Various text and label options exist. The center text can be formatted with the ``meterstyle`` parameter and uses
    the `TLabel` styles.  This also colors the progress bar arch.  You can prepend or append text to the center text
    using the ``textappend`` and ``textprepend`` parameters. This is most commonly used for '$', '%', or other such
    symbols.

    Variable are generated automatically for this widget and can be linked to other widgets by referencing them via
    the ``amountusedvariable`` and ``amounttotalvariable`` attributes.

    The variable properties allow you to easily get and set the value of these variables. For example:
    ``Meter.amountused`` or ``Meter.amountused = 55`` will get or set the amount used on the widget without having to
    call the ``get`` or ``set`` methods of the tkinter variable.
    """
    def __init__(self,
                 master=None,
                 arcrange=None,
                 arcoffset=None,
                 amounttotal=100,
                 amountused=0,
                 interactive=False,
                 labelfont='Helvetica 10 bold',
                 labelstyle='secondary.TLabel',
                 labeltext=None,
                 metersize=200,
                 meterstyle='primary.TLabel',
                 metertype='full',
                 meterthickness=10,
                 showvalue=True,
                 stripethickness=0,
                 textappend=None,
                 textfont='Helvetica 25 bold',
                 textprepend=None,
                 wedgesize=0,
                 **kw):
        """
        Args:
            master (Widget): Parent widget
            arcoffset (int): The amount to offset the arc's starting position in degrees; 0 is at 3 o'clock.
            arcrange (int): The range of the arc in degrees from start to end.
            amounttotal (int): The maximum value of the meter.
            amountused (int): The current value of the meter; displayed if ``showvalue=True``.
            interactive (bool): Enables the meter to be adjusted with mouse interaction.
            labelfont(Font or str): The font of the supplemental label.
            labelstyle (str): The ttk style used to render the supplemental label.
            labeltext (str): Supplemental label text that appears `below` the center text.
            metersize (int): The size of the meter; represented by one side length of a square.
            meterstyle (str): The ttk style used to render the meter and center text.
            metertype (str): One of **full** or **semi**; displays a full-circle or semi-circle.
            meterthickness (int): The thickness of the meter's progress bar.
            showvalue (bool): Show the meter's value in the center text; default = True.
            stripethickness (int): The meter's progress bar can be displayed in solid or striped form. If the value is
                greater than 0, the meter's progress bar changes from a solid to striped, where the value is the
                thickness of the stripes.
            textappend (str): A short string appended to the center text.
            textfont (Font or str): The font of the center text.
            textprepend (str): A short string prepended to the center text.
            wedgesize (int): If greater than zero, the width of the wedge on either side of the current meter value.
        """
        super().__init__(master=master, **kw)

        self.box = ttk.Frame(self, width=metersize, height=metersize)

        if metertype == 'semi':
            self.arcoffset = arcoffset if arcoffset is not None else 135
            self.arcrange = arcrange if arcrange is not None else 270
        else:  # aka 'full'
            self.arcoffset = arcoffset if arcoffset is not None else -90
            self.arcrange = arcrange if arcrange is not None else 360

        # widget variables
        self.amountusedvariable = IntVar(value=amountused)
        self.amounttotalvariable = IntVar(value=amounttotal)
        self.labelvariable = StringVar(value=labeltext)
        self.amountusedvariable.trace_add('write', self.draw_meter)

        # misc widget settings
        self.towardsmaximum = True
        self.metersize = metersize
        self.meterthickness = meterthickness
        self.stripethickness = stripethickness
        self.showvalue = showvalue
        self.wedgesize = wedgesize

        # translate system colors if a ttkbootstrap style is not used
        if 'system' in self.lookup(meterstyle, 'foreground').lower():
            self.meterforeground = self.convert_system_color(
                self.lookup(meterstyle, 'foreground'))
        else:
            self.meterforeground = self.lookup(meterstyle, 'foreground')
        if 'system' in self.lookup(meterstyle, 'background').lower():
            self.meterbackground = Colors.update_hsv(self.convert_system_color(
                self.lookup(meterstyle, 'background')),
                                                     vd=-0.1)
        else:
            self.meterbackground = Colors.update_hsv(self.lookup(
                meterstyle, 'background'),
                                                     vd=-0.1)

        # meter image
        self.meter = ttk.Label(self.box)
        self.draw_base_image()
        self.draw_meter()

        # text & label widgets
        self.textcontainer = ttk.Frame(self.box)
        self.textprepend = ttk.Label(self.textcontainer,
                                     text=textprepend,
                                     font=labelfont,
                                     style=labelstyle)
        self.textprepend.configure(anchor='s', padding=(0, 5))
        self.text = ttk.Label(self.textcontainer,
                              textvariable=self.amountusedvariable,
                              style=meterstyle,
                              font=textfont)
        self.textappend = ttk.Label(self.textcontainer,
                                    text=textappend,
                                    font=labelfont,
                                    style=labelstyle)
        self.textappend.configure(anchor='s', padding=(0, 5))
        self.label = ttk.Label(self.box,
                               text=labeltext,
                               style=labelstyle,
                               font=labelfont)

        # set interactive mode
        if interactive:
            self.meter.bind('<B1-Motion>', self.on_dial_interact)
            self.meter.bind('<Button-1>', self.on_dial_interact)

        # geometry management
        self.meter.place(x=0, y=0)
        self.box.pack()
        if labeltext:
            self.textcontainer.place(relx=0.5, rely=0.45, anchor='center')
        else:
            self.textcontainer.place(relx=0.5, rely=0.5, anchor='center')
        if textprepend:
            self.textprepend.pack(side='left', fill='y')
        if showvalue:
            self.text.pack(side='left', fill='y')
        if textappend:
            self.textappend.pack(side='left', fill='y')
        self.label.place(relx=0.5, rely=0.6, anchor='center')

    @property
    def amountused(self):
        return self.amountusedvariable.get()

    @amountused.setter
    def amountused(self, value):
        self.amountusedvariable.set(value)

    @property
    def amounttotal(self):
        return self.amounttotalvariable.get()

    @amounttotal.setter
    def amounttotal(self, value):
        self.amounttotalvariable.set(value)

    def convert_system_color(self, systemcolorname):
        """Convert a system color name to a hexadecimal value

        Args:
            systemcolorname (str): a system color name, such as `SystemButtonFace`
        """
        r, g, b = [x >> 8 for x in self.winfo_rgb(systemcolorname)]
        return f'#{r:02x}{g:02x}{b:02x}'

    def draw_base_image(self):
        """Draw the base image to be used for subsequent updates"""
        self.base_image = Image.new('RGBA',
                                    (self.metersize * 5, self.metersize * 5))
        draw = ImageDraw.Draw(self.base_image)

        # striped meter
        if self.stripethickness > 0:
            for x in range(
                    self.arcoffset, self.arcrange + self.arcoffset,
                    2 if self.stripethickness == 1 else self.stripethickness):
                draw.arc(
                    (0, 0, self.metersize * 5 - 20, self.metersize * 5 - 20),
                    x, x + self.stripethickness - 1, self.meterbackground,
                    self.meterthickness * 5)
        # solid meter
        else:
            draw.arc((0, 0, self.metersize * 5 - 20, self.metersize * 5 - 20),
                     self.arcoffset, self.arcrange + self.arcoffset,
                     self.meterbackground, self.meterthickness * 5)

    def draw_meter(self, *args):
        """Draw a meter

        Args:
            *args: if triggered by a trace, will be `variable`, `index`, `mode`.
        """
        im = self.base_image.copy()
        draw = ImageDraw.Draw(im)
        if self.stripethickness > 0:
            self.draw_striped_meter(draw)
        else:
            self.draw_solid_meter(draw)
        self.meterimage = ImageTk.PhotoImage(
            im.resize((self.metersize, self.metersize), Image.CUBIC))
        self.meter.configure(image=self.meterimage)

    def draw_solid_meter(self, draw):
        """Draw a solid meter

        Args:
            draw (ImageDraw.Draw): an object used to draw an arc on the meter
        """
        if self.wedgesize > 0:
            meter_value = self.meter_value()
            draw.arc((0, 0, self.metersize * 5 - 20, self.metersize * 5 - 20),
                     meter_value - self.wedgesize,
                     meter_value + self.wedgesize, self.meterforeground,
                     self.meterthickness * 5)
        else:
            draw.arc((0, 0, self.metersize * 5 - 20, self.metersize * 5 - 20),
                     self.arcoffset, self.meter_value(), self.meterforeground,
                     self.meterthickness * 5)

    def draw_striped_meter(self, draw):
        """Draw a striped meter

        Args:
            draw (ImageDraw.Draw): an object used to draw an arc on the meter
        """
        if self.wedgesize > 0:
            meter_value = self.meter_value()
            draw.arc((0, 0, self.metersize * 5 - 20, self.metersize * 5 - 20),
                     meter_value - self.wedgesize,
                     meter_value + self.wedgesize, self.meterforeground,
                     self.meterthickness * 5)
        else:
            for x in range(self.arcoffset,
                           self.meter_value() - 1, self.stripethickness):
                draw.arc(
                    (0, 0, self.metersize * 5 - 20, self.metersize * 5 - 20),
                    x, x + self.stripethickness - 1, self.meterforeground,
                    self.meterthickness * 5)

    def lookup(self, style, option):
        """Wrapper around the tcl style lookup command

        Args:
            style (str): the name of the style used for rendering the widget.
            option (str): the option to lookup from the style option database.

        Returns:
            any: the value of the option looked up.
        """
        return self.tk.call("ttk::style", "lookup", style, '-%s' % option,
                            None, None)

    def meter_value(self):
        """Calculate the meter value

        Returns:
            int: the value to be used to draw the arc length of the progress meter
        """
        return int((self.amountused / self.amounttotal) * self.arcrange +
                   self.arcoffset)

    def on_dial_interact(self, e):
        """Callback for mouse drag motion on indicator

        Args:
            e (Event): event callback for drag motion.
        """
        dx = e.x - self.metersize // 2
        dy = e.y - self.metersize // 2
        rads = math.atan2(dy, dx)
        degs = math.degrees(rads)

        if degs > self.arcoffset:
            factor = degs - self.arcoffset
        else:
            factor = 360 + degs - self.arcoffset

        # clamp value between 0 and ``amounttotal``
        amountused = int(self.amounttotal / self.arcrange * factor)
        if amountused < 0:
            self.amountused = 0
        elif amountused > self.amounttotal:
            self.amountused = self.amounttotal
        else:
            self.amountused = amountused

    def step(self, delta=1):
        """Increase the indicator value by ``delta``.

        The default increment is 1. The indicator will reverse direction and count down once it reaches the maximum
        value.

        Keyword Args:
            delta (int): the amount to change the indicator.
        """
        if self.amountused >= self.amounttotal:
            self.towardsmaximum = True
            self.amountused = self.amountused - delta
        elif self.amountused <= 0:
            self.towardsmaximum = False
            self.amountused = self.amountused + delta
        elif self.towardsmaximum:
            self.amountused = self.amountused - delta
        else:
            self.amountused = self.amountused + delta
Example #7
0
from tkinter import Frame, Tk, Scale, IntVar


def change_color(variable, index, mode):
    frame['bg'] = '#%0x%0x%0x' % (var.get() * 16, var.get() * 16,
                                  var.get() * 16)


if __name__ == '__main__':
    root = Tk()
    frame = Frame(root, width=100, height=100)
    var = IntVar()
    scale = Scale(root,
                  orient='horizontal',
                  variable=var,
                  length=300,
                  from_=0,
                  to=99,
                  tickinterval=10,
                  resolution=10)
    var.trace_add('write', change_color)
    frame.pack()
    scale.pack()
    root.mainloop()
class AuxMode(Frame):
    def __init__(self, root, parent):
        Frame.__init__(self, root, borderwidth=2, relief='groove', height=10)
        settings = parent.settings('aux_mode')
        self.parent = parent

        lbl_power = Label(self, text='Power:')
        lbl_power.grid(row=0, column=0, pady=2)
        self.cmb_power = ttk.Combobox(self, value=['Off', 'On'])
        self.cmb_power.grid(row=0, column=1, pady=2)
        self.cmb_power.set(settings['power'])
        self.cmb_power['state'] = 'readonly'
        self.cmb_power.bind('<<ComboboxSelected>>', self.set_power)

        lbl_aux_pin = Label(self, text='AUX pin:')
        lbl_aux_pin.grid(row=1, column=0, pady=2)
        self.cmb_aux_pin = ttk.Combobox(self, values=['AUX', 'CS'])
        self.cmb_aux_pin.grid(row=1, column=1, pady=2)
        self.cmb_aux_pin['state'] = 'readonly'
        self.cmb_aux_pin.set(settings['aux_pin'])
        self.cmb_aux_pin.bind('<<ComboboxSelected>>', self.select_aux_pin)

        lbl_aux = Label(self, text='AUX mode:')
        lbl_aux.grid(row=2, column=0, pady=2)
        self.cmb_aux_mode = ttk.Combobox(
            self, values=['Input', 'Output', 'Servo', 'PWM'])
        self.cmb_aux_mode.grid(row=2, column=1, pady=2)
        self.cmb_aux_mode['state'] = 'readonly'
        self.cmb_aux_mode.set(settings['mode'])
        self.cmb_aux_mode.bind('<<ComboboxSelected>>', self.select_aux_mode)

        self.aux_servo = Scale(self, from_=0, to=180, orient='horizontal')
        self.aux_servo.set(settings['servo'])
        self.aux_servo.bind('<ButtonRelease-1>', self.select_aux_mode)

        self.aux_pin_state = IntVar()
        self.aux_pin_state.set(settings['aux_state'])
        self.aux_pin_state.trace_add('write', self.select_aux_mode)

        self.aux_high = Radiobutton(self,
                                    text='HIGH',
                                    value=1,
                                    variable=self.aux_pin_state)
        self.aux_low = Radiobutton(self,
                                   text='LOW',
                                   value=0,
                                   variable=self.aux_pin_state)

        self.aux_pwm_lbl = Label(self, text='Frequency (KHz):')
        self.aux_pwm_freq = Entry(self)
        self.aux_pwm_freq.insert(0, settings['pwm_freq'])
        self.aux_pwm_freq.bind('<KeyRelease>', self.select_aux_mode)

        self.aux_pwm_duty_lbl = Label(self, text='Duty cycle (%):')
        self.aux_pwm_duty = Scale(self, from_=0, to=99, orient='horizontal')
        self.aux_pwm_duty.set(settings['pwm_duty'])
        self.aux_pwm_duty.bind('<ButtonRelease-1>', self.select_aux_mode)

    def __call__(self):
        return {
            'power': self.cmb_power.get(),
            'mode': self.cmb_aux_mode.get(),
            'aux_state': self.aux_pin_state.get(),
            'aux_pin': self.cmb_aux_pin.get(),
            'servo': self.aux_servo.get(),
            'pwm_freq': self.aux_pwm_freq.get(),
            'pwm_duty': self.aux_pwm_duty.get()
        }

    def select_aux_mode(self, e=None, a=None, b=None):

        for i, widget in enumerate(self.winfo_children()):
            if i > 5:
                widget.grid_forget()
        mode = self.cmb_aux_mode.get()

        # if self.parent.console.mode == 'HiZ': return
        if mode == 'Input':
            self.parent.console.aux('Input')

        if mode == 'Output':
            self.aux_high.grid(row=3, column=1)
            self.aux_low.grid(row=4, column=1)
            self.parent.console.aux('Output', self.aux_pin_state.get())

        if mode == 'Servo':
            self.aux_servo.grid(row=3, column=1)
            self.parent.console.servo(self.aux_servo.get())

        if mode == 'PWM':
            self.aux_pwm_lbl.grid(row=3, column=0)
            self.aux_pwm_freq.grid(row=3, column=1)
            self.aux_pwm_duty_lbl.grid(row=4, column=0)
            self.aux_pwm_duty.grid(row=4, column=1)
            self.parent.console.pwm(self.aux_pwm_freq.get(),
                                    self.aux_pwm_duty.get())

        if mode == 'CS':
            self.parent.console.cs()

        self.parent.settings('aux_mode', self())

    def select_aux_pin(self, e=None):
        self.parent.console.aux_pin(self.cmb_aux_pin.get())

    def set_power(self, e=None):
        self.parent.console.power(self.cmb_power.get())
        self.parent.settings('aux_mode', self())

    def disable(self):
        self.cmb_power['state'] = 'disabled'
        self.cmb_aux_mode['state'] = 'disabled'
        self.aux_high['state'] = 'disabled'
        self.aux_low['state'] = 'disabled'
        self.aux_servo['state'] = 'disabled'
        self.aux_pwm_freq['state'] = 'disabled'
        self.aux_pwm_duty['state'] = 'disabled'

    def enable(self):
        self.cmb_power['state'] = 'readonly'
        self.cmb_aux_mode['state'] = 'readonly'
        self.aux_high['state'] = 'normal'
        self.aux_low['state'] = 'normal'
        self.aux_servo['state'] = 'normal'
        self.aux_pwm_freq['state'] = 'normal'
        self.aux_pwm_duty['state'] = 'normal'
Example #9
0
class App():
    """
    Start of the applications
    """
    def __init__(self):

        self.__version__ = '0.2.1'
        # Larch
        self.mylarch = larch.Interpreter()
        self.root = Tk(className='EXAFS Neo GUI')
        self.root.wm_title("Graphical User Interface for EXAFS Analysis (Beta)")
        # Standard default geometry
        self.root.geometry("750x500")
        self.padx = 5
        self.pady = 3

        self.os = get_platform()
        base_folder = os.path.dirname(os.path.join(os.getcwd(),__file__))
        icon_loc = os.path.join(base_folder,'media/icon.png')

        img = PhotoImage(file=icon_loc)
        self.root.tk.call('wm','iconphoto',self.root._w,img)

        # Set default font
        self.entryFont = Font(family="TkFixedFont", size=10)
        self.menuFont = Font(family="TkMenuFont",size=10)
        self.labelFont = Font(family="TkTextFont", size=11)
        # Generate the mainframe
        self.mainframe = ttk.Notebook(self.root,height=40,padding="5")
        self.mainframe.grid(column=0, row=0, sticky=(N, W, E, S))

        # Initalize variable
        self.initialize_var()
        self.initialize_tab()
        self.Build_tabs()

    def initialize_var(self):
        """
        Initalize all possible variables in the gui.

        Future additions starts here.
        """
        # Inputs
        self.data_file = StringVar(self.root,'Please choose a file')
        self.temp_data_file = StringVar(self.root,'Please choose a file')
        self.output_file = StringVar(self.root,'Please choose a file')
        self.ncomp = IntVar(self.root,'0') # Number of compounds
        self.feff_file = StringVar(self.root,'Please choose a directory')
        self.series = BooleanVar(self.root,'False')
        # Populations
        self.populations = IntVar(self.root,1000)
        self.num_gen = IntVar(self.root,100)
        self.best_sample = IntVar(self.root,20)
        self.lucky_few = IntVar(self.root,20)

        # Mutations
        self.chance_of_mutation = IntVar(self.root,20)
        self.orginal_chance_of_mutation = IntVar(self.root,20)
        self.chance_of_mutation_e0 = IntVar(self.root,20)
        self.mutation_options = IntVar(self.root,0)

        # Paths
        self.individual_path = BooleanVar(self.root,True)
        self.path_range = IntVar(self.root,20)
        temp_list = ",".join(np.char.mod('%i', np.arange(1,self.path_range.get()+1)))
        self.path_list = StringVar(self.root,temp_list)
        self.path_optimize = BooleanVar(self.root,False)
        self.path_optimize_pert = DoubleVar(self.root,0.01)
        self.path_optimize_only = BooleanVar(self.root,False)

        # Larch Paths
        self.kmin = DoubleVar(self.root,2.5)
        self.kmax = DoubleVar(self.root,15)
        self.k_weight = DoubleVar(self.root,2)
        self.delta_k = DoubleVar(self.root,0.05)
        self.r_bkg = DoubleVar(self.root,1.0)
        self.bkg_kw = DoubleVar(self.root, 1.0)
        self.bkg_kmax = DoubleVar(self.root, 15)

        #Outputs
        self.print_graph = BooleanVar(self.root, False)
        self.num_output_paths = BooleanVar(self.root, True)
        self.steady_state_exit = BooleanVar(self.root, True)

        # Pertubutuions
        self.n_ini = IntVar(self.root,100)

    def initialize_tab(self):
        """
        Initialize tab for the main frame. more tabs
        """

        s = ttk.Style()
        s.configure('TNotebook.Tab', font=('TkHeadingFont','11') )

        height=1
        self.tab_Inputs = tk.Frame(self.mainframe,height=height)
        self.tab_Populations = tk.Frame(self.mainframe,height=height)
        self.tab_Paths = tk.Frame(self.mainframe,height=height)
        self.tab_Mutation = tk.Frame(self.mainframe,height=height)
        self.tab_Larch = tk.Frame(self.mainframe,height=height)
        self.tab_Bkg = tk.Frame(self.mainframe,height=height)
        self.tab_Output = tk.Frame(self.mainframe,height=height)
        self.tab_Analysis = tk.Frame(self.mainframe,height=height)
        self.tab_Expert = tk.Frame(self.mainframe,height=height)

        # Add all the secondary tabs on the top window
        self.mainframe.add(self.tab_Inputs, text="Inputs")
        self.mainframe.add(self.tab_Populations, text="Populations")
        self.mainframe.add(self.tab_Paths, text="Paths")
        self.mainframe.add(self.tab_Mutation, text="Mutations")
        self.mainframe.add(self.tab_Larch, text="Larch")
        self.mainframe.add(self.tab_Bkg, text="Background Plots")
        self.mainframe.add(self.tab_Output, text="Outputs")
        self.mainframe.add(self.tab_Analysis, text='Analysis')
        self.mainframe.add(self.tab_Expert, text='Expert')
        self.mainframe.grid(row=0,column=0,columnspan=4,padx=self.padx,pady=self.pady,sticky=E+W+N+S)

    def description_tabs(self,arr,tabs,sticky=(W,E),row=None,return_description=False):
        # Rows = index of rows
        description_list = []
        if row is not None:
            assert len(row) == len(arr);
        for i,inputs in enumerate(arr):
            entry = ttk.Label(tabs,text=inputs,font=self.labelFont)
            if row is not None:
                k = row[i]
            else:
                k = i
            entry.grid_configure(column=0,row=k,sticky=sticky,padx=self.padx,pady=self.pady)
            description_list.append(entry)
        if description_list:
            return description_list

    def Build_tabs(self):
        """
        Build tabs
        """
        # Building all arrays
        self.Build_global()
        self.Build_inputs_tab()
        self.Build_population_tab()
        self.Build_path_tab()
        self.Build_mutations_tab()
        self.Build_larch_tab()
        self.Build_background_tab()
        self.Build_output_tab()
        self.Build_analysis_tab()
        self.Build_expert_tab()

        self.mainframe.grid_rowconfigure(0,weight=1)
        self.mainframe.grid_columnconfigure(0,weight=1)
        self.mainframe.grid_columnconfigure(1,weight=1)

    def Write_ini(self,filename):
        """
            Write the ini for the specific file
        """
        inputs = ("[Inputs] \nnum_compounds = {compound} \ncsv_file = {data} \noutput_file = {out} \nfeff_file = {feff}\ncsv_series = {series}"
            .format(compound=str(self.ncomp.get()),
                    data=str(self.data_file.get()),
                    out=str(self.output_file.get()),
                    feff=str(self.feff_file.get()),
                    series=str(self.series.get())))

        populations = ("\n\n[Populations] \npopulation = {pop} \nnum_gen = {numgen} \nbest_sample = {best} \nlucky_few = {luck}"
            .format(pop=str(self.populations.get()),
                    numgen=str(self.num_gen.get()),
                    best=str(self.best_sample.get()),
                    luck=str(self.lucky_few.get())))

        mutations = ("\n\n[Mutations] \nchance_of_mutation = {chance} \noriginal_chance_of_mutation = {original} \nchance_of_mutation_e0 = {e0} \nmutated_options = {opt}"
            .format(chance=str(self.chance_of_mutation.get()),
                    original=str(self.orginal_chance_of_mutation.get()),
                    e0=str(self.chance_of_mutation_e0.get()),
                    opt=str(self.mutation_options.get())))

        paths = ("\n\n[Paths] \nindividual_path = {tf}  \npath_range = {range} \npath_list = {list} \npath_optimize = {optimize} \noptimize_percent = {optimize_pert} \noptimize_only = {optimize_only}"
            .format(tf=str(self.individual_path.get()),
                    range=str(self.path_range.get()),
                    list=str(self.path_list.get().replace(" ","")),
                    optimize=str(self.path_optimize.get()),
                    optimize_pert = str(self.path_optimize_pert.get()),
                    optimize_only = str(self.path_optimize_only.get())
                    ))

        larch_paths = ("\n\n[Larch_Paths] \nkmin = {min} \nkmax = {max} \nkweight = {weight} \ndeltak = {delk} \nrbkg = {rb} \nbkgkw = {bk} \nbkgkmax = {bmax}"
            .format(min=self.kmin.get(),
                    max=self.kmax.get(),
                    weight=self.k_weight.get(),
                    delk=self.delta_k.get(),
                    rb=self.r_bkg.get(),
                    bk=self.bkg_kw.get(),
                    bmax=self.bkg_kmax.get()))

        outputs = ("\n\n[Outputs] \nprint_graph = {pg} \nnum_output_paths = {outpath}\nsteady_state_exit = {steady}"
            .format(pg=self.print_graph.get(),
                    outpath=self.num_output_paths.get(),
                    steady=self.steady_state_exit.get()))

        with open(filename,'w') as writer:
            writer.write(str(inputs))
            writer.write(str(populations))
            writer.write(str(mutations))
            writer.write(str(paths))
            writer.write(str(larch_paths))
            writer.write(str(outputs))

    def Generate_ini(self):
        os.chdir("..") #change the working directory from gui to EXAFS
        # while proceed ==  False:
        ini_file= filedialog.asksaveasfilename(initialdir = os.getcwd(),
            title = "Choose output ini file",
            filetypes = [("ini files","*.ini")])
        if ini_file is None:
            return
        if isinstance(ini_file,tuple) == False:
            if len(ini_file) != 0:
                self.Write_ini(ini_file)
                messagebox.showinfo('','Ini file written to {fileloc}'.format(fileloc=ini_file))

        os.chdir("gui")

    def stop_term(self):
        if hasattr(self,'proc'):
            # print("Stopped EXAFS")
            self.proc.kill()

    def run_term(self,file = 'test_temp.i'):
        """
        if hasattr(self,'terminal'):
            # Need to close previous threads
            self.terminal.destroy()
        # command = ['exafs','-i','test.ini']
        self.Write_ini('test_temp.i')
        command = 'exafs -i test_temp.i'.split(' ')
        # print(command)
        self.terminal = Console(self.txtbox,command)
        """
        self.Write_ini('test_temp.i')
        self.stop_term()

        # command = 'exafs -i test_temp.i'
        command = ['exafs','-i',file]
        if self.os == 'Windows':
            print(' '.join(command))
            self.proc = subprocess.Popen(' '.join(command),shell=True)
        else:
            self.proc = subprocess.Popen("exec " + ' '.join(command),shell=True)

    def run_ini(self,file = 'test_temp.i'):

        command = ['exafs','-i',file]
        self.proc = subprocess.Popen("exec " + ' '.join(command),shell=True)
        self.proc.wait()

    def Build_global(self):
        '''
        Create global generate ini
        '''

        def about_citation():
            """
            Create about popup
            """
            popup = tk.Toplevel()
            popup.wm_title("About: Ver: " + str(self.__version__))

            popup.resizable(False,False)
            cite = tk.Label(popup,text='Citation:',font='TkTextFont')
            cite.grid(column=0,row=0,sticky=N,padx=self.padx,pady=self.pady)
            citation = scrolledtext.ScrolledText(popup,
                                      width = 75,
                                      height = 10,
                                      font="TkTextFont")
            citation.grid(column=0,row=1,sticky=N,padx=self.padx,pady=self.pady)
            citation.configure(state ='disabled')

            with open('media/Citation') as f:
                citation.insert(tk.END,f.read())

            License_Label = tk.Label(popup,text='License:',font='TkTextFont')
            License_Label.grid(column=0,row=2,sticky=N,padx=self.padx,pady=self.pady)
            license = scrolledtext.ScrolledText(popup,
                                    width = 75,
                                    font = "TkTextFont")
            license.grid(column=0,row=3,sticky=N,padx=self.padx,pady=self.pady)
            license.configure(state ='disabled')
            with open('../LICENSE') as f:
                license.insert(tk.END,f.read())
            B1 = ttk.Button(popup, text="Okay", command = popup.destroy)
            B1.grid(column=0,row=4,padx=self.padx,pady=self.pady)

            # popup.grid_columnconfigure((1,3),weight=1)
            # popup.grid_rowconfigure((1,3),weight=1)

            popup.grid_columnconfigure((0,2),weight=1)
            popup.grid_rowconfigure((0,2),weight=1)

            popup.protocol('WM_DELETE_WINDOW', popup.destroy)

        self.generate_button = tk.Button(self.root, text="Generate Input", command=self.Generate_ini)
        self.generate_button.grid(column=3,row=2,sticky=E,padx=self.padx,pady=self.pady)

        self.run_button = tk.Button(self.root,text='Run',command=self.run_term)
        self.run_button.grid(column=1,row=2,columnspan=1,sticky=E,padx=self.padx,pady=self.pady)

        self.stop_button = tk.Button(self.root,text='Stop',command=self.stop_term)
        self.stop_button.grid(column=2,row=2,columnspan=1,sticky=W,padx=self.padx,pady=self.pady)

        if self.os == 'Windows':
            self.stop_button.config(state='disabled')

        self.about_button = tk.Button(self.root,text='About',command=about_citation)
        self.about_button.grid(column=0,row=2,columnspan=1,sticky=W,padx=self.padx,pady=self.pady)

        self.root.grid_columnconfigure(1, weight=1)
        self.root.grid_columnconfigure(2, weight=1)

        self.root.grid_rowconfigure(0,weight=1)

        # Create a empty frame
        self.label_frame = LabelFrame(self.root, text="Terminal", padx=5, pady=5)
        self.label_frame.grid(column=0,row=1, columnspan=4, padx=self.padx, pady=self.pady, sticky=E+W+N+S)

        # Create the textbox
        self.label_frame.rowconfigure(0,weight=1)
        self.label_frame.columnconfigure(0,weight=1)
        self.txtbox = scrolledtext.ScrolledText(self.label_frame, width=40, height=10)
        self.txtbox.grid(row=0, column=0, sticky=E+W+N+S)

    def Build_inputs_tab(self):
        arr_input = ["Data file", "Output File","Number of FEFF folder"]
        #FEFF Folder
        self.description_tabs(arr_input,self.tab_Inputs,row = [0,1,3])

        self.tab_Inputs.grid_columnconfigure(1,weight=1)

        entry_data_file = ttk.Combobox(self.tab_Inputs, textvariable=self.temp_data_file, font=self.entryFont)
        entry_data_file.grid(column=1, row=0, sticky=(W, E),padx=self.padx,pady=self.pady)

        entry_output_file = tk.Entry(self.tab_Inputs,textvariable=self.output_file,font=self.entryFont)
        entry_output_file.grid(column=1,row=1,sticky=(W,E),padx=self.padx,pady=self.pady)

        separator = ttk.Separator(self.tab_Inputs, orient='horizontal')
        separator.grid(column=0, row=2,columnspan=4,sticky=W+E,padx=self.padx)

        comp_list = list(range(1,6))
        entry_ncomp = ttk.Combobox(self.tab_Inputs, width=7, values=comp_list,textvariable=self.ncomp, font=self.entryFont)
        entry_ncomp.grid(column=1, row=3, sticky=(W, E),padx=self.padx)

        def select_data_file():
            os.chdir("..") #change the working directory from gui to EXAFS
            file_name =  filedialog.askopenfilenames(initialdir = os.getcwd(), title = "Choose xmu/csv", filetypes = (("xmu files", "*.xmu"),("csv files","*.csv"),("all files","*.*")))
            if not file_name:
                self.data_file.set('Please choose file/s')
                self.temp_data_file.set('Please choose file/s')
            else:
                if isinstance(file_name,tuple):
                    if len(file_name)==1:
                        self.data_file.set(str(file_name[0]))
                        self.temp_data_file.set(str(file_name[0]))
                    else:
                        file_list = list(self.root.splitlist(file_name))
                        separator = ' '
                        self.data_file.set(separator.join(file_list))
                        entry_data_file['value'] = file_list
                        self.series.set(True)
            os.chdir("gui")

        def select_output_file():
            os.chdir("..") #change the working directory from gui to EXAFS
            file_name =  filedialog.asksaveasfilename(initialdir = os.getcwd(), title = "Choose data_file", filetypes = (("csv files","*.csv"),("all files","*.*")))
            if not file_name:
                self.output_file.set('Please choose a file')
            else:
                self.output_file.set(file_name)
            os.chdir("gui")

        def feff_trace(var,indx,mode):
            # Todo: Need to add assertion to make sure every folder is not normal
            raw_str = []
            for i in range(len(self.feff_file_list)):
                raw_str.append(self.feff_file_list[i].get())
            raw_feff = ','.join(raw_str)
            self.feff_file.set(raw_feff)
            # print(raw_feff)
        def gen_feff_folder(var,indx,mode):
            ncomp = self.ncomp.get()
            self.feff_file_toggle = [True for i in range(self.ncomp.get())]
            k = 4
            try:
                self.arr_feff
                # self.input_list
            except AttributeError:
                pass
            else:
                for i in range(len(self.feff_input_list)):
                    self.feff_input_list[i].destroy()
                    self.feff_button_list[i].destroy()
                    self.feff_description_list[i].destroy()
            self.feff_file_list = []
            self.arr_feff= []
            arr_row = []
            # parameter sets
            self.feff_input_list = []
            self.feff_button_list = []
            self.feff_description_list = []
            # Need to remove previous one
            for i in range(ncomp):
                self.arr_feff.append('FEFF Folder (' + str(i+1) +")")
                arr_row.append(i+k)

                # Generate a list of variables
                temp_var = StringVar(self.root,'Please choose a directory')
                self.feff_file_list.append(temp_var)

                # Add trace back
                temp_var.trace_add('write',feff_trace)
                # Setup each entry
                temp_entry = tk.Entry(self.tab_Inputs,textvariable=temp_var,
                    font=self.entryFont)

                temp_entry.grid(column=1,row=k+i,sticky=(W,E),
                    padx=self.padx,pady=self.pady)
                self.feff_input_list.append(temp_entry)

                # setup each button
                temp_button = ttk.Button(self.tab_Inputs,text="Choose",
                        command=lambda x=i:select_feff_folder(self.feff_file_list[x]), style='my.TButton')
                temp_button.grid(column=3, row=k+i, sticky=W,padx=self.padx,pady=self.pady)
                self.feff_button_list.append(temp_button)

            self.feff_description_list = self.description_tabs(self.arr_feff,self.tab_Inputs,row=arr_row,return_description=True)

        def check_feff_folder(pathlib_Path):
            feff_inp_exists = False
            num_feff_file = 0
            folder_Path = pathlib.Path(pathlib_Path)
            for i in folder_Path.iterdir():
                file = pathlib.Path(i).name
                if fnmatch.fnmatch(file,'feff????.dat'):
                    num_feff_file +=1

            if num_feff_file == 0:
                # Check no scattering paths
                for i in folder_Path.iterdir():
                    file = pathlib.Path(i).name
                    if fnmatch.fnmatch(file,'feff.inp'):
                        feff_inp_exists = True
                        feff_inp_loc = file
                abs_feff_inp_loc = folder_Path.joinpath('feff.inp')
                create_feff_folder(abs_feff_inp_loc)
            else:
                # self.txtbox.insert('No feff.inp in folder')
                self.txtbox.insert(tk.END,"No feff.inp in folder\n")

                # return False
        def select_feff_folder(var):
            os.chdir("..") #change the working directory from gui to EXAFS
            # select folder name
            folder_name = filedialog.askdirectory(initialdir = os.getcwd(), title = "Select folder")

            if not folder_name:
                var.set('Please choose a directory')
            else:
                check_feff_folder(folder_name)
                folder_name = os.path.join(folder_name,'feff')
                var.set(folder_name)

            os.chdir("gui")

        # add trace back
        self.ncomp.trace_add('write',gen_feff_folder)
        self.ncomp.set(1)

        button_data_file = ttk.Button(self.tab_Inputs, text="Choose",
                command=select_data_file, style='my.TButton')
        button_data_file.grid(column=3, row=0, sticky=W,padx=self.padx,pady=self.pady)

        button_output_file = ttk.Button(self.tab_Inputs,text="Choose",
                command=select_output_file, style='my.TButton')
        button_output_file.grid(column=3, row=1, sticky=W,padx=self.padx,pady=self.pady)


    def Build_population_tab(self):
        arr_pop = ["Population", "Number of Generations", "Best Individuals(%)", "Lucky Survivor(%)"]
        self.description_tabs(arr_pop,self.tab_Populations)

        self.tab_Populations.grid_columnconfigure(1,weight=1)

        entry_population = tk.Entry(self.tab_Populations, textvariable=self.populations, font=self.entryFont)
        entry_population.grid(column=1, row=0, sticky=(W, E),padx=self.padx)

        entry_num_gen = tk.Entry(self.tab_Populations, textvariable=self.num_gen, font=self.entryFont)
        entry_num_gen.grid(column=1, row=1, sticky=(W, E),padx=self.padx)

        entry_best_sample = tk.Entry(self.tab_Populations, textvariable=self.best_sample, font=self.entryFont)
        entry_best_sample.grid(column=1, row=2, sticky=(W, E),padx=self.padx)

        entry_lucky_few = tk.Entry(self.tab_Populations, textvariable=self.lucky_few, font=self.entryFont)
        entry_lucky_few.grid(column=1, row=3, sticky=(W, E),padx=self.padx)

    def Build_path_tab(self):
        """
        Build path tabs
        """

        arr_paths = ['Path Optimize','Multi-Path Optimize','Path Optimize Percentage']
        self.description_tabs(arr_paths,self.tab_Paths,row = [0,1,2])

        def checkbox_individual_paths():
            if self.individual_path.get() == True:
                entry_path_range.config(state='disabled')
                entry_path_list.config(state='normal')

            else:
                entry_path_range.config(state='normal')
                entry_path_list.config(state='disabled')

        # def path_list_cb(var, indx, mode):
        #     """
        #     Path_list call-back for the number of lists
        #     """
        #     if self.individual_path.get()== True:
        #         self.path_list.set(self.path_list_call.get())
        #         counts = 0
        #         test_list = self.path_list.get().split(",")
        #         for i in range(len(test_list)):
        #             if test_list[i] != '':
        #                 counts += 1
        #         self.path_range_call.set(counts)

        # entry_individual_paths = ttk.Checkbutton(self.tab_Paths,
        #     variable = self.individual_path,command = checkbox_individual_paths)
        # entry_individual_paths.grid(column=1,row=0,sticky=(W),padx=self.padx)

        # self.path_range_call = StringVar(self.tab_Paths,str(self.path_range.get()))
        # self.path_range_call.trace_add("write",path_range_cb)
        # entry_path_range = ttk.Entry(self.tab_Paths, width=7,
        #         textvariable=self.path_range_call, font=self.entryFont)
        # entry_path_range.grid(column=1, row=1, sticky=(W),padx=self.padx)

        # self.path_list_call = StringVar(self.tab_Paths,self.path_list.get())
        # self.path_list_call.trace_add('write',path_list_cb)
        # entry_path_list = ttk.Entry(self.tab_Paths,
        #         textvariable=self.path_list_call, font=self.entryFont)
        # entry_path_list.grid(column=1, row=2, sticky=(W, E),padx=self.padx)
        # entry_path_list.config(state='disabled')

        # def path_range_cb(var, indx, mode):
        #     if self.individual_path.get()==False:
        #         if self.path_range_call.get() == '':
        #             int_test = 0
        #         else:
        #             int_test = int(float(self.path_range_call.get()))
        #         self.path_range_call.set(int_test)
        #         self.path_range.set(int_test)
        #
        #         custom_path_list = ",".join(np.char.mod('%i', np.arange(1,self.path_range.get()+1)))
        #         self.path_list_call.set(custom_path_list)
        #         self.path_list.set(custom_path_list)
        # def test_str(var):


        def output_var_trace(var,indx,mode):
            """
            Updates the variables whenever it gets changes
            """
            raw_str = []
            # compounds
            if self.ncomp.get() > 1:
                for i in range(len(self.path_file_list)):
                        # print(self.path_file_list[i].get())
                        # create the internal brackets
                        # base_str = list(self.path_file_list[i].get())
                        var = self.path_file_list[i].get()
                        if var == str(0) or var == "":
                            base_str = ''
                            # del the corresponding one from the final output
                            self.feff_file_toggle[i] = False
                        else:
                            base_str = "[" + var + "]"
                            self.feff_file_toggle[i] = True
                        raw_str.append(base_str)

                # call back for path and feff
                temp_path_list = []
                temp_feff_list = []
                for i in range(len(self.path_file_list)):
                    if self.feff_file_toggle[i] == True:
                        temp_path_list.append(raw_str[i])
                        temp_feff_list.append(self.feff_file_list[i].get())
                raw_path = ','.join(temp_path_list)
                raw_feff = ','.join(temp_feff_list)
                self.path_list.set(raw_path)
                self.feff_file.set(raw_feff)
                self.individual_path.set(True)
            # else calculate compounds
            else:
                self.path_list.set(self.path_file_list[0].get())

            # print("-----------------------")
            # print(self.feff_file_toggle)
            # print(self.feff_file.get())
            # print(self.path_list.get())

        def ncomp_trace_cb(var, indx, mode):
            """
                Trace the number of components, if changes, recomputed
            """
            ncomp = self.ncomp.get()
            k = 5 # Starting components

            # Check if arr_pathlist exists
            try:
                self.arr_pathlist
            except AttributeError:
                pass
            else:
                # Destory all in the current list
                for i in range(len(self.path_input_list)):
                    self.path_description_list[i].destroy()
                    self.path_input_list[i].destroy()
            # Create the list
            self.arr_pathlist = []
            self.path_input_list = []
            self.path_file_list = []
            arr_row = []
            for i in range(ncomp):
                self.arr_pathlist.append('Pathlist Folder ('+ str(i+1) + ")")
                arr_row.append(i+k)
                # Create the entry variable
                temp_path_var = StringVar(self.root,'Path_list')
                temp_path_var.trace_add('write',output_var_trace)
                # temp_path_var.trace_add('write',)
                self.path_file_list.append(temp_path_var)
                # Create the entry
                temp_entry = tk.Entry(self.tab_Paths,textvariable=self.path_file_list[i],
                    font=self.entryFont)
                # lock to the grid
                temp_entry.grid(column=1,columnspan=2,row=k+i,sticky=(W,E),
                    padx=self.padx,pady=self.pady)

                self.path_input_list.append(temp_entry)

            # create the descriptions for it.
            self.path_description_list = self.description_tabs(self.arr_pathlist,self.tab_Paths,row=arr_row,return_description=True)

        entry_path_optimize = ttk.Checkbutton(self.tab_Paths,
            variable = self.path_optimize)
        entry_path_optimize.grid(column=1,row=0,sticky=(W,E),padx=self.padx)

        entry_path_optimize_only = ttk.Checkbutton(self.tab_Paths,
            variable = self.path_optimize_only)
        entry_path_optimize_only.grid(column=1,row=1,sticky=(W,E),padx=self.padx)

        entry_optimize_perc= ttk.Entry(self.tab_Paths, textvariable=self.path_optimize_pert, font=self.entryFont)
        entry_optimize_perc.grid(column=1, row=2, sticky=(W, E),padx=self.padx)

        separator = ttk.Separator(self.tab_Paths, orient='horizontal')
        separator.grid(column=0, row=3,columnspan=4,sticky=(W,E),padx=self.padx)
        self.tab_Paths.columnconfigure(4,weight=1)

        # add the call back for it to modify if it get changes
        self.ncomp.trace_add('write',ncomp_trace_cb)

        # inital default value
        self.ncomp.set(1)

    def Build_mutations_tab(self):
        arr_muts = ["Mutation Chance (%)", "Original chance of mutation (%)", "E0 Mutation Chance (%)", "Mutation Options"]
        self.description_tabs(arr_muts,self.tab_Mutation)

        mut_list = list(range(101))
        # self.tab_Inputs.grid_columnconfigure(1,weight=1)

        entry_chance_of_mutation = ttk.Combobox(self.tab_Mutation, width=7, values=mut_list,textvariable=self.chance_of_mutation, font=self.entryFont)
        entry_chance_of_mutation.grid(column=1, row=0, sticky=(W, E),padx=self.padx)

        entry_chance_of_mutation = ttk.Combobox(self.tab_Mutation, width=7, values=mut_list,textvariable=self.orginal_chance_of_mutation, font=self.entryFont)
        entry_chance_of_mutation.grid(column=1, row=1, sticky=(W, E),padx=self.padx)

        entry_chance_of_mutation = ttk.Combobox(self.tab_Mutation, width=7, values=mut_list,textvariable=self.chance_of_mutation_e0, font=self.entryFont)
        entry_chance_of_mutation.grid(column=1, row=2, sticky=(W, E),padx=self.padx)

        mut_list = list(range(3))
        entry_chance_of_mutation = ttk.Combobox(self.tab_Mutation, width=7, values=mut_list,textvariable=self.mutation_options, font=self.entryFont)
        entry_chance_of_mutation.grid(column=1, row=3, sticky=(W, E),padx=self.padx)

    def Build_larch_tab(self):
        arr_larch = ["Kmin", "Kmax", "Kweight", "Delta k", "R Bkg", "Bkg Kw", "Bkg Kmax"]
        self.description_tabs(arr_larch,self.tab_Larch)

        entry_kmin = ttk.Entry(self.tab_Larch, textvariable=self.kmin, font=self.entryFont)
        entry_kmin.grid(column=1, row=0, sticky=(W, E),padx=self.padx)

        entry_kmax = ttk.Entry(self.tab_Larch, textvariable=self.kmax, font=self.entryFont)
        entry_kmax.grid(column=1, row=1, sticky=(W, E),padx=self.padx)

        entry_k_weight = ttk.Entry(self.tab_Larch, textvariable=self.k_weight, font=self.entryFont)
        entry_k_weight.grid(column=1, row=2, sticky=(W, E),padx=self.padx)

        entry_delta_k = ttk.Entry(self.tab_Larch, textvariable=self.delta_k, font=self.entryFont)
        entry_delta_k.grid(column=1, row=3, sticky=(W, E),padx=self.padx)

        entry_r_bkg = ttk.Entry(self.tab_Larch, textvariable=self.r_bkg, font=self.entryFont)
        entry_r_bkg.grid(column=1, row=4, sticky=(W, E),padx=self.padx)

        entry_bkg_kw = ttk.Entry(self.tab_Larch, textvariable=self.bkg_kw, font=self.entryFont)
        entry_bkg_kw.grid(column=1, row=5, sticky=(W, E),padx=self.padx)

        entry_bkg_kmax = ttk.Entry(self.tab_Larch, textvariable=self.bkg_kmax, font=self.entryFont)
        entry_bkg_kmax.grid(column=1, row=6, sticky=(W, E),padx=self.padx)

    def Build_background_tab(self):

        def button_bkg_draw():
            # TODO:
                # Makes it so
            bkg_plot.inital_parameters(self.temp_data_file,self.r_bkg,self.bkg_kw,self.bkg_kmax,self.kmin,self.kmax,self.delta_k,self.k_weight)
            bkg_plot.draw_background()

        arr_bkg = ["R Bkg", "K min","K max","Bkg Kw", "Bkg Kmax"]
        self.description_tabs(arr_bkg,self.tab_Bkg,sticky=(W,E,N))
        # self.tab_Bkg.grid_rowconfigure(3,weight=1)
        # self.tab_Bkg.grid_rowconfigure(4,weight=1)
        # self.tab_Bkg.grid_rowconfigure(5,weight=1)
        # self.tab_Bkg.grid_rowconfigure(6,weight=1)

        self.tab_Bkg.rowconfigure(8,weight=1)
        self.tab_Bkg.columnconfigure(2,weight=1)

        entry_r_bkg = ttk.Entry(self.tab_Bkg, textvariable=self.r_bkg, font=self.entryFont)
        entry_r_bkg.grid(column=1, row=0, sticky=(W,E,N),padx=self.padx,pady=self.pady)

        entry_k_min = ttk.Entry(self.tab_Bkg, textvariable=self.kmin, font=self.entryFont)
        entry_k_min.grid(column=1, row=1, sticky=(W,E,N),padx=self.padx,pady=self.pady)

        entry_k_max = ttk.Entry(self.tab_Bkg, textvariable=self.kmax, font=self.entryFont)
        entry_k_max.grid(column=1, row=2, sticky=(W,E,N),padx=self.padx,pady=self.pady)

        entry_bkg_kw = ttk.Entry(self.tab_Bkg, textvariable=self.bkg_kw, font=self.entryFont)
        entry_bkg_kw.grid(column=1, row=3, sticky=(W,E,N),padx=self.padx,pady=self.pady)

        entry_bkg_kmax = ttk.Entry(self.tab_Bkg, textvariable=self.bkg_kmax, font=self.entryFont)
        entry_bkg_kmax.grid(column=1, row=4, sticky=(W,E,N),padx=self.padx,pady=self.pady)

        bkg_plot = BKG_plot(self.tab_Bkg,self.mylarch)

        button_bkg_mu = ttk.Button(self.tab_Bkg, text="Plot Background and Mu",
            command=button_bkg_draw)
        button_bkg_mu.grid(column=0, row=5,columnspan=2,sticky=W+E,padx=self.padx,pady=self.pady)

        button_kspace = ttk.Button(self.tab_Bkg, text="K space",
            command=bkg_plot.draw_kspace)
        button_kspace.grid(column=0, row=6,columnspan=2,sticky=W+E,padx=self.padx,pady=self.pady)

        button_rspace = ttk.Button(self.tab_Bkg, text="R space",
            command=bkg_plot.draw_rspace)
        button_rspace.grid(column=0, row=7,columnspan=2,sticky=W+E,padx=self.padx,pady=self.pady)

    def Build_output_tab(self):

        pop_min = IntVar(self.tab_Output,100)
        pop_max = IntVar(self.tab_Output,5001)
        gen_min = IntVar(self.tab_Output,20)
        gen_max = IntVar(self.tab_Output,501)
        mut_min = IntVar(self.tab_Output,20)
        mut_max = IntVar(self.tab_Output,51)

        pertub_check = IntVar(self.tab_Output,0)
        def generate_multi_ini():
            # os.chdir("..")
            pop_range = np.arange(pop_min.get(),pop_max.get(),100)
            gen_range = np.arange(gen_min.get(),gen_max.get(),5)
            mut_range = np.arange(mut_min.get(),mut_max.get(),10)
            # exit()
            multi_folder = filedialog.askdirectory(initialdir = os.getcwd(),title = 'Select folder')
            if not multi_folder:
                return
            else:
                og_pop = self.populations.get()
                og_gen = self.num_gen.get()
                og_mut = self.chance_of_mutation.get()
                og_out_file = self.output_file.get()

                for i in range(self.n_ini.get()):

                    pop_select = np.random.choice(pop_range)
                    gen_select = np.random.choice(gen_range)
                    mut_select = np.random.choice(mut_range)
                    base_file = os.path.splitext(og_out_file)[0]
                    self.output_file.set(os.path.join(base_file +"_"+str(i).zfill(3) +".ini"))
                    self.populations.set(pop_select)
                    self.num_gen.set(gen_select)
                    self.chance_of_mutation.set(mut_select)
                    self.Write_ini(multi_folder + "/file_" + str(i).zfill(3)+'.i')
                # set back og ini
                self.populations.set(og_pop)
                self.num_gen.set(og_gen)
                self.chance_of_mutation.set(og_mut)
                self.output_file.set(og_out_file)
            # os.chdir("gui")
            return multi_folder
        def run_multi_ini():
            """
            Run multiple ini file
            """
            folder_loc = generate_multi_ini()

            full_file_list = []
            file_list = glob.glob(folder_loc + "/*.i")
            for i in file_list:
                full_file_list.append(os.path.join(folder_loc,i))

            full_file_list.sort(key=natural_keys)
            for i in full_file_list:
                print(bcolors.BOLD + str(i) + bcolors.ENDC)
                self.run_ini(i)
        def checkbox_multi():
            widget_lists=[
                entry_n_ini,
                entry_pertub_pop_min,
                entry_pertub_pop_max,
                entry_pertub_gen_min,
                entry_pertub_gen_max,
                entry_pertub_mut_min,
                entry_pertub_mut_max,
                button_gen_nini,
                button_run_nini]
            if pertub_check.get() == 0:
                for i in widget_lists:
                    i.config(state='disabled')
            elif pertub_check.get() == 1:
                for i in widget_lists:
                    i.config(state='normal')

        arr_out = ["Print graph", "Steady state exit"]
        self.description_tabs(arr_out,self.tab_Output)

        checkbutton_print_graph = ttk.Checkbutton(self.tab_Output, var=self.print_graph)
        checkbutton_print_graph.grid(column=1, row=0,sticky=W+E,padx=self.padx)

        checkbutton_steady_state= ttk.Checkbutton(self.tab_Output, var=self.steady_state_exit)
        checkbutton_steady_state.grid(column=1, row=1,sticky=W+E,padx=self.padx)

        # Create separators
        separator = ttk.Separator(self.tab_Output, orient='horizontal')
        separator.grid(column=0, row=2,columnspan=4,sticky=W+E,padx=self.padx)
        self.tab_Output.columnconfigure(3,weight=1)

        arr_out = ["Create Multiple Input Files","Number of Ini Files","Pertubutions-Population(min,max)", "Pertubutions-Generation(min,max)","Pertubutions-Mutation(min,max)"]
        self.description_tabs(arr_out,self.tab_Output,row=[3,5,6,7,8])

        # Create New pertubutuions
        checkbutton_pertub= ttk.Checkbutton(self.tab_Output, var=pertub_check,command=checkbox_multi)
        checkbutton_pertub.grid(column=1, row=3,sticky=W+E,padx=self.padx)

        pertub_list = list(range(1,101))

        text ='Each entry allows user to control perturbation percentage of the desire variables.'
        entry = ttk.Label(self.tab_Output,text=text,font=self.labelFont)
        entry.grid_configure(column=0,row=4,columnspan=3,sticky=W+E,padx=self.padx,pady=self.pady)

        entry_n_ini = tk.Entry(self.tab_Output,textvariable=self.n_ini,font=self.entryFont)
        entry_n_ini.grid(column=1, row=5,columnspan=2,sticky=(W, E),padx=self.padx)

        entry_n_ini.config(state='disabled')

        width = 5
        # --------------
        entry_pertub_pop_min= ttk.Entry(self.tab_Output, width=width,textvariable=pop_min, font=self.entryFont)
        entry_pertub_pop_min.grid(column=1, row=6, sticky=(W, E),padx=self.padx)

        entry_pertub_pop_max= ttk.Entry(self.tab_Output, width=width,textvariable=pop_max, font=self.entryFont)
        entry_pertub_pop_max.grid(column=2, row=6, sticky=(W, E),padx=self.padx)

        entry_pertub_pop_min.config(state='disabled')
        entry_pertub_pop_max.config(state='disabled')

        # --------------
        entry_pertub_gen_min= ttk.Entry(self.tab_Output, width=width,textvariable=gen_min, font=self.entryFont)
        entry_pertub_gen_min.grid(column=1, row=7, sticky=(W, E),padx=self.padx)

        entry_pertub_gen_max= ttk.Entry(self.tab_Output, width=width,textvariable=gen_max, font=self.entryFont)
        entry_pertub_gen_max.grid(column=2, row=7, sticky=(W, E),padx=self.padx)

        entry_pertub_gen_min.config(state='disabled')
        entry_pertub_gen_max.config(state='disabled')

        # --------------
        entry_pertub_mut_min= ttk.Entry(self.tab_Output, width=width,textvariable=mut_min, font=self.entryFont)
        entry_pertub_mut_min.grid(column=1, row=8, sticky=(W, E),padx=self.padx)

        entry_pertub_mut_max= ttk.Entry(self.tab_Output, width=width,textvariable=mut_max, font=self.entryFont)
        entry_pertub_mut_max.grid(column=2, row=8, sticky=(W, E),padx=self.padx)

        entry_pertub_mut_min.config(state='disabled')
        entry_pertub_mut_max.config(state='disabled')

        # --------------

        button_gen_nini = tk.Button(self.tab_Output,text="Generate Input Files",command=generate_multi_ini)
        button_gen_nini.grid(column=0, row=9,columnspan=3,sticky=W+E,padx=self.padx,pady=self.pady)
        button_gen_nini.config(state='disabled')

        button_run_nini = tk.Button(self.tab_Output,text="Run Multiple Input Files",command=run_multi_ini)
        button_run_nini.grid(column=0, row=10,columnspan=3,sticky=W+E,padx=self.padx,pady=self.pady)
        button_run_nini.config(state='disabled')

    def Build_analysis_tab(self):

        def select_analysis_folder():
            os.chdir("..") #change the working directory from gui to EXAFS
            folder_name = filedialog.askdirectory(initialdir = os.getcwd(), title = "Select folder")
            if not folder_name:
                analysis_folder.set('Please choose a directory')
            else:
                # folder_name = os.path.join(folder_name,'feff')
                analysis_folder.set(folder_name)
            # print(self.feff_file.get())
            os.chdir("gui")
        def run_analysis():
            params = {}
            # params['base'] = Path(os.getcwd()).parent
            params['base'] = ''
            params['Kmin'] = self.kmin.get()
            params['Kmax'] = self.kmax.get()
            params['kweight'] = self.k_weight.get()
            params['deltak'] = self.delta_k.get()
            params['rbkg'] = self.r_bkg.get()
            params['bkgkw'] = self.bkg_kw.get()
            params['bkgkmax'] = self.bkg_kmax.get()
            params['front'] = self.feff_file.get().split(',')
            params['CSV'] = self.data_file.get()
            params['optimize'] = self.path_optimize.get()
            params['series_index'] = series_index.get()
            params['series'] = self.series.get()
            # set up the params
            self.txtbox.insert(tk.END,"Running Analysis...\n")
            analysis_plot.setup_params(params)

            paths = '[' + self.path_list.get() + ']'
            paths_list = ast.literal_eval(paths)
            # analysis_plot.setup_paths(paths)
            print(paths)
            print(paths_list)
            print(type(paths_list))
            analysis_plot.setup_paths(ast.literal_eval(paths))

            analysis_plot.setup_dirs(analysis_folder.get())
            arr_str,latex_str = analysis_plot.extract_and_run(analysis_folder)

            self.txtbox.insert(tk.END,arr_str)
            self.txtbox.insert(tk.END,"-------------\n")
            self.txtbox.insert(tk.END,latex_str)
            self.txtbox.insert(tk.END,"\n-------------\n")
            self.txtbox.insert(tk.END,"Done")

        def plot_occurances():
            # plot the self_occurances, and then plot the others
            """
            To do: occurances only works with one
            """
            analysis_plot.plot_occurances(analysis_folder.get(),self.path_optimize_pert.get(),self.path_list.get())

        analysis_folder = StringVar(self.tab_Analysis,'Please choose a directory')
        series_index = IntVar(self.tab_Analysis,0)
        self.tab_Analysis.columnconfigure(1,weight=1)
        self.tab_Analysis.columnconfigure(2,weight=1)
        self.tab_Analysis.rowconfigure(10,weight=1)

        arr_out = ["Select folder"]
        self.description_tabs(arr_out,self.tab_Analysis)

        entry_analysis_folder = tk.Entry(self.tab_Analysis,textvariable=analysis_folder,font=self.entryFont)
        entry_analysis_folder.grid(column=1,row=0,columnspan=2,sticky=W+E,padx=self.padx,pady=self.pady)

        button_analysis_folder = ttk.Button(self.tab_Analysis,text="Choose",
                command=select_analysis_folder, style='my.TButton')
        button_analysis_folder.grid(column=3, row=0, sticky=W+E,padx=self.padx,pady=self.pady)

        separator = ttk.Separator(self.tab_Analysis, orient='horizontal')
        separator.grid(column=0, row=1,columnspan=4,sticky=W+E,padx=self.padx)

        analysis_plot = Analysis_Plot(self.tab_Analysis,self.mylarch)

        # ----------------------------------------------------------------------
        button_Run_Analysis = ttk.Button(self.tab_Analysis,text="Run Analysis",
                command=run_analysis, style='my.TButton')
        button_Run_Analysis.grid(column=0, row=2,columnspan=4, sticky=W+E,padx=self.padx,pady=self.pady)

        button_plot_kR = ttk.Button(self.tab_Analysis,text="Plot K and R Spectrum",
                command=analysis_plot.plot_k_r_space, style='my.TButton')
        button_plot_kR.grid(column=0, row=3,columnspan=1, sticky=W+E,padx=self.padx,pady=self.pady)

        button_plot_individual = ttk.Button(self.tab_Analysis,text='Plot K Individual',
                command=analysis_plot.plot_individual, style='my.TButton')
        button_plot_individual.grid(column=1, row=3,columnspan=1, sticky=W+E,padx=self.padx,pady=self.pady)


        button_plot_error = ttk.Button(self.tab_Analysis,text="Plot Error",
                command=analysis_plot.plot_error, style='my.TButton')
        button_plot_error.grid(column=2, row=3,columnspan=1, sticky=W+E,padx=self.padx,pady=self.pady)


        button_plot_occurances = ttk.Button(self.tab_Analysis,text='Plot Occurances',
                command=plot_occurances, style='my.TButton')
        button_plot_occurances.grid(column=3,row=3,columnspan=1,sticky=W+E,padx=self.padx,pady=self.pady)

    def Build_expert_tab(self):
        arr_muts = ["Override Num Compounds"]
        self.description_tabs(arr_muts,self.tab_Expert)

        ncomp_list = list(range(1,101))
        entry_ncomp = ttk.Combobox(self.tab_Expert, width=7, values=ncomp_list,textvariable=self.ncomp, font=self.entryFont)
        entry_ncomp.grid(column=1, row=0, sticky=(W, E),padx=self.padx)


    def On_closing(self):
        """
        on closing function
        """
        if messagebox.askokcancel("Quit", "Do you want to quit?"):
            self.stop_term()
            if hasattr(self,'terminal'):
                self.root.quit()
                self.terminal.destroy()
            else:
                self.root.quit()

    def Run(self):
        """
        Run the code
        """
        self.root.protocol('WM_DELETE_WINDOW', self.On_closing)
        self.beta_popup()

        self.root.mainloop()

    def beta_popup(self):
        beta_popup = tk.Toplevel(self.root)
        beta_popup.wm_title("Warning")
        msg = "This Graphical User Interface is still under active development.\nPlease contact us using Github Issues."
        entry = ttk.Label(beta_popup,text=msg)
        entry.grid(column=0,row=0,padx=5,pady=3)
        B1 = ttk.Button(beta_popup, text="Okay", command = beta_popup.destroy)
        B1.grid(column=0,row=1,padx=5,pady=3)

        beta_popup.grid_columnconfigure((0,1),weight=1)
        beta_popup.grid_rowconfigure((0,1),weight=1)
        beta_popup.protocol('WM_DELETE_WINDOW', beta_popup.destroy)
        beta_popup.attributes('-topmost', 'true')
Example #10
0
def on_value_change(event):
    global selected_chapter
    # The extra chapters have urls that contain dashes instead of dots (e. g. 64.5 becomes 64-5)
    selected_chapter = ((dropDown.get()).split(" ", 1)[0]).replace(".", "-")


def on_radiobutton_change(a, b, c):
    dropDown.config(values=choices[selected_manga.get()])
    dropDown_vol.config(values=choices_vol[selected_manga.get()])
    dropDown.current(0)
    dropDown_vol.current(0)


dropDown.bind("<<ComboboxSelected>>", on_value_change)
selected_manga.trace_add("write", on_radiobutton_change)

note_book.add(page_download_chapters, text="Chapters")
note_book.add(page_download_volumes, text="Volumes")
note_book.add(page_show_help, text="Info")

note_book.grid(column=0, row=0, padx=10, pady=10, ipadx=10, ipady=10)

progress = ttk.Progressbar(app,
                           orient="horizontal",
                           length=450,
                           mode='determinate')
progress.grid(column=0, row=2, ipady=5)

progressLabel = ttk.Label(app, text="Ready")
progressLabel.grid(column=0, row=1, pady=(5, 0))
Example #11
0
class MakeScale:
    """"create slider (scale) widgets"""
    def __init__(self, frame, step=0.0, offset=1.0, res=1):
        self.row_i = 1
        self.column = 2
        self.rowspan = 1
        self.sticky = 'NSEW'
        self.frame = frame
        self.text = ""

        self.from_ = 1
        self.to = 11
        self.step = step
        self.offset = offset
        self.res = res

        self.input_var = IntVar()

    def create_separator(self):
        Separator(self.frame).grid(row=self.row_i)

    def create_empty_space(self):
        Label(self.frame, anchor=W).grid(row=self.row_i)
        self.row_i += 1

    def create_scale(self):
        scale = Limiter(self.frame,
                        from_=self.from_,
                        to=self.to,
                        orient=HORIZONTAL,
                        length=200,
                        variable=self.input_var,
                        precision=0,
                        step=self.step,
                        offset=self.offset,
                        res=self.res)
        scale.grid(row=self.row_i,
                   column=self.column + 1,
                   columnspan=2,
                   rowspan=self.rowspan,
                   sticky=self.sticky)
        return scale

    def set_offset(self, label):
        var = self.input_var
        step = self.step
        res = self.res
        offset = self.offset

        def update_other_label(*args):
            value = var.get()
            multiplier = round(value * step, res)
            product = round(offset + multiplier - step, res)

            input_var_mult.set(product)

        self.input_var.trace_add("write", update_other_label)
        input_var_mult = DoubleVar()

        label.config(textvariable=input_var_mult)

    def create_text_label(self):
        txt = Label(self.frame, text=self.text, anchor=W)
        txt.grid(row=self.row_i,
                 column=self.column,
                 columnspan=1,
                 rowspan=self.rowspan,
                 sticky=self.sticky)

    def create_value_label(self):
        scale_nr = Label(self.frame,
                         textvariable=self.input_var,
                         anchor=E,
                         width=5)
        scale_nr.grid(row=self.row_i,
                      column=self.column + 4,
                      columnspan=1,
                      rowspan=self.rowspan,
                      sticky=self.sticky)

        return scale_nr

    def make(self, text, from_=1, to=11, step=0.0, offset=1.0, res=1):
        self.input_var = IntVar()

        self.from_ = from_
        self.to = to
        self.text = text
        self.step = step
        self.offset = offset
        self.res = res

        if (self.row_i % 3) == 0:  # create empty space every 2 sliders
            self.create_empty_space()

        self.create_separator()
        scale = self.create_scale()
        self.create_text_label()
        scale_nr = self.create_value_label()

        if step != 0:
            self.set_offset(scale_nr)

        self.row_i += 1
        return scale