from pyqtgraph.Qt import QtCore, QtGui
import numpy as np
from scipy.spatial import distance as dist
import glob
import re
import os
from PyQt5 import QtGui
from PyQt5.QtCore import *
from PyQt5.QtGui import *
import sys
import cv2
import pandas as pd
from PyQt5.Qt import *
import pyqtgraph as pg
#from PyQt4.Qt import *
#%%
class eggUI(QDialog):
    '''
    createOpenCVEggROI : take eggID defined ROIs and visualise
    
    '''
    sliderUpdate = QtCore.pyqtSignal()
    embryoUpdate = QtCore.pyqtSignal()
    keyPressed = QtCore.pyqtSignal()
    
    def __init__(self, parent=None):
        super(eggUI, self).__init__(parent)
        # Make QDialog
        self.diag = QtGui.QDialog()
        global parentPath, vidTime
        self.diag.setWindowTitle('Identify eggs')
        self.diag.imv = pg.ImageView()
        self.btn_save = QPushButton('Save', self)

#==============================================================================
# 
#==============================================================================
    def showUI(self,ims,eggRotBBox, eggBoxPoints, embryoLabels, eggInt):
        self.eggInt = eggInt
        self.embryoLabels = embryoLabels
        self.diag.setWindowTitle('Identify eggs')
        # Make ImageView
        self.diag.imv = pg.ImageView()
        self.diag.resize(1000,600)
        # Make ROI
        self.importOpenCVROIs(eggRotBBox, eggBoxPoints)
        if (eggRotBBox[0][0][0] != 'nan'): 
            self.createOpenCVEggROI()
            self.diag.imv.addItem(self.roi)
        # Remove buttons from ImageView widget
        self.diag.imv.ui.roiBtn.hide()
        self.diag.imv.ui.menuBtn.hide()
        # Make tableview
        self.diag.table = QtGui.QTableWidget()
        self.diag.table.setShowGrid(True)
        self.diag.table.setHorizontalHeaderLabels(['Embryo', 'Sorted'])
        # Sets different alignment data just on the first column
        self.diag.table.setRowCount(int(len(self.embryoLabels)))
        self.diag.table.setColumnCount(2)
        # Highlight first row
        self.diag.table.selectRow(0)
        # Make layout
        checkLayout = QGridLayout()
        # Deal with stretching for approrpraite formatting.
        checkLayout.setColumnStretch(0, 3)
        checkLayout.setColumnStretch(1, 1)
        checkLayout.setRowStretch(0, 1)
        checkLayout.setRowStretch(1, 3)
        # Add to layout
        checkLayout.addWidget(self.diag.imv,0,0,2,2)
        checkLayout.addWidget(self.diag.table,1,5)
        # Apply layout
        self.diag.setLayout(checkLayout)
        # Make buttons
        self.cpROI_btn = QtGui.QPushButton('&Copy ROI')
        self.cpROI_btn.setMinimumHeight(40);
        self.useCpROI_btn = QtGui.QPushButton('&Use Copied ROI')
        self.useCpROI_btn.setMinimumHeight(40);
        self.noEgg_btn = QtGui.QPushButton('&No Egg')
        self.noEgg_btn.setMinimumHeight(40);
        self.approveROI_btn = QtGui.QPushButton('&Approve ROIs')
        self.approveROI_btn.setMinimumHeight(40);
        self.exit_btn = QtGui.QPushButton('Exit')
        self.exit_btn.setMinimumHeight(40);
        # Make button layout
        self.btnLayout = QGridLayout()
        self.btnLayout.addWidget(self.cpROI_btn,0,0)
        self.btnLayout.addWidget(self.useCpROI_btn,0,1)
        self.btnLayout.addWidget(self.noEgg_btn,1,1)
        self.btnLayout.addWidget(self.approveROI_btn,1,0)
        # Exit button not implemented, just use window x (topRight).
        # self.btnLayout.addWidget(self.exit_btn,2,1)
        # Add button layout to GridLayout.
        checkLayout.addLayout(self.btnLayout,0,5)
        # Format images for pyqtgraph and put in ImageView
        # self.formatSequence(ims)
        self.imImport()
        self.diag.imv.setImage(self.compSeq)
        # Add the ROI to ImageItem        
        self.diag.show()
        # Call function to add data
        self.dataForTable()
        # Function for modifying the table when ROI is approved.
        self.approveROI_btn.clicked.connect(self.updateTable)
        # Copy current ROI
        self.cpROI_btn.clicked.connect(self.cpROI)
        # Apply copied ROI
        self.useCpROI_btn.clicked.connect(self.applyCopiedROI)
        # Assign nan to frames not containing egg
        self.noEgg_btn.clicked.connect(self.recordNoEgg)
        # Exit - prompt user to confirm
        #self.exit_btn.clicked.connect(self.closeEvent)
        # Connect changes in timeline so correct ROI is created and displayed.
        self.diag.imv.timeLine.sigPositionChanged.connect(self.updateOpenCVEggROICurrEmbryo)
        #self.diag.keyPressEvent(self.keyPressEvent)
#==============================================================================
#   Generate data for populating the embryo/approveROI table.
#==============================================================================
    def dataForTable(self):
        self.tableData = {'Embryo':list(self.embryoLabels),
        'ROI approved':['No'] * len(list(self.embryoLabels))}
        self.tableCols = [QtGui.QColor(0,0,100,120)]* len(list(self.embryoLabels))
        # Enter data onto Table
        horHeaders = []
        for n, key in enumerate(sorted(self.tableData.keys())):
            horHeaders.append(key)
            for m, item in enumerate(self.tableData[key]):
                newitem = QtGui.QTableWidgetItem(item)
                newitem.setBackground(QtGui.QColor(0,0,100,120))
                self.diag.table.setItem(m, n, newitem)
        # Add Header
        self.diag.table.setHorizontalHeaderLabels(horHeaders)  
        # Adjust size of Table
        self.diag.table.resizeRowsToContents()
        # self.diag.table.resizeColumnsToContents()

#==============================================================================
#   Update table when approve ROI button clicked.
#==============================================================================
    def updateTable(self):   
        self.tableData['ROI approved'][self.diag.table.currentRow()] = 'Approved'
        self.tableCols[self.diag.table.currentRow()] = QtGui.QColor(0,100,0,120)
        horHeaders = []
        for n, key in enumerate(sorted(self.tableData.keys())):
            horHeaders.append(key)
            for m, item in enumerate(self.tableData[key]):
                newitem = QtGui.QTableWidgetItem(item) 
                self.diag.table.setItem(m, n, newitem)
                newitem.setBackground(self.tableCols[m])
        #Add Header
        self.diag.table.setHorizontalHeaderLabels(horHeaders)  
        #Adjust size of Table
        self.diag.table.resizeRowsToContents()

#==============================================================================
#   Update the user interface        
#==============================================================================
    def updateUI(self,ims,eggRotBBox, eggBoxPoints):
        self.imImport()
        self.diag.imv.setImage(self.compSeq)
        self.importOpenCVROIs(eggRotBBox, eggBoxPoints)
        self.getSeqValsAndCurrROI()  
        self.updateOpenCVEggROINewEmbryo()
        # Add the ROI to ImageItem
        #self.diag.imv.addItem(self.roi)

#==============================================================================
#   Deal with data from the dataHandling class        
#==============================================================================
    def formatSequence(self,ims):
        # Format seq appropriately for pyqtgraph ROIs
        self.tSeqd = np.zeros_like(ims)
        for l in range(len(self.tSeqd)):
            self.tSeqd[l] = ims[l].T
 
#==============================================================================
#   Get folders for a particular embryo
#==============================================================================
    def getEmbryoFolders(self, parentPath, embryo):
        self.parentPath = parentPath
        self.embryo = embryo
        self.embryoFolders = glob.glob(parentPath + "*/" + embryo +"/")
        self.embryoFolders.sort(key=os.path.getctime) 
        
