#!/Users/meyer8/opt/anaconda3/bin/python
#

import sys  # nopep8
import os   # nopep8
try:
    from pathlib import Path
except:
    from pathlib2 import Path
import json
from ruamel import yaml
from ruamel.yaml.loader import SafeLoader
import numpy as np
from scipy import spatial
from pytangtv.pymorph import morphimage as mi
from pytangtv.pymorph import controls
from pytangtv.pymorph import menu
import getopt
from math import *
import pytangtv
from pytangtv.pymorph.bytescale import bytescale
from pytangtv.check4updates import check4updates
from scipy.io import readsav
try:
   from Tkinter import *
   import tkMessageBox as mbox
   import ttk
   from tkFileDialog import askopenfilename
except:
   from tkinter import *
   from tkinter import messagebox as mbox
   from tkinter import ttk
   from tkinter.filedialog import askopenfilename
#



try:
    from PIL import ImageTk, ImageDraw
    from PIL import ImageChops
    from PIL import Image as pImage
except:
    import Image as pImage
    import ImageTk
    import ImageDraw
    import ImageChops

thisfile = os.path.realpath(pytangtv.__file__)
thispath = os.path.dirname(thisfile)
bitmaps = thispath+'/bitmaps'

spawned = False
w = 0
h = 0
s = 1.0
winx = 640
winy = 860
morph = False
jopts = []

try:
    yconffile = str(Path.home())+'/pymorph.yaml'
    jconffile = str(Path.home())+'/pymorph.json'
    if os.path.exists(yconffile):
       with open(yconffile,'r') as f:
          jopts = yaml.load(f,Loader=SafeLoader)
    elif os.path.exists(jconffile):
       with open(jconffile,'r') as f:
          jopts = json.load(f)
    else:
       raise
    defaults = jopts['*']['window']
    if 'windowx' in defaults:
        winx = defaults['windowx']
    if 'windowy' in defaults:
        winy = defaults['windowy']
    if 'scale' in defaults:
        s = defaults['scale']
    if 'height' in defaults:
        h = defaults['height']
    if 'width' in defaults:
        w = defaults['width']
except:
    print("Problem reading pymorph conf file")
    pass

diag = {}

options = ['width=', 'height=', 'scale=', 'spawn', 'winx=', 'winy=', 'diag=']
optlist, args = getopt.getopt(sys.argv[1:], 'ult:w:h:s:', options)
optdict = {}
sys.stderr.write("\n")
for o in optlist:
    optdict.update({o[0]: o[1]})
if '-w' in optdict:
    w = int(optdict['-w'])
if '--width' in optdict:
    w = int(optdict['--width'])
if '-s' in optdict:
    s = float(optdict['-s'])
if '--scale' in optdict:
    s = float(optdict['--scale'])
if '-h' in optdict:
    h = int(optdict['-h'])
if '--height' in optdict:
    h = int(optdict['--height'])
if '--spawn' in optdict:
    spawned = True
if '--winx' in optdict:
    winx = int(optdict['--winx'])
if '--winy' in optdict:
    winy = int(optdict['--winy'])
if '--diag' in optdict:
    if optdict['--diag'] in jopts:
        diag = jopts[optdict['--diag']]
        if 'window' in diag:
            defaults = diag['window']
            if 'windowx' in defaults:
                winx = defaults['windowx']
            if 'windowy' in defaults:
                winy = defaults['windowy']
            if 'scale' in defaults:
                s = defaults['scale']
            if 'height' in defaults:
                h = defaults['height']
            if 'width' in defaults:
                w = defaults['width']

#
# an image viewer


