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

import sys  # nopep8
import os   # nopep8
import time # nopep8
try:
    from pathlib import Path
except:
    from pathlib2 import Path
import json
from ruamel import yaml
from ruamel.yaml.loader import SafeLoader
from ruamel.yaml.main import round_trip_dump as yaml_dump
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)
        with open(yfilename, 'w') as outfile:
             outfile.write("# \n")
             outfile.write("# Written by "+os.getlogin()+"\n")
             outfile.write("# on  "+time.ctime()+"\n")
             outfile.write("# \n")
             outfile.write(yaml_dump(warp,indent=4,block_seq_indent=4))
     

    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()