#==============================================================================
#   Get image
#==============================================================================
    def imImport(self):
        for f in range(len(self.eggUIimPaths)):
            im = cv2.imread(self.eggUIimPaths[f],cv2.IMREAD_ANYDEPTH)
            ran = (im.max()-im.min())/255.
            out = (im/ran)
            out = out-out.min()
            self.compSeq[int(f)] = out.astype(np.uint8)
            self.compSeq[f] = self.compSeq[f].T
#==============================================================================
#   Update image iteratively when slider moved
#==============================================================================
#==============================================================================
#     def updateImage(self):
#         self.getSeqValsAndCurrROI()
#         #self.UI.compSeq[e*len(self.eggIDIms):(e*len(self.eggIDIms)+len(self.eggIDIms))] = self.seq
#         #self.UI.comp(self.imImport(self.diag.imv.currentIndex()))
#         im = cv2.imread(self.eggUIimPaths[self.diag.imv.currentIndex],cv2.IMREAD_ANYDEPTH)
#         ran = (im.max()-im.min())/255.
#         out = (im/ran)
#         out = out-out.min()
#         self.compSeq[self.diag.imv.currentIndex] = out.astype(np.uint8)
#         self.diag.imv.setImage(self.compSeq.T)
#         self.diag.imv.show()
# #========
#==============================================================================
#==============================================================================
# ROI functions
#==============================================================================         
#==============================================================================
#   Import OpenCV determined ROIs from dataHandling instance. Called from showUI and updateUI.
#==============================================================================
    def importOpenCVROIs(self,eggRotBBox, eggBoxPoints):
        self.eggRotBBox = eggRotBBox
        self.eggBoxPoints = eggBoxPoints
        self.originalEggRotBBox = eggRotBBox.copy()
        self.originalEggBoxPoints = eggBoxPoints.copy()

#==============================================================================
#   Get index values for ROI data.     
#==============================================================================
    def getSeqValsAndCurrROI(self):
        # Calculate the indices for current frame
        if self.eggInt != 1234:
            self.divVal = self.diag.imv.currentIndex/float(len(self.eggRotBBox[1]))
            self.intDivVal = int(self.divVal)
            self.withinSeqVal = int((self.divVal - self.intDivVal)*len(self.eggRotBBox[self.intDivVal]))
            self.currROI_eggRotBBox = self.eggRotBBox[self.intDivVal,self.withinSeqVal]
            self.currROI_eggBoxPoints = self.eggBoxPoints[self.intDivVal,self.withinSeqVal]
        else:
            self.divVal = self.diag.imv.currentIndex
            self.intDivVal = int(self.divVal)
            self.currROI_eggRotBBox = self.eggRotBBox[0,self.intDivVal] 
            self.currROI_eggBoxPoints = self.eggBoxPoints[0,self.intDivVal] 
#==============================================================================
#   Generate a pyqtgraph ROI, using data from OpenCV.
#==============================================================================
    def createOpenCVEggROI(self):
        # Get relevant sequence position and ROI.
        self.getSeqValsAndCurrROI()   
        if (self.currROI_eggRotBBox[0] != 'nan'):
            # 0 or 90 degree angles seem very buggy. Shift to 1 and 89 as a bodge fix.
            if self.currROI_eggRotBBox[4] == -90:
                #self.currROI_eggRotBBox[4] = -89
                # Get rotated bounding box points
                ySorted = self.currROI_eggBoxPoints[np.argsort(self.currROI_eggBoxPoints[:, 1]), :]
                # Get bottom most, and top most sorted corner points
                bottomMost = ySorted[:2, :]
                topMost = ySorted[2:, :]
                # Get bottom most
                bottomMost = bottomMost[np.argsort(bottomMost[:, 1]), :]
                (bl, br) = bottomMost
                # Use bottom-left coordinate as anchor to calculate the Euclidean distance between the
                # The point with the largest distance will be our bottom-right point
                D = dist.cdist(bl[np.newaxis], topMost, "euclidean")[0]
                (tl, tr) = topMost[np.argsort(D)[::-1], :]
                self.roi = pg.ROI([bl[0], bl[1]], [self.currROI_eggRotBBox[2], self.currROI_eggRotBBox[3]])
            elif self.currROI_eggRotBBox[4] == -0:
                #self.currROI_eggRotBBox[4] = -1  
                ySorted = self.currROI_eggBoxPoints[np.argsort(self.currROI_eggBoxPoints[:, 1]), :]
                # Get bottom most, and top most sorted corner points
                bottomMost = ySorted[:2, :]
                topMost = ySorted[2:, :]
                # Get bottom most
                bottomMost = bottomMost[np.argsort(bottomMost[:, 1]), :]
                (bl, br) = bottomMost
                # Use bottom-left coordinate as anchor to calculate the Euclidean distance between the
                # The point with the largest distance will be our bottom-right point
                D = dist.cdist(bl[np.newaxis], topMost, "euclidean")[0]
                (tl, tr) = topMost[np.argsort(D)[::-1], :]
                self.roi = pg.ROI([bl[0], bl[1]], [self.currROI_eggRotBBox[2], self.currROI_eggRotBBox[3]])
            elif self.currROI_eggRotBBox[4] == -180:
                #self.currROI_eggRotBBox[4] = -179
                ySorted = self.currROI_eggBoxPoints[np.argsort(self.currROI_eggBoxPoints[:, 1]), :]
                # Get bottom most, and top most sorted corner points
                bottomMost = ySorted[:2, :]
                topMost = ySorted[2:, :]
                # Get bottom most
                bottomMost = bottomMost[np.argsort(bottomMost[:, 1]), :]
                (bl, br) = bottomMost
                # Use bottom-left coordinate as anchor to calculate the Euclidean distance between the
                # The point with the largest distance will be our bottom-right point
                D = dist.cdist(bl[np.newaxis], topMost, "euclidean")[0]
                (tl, tr) = topMost[np.argsort(D)[::-1], :]
                self.roi = pg.ROI([bl[0], bl[1]], [self.currROI_eggRotBBox[2], self.currROI_eggRotBBox[3]])
            
            else:
                # Get rotated bounding box points
                ySorted = self.currROI_eggBoxPoints[np.argsort(self.currROI_eggBoxPoints[:, 1]), :]
                # Get bottom most, and top most sorted corner points
                bottomMost = ySorted[:2, :]
                topMost = ySorted[2:, :]
                # Get bottom most
                bottomMost = bottomMost[np.argsort(bottomMost[:, 1]), :]
                (bl, br) = bottomMost
                # Use bottom-left coordinate as anchor to calculate the Euclidean distance between the
                # The point with the largest distance will be our bottom-right point
                D = dist.cdist(bl[np.newaxis], topMost, "euclidean")[0]
                (tl, tr) = topMost[np.argsort(D)[::-1], :]
        
                # Make ROI - note non 0,or 90 degree angles, require different of the X size
                # Rectangular ROI used to enable more easy handling of corner handles for tracking user chagnges.
                if (self.currROI_eggRotBBox[4] == -90.0) | (self.currROI_eggRotBBox[4] == -0.0)| (self.currROI_eggRotBBox[4] == 0.0):
                    self.roi = pg.ROI([bl[0], bl[1]], [self.currROI_eggRotBBox[2], self.currROI_eggRotBBox[3]])
                    # roi = pg.EllipseROI([bottomMost[0][0], bottomMost[0][1]], [eggRotBBox[vidTime][2], eggRotBBox[vidTime][3]])
                    # Debug
                    # print 'no angle'    
                else:
                    # Random angle ROIs
                    self.roi = pg.ROI([bottomMost[0][0], bottomMost[0][1]], [-self.currROI_eggRotBBox[2], self.currROI_eggRotBBox[3]])
                    self.roi.setAngle(self.currROI_eggRotBBox[4], update=True)
                    # roi = pg.EllipseROI([bottomMost[0][0], bottomMost[0][1]], [-eggRotBBox[vidTime][2], eggRotBBox[vidTime][3]])
            # Add handles
            self.roi.addRotateHandle([1, 0],[0.5,0.5])
            self.roi.addRotateHandle([0, 1], [0.5,0.5])
            self.roi.addScaleHandle([1, 1], [0, 0])
            self.roi.addScaleHandle([0, 0], [1, 1])
            self.roi.setPen('y',width=3)
            self.roi.removable
            self.roi.invertible = 'True'
            # Make var for dealing with modifications to roi
            self.updatedEggROI=[]
            self.roi.sigRegionChangeFinished.connect(self.updateROI)
        #else:
#==============================================================================
#   Update the ROI for current embryo.
#==============================================================================    
    def updateOpenCVEggROICurrEmbryo(self):
        # Remove previous
        if (hasattr(self, 'roi')):
            self.diag.imv.removeItem(self.roi)
        # Get relevant video position and ROI.
        self.getSeqValsAndCurrROI()      
        # 0 or 90 degree angles seem very buggy. Shift to 1 and 89 as a bodge fix.
        if self.currROI_eggRotBBox[4] == -90:
            #self.currROI_eggRotBBox[4] = -89
            # Get rotated bounding box points
            ySorted = self.currROI_eggBoxPoints[np.argsort(self.currROI_eggBoxPoints[:, 1]), :]
            # Get bottom most, and top most sorted corner points
            bottomMost = ySorted[:2, :]
            topMost = ySorted[2:, :]
            # Get bottom most
            bottomMost = bottomMost[np.argsort(bottomMost[:, 1]), :]
            (bl, br) = bottomMost
            # Use bottom-left coordinate as anchor to calculate the Euclidean distance between the
            # The point with the largest distance will be our bottom-right point
            D = dist.cdist(bl[np.newaxis], topMost, "euclidean")[0]
            (tl, tr) = topMost[np.argsort(D)[::-1], :]
            self.roi = pg.ROI([bl[0], bl[1]], [self.currROI_eggRotBBox[2], self.currROI_eggRotBBox[3]])
        elif self.currROI_eggRotBBox[4] == -0:
            #self.currROI_eggRotBBox[4] = -1  
            ySorted = self.currROI_eggBoxPoints[np.argsort(self.currROI_eggBoxPoints[:, 1]), :]
            # Get bottom most, and top most sorted corner points
            bottomMost = ySorted[:2, :]
            topMost = ySorted[2:, :]
            # Get bottom most
            bottomMost = bottomMost[np.argsort(bottomMost[:, 1]), :]
            (bl, br) = bottomMost
            # Use bottom-left coordinate as anchor to calculate the Euclidean distance between the
            # The point with the largest distance will be our bottom-right point
            D = dist.cdist(bl[np.newaxis], topMost, "euclidean")[0]
            (tl, tr) = topMost[np.argsort(D)[::-1], :]
            self.roi = pg.ROI([bl[0], bl[1]], [self.currROI_eggRotBBox[2], self.currROI_eggRotBBox[3]])
        elif self.currROI_eggRotBBox[4] == -180:
            #self.currROI_eggRotBBox[4] = -179
            ySorted = self.currROI_eggBoxPoints[np.argsort(self.currROI_eggBoxPoints[:, 1]), :]
            # Get bottom most, and top most sorted corner points
            bottomMost = ySorted[:2, :]
            topMost = ySorted[2:, :]
            # Get bottom most
            bottomMost = bottomMost[np.argsort(bottomMost[:, 1]), :]
            (bl, br) = bottomMost
            # Use bottom-left coordinate as anchor to calculate the Euclidean distance between the
            # The point with the largest distance will be our bottom-right point
            D = dist.cdist(bl[np.newaxis], topMost, "euclidean")[0]
            (tl, tr) = topMost[np.argsort(D)[::-1], :]
            self.roi = pg.ROI([bl[0], bl[1]], [self.currROI_eggRotBBox[2], self.currROI_eggRotBBox[3]])
        
        else:
            # Get rotated bounding box points
            ySorted = self.currROI_eggBoxPoints[np.argsort(self.currROI_eggBoxPoints[:, 1]), :]
            # Get bottom most, and top most sorted corner points
            bottomMost = ySorted[:2, :]
            topMost = ySorted[2:, :]
            # Get bottom most
            bottomMost = bottomMost[np.argsort(bottomMost[:, 1]), :]
            (bl, br) = bottomMost
            # Use bottom-left coordinate as anchor to calculate the Euclidean distance between the
            # The point with the largest distance will be our bottom-right point
            D = dist.cdist(bl[np.newaxis], topMost, "euclidean")[0]
            (tl, tr) = topMost[np.argsort(D)[::-1], :]
    
            # Make ROI - note non 0,or 90 degree angles, require different of the X size
            # Rectangular ROI used to enable more easy handling of corner handles for tracking user chagnges.
            if (self.currROI_eggRotBBox[4] == -90.0) | (self.currROI_eggRotBBox[4] == -0.0)| (self.currROI_eggRotBBox[4] == 0.0):
                self.roi = pg.ROI([bl[0], bl[1]], [self.currROI_eggRotBBox[2], self.currROI_eggRotBBox[3]])
                # roi = pg.EllipseROI([bottomMost[0][0], bottomMost[0][1]], [eggRotBBox[vidTime][2], eggRotBBox[vidTime][3]])
                # Debug
                # print 'no angle'    
            else:
                # Random angle ROIs
                self.roi = pg.ROI([bottomMost[0][0], bottomMost[0][1]], [-self.currROI_eggRotBBox[2], self.currROI_eggRotBBox[3]])
                self.roi.setAngle(self.currROI_eggRotBBox[4], update=True)
                # roi = pg.EllipseROI([bottomMost[0][0], bottomMost[0][1]], [-eggRotBBox[vidTime][2], eggRotBBox[vidTime][3]])
 
            # roi = pg.EllipseROI([bottomMost[0][0], bottomMost[0][1]], [-eggRotBBox[vidTime][2], eggRotBBox[vidTime][3]])
        # Add handles
        self.roi.addRotateHandle([1, 0],[0.5,0.5])
        self.roi.addRotateHandle([0, 1], [0.5,0.5])
        self.roi.addScaleHandle([1, 1], [0, 0])
        self.roi.addScaleHandle([0, 0], [1, 1])
        self.roi.setPen('y',width=3)
        self.roi.removable
        self.roi.invertible = 'True'
        # Make var for dealing with modifications to roi
        self.updatedEggROI=[]
        ### Still to do...
        self.diag.imv.addItem(self.roi)
        self.roi.sigRegionChangeFinished.connect(self.updateROI)