class UI(Frame):

    def __init__(self, master, im, s=1.0, winx=800, winy=600):
        self.winx = winx
        self.winy = winy
        Frame.__init__(self, master, width=self.winx, height=self.winy)
        self.pack(side=RIGHT, fill=BOTH, expand=TRUE)
        self.window = master
        self.parent = master
        self.image = im
        self.dimage = im
        self.buimage = im
        self.mimage = im
        self.realdirty = True
        self.fdirty = True
        self.bdirty = True
        self.viddata = None
        self.vidind = 0
        self.vidnum = 0
        self.mode = 1
        self.degree = 1
        self.warpdirection = 1
        self.warptype = 1
        self.W, self.H = self.image.size
        self.xS = s
        self.yS = s
        self.transpose = False
        self.vflip = False
        self.hflip = False
        self.draw = ImageDraw.Draw(self.image)
        self.bitmap = ImageTk.PhotoImage(im)
        if self.W > self.winx or self.H > self.winy:
            # self.frame = Frame(self,width=self.winx, height=self.winy)
            # self.frame.grid(row=0,column=0)
            self.canvas = Canvas(
                self, width=self.winx, height=self.winy, scrollregion=(0, 0, self.W, self.H), cursor="crosshair")
            self.canvas.bind("<Button-1>", self.mark)
            self.canvas.bind("<B1-Motion>", self.motion)
            self.canvas.bind("<ButtonRelease-1>", self.relpick)
            self.canvas.bind("<Button-2>", self.remmark)
            self.canvas.bind("<Button-3>", self.mark)
            self.canvas.bind("<MouseWheel>", self.mouse_wheel)
            self.canvas.bind("<Button-4>", self.mouse_wheel)
            self.canvas.bind("<Button-5>", self.mouse_wheel)
            self.hbar = Scrollbar(self, orient=HORIZONTAL,
                                  command=self.scrollx)
            self.hbar.pack(side=TOP, fill=X)
            self.vbar = Scrollbar(self, orient=VERTICAL)
            self.vbar.pack(side=LEFT, fill=Y)
            self.vbar.config(command=self.scrolly)
            self.canvas.config(xscrollcommand=self.hbar.set,
                               yscrollcommand=self.vbar.set)
            self.canvas.create_image(0, 0, anchor=NW, image=self.bitmap)
            self.canvas.pack(side=LEFT, expand=True, fill=BOTH)
        else:
            self.canvas = Canvas(self, width=self.W,
                                 height=self.H, cursor="crosshair")
            self.canvas.bind("<Button-1>", self.mark)
            self.canvas.bind("<B1-Motion>", self.motion)
            self.canvas.bind("<ButtonRelease-1>", self.relpick)
            self.canvas.bind("<Button-2>", self.remmark)
            self.canvas.bind("<Button-3>", self.mark)
            self.canvas.bind("<MouseWheel>", self.mouse_wheel)
            self.canvas.bind("<Button-4>", self.mouse_wheel)
            self.canvas.bind("<Button-5>", self.mouse_wheel)
            self.canvas.create_image(0, 0, anchor=NW, image=self.bitmap)
            self.canvas.pack()
            self.hbar = None
            self.vbar = None
        self.bgimage = None
        self.bubgimage = None
        self.im = im
        self.hstep = 5
        self.hpos = 0
        self.vstep = 5
        self.vpos = 0
        self.rstep = 1
        self.spawned = spawned
        self.rot = 0
        self.bl = 0
        self.wmarks = []
        self.bmarks = []
        self.xi = []
        self.yi = []
        self.xo = []
        self.yo = []
        self.mdswarp = {}
        self.mdsdata = {}
        self.savefiledata = {}
        self.savefilewarp = {}

    def load_data_from_savefile(self, sfilename):
        sf = readsav(sfilename)
        varname = 'viddata'
        if 'varname' in self.savefiledata:
            varname = self.savefiledata['varname']
        self.viddata = sf[varname]
        self.cminentry.delete(0, END)
        self.cminentry.insert(0, "%d" % (self.viddata.min()))
        self.cmaxentry.delete(0, END)
        self.cmaxentry.insert(0, "%d" % (self.viddata.max()))
        self.vidind = 0
        self.vidnum = self.viddata.shape[0]
        self.dlabel.set('Frame(%d)' % (ui.vidnum,))
        self.transpose = False
        self.vflip = False
        self.hflip = False
        if 'transpose' in self.savefiledata and self.savefiledata['transpose'] == 1:
            self.transpose = True
        if 'vflip' in self.savefiledata and self.savefiledata['vflip'] == 1:
            self.vflip = True
        if 'hflip' in self.savefiledata and self.savefiledata['hflip'] == 1:
            self.hflip = True
        self.refresh()

    def load_data_from_mdsplus(self, mdsargs, shot=None):
        import MDSplus as mds
        if 'mdsserver' in mdsargs:
            mdsserver = mds.Connection(mdsargs['mdsserver'])
            if shot != None:
                tree = mdsserver.openTree(mdsargs['mdstree'], shot)
                self.transpose = False
                self.vflip = False
                self.hflip = False
                self.viddata = np.array(mdsserver.get(mdsargs['node']))
                self.cminentry.delete(0, END)
                self.cminentry.insert(0, "%d" % (self.viddata.min()))
                self.cmaxentry.delete(0, END)
                self.cmaxentry.insert(0, "%d" % (self.viddata.max()))
                try:
                   self.viddata = self.viddata.reshape(self.viddata.shape[::-1])
                   self.vidnum = self.viddata.shape[0]
                except:
                   if 'dims' in mdsargs:
                      dims = mdsargs['dims']
                      self.vidnum = int(self.viddata.size / (dims[0]*dims[1]))
                      self.viddata = self.viddata.reshape([self.vidnum,dims[0],dims[1]])
                if 'transpose' in mdsargs and mdsargs['transpose'] == 1:
                    self.transpose = True
                if 'vflip' in mdsargs and mdsargs['vflip'] == 1:
                    self.vflip = True
                if 'hflip' in mdsargs and mdsargs['hflip'] == 1:
                    self.hflip = True
                self.vidind = 0
                print(self.viddata.shape)
            else:
                print("No shot specified")
            mdsserver.disconnect()
            self.dlabel.set('Frame(%d)' % (ui.vidnum,))
        else:
            print("No MDSPlus server")

    def load_warp_from_mdsplus(self, mdsargs, shot=None):
        import MDSplus as mds
        if 'mdsserver' in mdsargs:
            mdsserver = mds.Connection(mdsargs['mdsserver'])
            if shot != None:
                tree = mdsserver.openTree(mdsargs['mdstree'], shot)
                self.xi = mdsserver.get(mdsargs['Xi']) * self.imscale
                self.xo = mdsserver.get(mdsargs['Xo']) * self.imscale
                self.yi = mdsserver.get(mdsargs['Yi']) * self.imscale
                self.yo = mdsserver.get(mdsargs['Yo']) * self.imscale
                if 'vflip' in mdsargs and mdsargs['vflip'] == 1:
                    self.yi = h - 1 - self.yi
                    self.yo = h - 1 - self.yo
                if 'hflip' in mdsargs and mdsargs['vflip'] == 1:
                    self.xi = w - 1 - self.xi
                    self.xo = w - 1 - self.xo
                self.realdirty = True
                self.wmarks = np.transpose((self.xi, self.yi)).tolist()
                self.bmarks = np.transpose((self.xo, self.yo)).tolist()
                if 'xshift' in mdsargs:
                    xshift = mdsserver.get(mdsargs['xshift'])
                    self.xposentry.delete(0, END)
                    self.xposentry.insert(0, "%d" % xshift)
                if 'yshift' in mdsargs:
                    yshift = mdsserver.get(mdsargs['yshift'])
                self.yposentry.delete(0, END)
                self.yposentry.insert(0, "%d" % yshift)
                if 'rotation' in mdsargs:
                    rshift = mdsserver.get(mdsargs['rotation'])
                    self.rposentry.delete(0, END)
                    self.rposentry.insert(0, "%g" % rshift)
                if 'degree' in mdsargs:
                    self.degree = mdsserver.get(mdsargs['degree'])
                    degree.set(self.degree)
                if 'rendering' in mdsargs:
                    i = np.array(mdsserver.get(mdsargs['rendering']))
                    if 'transpose' in mdsargs:
                        i = i.T
                    if 'vflip' in mdsargs and mdsargs['vflip'] == 1:
                        i = np.flipud(i)
                    if 'hflip' in mdsargs and mdsargs['hflip'] == 1:
                        i = np.fliplr(i)
                    self.image = pImage.fromarray(
                        bytescale(i)).resize((self.W, self.H))
            else:
                print("No shot specified")
            mdsserver.disconnect()
            self.refresh()
        else:
            print("No MDSPlus server")

    def mouse_wheel(self, event):
        self.vidind = self.vidind + event.delta
        self.bgupdate()

    def range_update(self, event):
        self.bgupdate()

    def frame_update(self, event):
        self.vidind = int(self.frentry.get())
        self.bgupdate()

    def frinc(self):
        self.vidind = self.vidind+1
        self.bgupdate()

    def frdec(self):
        self.vidind = self.vidind-1
        self.bgupdate()

    def bgupdate(self):
        self.bdirty = True
        i = np.asarray(self.bgimage)
        if self.vidind < 0:
            self.vidind = 0
        elif self.vidind >= self.vidnum:
            self.vidind = self.vidnum - 1
        if self.vidnum > 0:
            self.frentry.delete(0, END)
            self.frentry.insert(0, "%d" % self.vidind)
            i = self.viddata[self.vidind, :, :]
            if self.transpose:
                i = i.T
            if self.vflip:
                i = np.flipud(i)
            if self.hflip:
                i = np.fliplr(i)
        self.bgimage = pImage.fromarray(bytescale(i, cmin=int(
              self.cminentry.get()), cmax=int(self.cmaxentry.get())))
        if self.imscale != 1.0:
              self.bgimage = self.bgimage.resize((self.W, self.H))
        self.refresh()

    def mapx(self, event):
        if self.hbar != None:
            f = self.hbar.get()
            lx = f[0] * self.W
            rx = f[1] * self.W
            return(int(lx + event.x - 1))
        else:
            return(event.x)

    def mapy(self, event):
        if self.vbar != None:
            f = self.vbar.get()
            ly = f[0] * self.H
            ry = f[1] * self.H
            return(int(ly + event.y - 1))
        else:
            return(event.y)

    def selmode(self):
        global mode
        self.mode = int(mode.get())
        self.realdirty = True
        self.refresh()

    def seldirection(self):
        global direction
        self.warpdirection = int(direction.get())
        self.realdirty = True
        self.refresh()

    def seldeg(self):
        global degree
        self.degree = degree.get()
        if morph and len(self.bmarks) < (self.degree+1)**2:
            self.morphbut.config(relief="sunken", image=add)
        elif morph:
            self.morphbut.config(relief="sunken", image=on)
        self.realdirty = True
        self.refresh()

    def relpick(self, event):
        cx = self.mapx(event)
        cy = self.mapy(event)
        self.realdirty = True
        self.degree = int(degree.get())
        if self.mode == 1:  # add
            self.bmarks.append([cx, cy])
        elif self.mode == 2:  # edit
            self.bmarks[self.editind][0] = cx
            self.bmarks[self.editind][1] = cy
        elif self.mode == 3:  # delete
            # nothing to do for delete
            pass
        if len(self.wmarks) > 0:
            self.xi = np.array(self.wmarks)[:, 0]
            self.yi = np.array(self.wmarks)[:, 1]
            self.xo = np.array(self.bmarks)[:, 0]
            self.yo = np.array(self.bmarks)[:, 1]

        self.refresh()

    def scrollx(self, event, step, what=None):
        if event == "moveto":
            self.canvas.xview(event, step)
        if event == "scroll":
            self.canvas.xview(event, step, what)

    def scrolly(self, event, step, what=None):
        if event == "moveto":
            self.canvas.yview(event, step)
        if event == "scroll":
            self.canvas.yview(event, step, what)

    def motion(self, event):
        if self.line != None:
            self.canvas.delete(self.line)
        self.x2 = self.mapx(event)
        self.y2 = self.mapy(event)
        self.line = self.canvas.create_line(
            self.x1, self.y1, self.x2, self.y2, fill='white')

    def mark(self, event):
        self.line = None
        cx = self.mapx(event)
        cy = self.mapy(event)
        if len(self.bmarks) >= (self.degree+1)**2:
            self.xi = np.array(self.wmarks)[:, 0]
            self.yi = np.array(self.wmarks)[:, 1]
            self.xo = np.array(self.bmarks)[:, 0]
            self.yo = np.array(self.bmarks)[:, 1]
            self.kx, self.ky = mi.polywarp(
                self.xi, self.yi, self.xo, self.yo, degree=self.degree)
            self.rkx, self.rky = mi.polywarp(
                self.xo, self.yo, self.xi, self.yi, degree=self.degree)
        if morph and self.warpdirection == 1 and len(self.bmarks) >= (self.degree+1)**2:
            cx, cy = mi.poly_pt(cx, cy, self.kx, self.ky)
        if morph and self.warpdirection == 2 and len(self.bmarks) >= (self.degree+1)**2:
            cx, cy = mi.poly_pt(cx, cy, self.kx, self.ky)
        self.x1 = cx
        self.y1 = cy
        if self.mode == 1:  # add mode
            self.wmarks.append([cx, cy])
        elif self.mode == 2:  # edit mode
            tree = spatial.cKDTree(list(zip(self.xi, self.yi)))
            pt = [cx, cy]
            d, i = tree.query(pt, k=1)
            self.editind = i
            self.wmarks[i][0] = cx
            self.wmarks[i][1] = cy
        elif self.mode == 3:  # delete mode
            tree = spatial.cKDTree(list(zip(self.xi, self.yi)))
            pt = [cx, cy]
            d, i = tree.query(pt, k=1)
            self.editind = i
            del self.wmarks[i]
            del self.bmarks[i]

        self.dirty = True
        self.refresh()

    def remmark(self, event):
        self.realdirty = True
        self.mimage = self.image
        self.wmarks = []
        self.bmarks = []
        self.kx = []
        self.ky = []
        self.rkx = []
        self.rky = []
        self.xi = []
        self.yi = []
        self.xo = []
        self.yo = []
        self.refresh()

    def reset(self):
        self.hpos = 0
        self.vpos = 0
        self.rot = 0
        self.xposentry.delete(0, END)
        self.xposentry.insert(0, "%d" % self.hpos)
        self.yposentry.delete(0, END)
        self.yposentry.insert(0, "%d" % self.vpos)
        self.rposentry.delete(0, END)
        self.rposentry.insert(0, "%d" % self.rot)
        self.image = self.buimage
        self.bgimage = self.bubgimage
        self.realdirty = True
        self.refresh()

    def rightstep(self):
        self.hstep = int(self.xstepentry.get())
        self.hpos = self.hpos + self.hstep
        self.xposentry.delete(0, END)
        self.xposentry.insert(0, "%d" % self.hpos)
        self.refresh()

    def leftstep(self):
        self.hstep = int(self.xstepentry.get())
        self.hpos = self.hpos - self.hstep
        self.xposentry.delete(0, END)
        self.xposentry.insert(0, "%d" % self.hpos)
        self.refresh()

    def downstep(self):
        self.vstep = int(self.ystepentry.get())
        self.vpos = self.vpos + self.vstep
        self.yposentry.delete(0, END)
        self.yposentry.insert(0, "%d" % -self.vpos)
        self.refresh()

    def upstep(self):
        self.vstep = int(self.ystepentry.get())
        self.vpos = self.vpos - self.vstep
        self.yposentry.delete(0, END)
        self.yposentry.insert(0, "%d" % -self.vpos)
        self.refresh()

    def rotr(self):
        self.rstep = float(self.rstepentry.get())
        self.rot = self.rot - self.rstep
        self.rposentry.delete(0, END)
        self.rposentry.insert(0, "%g" % -self.rot)
        self.refresh()

    def rotl(self):
        self.rstep = float(self.rstepentry.get())
        self.rot = self.rot + self.rstep
        self.rposentry.delete(0, END)
        self.rposentry.insert(0, "%g" % -self.rot)
        self.refresh()

    def iwrite(self):
        self.refresh()
        self.simage.save('pyalign.tiff')

    def showwarp(self):
        fl = ['{}' for item in self.xi]
        s = ','.join(fl)
        mbox.showinfo("Current Control Points",
                      "Xi=["+s.format(*self.xi)+"]\n" +
                      "Yi=["+s.format(*self.yi)+"]\n" +
                      "Xo=["+s.format(*self.xo)+"]\n" +
                      "Yo=["+s.format(*self.yo)+"]")

    def savewarpyaml(self, yfilename='warp.yaml'):
        warp = {}
        warp['xi'] = self.xi.tolist()
        warp['yi'] = self.yi.tolist()
        warp['xo'] = self.xo.tolist()
        warp['yo'] = self.yo.tolist()
        warp['xshift'] = self.hpos
        warp['yshift'] = self.vpos
        warp['rotation'] = self.rot
        warp['degree'] = self.degree
        warp['type'] = self.warptype
        warp['direction'] = self.warpdirection
        with open(yfilename, 'w') as outfile:
            yaml.dump(warp, outfile, indent=8)

    def savewarpjson(self, jfilename='warp.json'):
        warp = {}
        warp['xi'] = self.xi.tolist()
        warp['yi'] = self.yi.tolist()
        warp['xo'] = self.xo.tolist()
        warp['yo'] = self.yo.tolist()
        warp['xshift'] = self.hpos
        warp['yshift'] = self.vpos
        warp['rotation'] = self.rot
        warp['degree'] = self.degree
        warp['type'] = self.warptype
        warp['direction'] = self.warpdirection
        with open(jfilename, 'w') as outfile:
            json.dump(warp, outfile, indent=8)

    def loadwarpyaml(self, yfilename='warp.yaml'):
        with open(yfilename, 'r') as infile:
            warp = yaml.load(infile,Loader=SafeLoader)
        self.xi = np.array(warp['xi'])
        self.yi = np.array(warp['yi'])
        self.xo = np.array(warp['xo'])
        self.yo = np.array(warp['yo'])
        self.hpos = warp['xshift']
        self.vpos = warp['yshift']
        self.rot = warp['rotation']
        self.degree = warp['degree']
        self.xposentry.delete(0, END)
        self.xposentry.insert(0, "%d" % self.hpos)
        self.yposentry.delete(0, END)
        self.yposentry.insert(0, "%d" % -self.vpos)
        self.rposentry.delete(0, END)
        self.rposentry.insert(0, "%d" % -self.rot)
        self.wmarks = np.transpose((self.xi, self.yi)).tolist()
        self.bmarks = np.transpose((self.xo, self.yo)).tolist()
        if 'direction' in warp:
            if warp['direction'] == 'forward':
                self.warpdirection = 1
            elif warp['direction'] == 'reverse':
                self.warpdirection = 2
            else:
                self.warpdirection = 0
        else:
            self.warpdirection = 0
        if 'type' in warp:
            self.warptype = warp['type']
        else:
            self.warpversion = 0
        self.realdirty = True
        self.refresh()


    def loadwarpjson(self, jfilename='warp.json'):
        with open(jfilename, 'r') as infile:
            warp = json.load(infile)
        self.xi = np.array(warp['xi'])
        self.yi = np.array(warp['yi'])
        self.xo = np.array(warp['xo'])
        self.yo = np.array(warp['yo'])
        self.hpos = warp['xshift']
        self.vpos = warp['yshift']
        self.rot = warp['rotation']
        self.degree = warp['degree']
        self.xposentry.delete(0, END)
        self.xposentry.insert(0, "%d" % self.hpos)
        self.yposentry.delete(0, END)
        self.yposentry.insert(0, "%d" % -self.vpos)
        self.rposentry.delete(0, END)
        self.rposentry.insert(0, "%d" % -self.rot)
        self.wmarks = np.transpose((self.xi, self.yi)).tolist()
        self.bmarks = np.transpose((self.xo, self.yo)).tolist()
        if 'direction' in warp:
            if warp['direction'] == 'forward':
                self.warpdirection = 1
            elif warp['direction'] == 'reverse':
                self.warpdirection = 2
            else:
                self.warpdirection = 0
        else:
            self.warpdirection = 0
        if 'type' in warp:
            self.warptype = warp['type']
        else:
            self.warpversion = 0
        self.realdirty = True
        self.refresh()

    def morphit(self):
        global morph
        if self.morphbut.config('relief')[-1] == 'sunken':
            self.morphbut.config(relief="raised", image=off)
            morph = False
        else:
            if len(self.bmarks) < (self.degree+1)**2:
                self.morphbut.config(relief="sunken", image=add)
            else:
                self.morphbut.config(relief="sunken", image=on)
            morph = True
        self.realdirty = True
        self.refresh()

    def refreshcb(self, val):
        self.refresh()

    def refresh(self):
        self.rot = -float(self.rposentry.get())
        self.hpos = int(self.xposentry.get())
        self.vpos = -int(self.yposentry.get())
        self.xS = float(self.xstr.get())
        self.yS = float(self.ystr.get())
        xoff = int(self.hpos*self.xS)
        yoff = int(self.vpos*self.yS)
        width, height = self.image.size
        im1 = self.image
        if morph and self.warpdirection == 1:
            if len(self.bmarks) >= (self.degree+1)**2:
                self.morphbut.config(relief="sunken", image=on)
                if self.realdirty:
                    self.kx, self.ky = mi.polywarp(
                        self.xi, self.yi, self.xo, self.yo, degree=self.degree)
                    self.realdirty = False
                    self.fdirty = True
                if self.fdirty:
                    self.mimage = pImage.fromarray(mi.poly_2d(
                        np.asarray(self.image), self.kx, self.ky))
                    self.fdirty = False
                im1 = self.mimage
            else:
                self.morphbut.config(relief="sunken", image=add)

        # im1 = ImageChops.offset(im1.rotate(
        #    self.rot), xoffset=xoff, yoffset=yoff)
        # if xoff > 0:
        #    im1.paste(pImage.new('L', (xoff, height)), (0, 0, xoff, height))
        # if xoff < 0:
        #    im1.paste(pImage.new('L', (abs(xoff), height)),
        #              (width+xoff, 0, width, height))
        # if yoff > 0:
        #    im1.paste(pImage.new('L', (width, yoff)), (0, 0, width, yoff))
        # if yoff < 0:
        #    im1.paste(pImage.new('L', (width, abs(yoff))),
        #              (0, height+yoff, width, height))
        wsize = int((float(self.image.size[0])*float(self.xstr.get())))
        hsize = int((float(self.image.size[1])*float(self.ystr.get())))
        # hsize = int((float(self.image.size[1])*float(self.xstr.get())))
        im1 = im1.resize((wsize, hsize), pImage.ANTIALIAS)
        dimage = im1
        self.im1 = im1
        s = self.scale.get()

        if self.bgimage != None:
            im2 = pImage.new('L', (self.image.size[0], self.image.size[1]))
            im2.paste(self.bgimage, (0, 0))
            if morph and self.warpdirection == 2:
                if len(self.bmarks) >= (self.degree+1)**2:
                    self.morphbut.config(relief="sunken", image=on)
                    if self.realdirty:
                        self.kx, self.ky = mi.polywarp(
                            self.xi, self.yi, self.xo, self.yo, degree=self.degree)
                        self.realdirty = False
                        self.bdirty = True
                    if self.bdirty:
                        self.mimage = pImage.fromarray(mi.poly_2d(
                            np.asarray(im2), self.kx, self.ky))
                        self.bdirty = False
                    im2 = self.mimage
                else:
                    self.morphbut.config(relief="sunken", image=add)
            im2 = ImageChops.offset(im2.rotate(
                self.rot), xoffset=-xoff, yoffset=-yoff)
            if -xoff > 0:
                im2.paste(pImage.new('L', (-xoff, height)),
                          (0, 0, -xoff, height))
            if -xoff < 0:
                im2.paste(pImage.new('L', (abs(-xoff), height)),
                          (width+-xoff, 0, width, height))
            if -yoff > 0:
                im2.paste(pImage.new('L', (width, -yoff)), (0, 0, width, -yoff))
            if -yoff < 0:
                im2.paste(pImage.new('L', (width, abs(-yoff))),
                          (0, height+-yoff, width, height))
            self.im2 = im2
            if self.bl == -1:
                dimage = im2
            elif self.bl == 0:
                dimage = im1
            elif self.bl == 1:
                dimage = ImageChops.add(im1, im2)
            elif self.bl == 2:
                dimage = ImageChops.difference(im1, im2)
            elif self.bl == 3:
                dimage = ImageChops.darker(im1, im2)
            elif self.bl == 4:
                dimage = ImageChops.lighter(im1, im2)
            elif self.bl == 5:
                dimage = ImageChops.logical_and(
                    im1.convert("1"), im2.convert("1"))
            elif self.bl == 6:
                dimage = ImageChops.logical_or(
                    im1.convert("1"), im2.convert("1"))
            elif self.bl == 7:
                dimage = ImageChops.logical_xor(
                    im1.convert("1"), im2.convert("1"))
            elif self.bl == 8:
                dimage = ImageChops.multiply(im1, im2)
            elif self.bl == 9:
                dimage = ImageChops.blend(im1, im2, s)

        self.bitmap = ImageTk.PhotoImage(dimage)
        self.simage = dimage
        self.canvas.delete("all")
        self.canvas.create_image(0, 0, anchor=NW, image=self.bitmap)
        if self.mode != 99:
            for m in self.wmarks:
                self.canvas.create_oval(
                    m[0]-3, m[1]-3, m[0]+3, m[1]+3, outline="red", fill='red')
            for m in self.bmarks:
                self.canvas.create_oval(
                    m[0]-3, m[1]-3, m[0]+3, m[1]+3, outline="blue", fill='blue')

