          vid_ext = ''
          for ve in [ve.replace('.', '') for ve in DataItem.vid_ext]:
              if ve in zero_pad:
                  vid_ext = ve
                  zero_pad = len(zero_pad.replace(ve, ''))
                  break
  
          zero_pad = str(zero_pad).zfill(2)
          filename_list = [name, vid_ext + '%0' + zero_pad + 'd', img_ext]
          return '.'.join(filename_list)
 
</s> remove         filename_list = [name, vid_ext + '%0' + zero_pad + 'd', img_ext]
 </s> add         filename_list = [name, vid_ext + underscore + '%' + zero_pad + 'd',
                         img_ext] </s> remove     @staticmethod
    def __parse_transpose(value):
        index = 0
        opts = ["(0, 90CounterClockwise&VerticalFlip)",
                "(1, 90Clockwise)",
                "(2, 90CounterClockwise)",
                "(3, 90Clockwise&VerticalFlip)",
                "None"]
        if len(value) == 1:
            index = int(value)
        else:
            for i in range(5):
                if value in opts[i]:
                    index = i
                    break
        return opts[index]

 </s> add  </s> remove         self.opts = self.extract_options(subparsers)
        self.utils = Utils(self.opts, calling_file=cmd[0])
        self.root = FaceswapGui(self.utils, calling_file=cmd[0])

    @staticmethod
    def check_display():
        """ Check whether there is a display to output the GUI. If running on
            Windows then assume not running in headless mode """
        if not os.environ.get('DISPLAY', None) and os.name != 'nt':
            if os.name == 'posix':
                print('macOS users need to install XQuartz. '
                      'See https://support.apple.com/en-gb/HT201341')
            return False
        return True

    @staticmethod
    def check_tkinter_available():
        """ Check whether TkInter is installed on user's machine """
        tkinter_vars = [tk, ttk, filedialog, messagebox, TclError]
        if any(var is None for var in tkinter_vars):
            print(
                "It looks like TkInter isn't installed for your OS, so "
                "the GUI has been "
                "disabled. To enable the GUI please install the TkInter "
                "application.\n"
                "You can try:\n"
                "  Windows/macOS:      Install ActiveTcl Community "
                "Edition from "
                "www.activestate.com\n"
                "  Ubuntu/Mint/Debian: sudo apt install python3-tk\n"
                "  Arch:               sudo pacman -S tk\n"
                "  CentOS/Redhat:      sudo yum install tkinter\n"
                "  Fedora:             sudo dnf install python3-tkinter\n",
                file=sys.stderr)
            return False
        return True

    def extract_options(self, subparsers):
        """ Extract the existing ArgParse Options """
        opts = {cmd: subparsers[cmd].argument_list + subparsers[cmd].optional_arguments
                for cmd in subparsers.keys()}
        for command in opts.values():
            for opt in command:
                if opt.get('help', '') == SUPPRESS:
                    command.remove(opt)
                ctl, sysbrowser, filetypes, actions_open_types = self.set_control(opt)
                opt['control_title'] = self.set_control_title(
                    opt.get('opts', ''))
                opt['control'] = ctl
                opt['filesystem_browser'] = sysbrowser
                opt['filetypes'] = filetypes
                opt['actions_open_types'] = actions_open_types
        return opts

    @staticmethod
    def set_control_title(opts):
        """ Take the option switch and format it nicely """
        ctltitle = opts[1] if len(opts) == 2 else opts[0]
        ctltitle = ctltitle.replace('-', ' ').replace('_', ' ').strip().title()
        return ctltitle

    @staticmethod
    def set_control(option):
        """ Set the control and filesystem browser to use for each option """
        sysbrowser = None
        filetypes = None
        actions_open_type = None
        ctl = ttk.Entry
        if option.get('action', '') == FullPaths:
            sysbrowser = 'folder'
        elif option.get('action', '') == DirFullPaths:
            sysbrowser = 'folder'
        elif option.get('action', '') == FileFullPaths:
            sysbrowser = 'load'
            filetypes = option.get('filetypes', None)
        elif option.get('action', '') == ComboFullPaths:
            sysbrowser = 'combo'
            actions_open_type = option['actions_open_type']
            filetypes = option.get('filetypes', None)
        elif option.get('choices', '') != '':
            ctl = ttk.Combobox
        elif option.get('action', '') == 'store_true':
            ctl = ttk.Checkbutton
        return ctl, sysbrowser, filetypes, actions_open_type
 </s> add         self.root = FaceswapGui(pathscript) </s> remove from lib.cli import FullPaths, ComboFullPaths, DirFullPaths, FileFullPaths
