#! /usr/bin/python3 # Last edited on 2026-10-12 10:48:47 by stolfi # Functions for correcting errors and expanding abbreviations # in SBJ (hanz) or SPS (EVA) text. import sys, os, re from sys import stdout as out, stderr as err, stdin as inp from error_funcs import arg_error, file_line_error, prog_error from process_funcs import bash, basic_line_loop from chinese_funcs import read_chinese_char_set from compute_stats_funcs import compute_and_print_stats import bencao_starps_convert_funcs as convf from math import sqrt, hypot, exp, log, pi, inf, nan, floor, ceil def normalize_text(text, utype, del_qo, exp_irm, data_error): # Modifies a {text} (typically after {cleanup_text}) from an SBJ or # SPS transcription file according to {utype}, by replacing certain # substrings that are assumed to be scribal errors, abbreviations, or # non-significant variants. # # See {normalize_bencao_text} for the meaning of {utype} is "ch" or "wh". # # See {normalize_starps_text} for the meaning of {utype}s "ec", "wp", # and "wc". The parameters {del_qo} and {exp_irm} are used only for # these {utype}s. # if utype == "ch" or utype == "wh": text = normalize_bencao_text(text, utype, data_error) elif utype == "ec" or utype == "wc" or utype == "wp": text = normalize_starps_text(text, utype, del_qo, exp_irm, data_error) return text # ---------------------------------------------------------------------- def normalize_starps_text(text, utype, del_qo, exp_irm, data_error): # Normalizes the raw {text} from an SPS transcription file according # to {utype} for use in Note 077 analysis. Returns the normalized text # # For all {utype}s, the normalization entails fixing assumed scribal # mistakes and assumed non-significant handwriting variation. # # Specifically, if {del_qo} is true, deletes all "qo". # If {exp_irm} is true, expands all "ir", "is", and "m". # if utype == "ec" or utype == "wc" or utype == "wp": # Reduce presumed handwriting variants: text = re.sub(r"g", "m", text) text = re.sub(r"u", "n", text) # Correct presumed scribal and transcription errors: text = re.sub(r"ch[?]dy", "chedy", text) text = re.sub(r"sh[?]dy", "shedy", text) text = re.sub(r"q[?e]", "qo", text) text = re.sub(r"hh", "he", text) text = re.sub(r"ih", "ch", text) text = re.sub(r"i([ktpf])h", r"c\1h", text) if exp_irm: # Expand presumed scribal abbreviations text = re.sub(r"i([-,.]*)r", r"i\1in", text) text = re.sub(r"i([-,.]*)s", r"i\1in", text) text = re.sub(r"m", "iin", text) if del_qo: # Remove the "qo" glyphs. text = re.sub(r"qo", "", text) # Remove double punct that may have been created by normalization: if utype == "wc" or utype == "wp": text = re.sub(r"[,.]*[.][,.]*", ".", text) else: arg_error(f"invalid {utype = !r}") return text # ---------------------------------------------------------------------- def normalize_bencao_text(text, utype, data_error): # Normalizes the raw {text} from an SBJ transcription file according to {utype} # for use in Note 077 analysis. Returns the normalized {text}. # # If {utype} is "ch", the input raw {text} must have no punctuation, # just the hanzi letters. # # If the {utype} is "wh", it may have # punctuation, including ideographic brackets '' around keywords 味, # 主, 久服, etc. # # For both {utype}s, normalizing entails replacing some keys that # the are incorrect in the CTP version. convf.check_bencao_conversion(text, utype, data_error) if utype == "ch" or utype == "wh": # Fix CTP errors: text = re.sub(r"主治", "主", text) # Seems that SBJ never used 主治. else: assert False, f"invalid text type {utype = !r}" return text # ---------------------------------------------------------------------- def test_stuff(): def data_error(msg): err.write(f"** {msg}\n"); assert False # .................................................................... return # ---------------------------------------------------------------------- if len(sys.argv) > 1 and sys.argv[1] == "BSNF.TEST": test_stuff()