If there is not currently a selected NV within self.settings[patch_size] of pt, adds it to the selected list. If
        there is, removes that point from the selected list.
        Args:
            pt: the point to add or remove from the selected list

        Poststate: updates selected list

def toggle_NV(self, pt):
        '''
        If there is not currently a selected NV within self.settings[patch_size] of pt, adds it to the selected list. If
        there is, removes that point from the selected list.
        Args:
            pt: the point to add or remove from the selected list

        Poststate: updates selected list

        '''

        if not self.data['nv_locations']: #if self.data is empty so this is the first point
            self.data['nv_locations'].append(pt)
            self.data['image_data'] = None # clear image data

        else:
            # use KDTree to find NV closest to mouse click
            tree = scipy.spatial.KDTree(self.data['nv_locations'])
            #does a search with k=1, that is a search for the nearest neighbor, within distance_upper_bound
            d, i = tree.query(pt,k = 1, distance_upper_bound = self.settings['patch_size'])

            # removes NV if previously selected
            if d is not np.inf:
                self.data['nv_locations'].pop(i)
            # adds NV if not previously selected
            else:
                self.data['nv_locations'].append(pt)

        # if type is not free we calculate the total points of locations from the first selected points
        if self.settings['type'] == 'square' and len(self.data['nv_locations'])>1:
            # here we create a rectangular grid, where pts a and be define the top left and bottom right corner of the rectangle
            Nx, Ny = self.settings['Nx'], self.settings['Ny']
            pta = self.data['nv_locations'][0]
            ptb = self.data['nv_locations'][1]
            tmp  = np.array([[[pta[0] + 1.0*i*(ptb[0]-pta[0])/(Nx-1), pta[1] + 1.0*j*(ptb[1]-pta[1])/(Ny-1)] for i in range(Nx)] for j in range(Ny)])
            self.data['nv_locations'] = np.reshape(tmp, (Nx * Ny, 2))
            self.stop()


        elif self.settings['type'] == 'line' and len(self.data['nv_locations'])>1:
            # here we create a straight line between points a and b
            N = self.settings['Nx']
            pta = self.data['nv_locations'][0]
            ptb = self.data['nv_locations'][1]
            self.data['nv_locations']  = [np.array([pta[0] + 1.0*i*(ptb[0]-pta[0])/(N-1), pta[1] + 1.0*i*(ptb[1]-pta[1])/(N-1)]) for i in range(N)]
            self.stop()

        elif self.settings['type'] == 'ring' and len(self.data['nv_locations'])>1:
            # here we create a circular grid, where pts a and be define the center and the outermost ring
            Nx, Ny = self.settings['Nx'], self.settings['Ny']

            pta = self.data['nv_locations'][0] # center
            ptb = self.data['nv_locations'][1] # outermost ring

            # radius of outermost ring:
            rmax = np.sqrt((pta[0] - ptb[0]) ** 2 + (pta[1] - ptb[1]) ** 2)

            # create points on rings
            tmp = []
            for r in np.linspace(rmax, 0, Ny + 1)[0:-1]:
                for theta in np.linspace(0, 2 * np.pi, Nx+1)[0:-1]:
                    tmp += [[r * np.sin(theta)+pta[0], r * np.cos(theta)+pta[1]]]

            self.data['nv_locations'] = np.array(tmp)
            self.stop()