from lib.Serializer import JSONSerializer


PATHSCRIPT = os.path.realpath(os.path.dirname(sys.argv[0]))

# An error will be thrown when importing tkinter for users without tkinter
# distribution packages or without an X-Console. Therefore if importing fails
# no attempt will be made to instantiate the gui.
try:
    import tkinter as tk
    from tkinter import ttk
    from tkinter import filedialog
    from tkinter import messagebox
    from tkinter import TclError
except ImportError:
    tk = None
    ttk = None
    filedialog = None
    messagebox = None
    TclError = None


class Utils(object):
    """ Inter-class object holding items that are required across classes """

    def __init__(self, options, calling_file="faceswap.py"):
        self.opts = options

        self.icons = dict()
        self.guitext = dict()
        self.actionbtns = dict()

        self.console = None
        self.debugconsole = False

        self.serializer = JSONSerializer
        self.filetypes = (('Faceswap files', '*.fsw'), ('All files', '*.*'))

        self.task = FaceswapControl(self, calling_file=calling_file)
        self.runningtask = False

        self.previewloc = os.path.join(PATHSCRIPT, '.gui_preview.png')

        self.lossdict = dict()

    def init_tk(self):
        """ TK System must be on prior to setting tk variables,
        so initialised from GUI """
        pathicons = os.path.join(PATHSCRIPT, 'icons')
        self.icons['folder'] = tk.PhotoImage(
            file=os.path.join(pathicons, 'open_folder.png'))
        self.icons['load'] = tk.PhotoImage(
            file=os.path.join(pathicons, 'open_file.png'))
        self.icons['save'] = tk.PhotoImage(
            file=os.path.join(pathicons, 'save.png'))
        self.icons['reset'] = tk.PhotoImage(
            file=os.path.join(pathicons, 'reset.png'))
        self.icons['clear'] = tk.PhotoImage(
            file=os.path.join(pathicons, 'clear.png'))

        self.guitext['help'] = tk.StringVar()
        self.guitext['status'] = tk.StringVar()

    def action_command(self, command):
        """ The action to perform when the action button is pressed """
        if self.runningtask:
            self.action_terminate()
        else:
            self.action_execute(command)

    def action_execute(self, command):
        """ Execute the task in Faceswap.py """
        self.clear_console()
        self.task.prepare(self.opts, command)
        self.task.execute_script()

    def action_terminate(self):
        """ Terminate the subprocess Faceswap.py task """
        self.task.terminate()
        self.runningtask = False
        self.clear_display_panel()
        self.change_action_button()

    def clear_display_panel(self):
        """ Clear the preview window and graph """
        self.delete_preview()
        self.lossdict = dict()

    def change_action_button(self):
        """ Change the action button to relevant control """
        for cmd in self.actionbtns.keys():
            btnact = self.actionbtns[cmd]
            if self.runningtask:
                ttl = 'Terminate'
                hlp = 'Exit the running process'
            else:
                ttl = cmd.title()
                hlp = 'Run the {} script'.format(cmd.title())
            btnact.config(text=ttl)
            Tooltip(btnact, text=hlp, wraplength=200)

    def clear_console(self):
        """ Clear the console output screen """
        self.console.delete(1.0, tk.END)

    def load_config(self, command=None):
        """ Load a saved config file """
        cfgfile = filedialog.askopenfile(mode='r', filetypes=self.filetypes)
        if not cfgfile:
            return
        cfg = self.serializer.unmarshal(cfgfile.read())
        if command is None:
            for cmd, opts in cfg.items():
                self.set_command_args(cmd, opts)
        else:
            opts = cfg.get(command, None)
            if opts:
                self.set_command_args(command, opts)
            else:
                self.clear_console()
                print('No ' + command + ' section found in file')

    def set_command_args(self, command, options):
        """ Pass the saved config items back to the GUI """
        for srcopt, srcval in options.items():
            for dstopts in self.opts[command]:
                if dstopts['control_title'] == srcopt:
                    dstopts['value'].set(srcval)
                    break

    def save_config(self, command=None):
        """ Save the current GUI state to a config file in json format """
        cfgfile = filedialog.asksaveasfile(mode='w',
                                           filetypes=self.filetypes,
                                           defaultextension='.fsw')
        if not cfgfile:
            return
        if command is None:
            cfg = {cmd: {opt['control_title']: opt['value'].get() for opt in opts}
                   for cmd, opts in self.opts.items()}
        else:
            cfg = {command: {opt['control_title']: opt['value'].get()
                             for opt in self.opts[command]}}
        cfgfile.write(self.serializer.marshal(cfg))
        cfgfile.close()

    def reset_config(self, command=None):
        """ Reset the GUI to the default values """
        if command is None:
            options = [opt for opts in self.opts.values() for opt in opts]
        else:
            options = [opt for opt in self.opts[command]]
        for option in options:
            default = option.get('default', '')
            default = '' if default is None else default
            option['value'].set(default)

    def clear_config(self, command=None):
        """ Clear all values from the GUI """
        if command is None:
            options = [opt for opts in self.opts.values() for opt in opts]
        else:
            options = [opt for opt in self.opts[command]]
        for option in options:
            if isinstance(option['value'].get(), bool):
                option['value'].set(False)
            elif isinstance(option['value'].get(), int):
                option['value'].set(0)
            else:
                option['value'].set('')

    def delete_preview(self):
        """ Delete the preview file """
        if os.path.exists(self.previewloc):
            os.remove(self.previewloc)

    def get_chosen_action(self, task_name):
        return self.opts[task_name][0]['value'].get()


