docs: def cluster(self, matrix=None, level=None, sequence=None):
          """
          Perform hierarchical clustering.
  
          :param matrix: The 2D list that is currently under processing. The
              matrix contains the distances of each item with each other
          :param level: The current level of clustering
          :param sequence: The sequence number of the clustering
          """
          logger.info("Performing cluster()")
  
          if matrix is None:
              # create level 0, first iteration (sequence)
              level = 0
              sequence = 0
              matrix = []
  
          # if the matrix only has two rows left, we are done
          linkage = partial(self.linkage, distance_function=self.distance)
          initial_element_count = len(self._data)
          while len(matrix) > 2 or matrix == []:
  
              item_item_matrix = Matrix(self._data,
                                        linkage,
                                        True,
                                        0)
              item_item_matrix.genmatrix(self.num_processes)
              matrix = item_item_matrix.matrix
  
              smallestpair = None
              mindistance = None
              rowindex = 0  # keep track of where we are in the matrix
              # find the minimum distance
              for row in matrix:
                  cellindex = 0  # keep track of where we are in the matrix
                  for cell in row:
                      # if we are not on the diagonal (which is always 0)
                      # and if this cell represents a new minimum...
                      cell_lt_mdist = cell < mindistance if mindistance else False
                      if ((rowindex != cellindex) and
                              (cell_lt_mdist or smallestpair is None)):
                          smallestpair = (rowindex, cellindex)
                          mindistance = cell
                      cellindex += 1
                  rowindex += 1
  
              sequence += 1
              level = matrix[smallestpair[1]][smallestpair[0]]
              cluster = Cluster(level, self._data[smallestpair[0]],
                                self._data[smallestpair[1]])
  
              # maintain the data, by combining the the two most similar items
              # in the list we use the min and max functions to ensure the
              # integrity of the data.  imagine: if we first remove the item
              # with the smaller index, all the rest of the items shift down by
              # one. So the next index will be wrong. We could simply adjust the
              # value of the second "remove" call, but we don't know the order
              # in which they come. The max and min approach clarifies that
              self._data.remove(self._data[max(smallestpair[0],
                                               smallestpair[1])])  # remove item 1
              self._data.remove(self._data[min(smallestpair[0],
                                               smallestpair[1])])  # remove item 2
              self._data.append(cluster)  # append item 1 and 2 combined
  
              self.publish_progress(initial_element_count, len(self._data))
  
          # all the data is in one single cluster. We return that and stop
          self.__cluster_created = True
          logger.info("Call to cluster() is complete")
          return