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