def diff(self, catalogue, tokenizer, output_fh):
        """Returns `output_fh` populated with CSV results giving the n-grams
        that are unique to the witnesses of each labelled set of works
        in `catalogue`.

        Note that this is not the same as the symmetric difference of
        these sets, except in the case where there are only two
        labels.

        :param catalogue: catalogue matching filenames to labels
        :type catalogue: `Catalogue`
        :param tokenizer: tokenizer for the n-grams
        :type tokenizer: `Tokenizer`
        :param output_fh: object to output results to
        :type output_fh: file-like object
        :rtype: file-like object

        """
        labels = self._sort_labels(self._set_labels(catalogue))
        if len(labels) < 2:
            raise MalformedQueryError(
                constants.INSUFFICIENT_LABELS_QUERY_ERROR)
        label_placeholders = self._get_placeholders(labels)
        query = constants.SELECT_DIFF_SQL.format(label_placeholders,
                                                 label_placeholders)
        parameters = labels + labels
        self._logger.info('Running diff query')
        self._logger.debug('Query: {}\nLabels: {}'.format(query, labels))
        self._log_query_plan(query, parameters)
        cursor = self._conn.execute(query, parameters)
        return self._diff(cursor, tokenizer, output_fh)
Returns `output_fh` populated with CSV results giving the n-grams
        that are unique to the witnesses of each labelled set of works
        in `catalogue`.

        Note that this is not the same as the symmetric difference of
        these sets, except in the case where there are only two
        labels.

        :param catalogue: catalogue matching filenames to labels
        :type catalogue: `Catalogue`
        :param tokenizer: tokenizer for the n-grams
        :type tokenizer: `Tokenizer`
        :param output_fh: object to output results to
        :type output_fh: file-like object
        :rtype: file-like object