class Tooltip:
    """
    Create a tooltip for a given widget as the mouse goes on it.

    Adapted from StackOverflow:

    http://stackoverflow.com/questions/3221956/
           what-is-the-simplest-way-to-make-tooltips-
           in-tkinter/36221216#36221216

    http://www.daniweb.com/programming/software-development/
           code/484591/a-tooltip-class-for-tkinter

    - Originally written by vegaseat on 2014.09.09.

    - Modified to include a delay time by Victor Zaccardo on 2016.03.25.

    - Modified
        - to correct extreme right and extreme bottom behavior,
        - to stay inside the screen whenever the tooltip might go out on
          the top but still the screen is higher than the tooltip,
        - to use the more flexible mouse positioning,
        - to add customizable background color, padding, waittime and
          wraplength on creation
      by Alberto Vassena on 2016.11.05.

      Tested on Ubuntu 16.04/16.10, running Python 3.5.2

    """

    def __init__(self, widget,
                 *,
                 background='#FFFFEA',
                 pad=(5, 3, 5, 3),
                 text='widget info',
                 waittime=400,
                 wraplength=250):

        self.waittime = waittime  # in miliseconds, originally 500
        self.wraplength = wraplength  # in pixels, originally 180
        self.widget = widget
        self.text = text
        self.widget.bind("<Enter>", self.on_enter)
        self.widget.bind("<Leave>", self.on_leave)
        self.widget.bind("<ButtonPress>", self.on_leave)
        self.background = background
        self.pad = pad
        self.ident = None
        self.topwidget = None

    def on_enter(self, event=None):
        """ Schedule on an enter event """
        self.schedule()

    def on_leave(self, event=None):
        """ Unschedule on a leave event """
        self.unschedule()
        self.hide()

    def schedule(self):
        """ Show the tooltip after wait period """
        self.unschedule()
        self.ident = self.widget.after(self.waittime, self.show)

    def unschedule(self):
        """ Hide the tooltip """
        id_ = self.ident
        self.ident = None
        if id_:
            self.widget.after_cancel(id_)

    def show(self):
        """ Show the tooltip """
        def tip_pos_calculator(widget, label,
                               *,
                               tip_delta=(10, 5), pad=(5, 3, 5, 3)):
            """ Calculate the tooltip position """

            s_width, s_height = widget.winfo_screenwidth(), widget.winfo_screenheight()

            width, height = (pad[0] + label.winfo_reqwidth() + pad[2],
                             pad[1] + label.winfo_reqheight() + pad[3])

            mouse_x, mouse_y = widget.winfo_pointerxy()

            x_1, y_1 = mouse_x + tip_delta[0], mouse_y + tip_delta[1]
            x_2, y_2 = x_1 + width, y_1 + height

            x_delta = x_2 - s_width
            if x_delta < 0:
                x_delta = 0
            y_delta = y_2 - s_height
            if y_delta < 0:
                y_delta = 0

            offscreen = (x_delta, y_delta) != (0, 0)

            if offscreen:

                if x_delta:
                    x_1 = mouse_x - tip_delta[0] - width

                if y_delta:
                    y_1 = mouse_y - tip_delta[1] - height

            offscreen_again = y_1 < 0  # out on the top

            if offscreen_again:
                # No further checks will be done.

                # TIP:
                # A further mod might automagically augment the
                # wraplength when the tooltip is too high to be
                # kept inside the screen.
                y_1 = 0

            return x_1, y_1

        background = self.background
        pad = self.pad
        widget = self.widget

        # creates a toplevel window
        self.topwidget = tk.Toplevel(widget)

        # Leaves only the label and removes the app window
        self.topwidget.wm_overrideredirect(True)

        win = tk.Frame(self.topwidget,
                       background=background,
                       borderwidth=0)
        label = tk.Label(win,
                         text=self.text,
                         justify=tk.LEFT,
                         background=background,
                         relief=tk.SOLID,
                         borderwidth=0,
                         wraplength=self.wraplength)

        label.grid(padx=(pad[0], pad[2]),
                   pady=(pad[1], pad[3]),
                   sticky=tk.NSEW)
        win.grid()

        xpos, ypos = tip_pos_calculator(widget, label)

        self.topwidget.wm_geometry("+%d+%d" % (xpos, ypos))

    def hide(self):
        """ Hide the tooltip """
        topwidget = self.topwidget
        if topwidget:
            topwidget.destroy()
        self.topwidget = None


