"""Bundled system ontology templates and restore helpers.""" from __future__ import annotations from copy import deepcopy from sqlalchemy.orm import Session from models import Template RESERVED_UNCLASSIFIED_CLASS = { "id": "reserved-unclassified", "name": "待分类", "color": "#000000", "zIndex": 0, "maskId": 0, "category": "系统保留", } def _with_reserved_unclassified_class(classes: list[dict]) -> list[dict]: filtered = [ item for item in classes if item.get("id") != RESERVED_UNCLASSIFIED_CLASS["id"] and item.get("name") != RESERVED_UNCLASSIFIED_CLASS["name"] and item.get("maskId") != 0 ] return [*filtered, dict(RESERVED_UNCLASSIFIED_CLASS)] def _template_classes( template_name: str, names: list[str], colors: list[tuple[int, int, int]], *, id_prefix: str, ) -> list[dict]: classes = [] for idx, (rgb, name) in enumerate(zip(colors, names)): color_hex = f"#{rgb[0]:02x}{rgb[1]:02x}{rgb[2]:02x}" classes.append({ "id": f"{id_prefix}-{idx}", "name": name, "color": color_hex, "zIndex": (len(names) - idx) * 10, "maskId": idx + 1, "category": template_name, }) return classes def bundled_default_template_definitions() -> list[dict]: """Return fresh definitions for all bundled system templates.""" return [ { "name": "腹腔镜胆囊切除术", "description": "腹腔镜胆囊切除术(LC)手术器械与解剖结构语义分割模板,共35个分类", "color": "#06b6d4", "z_index": 0, "classes": _with_reserved_unclassified_class(_template_classes( "腹腔镜胆囊切除术", [ "针", "线", "肿瘤", "血管阻断夹", "棉球", "双极电凝", "肝脏", "胆囊", "分离钳", "脂肪", "止血海绵", "肝总管", "吸引器", "剪刀", "超声刀", "止血纱布", "胆总管", "生物夹", "无损伤钳", "钳夹", "喷洒", "胆囊管", "动脉", "电凝", "静脉", "标本袋", "引流管", "纱布", "金属钛夹", "韧带", "肝蒂", "推结器", "乳胶管-血管阻断", "吻合器", "术中超声", ], [ (134, 124, 118), (0, 157, 142), (245, 161, 0), (255, 172, 159), (146, 175, 236), (155, 62, 0), (255, 91, 0), (255, 234, 0), (85, 111, 181), (155, 132, 0), (181, 227, 14), (72, 0, 255), (255, 0, 255), (29, 32, 136), (240, 16, 116), (160, 15, 95), (0, 155, 33), (0, 160, 233), (52, 184, 178), (66, 115, 82), (90, 120, 41), (255, 0, 0), (117, 0, 0), (167, 24, 233), (42, 8, 66), (112, 113, 150), (0, 255, 0), (255, 255, 255), (0, 255, 255), (181, 85, 105), (113, 102, 140), (202, 202, 200), (197, 83, 181), (136, 162, 196), (138, 251, 213), ], id_prefix="cls-lap", )), }, { "name": "头颈部CT分割", "description": "头颈部CT分割", "color": "#ef4444", "z_index": 10, "classes": _with_reserved_unclassified_class(_template_classes( "头颈部CT分割", [ "肿瘤/结节 (Tumor/Nodule)", "下颌骨 (Mandible)", "甲状腺 (Thyroid)", "气管 (Trachea)", "颈椎 (Cervical Spine)", "颈动脉 (Carotid Artery)", "颈静脉 (Jugular Vein)", "腮腺 (Parotid Gland)", "下颌下腺 (Submandibular Gland)", "舌骨 (Hyoid Bone)", ], [ (255, 0, 0), (0, 255, 0), (0, 0, 255), (255, 255, 0), (255, 0, 255), (0, 255, 255), (255, 128, 0), (128, 0, 128), (0, 128, 128), (128, 128, 0), ], id_prefix="cls-head-neck-ct", )), }, ] def ensure_default_templates(db: Session, *, restore_existing: bool = False) -> list[Template]: """Create bundled system templates, optionally restoring existing ones exactly.""" templates: list[Template] = [] for definition in bundled_default_template_definitions(): existing = db.query(Template).filter( Template.name == definition["name"], Template.owner_user_id.is_(None), ).first() if existing is None: existing = Template(owner_user_id=None) db.add(existing) elif not restore_existing: templates.append(existing) continue existing.name = definition["name"] existing.description = definition["description"] existing.color = definition["color"] existing.z_index = definition["z_index"] existing.owner_user_id = None existing.mapping_rules = { "classes": deepcopy(definition["classes"]), "rules": [], } templates.append(existing) db.commit() for template in templates: db.refresh(template) return templates def restore_default_templates(db: Session) -> list[Template]: """Restore bundled system templates after demo factory reset.""" return ensure_default_templates(db, restore_existing=True)