code: def deal_bb(result_token):
      """
      In our opinion, <b></b> always occurs in <thead></thead> text's context.
      This function will find out all tokens in <thead></thead> and insert <b></b> by manual.
      :param result_token:
      :return:
      """
      # find out <thead></thead> parts.
      thead_pattern = "<thead>(.*?)</thead>"
      if re.search(thead_pattern, result_token) is None:
          return result_token
      thead_part = re.search(thead_pattern, result_token).group()
      origin_thead_part = copy.deepcopy(thead_part)
  
      # check "rowspan" or "colspan" occur in <thead></thead> parts or not .
      span_pattern = '<td rowspan="(\d)+" colspan="(\d)+">|<td colspan="(\d)+" rowspan="(\d)+">|<td rowspan="(\d)+">|<td colspan="(\d)+">'
      span_iter = re.finditer(span_pattern, thead_part)
      span_list = [s.group() for s in span_iter]
      has_span_in_head = True if len(span_list) > 0 else False
  
      if not has_span_in_head:
          # <thead></thead> not include "rowspan" or "colspan" branch 1.
          # 1. replace <td> to <td><b>, and </td> to </b></td>
          # 2. it is possible to predict text include <b> or </b> by Text-line recognition,
          #    so we replace <b><b> to <b>, and </b></b> to </b>
          thead_part = (
              thead_part.replace("<td>", "<td><b>")
              .replace("</td>", "</b></td>")
              .replace("<b><b>", "<b>")
              .replace("</b></b>", "</b>")
          )
      else:
          # <thead></thead> include "rowspan" or "colspan" branch 2.
          # Firstly, we deal rowspan or colspan cases.
          # 1. replace > to ><b>
          # 2. replace </td> to </b></td>
          # 3. it is possible to predict text include <b> or </b> by Text-line recognition,
          #    so we replace <b><b> to <b>, and </b><b> to </b>
  
          # Secondly, deal ordinary cases like branch 1
  
          # replace ">" to "<b>"
          replaced_span_list = []
          for sp in span_list:
              replaced_span_list.append(sp.replace(">", "><b>"))
          for sp, rsp in zip(span_list, replaced_span_list):
              thead_part = thead_part.replace(sp, rsp)
  
          # replace "</td>" to "</b></td>"
          thead_part = thead_part.replace("</td>", "</b></td>")
  
          # remove duplicated <b> by re.sub
          mb_pattern = "(<b>)+"
          single_b_string = "<b>"
          thead_part = re.sub(mb_pattern, single_b_string, thead_part)
  
          mgb_pattern = "(</b>)+"
          single_gb_string = "</b>"
          thead_part = re.sub(mgb_pattern, single_gb_string, thead_part)
  
          # ordinary cases like branch 1
          thead_part = thead_part.replace("<td>", "<td><b>").replace(
              "<b><b>", "<b>"
          )
  
      # convert <tb><b></b></tb> back to <tb></tb>, empty cell has no <b></b>.
      # but space cell(<tb> </tb>)  is suitable for <td><b> </b></td>
      thead_part = thead_part.replace("<td><b></b></td>", "<td></td>")
      # deal with duplicated <b></b>
      thead_part = deal_duplicate_bb(thead_part)
      # deal with isolate span tokens, which causes by wrong predict by structure prediction.
      # eg.PMC5994107_011_00.png
      thead_part = deal_isolate_span(thead_part)
      # replace original result with new thead part.
      result_token = result_token.replace(origin_thead_part, thead_part)
      return result_token
  
imports: import os
  import re
  import cv2
  import glob
  import copy
  import math
  import pickle
  import numpy
  from shapely.geometry import Polygon, MultiPoint
label_desc: Use image node_id 28 for calling a global function with example usage: deal_bb(result_token) and returns: result_token, result_token