class FaceswapGui(object):
 </s> add class FaceswapGui(tk.Tk):
                zero_pad = zero_pad.replace(ve, '')
                if '_' in zero_pad:
                    zero_pad = len(zero_pad.replace('_', ''))
                    underscore = '_'
                else:
                    zero_pad = len(zero_pad)
          vid_ext = ''
          for ve in [ve.replace('.', '') for ve in DataItem.vid_ext]:
              if ve in zero_pad:
                  vid_ext = ve
                zero_pad = zero_pad.replace(ve, '')
                if '_' in zero_pad:
                    zero_pad = len(zero_pad.replace('_', ''))
                    underscore = '_'
                else:
                    zero_pad = len(zero_pad)
                  break
  
          zero_pad = str(zero_pad).zfill(2)
          filename_list = [name, vid_ext + '%0' + zero_pad + 'd', img_ext]
          return '.'.join(filename_list)
keep keep keep keep replace keep keep keep keep keep
 Gui v3.0b (#436)

* GUI version 3 (#411)

GUI version 3.0a

* Required for Shaonlu mode (#416)

Added two modes - Original and Shaonlu.
The later requires this file to function.

* model update (#417)

New, functional Original 128 model

* OriginalHighRes 128 model update (#418)

Required for OriginalHighRes Model to function

* Add OriginalHighRes 128 update to gui branch (#421)

* Required for Shaonlu mode (#416)

Added two modes - Original and Shaonlu.
The later requires this file to function.

* model update (#417)

New, functional Original 128 model

* OriginalHighRes 128 model update (#418)

Required for OriginalHighRes Model to function

* Dev gui (#420)

* reduce singletons

* Fix tooltips and screen boundaries on popup

* Remove dpi fix. Fix context filebrowsers

* fix tools.py execution and context filebrowser bugs

* Bugfixes (#422)

* Bump matplotlib requirement. Fix polyfit. Fix TQDM on sort

* Fixed memory usage at 6GB cards. (#423)

- Switched default encoder to ORIGINAL
- Fixed memory consumption. Tested with geforce gtx 9800 ti with 6Gb; batch_size 8 no OOM or memory warnings now.

* Staging (#426)

* altered trainer (#425)

altered trainer to accommodate with model change

* Update Model.py (#424)

- Added saving state (currently only saved epoch number, to be extended in future)
- Changed saving to ThreadPoolExecutor

* Add DPI Scaling (#428)

* Add dpi scaling

* Hotfix for effmpeg. (#429)

effmpeg fixed so it works both in cli and gui.
Initial work done to add previewing feature to effmpeg (currently does nothing).
Some small spacing changes in other files to improve PEP8 conformity.

* PEP8 Linting (#430)

* pep8 linting

* Requirements version bump (#432)

* altered trainer (#425)

altered trainer to accommodate with model change

* Update Model.py (#424)

- Added saving state (currently only saved epoch number, to be extended in future)
- Changed saving to ThreadPoolExecutor

* Requirements version bump (#431)

This bumps the versions of:

    scandir
    h5py
    Keras
    opencv-python

to their latest vesions.

Virtual Environment will need to be setup again to make use of these.

* High DPI Fixes (#433)

* dpi scaling

* DPI Fixes

* Fix and improve context manager. (#434)

effmpeg tool:
Context manager for GUI fixed.

Context manager in general:
Functionality extended to allow configuring the context with both:
  command -> action
  command -> variable (cli argument) -> action

* Change epoch option to iterations

* Change epochs to iterations 
tools/effmpeg.py