#==============================================================================
#   Update ROI for new embryo.        
#==============================================================================
    def updateOpenCVEggROINewEmbryo(self):
        # Remove old ROI
        if (hasattr(self, 'roi')):
            self.diag.imv.removeItem(self.roi)
        # Get relevant video position and ROI
        self.getSeqValsAndCurrROI()    
        # 0 or 90 degree angles seem very buggy. Shift to 1 and 89 as a bodge fix.        
        if self.currROI_eggRotBBox[4] == -90:
            #self.currROI_eggRotBBox[4] = -89
            # Get rotated bounding box points
            ySorted = self.currROI_eggBoxPoints[np.argsort(self.currROI_eggBoxPoints[:, 1]), :]
            # Get bottom most, and top most sorted corner points
            bottomMost = ySorted[:2, :]
            topMost = ySorted[2:, :]
            # Get bottom most
            bottomMost = bottomMost[np.argsort(bottomMost[:, 1]), :]
            (bl, br) = bottomMost
            # Use bottom-left coordinate as anchor to calculate the Euclidean distance between the
            # The point with the largest distance will be our bottom-right point
            D = dist.cdist(bl[np.newaxis], topMost, "euclidean")[0]
            (tl, tr) = topMost[np.argsort(D)[::-1], :]
            self.roi = pg.ROI([bl[0], bl[1]], [self.currROI_eggRotBBox[2], self.currROI_eggRotBBox[3]])
        elif self.currROI_eggRotBBox[4] == -0:
            #self.currROI_eggRotBBox[4] = -1  
            ySorted = self.currROI_eggBoxPoints[np.argsort(self.currROI_eggBoxPoints[:, 1]), :]
            # Get bottom most, and top most sorted corner points
            bottomMost = ySorted[:2, :]
            topMost = ySorted[2:, :]
            # Get bottom most
            bottomMost = bottomMost[np.argsort(bottomMost[:, 1]), :]
            (bl, br) = bottomMost
            # Use bottom-left coordinate as anchor to calculate the Euclidean distance between the
            # The point with the largest distance will be our bottom-right point
            D = dist.cdist(bl[np.newaxis], topMost, "euclidean")[0]
            (tl, tr) = topMost[np.argsort(D)[::-1], :]
            self.roi = pg.ROI([bl[0], bl[1]], [self.currROI_eggRotBBox[2], self.currROI_eggRotBBox[3]])
        elif self.currROI_eggRotBBox[4] == -180:
            #self.currROI_eggRotBBox[4] = -179
            ySorted = self.currROI_eggBoxPoints[np.argsort(self.currROI_eggBoxPoints[:, 1]), :]
            # Get bottom most, and top most sorted corner points
            bottomMost = ySorted[:2, :]
            topMost = ySorted[2:, :]
            # Get bottom most
            bottomMost = bottomMost[np.argsort(bottomMost[:, 1]), :]
            (bl, br) = bottomMost
            # Use bottom-left coordinate as anchor to calculate the Euclidean distance between the
            # The point with the largest distance will be our bottom-right point
            D = dist.cdist(bl[np.newaxis], topMost, "euclidean")[0]
            (tl, tr) = topMost[np.argsort(D)[::-1], :]
            self.roi = pg.ROI([bl[0], bl[1]], [self.currROI_eggRotBBox[2], self.currROI_eggRotBBox[3]])
        
        else:
            # Get rotated bounding box points
            ySorted = self.currROI_eggBoxPoints[np.argsort(self.currROI_eggBoxPoints[:, 1]), :]
            # Get bottom most, and top most sorted corner points
            bottomMost = ySorted[:2, :]
            topMost = ySorted[2:, :]
            # Get bottom most
            bottomMost = bottomMost[np.argsort(bottomMost[:, 1]), :]
            (bl, br) = bottomMost
            # Use bottom-left coordinate as anchor to calculate the Euclidean distance between the
            # The point with the largest distance will be our bottom-right point
            D = dist.cdist(bl[np.newaxis], topMost, "euclidean")[0]
            (tl, tr) = topMost[np.argsort(D)[::-1], :]
    
            # Make ROI - note non 0,or 90 degree angles, require different of the X size
            # Rectangular ROI used to enable more easy handling of corner handles for tracking user chagnges.
            if (self.currROI_eggRotBBox[4] == -90.0) | (self.currROI_eggRotBBox[4] == -0.0)| (self.currROI_eggRotBBox[4] == 0.0):
                self.roi = pg.ROI([bl[0], bl[1]], [self.currROI_eggRotBBox[2], self.currROI_eggRotBBox[3]])
                # roi = pg.EllipseROI([bottomMost[0][0], bottomMost[0][1]], [eggRotBBox[vidTime][2], eggRotBBox[vidTime][3]])
                # Debug
                # print 'no angle'    
            else:
                # Random angle ROIs
                self.roi = pg.ROI([bottomMost[0][0], bottomMost[0][1]], [-self.currROI_eggRotBBox[2], self.currROI_eggRotBBox[3]])
                self.roi.setAngle(self.currROI_eggRotBBox[4], update=True)
        # Add handles
        self.roi.addRotateHandle([1, 0],[0.5,0.5])
        self.roi.addRotateHandle([0, 1], [0.5,0.5])
        self.roi.addScaleHandle([1, 1], [0, 0])
        self.roi.addScaleHandle([0, 0], [1, 1])
        self.roi.setPen('y',width=3)
        self.roi.removable
        self.roi.invertible = 'True'
        # Make var for dealing with modifications to roi
        self.updatedEggROI=[]
        ### Still to do...
        self.diag.imv.addItem(self.roi)
        self.roi.sigRegionChangeFinished.connect(self.updateROI)

#==============================================================================
#   Update ROI.        
#==============================================================================
    def updateROI(self):
        #global vidTime, xyPosHandles, ellipse, changeAngle, roiChanges,updatedEggROI, changeX, changeY, changeScaleX, changeScaleY, changeAngle
        # Get changes to ROI scale, angle and position
        roiChanges = self.roi.getGlobalTransform()    
        changeX = -roiChanges.getTranslation()[0]
        changeY = roiChanges.getTranslation()[1]
        changeScaleX = roiChanges.getScale()[0]
        changeScaleY = roiChanges.getScale()[1]
        changeAngle = roiChanges.getAngle()
        # Update ROI, either updating the previously updated or taking the unaltered ROI from OpenCV as a starting point.
        #if len(self.updatedEggROI) == 0:
        self.updatedEggROI = (((self.currROI_eggRotBBox[0]-changeX),(self.currROI_eggRotBBox[1]+changeY)),((max((self.currROI_eggRotBBox[3]*changeScaleX),(self.currROI_eggRotBBox[2]*changeScaleY))),(min((self.currROI_eggRotBBox[3]*changeScaleX),(self.currROI_eggRotBBox[2]*changeScaleY)))),self.currROI_eggRotBBox[4]+changeAngle)
        #else:
            #self.updatedEggROI = (((self.updatedEggROI[0][0]-changeX),(self.updatedEggROI[0][1]+changeY)),((max((self.updatedEggROI[1][0]*changeScaleX),(self.updatedEggROI[1][1]*changeScaleY))),(min((self.updatedEggROI[1][0]*changeScaleX),(self.updatedEggROI[1][1]*changeScaleY)))),self.updatedEggROI[2]+changeAngle)
        hh = self.roi.getHandles()
        hh = [self.roi.mapToItem(self.diag.imv.getImageItem(), h.pos()) for h in hh]
        # Handle on each corner. Get handle positions
        self.xyPosHandles =[]  
        for h in hh:
            self.xyPosHandles.append([h.x(),h.y()]) 
        (eggBBX, eggBBY), (eggBBW, eggBBH), eggBBAng = cv2.minAreaRect(np.array(self.xyPosHandles, dtype=np.int32) )
        if eggBBAng == -90:
            eggBBAng = -89
        elif eggBBAng == -180:
            eggBBAng = -179
        elif eggBBAng == -0:
            eggBBAng = -1  
            # Save updated 
        # If more than one frame eggID per sequence..
        if self.eggInt != 1234:
            self.eggRotBBox[self.intDivVal,self.withinSeqVal] = [eggBBX, eggBBY, eggBBW, eggBBH, eggBBAng]
            self.eggBoxPoints[self.intDivVal,self.withinSeqVal] = cv2.boxPoints(((eggBBX, eggBBY), (eggBBW, eggBBH), eggBBAng))
        # Otherwise just save simply
        else:
            self.eggRotBBox[0,self.intDivVal] = [eggBBX, eggBBY, eggBBW, eggBBH, eggBBAng]
            self.eggBoxPoints[0,self.intDivVal] = cv2.boxPoints(((eggBBX, eggBBY), (eggBBW, eggBBH), eggBBAng))

#==============================================================================
#   Copy ROI on button click.
#==============================================================================
    def cpROI(self):
        self.originalEggRotBBox = self.currROI_eggRotBBox
        self.originalEggBoxPoints = self.currROI_eggBoxPoints

