code: def find_abbreviation(
      long_form_candidate: Span, short_form_candidate: Span
  ) -> Tuple[Span, Optional[Span]]:
      """
      Implements the abbreviation detection algorithm in "A simple algorithm
      for identifying abbreviation definitions in biomedical text.", (Schwartz & Hearst, 2003).
  
      The algorithm works by enumerating the characters in the short form of the abbreviation,
      checking that they can be matched against characters in a candidate text for the long form
      in order, as well as requiring that the first letter of the abbreviated form matches the
      _beginning_ letter of a word.
  
      Parameters
      ----------
      long_form_candidate: Span, required.
          The spaCy span for the long form candidate of the definition.
      short_form_candidate: Span, required.
          The spaCy span for the abbreviation candidate.
  
      Returns
      -------
      A Tuple[Span, Optional[Span]], representing the short form abbreviation and the
      span corresponding to the long form expansion, or None if a match is not found.
      """
      long_form = " ".join([x.text for x in long_form_candidate])
      short_form = " ".join([x.text for x in short_form_candidate])
  
      long_index = len(long_form) - 1
      short_index = len(short_form) - 1
  
      while short_index >= 0:
          current_char = short_form[short_index].lower()
          # We don't check non alpha-numeric characters.
          if not current_char.isalnum():
              short_index -= 1
              continue
  
              # Does the character match at this position? ...
          while (
              (
                  long_index >= 0
                  and long_form[long_index].lower() != current_char
              )
              or
              # .... or if we are checking the first character of the abbreviation, we enforce
              # to be the _starting_ character of a span.
              (
                  short_index == 0
                  and long_index > 0
                  and long_form[long_index - 1].isalnum()
              )
          ):
              long_index -= 1
  
          if long_index < 0:
              return short_form_candidate, None
  
          long_index -= 1
          short_index -= 1
  
      # The last subtraction will either take us on to a whitespace character, or
      # off the front of the string (i.e. long_index == -1). Either way, we want to add
      # one to get back to the start character of the long form
      long_index += 1
  
      # Now we know the character index of the start of the character span,
      # here we just translate that to the first token beginning after that
      # value, so we can return a spaCy span instead.
      word_lengths = 0
      starting_index = None
      for i, word in enumerate(long_form_candidate):
          # need to add 1 for the space characters
          word_lengths += len(word.text_with_ws)
          if word_lengths > long_index:
              starting_index = i
              break
  
      return short_form_candidate, long_form_candidate[starting_index:]
  
file_path: scispacy/scispacy/abbreviation.py
imports: from typing import Tuple, List, Optional, Set, Dict
  from collections import defaultdict
  from spacy.tokens import Span, Doc
  from spacy.matcher import Matcher
  from spacy.language import Language
label_desc: Use image node_id 1 for calling a global function with example usage: find_abbreviation(long_form_candidate, short_form_candidate) and returns: short_form_candidate,  long_form_candidate, short_form_candidate,  None