class_docstr: A single QA candidate answer.
docstr: Generates a string answer span using self.offset_answer_start and self.offset_answer_end. If the candidate
  is a no answer, an empty string is returned
  
  :param token_offsets: A list of ints which give the start character index of the corresponding token
  :param clear_text: The text from which the answer span is to be extracted
  :return: The string answer span, followed by the start and end character indices
docstr_tok: ["Generates","a","string","answer","span","using","self.offset_answer_start","and","self.offset_answer_end",".","If","the","candidate","is","a","no","answer",",","an","empty","string","is","returned",":","param","token_offsets",":","A","list","of","ints","which","give","the","start","character","index","of","the","corresponding","token",":","param","clear_text",":","The","text","from","which","the","answer","span","is","to","be","extracted",":","return",":","The","string","answer","span",",","followed","by","the","start","and","end","character","indices"]
code: def _span_to_string(self, token_offsets: List[int], clear_text: str):
      """
      Generates a string answer span using self.offset_answer_start and self.offset_answer_end. If the candidate
      is a no answer, an empty string is returned
  
      :param token_offsets: A list of ints which give the start character index of the corresponding token
      :param clear_text: The text from which the answer span is to be extracted
      :return: The string answer span, followed by the start and end character indices
      """
  
      if self.offset_unit != "token":
          logger.error(
              f"QACandidate needs to have self.offset_unit=token before calling _span_to_string() (id = {self.id})"
          )
  
      start_t = self.offset_answer_start
      end_t = self.offset_answer_end
  
      # If it is a no_answer prediction
      if start_t == -1 and end_t == -1:
          return "", 0, 0
  
      n_tokens = len(token_offsets)
  
      # We do this to point to the beginning of the first token after the span instead of
      # the beginning of the last token in the span
      end_t += 1
  
      # Predictions sometimes land on the very final special token of the passage. But there are no
      # special tokens on the document level. We will just interpret this as a span that stretches
      # to the end of the document
      end_t = min(end_t, n_tokens)
  
      start_ch = int(token_offsets[start_t])
      # i.e. pointing at the END of the last token
      if end_t == n_tokens:
          end_ch = len(clear_text)
      else:
          end_ch = token_offsets[end_t]
  
      final_text = clear_text[start_ch:end_ch]
  
      # if the final_text is more than whitespaces we trim it otherwise return a no_answer
      # final_text can be an empty string if start_t points to the very final token of the passage
      # final_text can be a whitespace if there is a whitespace token in the text, e.g.,
      # if the original text contained multiple consecutive whitespaces
      if len(final_text.strip()) > 0:
          final_text = final_text.strip()
      else:
          return "", 0, 0
      end_ch = int(start_ch + len(final_text))
  
      return final_text, start_ch, end_ch
  
imports: from typing import List, Any
  from abc import ABC
  import logging
label_desc: Use image node_id 6 for calling the QACandidate obj's underlying member method code with example usage: obj._span_to_string(token_offsets, clear_text) and returns: final_text,  start_ch,  end_ch, str,  int,  int, str,  int,  int