#==============================================================================
#   Assign nan to current ROI if 'No Egg' button clicked
#==============================================================================
    def recordNoEgg(self):
        # Remove ROI
        self.diag.imv.removeItem(self.roi)
        # Store nans in place of ROI
        if self.eggInt != 1234:
            self.eggRotBBox[self.intDivVal,self.withinSeqVal] = [np.nan, np.nan, np.nan, np.nan, np.nan]
            self.eggBoxPoints[0,self.intDivVal] = [np.nan,np.nan,np.nan,np.nan]
        else:
            self.eggBoxPoints[0,self.intDivVal] = [np.nan,np.nan,np.nan,np.nan]
            self.eggRotBBox[0,self.intDivVal] = [np.nan, np.nan, np.nan, np.nan, np.nan]
        
#==============================================================================
#   Copy ROI on button click.
#==============================================================================
    def applyCopiedROI(self):
        self.getSeqValsAndCurrROI()
        # Store copied ROI to embryo sequence ROIs
        if self.eggInt != 1234:
            self.divVal = self.diag.imv.currentIndex/float(len(self.eggRotBBox[1]))
            self.intDivVal = int(self.divVal)
            self.withinSeqVal = int((self.divVal - self.intDivVal)*len(self.eggRotBBox[self.intDivVal]))
            self.eggRotBBox[self.intDivVal,self.withinSeqVal] = self.originalEggRotBBox
            self.eggBoxPoints[self.intDivVal,self.withinSeqVal] = self.originalEggBoxPoints
        else:
            self.divVal = self.diag.imv.currentIndex
            self.intDivVal = int(self.divVal)
            self.eggRotBBox[0,self.intDivVal] = self.originalEggRotBBox
            self.eggBoxPoints[0,self.intDivVal] = self.originalEggBoxPoints 
        self.updateOpenCVEggROICurrEmbryo()
        
        
 
#==============================================================================
#        
#==============================================================================

#==============================================================================
#   Close button - not implemented (hidden)
#==============================================================================
#==============================================================================
#     def closeEvent(self, event):
#     
#         quit_msg = "Are you sure you want to exit the program?"
#         reply = QtGui.QMessageBox.question(self, 'Message', 
#                          quit_msg, QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
#     
#         if reply == QtGui.QMessageBox.Yes:
#             #event.accept()
#             app.quit()
#         else:
#             event.ignore()
#         
#==============================================================================
#==============================================================================
#         #self.originalEggRotBBox = eggRotBBox.copy()
#         #self.originalEggBoxPoints = eggBoxPoints.copy()
#         #self.currROI_eggRotBBox = self.eggRotBBox[self.intDivVal,self.withinSeqVal]
#         #self.currROI_eggBoxPoints = self.eggBoxPoints[self.intDivVal,self.withinSeqVal]
# 
#         # Modified version of updateOpenCVEggROICurrEmbryo
#         # Remove previous
#         self.diag.imv.removeItem(self.roi)
#         # Get relevant video position and ROI.
#         self.getSeqValsAndCurrROI()      
#         # Get rotated bounding box points
#         ySorted = self.originalEggBoxPoints[np.argsort(self.originalEggBoxPoints[:, 1]), :]
#         # Get bottom most, and top most sorted corner points
#         bottomMost = ySorted[:2, :]
#         topMost = ySorted[2:, :]
#         # Get bottom most
#         bottomMost = bottomMost[np.argsort(bottomMost[:, 1]), :]
#         (bl, br) = bottomMost
#         # Use bottom-left coordinate as anchor to calculate the Euclidean distance between the
#         # The point with the largest distance will be our bottom-right point
#         D = dist.cdist(bl[np.newaxis], topMost, "euclidean")[0]
#         (tl, tr) = topMost[np.argsort(D)[::-1], :]
#         # Make ROI - note non 0,or 90 degree angles, require different of the X size
#         # Rectangular ROI used to enable more easy handling of corner handles for tracking user chagnges.
#         if (self.originalEggRotBBox[4] == -90.0) | (self.originalEggRotBBox[4] == -0.0)| (self.originalEggRotBBox[4] == 0.0):
#             self.roi = pg.ROI([bottomMost[0][0], bottomMost[0][1]], [self.originalEggRotBBox[2], self.originalEggRotBBox[3]])
#             # roi = pg.EllipseROI([bottomMost[0][0], bottomMost[0][1]], [eggRotBBox[vidTime][2], eggRotBBox[vidTime][3]])
#         else:
#             # Random angle ROIs
#             self.roi = pg.ROI([bottomMost[0][0], bottomMost[0][1]], [-self.originalEggRotBBox[2], self.originalEggRotBBox[3]])
#             self.roi.setAngle(self.originalEggRotBBox[4], update=True)
#             # roi = pg.EllipseROI([bottomMost[0][0], bottomMost[0][1]], [-eggRotBBox[vidTime][2], eggRotBBox[vidTime][3]])
#         # Add handles
#         self.roi.addRotateHandle([1, 0],[0.5,0.5])
#         self.roi.addRotateHandle([0, 1], [0.5,0.5])
#         self.roi.addScaleHandle([1, 1], [0, 0])
#         self.roi.addScaleHandle([0, 0], [1, 1])
#         self.roi.setPen('y',width=3)
#         self.roi.removable
#         self.roi.invertible = 'True'
#         # Make var for dealing with modifications to roi
#         self.updatedEggROI=[]
#         ### Still to do...
#         self.diag.imv.addItem(self.roi)
#         self.roi.sigRegionChangeFinished.connect(self.updateROI)
#==============================================================================
        
