|
|
""" |
|
|
Medical Term Manager - управление медицинской терминологией |
|
|
""" |
|
|
|
|
|
import logging |
|
|
from pathlib import Path |
|
|
from typing import List, Set, Dict, Optional |
|
|
import re |
|
|
|
|
|
logger = logging.getLogger(__name__) |
|
|
|
|
|
|
|
|
class MedicalTermManager: |
|
|
""" |
|
|
Менеджер медицинских терминов для коррекции транскрипций. |
|
|
|
|
|
Функции: |
|
|
- Загрузка терминов из файлов |
|
|
- Поиск и валидация терминов |
|
|
- Категоризация (анатомия, процедуры, диагнозы) |
|
|
- Нормализация терминов |
|
|
""" |
|
|
|
|
|
def __init__(self, terms_file: Optional[Path] = None): |
|
|
""" |
|
|
Инициализация менеджера. |
|
|
|
|
|
Args: |
|
|
terms_file: Путь к файлу с медицинскими терминами |
|
|
""" |
|
|
self.terms: Set[str] = set() |
|
|
self.categories: Dict[str, List[str]] = { |
|
|
'imaging': [], |
|
|
'sequences': [], |
|
|
'anatomy': [], |
|
|
'pathology': [], |
|
|
'modifiers': [] |
|
|
} |
|
|
|
|
|
if terms_file: |
|
|
self.load_from_file(terms_file) |
|
|
|
|
|
def load_from_file(self, filepath: Path) -> int: |
|
|
""" |
|
|
Загрузить термины из файла. |
|
|
|
|
|
Args: |
|
|
filepath: Путь к файлу с терминами (разделитель: запятая) |
|
|
|
|
|
Returns: |
|
|
Количество загруженных терминов |
|
|
""" |
|
|
try: |
|
|
with open(filepath, 'r', encoding='utf-8') as f: |
|
|
content = f.read().strip() |
|
|
|
|
|
|
|
|
raw_terms = [term.strip() for term in content.split(',')] |
|
|
|
|
|
for term in raw_terms: |
|
|
if term: |
|
|
self.add_term(term) |
|
|
|
|
|
logger.info(f"Loaded {len(self.terms)} medical terms from {filepath}") |
|
|
return len(self.terms) |
|
|
|
|
|
except FileNotFoundError: |
|
|
logger.error(f"Terms file not found: {filepath}") |
|
|
return 0 |
|
|
except Exception as e: |
|
|
logger.error(f"Error loading terms: {e}") |
|
|
return 0 |
|
|
|
|
|
def add_term(self, term: str) -> None: |
|
|
""" |
|
|
Добавить термин в базу знаний. |
|
|
|
|
|
Args: |
|
|
term: Медицинский термин |
|
|
""" |
|
|
normalized = self.normalize_term(term) |
|
|
self.terms.add(normalized) |
|
|
|
|
|
|
|
|
self._categorize_term(normalized) |
|
|
|
|
|
def normalize_term(self, term: str) -> str: |
|
|
""" |
|
|
Нормализовать термин (удалить лишние пробелы, привести к единому формату). |
|
|
|
|
|
Args: |
|
|
term: Исходный термин |
|
|
|
|
|
Returns: |
|
|
Нормализованный термин |
|
|
""" |
|
|
|
|
|
normalized = ' '.join(term.split()) |
|
|
return normalized |
|
|
|
|
|
def _categorize_term(self, term: str) -> None: |
|
|
""" |
|
|
Автоматическая категоризация термина. |
|
|
|
|
|
Args: |
|
|
term: Термин для категоризации |
|
|
""" |
|
|
term_lower = term.lower() |
|
|
|
|
|
|
|
|
if any(x in term_lower for x in ['мрт', 'кт', 'мскт', 'рентген', 'узи']): |
|
|
self.categories['imaging'].append(term) |
|
|
|
|
|
|
|
|
elif any(x in term_lower for x in ['т1', 'т2', 'flair', 'stir', 'dwi', 'adc']): |
|
|
self.categories['sequences'].append(term) |
|
|
|
|
|
|
|
|
elif re.search(r'[cltsl]\d+', term_lower) or any(x in term_lower for x in |
|
|
['позвонок', 'диск', 'желудочк', 'цистерн', 'паренхима']): |
|
|
self.categories['anatomy'].append(term) |
|
|
|
|
|
|
|
|
elif any(x in term_lower for x in ['грыжа', 'протрузия', 'стеноз', 'экструзия', 'остеофит']): |
|
|
self.categories['pathology'].append(term) |
|
|
|
|
|
|
|
|
elif any(x in term_lower for x in ['гипер', 'гипо', 'изо', 'дорзальн', 'вентральн']): |
|
|
self.categories['modifiers'].append(term) |
|
|
|
|
|
def search_term(self, query: str) -> List[str]: |
|
|
""" |
|
|
Поиск термина в базе. |
|
|
|
|
|
Args: |
|
|
query: Поисковый запрос |
|
|
|
|
|
Returns: |
|
|
Список найденных терминов |
|
|
""" |
|
|
query_lower = query.lower() |
|
|
matches = [ |
|
|
term for term in self.terms |
|
|
if query_lower in term.lower() |
|
|
] |
|
|
return sorted(matches) |
|
|
|
|
|
def get_category_terms(self, category: str) -> List[str]: |
|
|
""" |
|
|
Получить термины по категории. |
|
|
|
|
|
Args: |
|
|
category: Название категории |
|
|
|
|
|
Returns: |
|
|
Список терминов категории |
|
|
""" |
|
|
return self.categories.get(category, []) |
|
|
|
|
|
def get_all_terms(self) -> List[str]: |
|
|
""" |
|
|
Получить все термины. |
|
|
|
|
|
Returns: |
|
|
Список всех терминов |
|
|
""" |
|
|
return sorted(list(self.terms)) |
|
|
|
|
|
def get_terms_as_text(self, separator: str = ', ') -> str: |
|
|
""" |
|
|
Получить все термины в виде текста. |
|
|
|
|
|
Args: |
|
|
separator: Разделитель терминов |
|
|
|
|
|
Returns: |
|
|
Строка с терминами |
|
|
""" |
|
|
return separator.join(sorted(self.terms)) |
|
|
|
|
|
def validate_transcription(self, text: str) -> Dict[str, any]: |
|
|
""" |
|
|
Валидировать транскрипцию на наличие медицинских терминов. |
|
|
|
|
|
Args: |
|
|
text: Текст транскрипции |
|
|
|
|
|
Returns: |
|
|
Словарь с результатами валидации |
|
|
""" |
|
|
found_terms = [] |
|
|
text_lower = text.lower() |
|
|
|
|
|
for term in self.terms: |
|
|
if term.lower() in text_lower: |
|
|
found_terms.append(term) |
|
|
|
|
|
return { |
|
|
'found_terms': found_terms, |
|
|
'count': len(found_terms), |
|
|
'coverage': len(found_terms) / len(self.terms) if self.terms else 0 |
|
|
} |
|
|
|
|
|
def get_statistics(self) -> Dict[str, any]: |
|
|
""" |
|
|
Получить статистику по базе знаний. |
|
|
|
|
|
Returns: |
|
|
Словарь со статистикой |
|
|
""" |
|
|
return { |
|
|
'total_terms': len(self.terms), |
|
|
'categories': { |
|
|
cat: len(terms) |
|
|
for cat, terms in self.categories.items() |
|
|
} |
|
|
} |
|
|
|