#
# script interface


if __name__ == "__main__":

    import sys

    from pkg_resources import get_distribution, DistributionNotFound
    try:
        _dist = get_distribution('PyTangtv')
    except DistributionNotFound:
        _version = 'Not installed with setup.py/pip'
    else:
        _version = _dist.version
    check4updates('https://pypi.org/pypi/pytangtv/json',thisver=_version)

    

    root = Tk()
    if len(args) == 0:
        ifilename = askopenfilename(filetypes=[("tiff", ".tif .tiff"),
                                               ("png", "*.png"),
                                               ("allfiles", "*")])
    else:
        ifilename = args[0]

    root.title(ifilename)
    mymenu = menu.mymenu(root)

    if s != 1:
        im = pImage.open(ifilename).convert('L')
        w, h = im.size
        w = int(w * s)
        h = int(h * s)
        im = Image.open(ifilename).convert('L').resize((w, h), pImage.ANTIALIAS)
    elif w != 0:
        im = pImage.open(ifilename).convert('L')
        iw, ih = im.size
        s = float(w) / float(iw)
        im = pImage.open(ifilename).convert('L').resize((w, h), pImage.ANTIALIAS)
    else:
        im = pImage.open(ifilename).convert('L')
        w, h = im.size
        s = 1.0

    frame = Frame(root)
    frame.pack(expand=FALSE, fill=BOTH)
    ui = UI(frame, im, s, winx=winx, winy=winy)
    mymenu.addui(ui)

    if len(args) > 1:
        #ui.bgimage = pImage.open(args[1]).convert('L').resize((w, h), pImage.ANTIALIAS)
        ui.bgimage = pImage.open(args[1]).convert('L')
    ui.bubgimage = ui.bgimage
    ui.imscale = s
    controls.controls(frame, ui)
    ttk.Separator(frame, orient='horizontal').pack(fill='x', side=TOP)
    on = ImageTk.PhotoImage(file=bitmaps+'/morphon.png')
    off = ImageTk.PhotoImage(file=bitmaps+'/morphoff.png')
    add = ImageTk.PhotoImage(file=bitmaps+'/add.png')
    ui.morphbut = Button(frame, width=100, text="Morph",
                         relief="raised", command=ui.morphit, image=off)
    ui.morphbut.pack(side=TOP)
    frame2 = Frame(frame)
    frame2.pack(side=TOP)
    degree = IntVar()
    Label(frame2, text='Degree Poly').pack(side=LEFT)
    R1 = Radiobutton(frame2, text="1", variable=degree,
                     value=1, command=ui.seldeg).pack(anchor=N)
    R2 = Radiobutton(frame2, text="2", variable=degree,
                     value=2, command=ui.seldeg).pack(anchor=N)
    R3 = Radiobutton(frame2, text="3", variable=degree,
                     value=3, command=ui.seldeg).pack(anchor=N)
    degree.set(1)
    frame2 = Frame(frame)
    frame2.pack(side=TOP)
    frame3 = Frame(frame2)
    frame3.pack(side=LEFT)
    frame4 = Frame(frame2)
    frame4.pack(side=LEFT)
    mode = IntVar()
    Label(frame3, text='Mode').pack(side=TOP)
    R1 = Radiobutton(frame3, text="add", variable=mode,
                     value=1, command=ui.selmode).pack(anchor=N)
    R2 = Radiobutton(frame3, text="edit", variable=mode,
                     value=2, command=ui.selmode).pack(anchor=N)
    R3 = Radiobutton(frame3, text="delete", variable=mode,
                     value=3, command=ui.selmode).pack(anchor=N)
    R99 = Radiobutton(frame3, text="hide", variable=mode,
                      value=99, command=ui.selmode).pack(anchor=N)
    mode.set(1)
    direction = IntVar()
    Label(frame4, text='Direction').pack(side=TOP)
    R1 = Radiobutton(frame4, text="forward", variable=direction,
                     value=1, command=ui.seldirection).pack(anchor=N)
    R2 = Radiobutton(frame4, text="reverse", variable=direction,
                     value=2, command=ui.seldirection).pack(anchor=N)
    direction.set(1)


    frame2 = Frame(frame)
    frame2.pack(side=TOP)
    ui.dlabel = StringVar()
    ui.dlabel.set('Frame(%d)' % (ui.vidnum,))
    Label(frame2, textvariable=ui.dlabel).pack(side=LEFT)
    ui.frentry = Entry(frame2, width=10)
    ui.frentry.bind('<Key-Return>', ui.frame_update)
    ui.frentry.insert(0, "0")
    ui.frentry.pack(side=LEFT, padx=2, pady=2)
    ui.frplus = Button(frame2, width=2, text="+", command=ui.frinc)
    ui.frplus.pack(side=LEFT, padx=2, pady=2)
    ui.frminus = Button(frame2, width=2, text="-", command=ui.frdec)
    ui.frminus.pack(side=LEFT, padx=2, pady=2)

    frame2 = Frame(frame)
    frame2.pack(side=TOP)
    Label(frame2, text='Image range').pack(side=LEFT)
    ui.cminentry = Entry(frame2, width=10)
    ui.cminentry.pack(side=LEFT, padx=2, pady=2)
    ui.cminentry.bind('<Key-Return>', ui.range_update)
    ui.cmaxentry = Entry(frame2, width=10)
    ui.cmaxentry.bind('<Key-Return>', ui.range_update)
    ui.cmaxentry.pack(side=LEFT, padx=2, pady=2)

    if 'mdsplus' in diag:
        mdsargs = diag['mdsplus']
        if 'data' in mdsargs:
            ui.mdsdata = mdsargs['data']
        if 'warp' in mdsargs:
            ui.mdswarp = mdsargs['warp']
    if 'savefile' in diag:
        savefileargs = diag['savefile']
        if 'data' in savefileargs:
            ui.savefiledata = savefileargs['data']
        if 'warp' in savefileargs:
            ui.savefilewarp = savefileargs['warp']

    ui.refresh()
    root.mainloop()