#===============
[((22, 19, 22, 38), 'pyqtgraph.Qt.QtCore.pyqtSignal', 'QtCore.pyqtSignal', ({}, {}), '()', False, 'from pyqtgraph.Qt import QtCore, QtGui\n'), ((23, 19, 23, 38), 'pyqtgraph.Qt.QtCore.pyqtSignal', 'QtCore.pyqtSignal', ({}, {}), '()', False, 'from pyqtgraph.Qt import QtCore, QtGui\n'), ((24, 17, 24, 36), 'pyqtgraph.Qt.QtCore.pyqtSignal', 'QtCore.pyqtSignal', ({}, {}), '()', False, 'from pyqtgraph.Qt import QtCore, QtGui\n'), ((29, 20, 29, 35), 'PyQt5.QtGui.QDialog', 'QtGui.QDialog', ({}, {}), '()', False, 'from PyQt5 import QtGui\n'), ((32, 24, 32, 38), 'pyqtgraph.ImageView', 'pg.ImageView', ({}, {}), '()', True, 'import pyqtgraph as pg\n'), ((43, 24, 43, 38), 'pyqtgraph.ImageView', 'pg.ImageView', ({}, {}), '()', True, 'import pyqtgraph as pg\n'), ((54, 26, 54, 46), 'PyQt5.QtGui.QTableWidget', 'QtGui.QTableWidget', ({}, {}), '()', False, 'from PyQt5 import QtGui\n'), ((75, 25, 75, 55), 'PyQt5.QtGui.QPushButton', 'QtGui.QPushButton', ({(75, 43, 75, 54): '"""&Copy ROI"""'}, {}), "('&Copy ROI')", False, 'from PyQt5 import QtGui\n'), ((77, 28, 77, 64), 'PyQt5.QtGui.QPushButton', 'QtGui.QPushButton', ({(77, 46, 77, 63): '"""&Use Copied ROI"""'}, {}), "('&Use Copied ROI')", False, 'from PyQt5 import QtGui\n'), ((79, 25, 79, 53), 'PyQt5.QtGui.QPushButton', 'QtGui.QPushButton', ({(79, 43, 79, 52): '"""&No Egg"""'}, {}), "('&No Egg')", False, 'from PyQt5 import QtGui\n'), ((81, 30, 81, 64), 'PyQt5.QtGui.QPushButton', 'QtGui.QPushButton', ({(81, 48, 81, 63): '"""&Approve ROIs"""'}, {}), "('&Approve ROIs')", False, 'from PyQt5 import QtGui\n'), ((83, 24, 83, 49), 'PyQt5.QtGui.QPushButton', 'QtGui.QPushButton', ({(83, 42, 83, 48): '"""Exit"""'}, {}), "('Exit')", False, 'from PyQt5 import QtGui\n'), ((142, 55, 142, 80), 'PyQt5.QtGui.QColor', 'QtGui.QColor', ({(142, 68, 142, 69): '0', (142, 70, 142, 73): '100', (142, 74, 142, 75): '0', (142, 76, 142, 79): '120'}, {}), '(0, 100, 0, 120)', False, 'from PyQt5 import QtGui\n'), ((172, 21, 172, 39), 'numpy.zeros_like', 'np.zeros_like', ({(172, 35, 172, 38): 'ims'}, {}), '(ims)', True, 'import numpy as np\n'), ((182, 29, 182, 71), 'glob.glob', 'glob.glob', ({(182, 39, 182, 70): "parentPath + '*/' + embryo + '/'"}, {}), "(parentPath + '*/' + embryo + '/')", False, 'import glob\n'), ((190, 17, 190, 69), 'cv2.imread', 'cv2.imread', ({(190, 28, 190, 48): 'self.eggUIimPaths[f]', (190, 49, 190, 68): 'cv2.IMREAD_ANYDEPTH'}, {}), '(self.eggUIimPaths[f], cv2.IMREAD_ANYDEPTH)', False, 'import cv2\n'), ((355, 23, 355, 103), 'pyqtgraph.ROI', 'pg.ROI', ({(355, 30, 355, 44): '[bl[0], bl[1]]', (355, 46, 355, 102): '[self.currROI_eggRotBBox[2], self.currROI_eggRotBBox[3]]'}, {}), '([bl[0], bl[1]], [self.currROI_eggRotBBox[2], self.currROI_eggRotBBox[3]]\n    )', True, 'import pyqtgraph as pg\n'), ((451, 23, 451, 103), 'pyqtgraph.ROI', 'pg.ROI', ({(451, 30, 451, 44): '[bl[0], bl[1]]', (451, 46, 451, 102): '[self.currROI_eggRotBBox[2], self.currROI_eggRotBBox[3]]'}, {}), '([bl[0], bl[1]], [self.currROI_eggRotBBox[2], self.currROI_eggRotBBox[3]]\n    )', True, 'import pyqtgraph as pg\n'), ((543, 71, 543, 114), 'numpy.array', 'np.array', (), '', True, 'import numpy as np\n'), ((554, 66, 554, 127), 'cv2.boxPoints', 'cv2.boxPoints', ({(554, 80, 554, 126): '((eggBBX, eggBBY), (eggBBW, eggBBH), eggBBAng)'}, {}), '(((eggBBX, eggBBY), (eggBBW, eggBBH), eggBBAng))', False, 'import cv2\n'), ((558, 50, 558, 111), 'cv2.boxPoints', 'cv2.boxPoints', ({(558, 64, 558, 110): '((eggBBX, eggBBY), (eggBBW, eggBBH), eggBBAng)'}, {}), '(((eggBBX, eggBBY), (eggBBW, eggBBH), eggBBAng))', False, 'import cv2\n'), ((122, 26, 122, 51), 'PyQt5.QtGui.QColor', 'QtGui.QColor', ({(122, 39, 122, 40): '(0)', (122, 41, 122, 42): '(0)', (122, 43, 122, 46): '(100)', (122, 47, 122, 50): '(120)'}, {}), '(0, 0, 100, 120)', False, 'from PyQt5 import QtGui\n'), ((128, 26, 128, 54), 'PyQt5.QtGui.QTableWidgetItem', 'QtGui.QTableWidgetItem', ({(128, 49, 128, 53): 'item'}, {}), '(item)', False, 'from PyQt5 import QtGui\n'), ((147, 26, 147, 54), 'PyQt5.QtGui.QTableWidgetItem', 'QtGui.QTableWidgetItem', ({(147, 49, 147, 53): 'item'}, {}), '(item)', False, 'from PyQt5 import QtGui\n'), ((263, 27, 263, 107), 'pyqtgraph.ROI', 'pg.ROI', ({(263, 34, 263, 48): '[bl[0], bl[1]]', (263, 50, 263, 106): '[self.currROI_eggRotBBox[2], self.currROI_eggRotBBox[3]]'}, {}), '([bl[0], bl[1]], [self.currROI_eggRotBBox[2], self.currROI_eggRotBBox[3]]\n    )', True, 'import pyqtgraph as pg\n'), ((353, 16, 353, 64), 'scipy.spatial.distance.cdist', 'dist.cdist', ({(353, 27, 353, 41): 'bl[np.newaxis]', (353, 43, 353, 50): 'topMost', (353, 52, 353, 63): '"""euclidean"""'}, {}), "(bl[np.newaxis], topMost, 'euclidean')", True, 'from scipy.spatial import distance as dist\n'), ((369, 23, 369, 103), 'pyqtgraph.ROI', 'pg.ROI', ({(369, 30, 369, 44): '[bl[0], bl[1]]', (369, 46, 369, 102): '[self.currROI_eggRotBBox[2], self.currROI_eggRotBBox[3]]'}, {}), '([bl[0], bl[1]], [self.currROI_eggRotBBox[2], self.currROI_eggRotBBox[3]]\n    )', True, 'import pyqtgraph as pg\n'), ((449, 16, 449, 64), 'scipy.spatial.distance.cdist', 'dist.cdist', ({(449, 27, 449, 41): 'bl[np.newaxis]', (449, 43, 449, 50): 'topMost', (449, 52, 449, 63): '"""euclidean"""'}, {}), "(bl[np.newaxis], topMost, 'euclidean')", True, 'from scipy.spatial import distance as dist\n'), ((465, 23, 465, 103), 'pyqtgraph.ROI', 'pg.ROI', ({(465, 30, 465, 44): '[bl[0], bl[1]]', (465, 46, 465, 102): '[self.currROI_eggRotBBox[2], self.currROI_eggRotBBox[3]]'}, {}), '([bl[0], bl[1]], [self.currROI_eggRotBBox[2], self.currROI_eggRotBBox[3]]\n    )', True, 'import pyqtgraph as pg\n'), ((129, 38, 129, 63), 'PyQt5.QtGui.QColor', 'QtGui.QColor', ({(129, 51, 129, 52): '(0)', (129, 53, 129, 54): '(0)', (129, 55, 129, 58): '(100)', (129, 59, 129, 62): '(120)'}, {}), '(0, 0, 100, 120)', False, 'from PyQt5 import QtGui\n'), ((261, 20, 261, 68), 'scipy.spatial.distance.cdist', 'dist.cdist', ({(261, 31, 261, 45): 'bl[np.newaxis]', (261, 47, 261, 54): 'topMost', (261, 56, 261, 67): '"""euclidean"""'}, {}), "(bl[np.newaxis], topMost, 'euclidean')", True, 'from scipy.spatial import distance as dist\n'), ((277, 27, 277, 107), 'pyqtgraph.ROI', 'pg.ROI', ({(277, 34, 277, 48): '[bl[0], bl[1]]', (277, 50, 277, 106): '[self.currROI_eggRotBBox[2], self.currROI_eggRotBBox[3]]'}, {}), '([bl[0], bl[1]], [self.currROI_eggRotBBox[2], self.currROI_eggRotBBox[3]]\n    )', True, 'import pyqtgraph as pg\n'), ((367, 16, 367, 64), 'scipy.spatial.distance.cdist', 'dist.cdist', ({(367, 27, 367, 41): 'bl[np.newaxis]', (367, 43, 367, 50): 'topMost', (367, 52, 367, 63): '"""euclidean"""'}, {}), "(bl[np.newaxis], topMost, 'euclidean')", True, 'from scipy.spatial import distance as dist\n'), ((383, 23, 383, 103), 'pyqtgraph.ROI', 'pg.ROI', ({(383, 30, 383, 44): '[bl[0], bl[1]]', (383, 46, 383, 102): '[self.currROI_eggRotBBox[2], self.currROI_eggRotBBox[3]]'}, {}), '([bl[0], bl[1]], [self.currROI_eggRotBBox[2], self.currROI_eggRotBBox[3]]\n    )', True, 'import pyqtgraph as pg\n'), ((463, 16, 463, 64), 'scipy.spatial.distance.cdist', 'dist.cdist', ({(463, 27, 463, 41): 'bl[np.newaxis]', (463, 43, 463, 50): 'topMost', (463, 52, 463, 63): '"""euclidean"""'}, {}), "(bl[np.newaxis], topMost, 'euclidean')", True, 'from scipy.spatial import distance as dist\n'), ((479, 23, 479, 103), 'pyqtgraph.ROI', 'pg.ROI', ({(479, 30, 479, 44): '[bl[0], bl[1]]', (479, 46, 479, 102): '[self.currROI_eggRotBBox[2], self.currROI_eggRotBBox[3]]'}, {}), '([bl[0], bl[1]], [self.currROI_eggRotBBox[2], self.currROI_eggRotBBox[3]]\n    )', True, 'import pyqtgraph as pg\n'), ((275, 20, 275, 68), 'scipy.spatial.distance.cdist', 'dist.cdist', ({(275, 31, 275, 45): 'bl[np.newaxis]', (275, 47, 275, 54): 'topMost', (275, 56, 275, 67): '"""euclidean"""'}, {}), "(bl[np.newaxis], topMost, 'euclidean')", True, 'from scipy.spatial import distance as dist\n'), ((291, 27, 291, 107), 'pyqtgraph.ROI', 'pg.ROI', ({(291, 34, 291, 48): '[bl[0], bl[1]]', (291, 50, 291, 106): '[self.currROI_eggRotBBox[2], self.currROI_eggRotBBox[3]]'}, {}), '([bl[0], bl[1]], [self.currROI_eggRotBBox[2], self.currROI_eggRotBBox[3]]\n    )', True, 'import pyqtgraph as pg\n'), ((344, 48, 344, 91), 'numpy.argsort', 'np.argsort', ({(344, 59, 344, 90): 'self.currROI_eggBoxPoints[:, (1)]'}, {}), '(self.currROI_eggBoxPoints[:, (1)])', True, 'import numpy as np\n'), ((349, 36, 349, 64), 'numpy.argsort', 'np.argsort', ({(349, 47, 349, 63): 'bottomMost[:, (1)]'}, {}), '(bottomMost[:, (1)])', True, 'import numpy as np\n'), ((381, 16, 381, 64), 'scipy.spatial.distance.cdist', 'dist.cdist', ({(381, 27, 381, 41): 'bl[np.newaxis]', (381, 43, 381, 50): 'topMost', (381, 52, 381, 63): '"""euclidean"""'}, {}), "(bl[np.newaxis], topMost, 'euclidean')", True, 'from scipy.spatial import distance as dist\n'), ((396, 16, 396, 64), 'scipy.spatial.distance.cdist', 'dist.cdist', ({(396, 27, 396, 41): 'bl[np.newaxis]', (396, 43, 396, 50): 'topMost', (396, 52, 396, 63): '"""euclidean"""'}, {}), "(bl[np.newaxis], topMost, 'euclidean')", True, 'from scipy.spatial import distance as dist\n'), ((402, 27, 402, 107), 'pyqtgraph.ROI', 'pg.ROI', ({(402, 34, 402, 48): '[bl[0], bl[1]]', (402, 50, 402, 106): '[self.currROI_eggRotBBox[2], self.currROI_eggRotBBox[3]]'}, {}), '([bl[0], bl[1]], [self.currROI_eggRotBBox[2], self.currROI_eggRotBBox[3]]\n    )', True, 'import pyqtgraph as pg\n'), ((408, 27, 408, 130), 'pyqtgraph.ROI', 'pg.ROI', ({(408, 34, 408, 70): '[bottomMost[0][0], bottomMost[0][1]]', (408, 72, 408, 129): '[-self.currROI_eggRotBBox[2], self.currROI_eggRotBBox[3]]'}, {}), '([bottomMost[0][0], bottomMost[0][1]], [-self.currROI_eggRotBBox[2],\n    self.currROI_eggRotBBox[3]])', True, 'import pyqtgraph as pg\n'), ((440, 48, 440, 91), 'numpy.argsort', 'np.argsort', ({(440, 59, 440, 90): 'self.currROI_eggBoxPoints[:, (1)]'}, {}), '(self.currROI_eggBoxPoints[:, (1)])', True, 'import numpy as np\n'), ((445, 36, 445, 64), 'numpy.argsort', 'np.argsort', ({(445, 47, 445, 63): 'bottomMost[:, (1)]'}, {}), '(bottomMost[:, (1)])', True, 'import numpy as np\n'), ((477, 16, 477, 64), 'scipy.spatial.distance.cdist', 'dist.cdist', ({(477, 27, 477, 41): 'bl[np.newaxis]', (477, 43, 477, 50): 'topMost', (477, 52, 477, 63): '"""euclidean"""'}, {}), "(bl[np.newaxis], topMost, 'euclidean')", True, 'from scipy.spatial import distance as dist\n'), ((492, 16, 492, 64), 'scipy.spatial.distance.cdist', 'dist.cdist', ({(492, 27, 492, 41): 'bl[np.newaxis]', (492, 43, 492, 50): 'topMost', (492, 52, 492, 63): '"""euclidean"""'}, {}), "(bl[np.newaxis], topMost, 'euclidean')", True, 'from scipy.spatial import distance as dist\n'), ((498, 27, 498, 107), 'pyqtgraph.ROI', 'pg.ROI', ({(498, 34, 498, 48): '[bl[0], bl[1]]', (498, 50, 498, 106): '[self.currROI_eggRotBBox[2], self.currROI_eggRotBBox[3]]'}, {}), '([bl[0], bl[1]], [self.currROI_eggRotBBox[2], self.currROI_eggRotBBox[3]]\n    )', True, 'import pyqtgraph as pg\n'), ((504, 27, 504, 130), 'pyqtgraph.ROI', 'pg.ROI', ({(504, 34, 504, 70): '[bottomMost[0][0], bottomMost[0][1]]', (504, 72, 504, 129): '[-self.currROI_eggRotBBox[2], self.currROI_eggRotBBox[3]]'}, {}), '([bottomMost[0][0], bottomMost[0][1]], [-self.currROI_eggRotBBox[2],\n    self.currROI_eggRotBBox[3]])', True, 'import pyqtgraph as pg\n'), ((252, 52, 252, 95), 'numpy.argsort', 'np.argsort', ({(252, 63, 252, 94): 'self.currROI_eggBoxPoints[:, (1)]'}, {}), '(self.currROI_eggBoxPoints[:, (1)])', True, 'import numpy as np\n'), ((257, 40, 257, 68), 'numpy.argsort', 'np.argsort', ({(257, 51, 257, 67): 'bottomMost[:, (1)]'}, {}), '(bottomMost[:, (1)])', True, 'import numpy as np\n'), ((289, 20, 289, 68), 'scipy.spatial.distance.cdist', 'dist.cdist', ({(289, 31, 289, 45): 'bl[np.newaxis]', (289, 47, 289, 54): 'topMost', (289, 56, 289, 67): '"""euclidean"""'}, {}), "(bl[np.newaxis], topMost, 'euclidean')", True, 'from scipy.spatial import distance as dist\n'), ((304, 20, 304, 68), 'scipy.spatial.distance.cdist', 'dist.cdist', ({(304, 31, 304, 45): 'bl[np.newaxis]', (304, 47, 304, 54): 'topMost', (304, 56, 304, 67): '"""euclidean"""'}, {}), "(bl[np.newaxis], topMost, 'euclidean')", True, 'from scipy.spatial import distance as dist\n'), ((310, 31, 310, 111), 'pyqtgraph.ROI', 'pg.ROI', ({(310, 38, 310, 52): '[bl[0], bl[1]]', (310, 54, 310, 110): '[self.currROI_eggRotBBox[2], self.currROI_eggRotBBox[3]]'}, {}), '([bl[0], bl[1]], [self.currROI_eggRotBBox[2], self.currROI_eggRotBBox[3]]\n    )', True, 'import pyqtgraph as pg\n'), ((316, 31, 316, 134), 'pyqtgraph.ROI', 'pg.ROI', ({(316, 38, 316, 74): '[bottomMost[0][0], bottomMost[0][1]]', (316, 76, 316, 133): '[-self.currROI_eggRotBBox[2], self.currROI_eggRotBBox[3]]'}, {}), '([bottomMost[0][0], bottomMost[0][1]], [-self.currROI_eggRotBBox[2],\n    self.currROI_eggRotBBox[3]])', True, 'import pyqtgraph as pg\n'), ((354, 31, 354, 44), 'numpy.argsort', 'np.argsort', ({(354, 42, 354, 43): 'D'}, {}), '(D)', True, 'import numpy as np\n'), ((358, 48, 358, 91), 'numpy.argsort', 'np.argsort', ({(358, 59, 358, 90): 'self.currROI_eggBoxPoints[:, (1)]'}, {}), '(self.currROI_eggBoxPoints[:, (1)])', True, 'import numpy as np\n'), ((363, 36, 363, 64), 'numpy.argsort', 'np.argsort', ({(363, 47, 363, 63): 'bottomMost[:, (1)]'}, {}), '(bottomMost[:, (1)])', True, 'import numpy as np\n'), ((450, 31, 450, 44), 'numpy.argsort', 'np.argsort', ({(450, 42, 450, 43): 'D'}, {}), '(D)', True, 'import numpy as np\n'), ((454, 48, 454, 91), 'numpy.argsort', 'np.argsort', ({(454, 59, 454, 90): 'self.currROI_eggBoxPoints[:, (1)]'}, {}), '(self.currROI_eggBoxPoints[:, (1)])', True, 'import numpy as np\n'), ((459, 36, 459, 64), 'numpy.argsort', 'np.argsort', ({(459, 47, 459, 63): 'bottomMost[:, (1)]'}, {}), '(bottomMost[:, (1)])', True, 'import numpy as np\n'), ((262, 35, 262, 48), 'numpy.argsort', 'np.argsort', ({(262, 46, 262, 47): 'D'}, {}), '(D)', True, 'import numpy as np\n'), ((266, 52, 266, 95), 'numpy.argsort', 'np.argsort', ({(266, 63, 266, 94): 'self.currROI_eggBoxPoints[:, (1)]'}, {}), '(self.currROI_eggBoxPoints[:, (1)])', True, 'import numpy as np\n'), ((271, 40, 271, 68), 'numpy.argsort', 'np.argsort', ({(271, 51, 271, 67): 'bottomMost[:, (1)]'}, {}), '(bottomMost[:, (1)])', True, 'import numpy as np\n'), ((368, 31, 368, 44), 'numpy.argsort', 'np.argsort', ({(368, 42, 368, 43): 'D'}, {}), '(D)', True, 'import numpy as np\n'), ((372, 48, 372, 91), 'numpy.argsort', 'np.argsort', ({(372, 59, 372, 90): 'self.currROI_eggBoxPoints[:, (1)]'}, {}), '(self.currROI_eggBoxPoints[:, (1)])', True, 'import numpy as np\n'), ((377, 36, 377, 64), 'numpy.argsort', 'np.argsort', ({(377, 47, 377, 63): 'bottomMost[:, (1)]'}, {}), '(bottomMost[:, (1)])', True, 'import numpy as np\n'), ((387, 48, 387, 91), 'numpy.argsort', 'np.argsort', ({(387, 59, 387, 90): 'self.currROI_eggBoxPoints[:, (1)]'}, {}), '(self.currROI_eggBoxPoints[:, (1)])', True, 'import numpy as np\n'), ((392, 36, 392, 64), 'numpy.argsort', 'np.argsort', ({(392, 47, 392, 63): 'bottomMost[:, (1)]'}, {}), '(bottomMost[:, (1)])', True, 'import numpy as np\n'), ((464, 31, 464, 44), 'numpy.argsort', 'np.argsort', ({(464, 42, 464, 43): 'D'}, {}), '(D)', True, 'import numpy as np\n'), ((468, 48, 468, 91), 'numpy.argsort', 'np.argsort', ({(468, 59, 468, 90): 'self.currROI_eggBoxPoints[:, (1)]'}, {}), '(self.currROI_eggBoxPoints[:, (1)])', True, 'import numpy as np\n'), ((473, 36, 473, 64), 'numpy.argsort', 'np.argsort', ({(473, 47, 473, 63): 'bottomMost[:, (1)]'}, {}), '(bottomMost[:, (1)])', True, 'import numpy as np\n'), ((483, 48, 483, 91), 'numpy.argsort', 'np.argsort', ({(483, 59, 483, 90): 'self.currROI_eggBoxPoints[:, (1)]'}, {}), '(self.currROI_eggBoxPoints[:, (1)])', True, 'import numpy as np\n'), ((488, 36, 488, 64), 'numpy.argsort', 'np.argsort', ({(488, 47, 488, 63): 'bottomMost[:, (1)]'}, {}), '(bottomMost[:, (1)])', True, 'import numpy as np\n'), ((276, 35, 276, 48), 'numpy.argsort', 'np.argsort', ({(276, 46, 276, 47): 'D'}, {}), '(D)', True, 'import numpy as np\n'), ((280, 52, 280, 95), 'numpy.argsort', 'np.argsort', ({(280, 63, 280, 94): 'self.currROI_eggBoxPoints[:, (1)]'}, {}), '(self.currROI_eggBoxPoints[:, (1)])', True, 'import numpy as np\n'), ((285, 40, 285, 68), 'numpy.argsort', 'np.argsort', ({(285, 51, 285, 67): 'bottomMost[:, (1)]'}, {}), '(bottomMost[:, (1)])', True, 'import numpy as np\n'), ((295, 52, 295, 95), 'numpy.argsort', 'np.argsort', ({(295, 63, 295, 94): 'self.currROI_eggBoxPoints[:, (1)]'}, {}), '(self.currROI_eggBoxPoints[:, (1)])', True, 'import numpy as np\n'), ((300, 40, 300, 68), 'numpy.argsort', 'np.argsort', ({(300, 51, 300, 67): 'bottomMost[:, (1)]'}, {}), '(bottomMost[:, (1)])', True, 'import numpy as np\n'), ((382, 31, 382, 44), 'numpy.argsort', 'np.argsort', ({(382, 42, 382, 43): 'D'}, {}), '(D)', True, 'import numpy as np\n'), ((397, 31, 397, 44), 'numpy.argsort', 'np.argsort', ({(397, 42, 397, 43): 'D'}, {}), '(D)', True, 'import numpy as np\n'), ((478, 31, 478, 44), 'numpy.argsort', 'np.argsort', ({(478, 42, 478, 43): 'D'}, {}), '(D)', True, 'import numpy as np\n'), ((493, 31, 493, 44), 'numpy.argsort', 'np.argsort', ({(493, 42, 493, 43): 'D'}, {}), '(D)', True, 'import numpy as np\n'), ((290, 35, 290, 48), 'numpy.argsort', 'np.argsort', ({(290, 46, 290, 47): 'D'}, {}), '(D)', True, 'import numpy as np\n'), ((305, 35, 305, 48), 'numpy.argsort', 'np.argsort', ({(305, 46, 305, 47): 'D'}, {}), '(D)', True, 'import numpy as np\n')]