@skaterqiang/protege-js 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/CHANGELOG.md +65 -0
  2. package/LICENSE +48 -0
  3. package/README.md +287 -0
  4. package/docs/API.md +654 -0
  5. package/docs/design/OWL2-/347/274/272/345/217/243/345/210/206/346/236/220.md +140 -0
  6. package/docs/owl2-rl/OWL2-RL-/350/247/204/345/210/231/347/273/206/345/210/231.md +168 -0
  7. package/docs/owl2-rl/owl2-profiles-spec-zh.html +1914 -0
  8. package/docs/owl2-rl/owl2-profiles-spec.html +1916 -0
  9. package/docs/owl2-rl/rl_rules.json +392 -0
  10. package/main.js +46 -0
  11. package/package.json +76 -0
  12. package/sample/README.md +74 -0
  13. package/sample/case1-ecommerce-risk.js +170 -0
  14. package/sample/case10-ecommerce-customer-service.js +454 -0
  15. package/sample/case2-family-swrl.js +147 -0
  16. package/sample/case3-pharma-safety.js +132 -0
  17. package/sample/case4-knowledge-publishing.js +111 -0
  18. package/sample/case5-obda-profiles.js +153 -0
  19. package/sample/case6-medical-ontology.js +152 -0
  20. package/sample/case7-manufacturing-ppr.js +155 -0
  21. package/sample/case8-real-medical-bfo-ogms.js +353 -0
  22. package/sample/case9-real-manufacturing-iao.js +360 -0
  23. package/sample/ontologies/bfo.owl +1715 -0
  24. package/sample/ontologies/iao.owl +8532 -0
  25. package/sample/ontologies/ogms.owl +4320 -0
  26. package/sample/ontologies/ro-core.owl +1010 -0
  27. package/scripts/verify-api.js +53 -0
  28. package/src/index.js +176 -0
  29. package/src/inference/OWL2ProfileReasoners.js +67 -0
  30. package/src/inference/OWL2RLReasoner.js +65 -0
  31. package/src/inference/ReasonerQueries.js +111 -0
  32. package/src/inference/SWRLReasoner.js +409 -0
  33. package/src/inference/TripleStore.js +82 -0
  34. package/src/inference/rdf.js +83 -0
  35. package/src/inference/rules/owl2el.js +33 -0
  36. package/src/inference/rules/owl2ql.js +29 -0
  37. package/src/inference/rules/owl2rl.js +823 -0
  38. package/src/io/FunctionalSyntaxParser.js +399 -0
  39. package/src/io/FunctionalSyntaxWriter.js +180 -0
  40. package/src/io/ManchesterSyntaxParser.js +398 -0
  41. package/src/io/OWLXMLParser.js +356 -0
  42. package/src/io/OntologyLoader.js +125 -0
  43. package/src/io/RDFGraphToOntology.js +702 -0
  44. package/src/io/RDFXMLParser.js +319 -0
  45. package/src/io/RDFXMLWriter.js +196 -0
  46. package/src/io/SWRLParser.js +150 -0
  47. package/src/io/TurtleParser.js +363 -0
  48. package/src/io/TurtleWriter.js +393 -0
  49. package/src/model/IRI.js +62 -0
  50. package/src/model/OWLAxiom.js +507 -0
  51. package/src/model/OWLClassExpression.js +242 -0
  52. package/src/model/OWLEntity.js +142 -0
  53. package/src/model/OWLLiteral.js +30 -0
  54. package/src/model/OWLModelManager.js +106 -0
  55. package/src/model/OWLOntology.js +119 -0
  56. package/src/model/SWRL.js +152 -0
  57. package/src/model/event/OWLModelManagerEvent.js +33 -0
  58. package/src/model/hierarchy/HierarchyProvider.js +214 -0
  59. package/src/profiles/OWL2Profiles.js +185 -0
  60. package/src/server/public/app.js +97 -0
  61. package/src/server/public/index.html +49 -0
  62. package/src/server/webServer.js +138 -0
  63. package/src/validation/GlobalRestrictionsValidator.js +172 -0
  64. package/test/core.test.js +111 -0
  65. package/test/exports-map.test.js +165 -0
  66. package/test/owl2/axioms.test.js +160 -0
  67. package/test/owl2/classExpressions.test.js +99 -0
  68. package/test/owl2/functional-syntax-writer.test.js +65 -0
  69. package/test/owl2/functional.test.js +113 -0
  70. package/test/owl2/global-restrictions.test.js +76 -0
  71. package/test/owl2/longtail.test.js +74 -0
  72. package/test/owl2/manchester-syntax.test.js +100 -0
  73. package/test/owl2/ontology-loader-imports.test.js +62 -0
  74. package/test/owl2/owlxml-parser.test.js +112 -0
  75. package/test/owl2/profile-reasoners.test.js +108 -0
  76. package/test/owl2/profiles.test.js +66 -0
  77. package/test/owl2/rdf-graph-to-ontology.test.js +177 -0
  78. package/test/owl2/rdfxml-punning.test.js +25 -0
  79. package/test/owl2/rdfxml-writer.test.js +55 -0
  80. package/test/owl2/rdfxml.test.js +91 -0
  81. package/test/owl2/reasoner-queries.test.js +58 -0
  82. package/test/owl2/sample-e2e.test.js +195 -0
  83. package/test/owl2/swrl-parser.test.js +60 -0
  84. package/test/owl2/swrl.test.js +131 -0
  85. package/test/owl2/turtle-writer.test.js +84 -0
  86. package/test/owl2/turtle.test.js +124 -0
  87. package/test/owl2rl/cax.test.js +57 -0
  88. package/test/owl2rl/cls.test.js +210 -0
  89. package/test/owl2rl/dt.test.js +72 -0
  90. package/test/owl2rl/eq.test.js +95 -0
  91. package/test/owl2rl/prp.test.js +198 -0
  92. package/test/owl2rl/scm.test.js +203 -0
@@ -0,0 +1,353 @@
1
+ 'use strict';
2
+
3
+ // ===========================================================================
4
+ // 业务案例 8:感冒临床诊疗路径 —— 真实 OGMS/BFO 本体 + 症状-诊断-治疗闭环
5
+ // ---------------------------------------------------------------------------
6
+ // 【业务背景】
7
+ // 社区医院全科门诊接诊「上呼吸道感染(感冒)」患者,需要按标准临床路径
8
+ // 完成:症状采集 → 体格检查 → 诊断 → 治疗方案 → 用药处方 → 随访评估。
9
+ // 本案例把真实临床数据挂到 OGMS(通用医学科学本体)标准类上:
10
+ // - symptom(症状) → OGMS_0000020
11
+ // - physical sign(体征) → OGMS_0000129
12
+ // - diagnosis(诊断) → OGMS_0000073
13
+ // - infectious disorder(感染性疾病)→ IDO_0000504
14
+ // - treatment(治疗) → OGMS_0000090
15
+ // - therapeutic procedure(治疗操作)→ OGMS_0000112
16
+ // - health care encounter(就诊)→ OGMS_0000097
17
+ // - clinical finding(临床发现)→ OGMS_0000014
18
+ // - acute disease course(急性病程)→ OGMS_0000094
19
+ // 推理机沿真实 OGMS/BFO 层级把「感冒治疗记录」归因为
20
+ // treatment → planned process → BFO process(therapeutic procedure 为兄弟类)。
21
+ //
22
+ // 【业务规则】
23
+ // 1. 患者主诉:发热(38.5°C)、咳嗽、咽痛、流涕 —— 归为 symptom
24
+ // 2. 体格检查:咽部充血、扁桃体肿大 —— 归为 physical sign
25
+ // 3. 诊断:急性上呼吸道感染(感冒)—— 归为 diagnosis + infectious disorder
26
+ // 4. 治疗方案:对症治疗(退热+止咳+抗病毒)—— 归为 treatment
27
+ // 5. 用药处方:对乙酰氨基酚(退热) + 右美沙芬(止咳) + 奥司他韦(抗病毒)
28
+ // 6. 随访:3天后复诊评估症状缓解情况 —— 归为 health care encounter
29
+ //
30
+ // 【用到的 OWL 2 能力】
31
+ // 真实 OGMS/BFO 类层级复用 / OWL 2 RL cax-sco 类层级归因 /
32
+ // owl:someValuesFrom(治疗方案包含用药)/ writeRDFXML 导出病历
33
+ //
34
+ // 【预期结果】
35
+ // - 感冒治疗记录沿真实 OGMS 层级归因到 treatment → planned process
36
+ // - 患者症状/体征/诊断/治疗/处方完整关联
37
+ // - 病历可导出为合法 RDF/XML 供 EMR 系统消费
38
+ // ===========================================================================
39
+
40
+ // 引入 Node 内置模块与解析器/序列化器/推理机
41
+ const fs = require('fs'); // 文件系统:读取本地 OWL 文件
42
+ const path = require('path'); // 路径处理:拼接 ontologies 目录
43
+ const { parseRDFXML } = require('../src/io/RDFXMLParser'); // RDF/XML 解析器:加载真实 OWL 文件
44
+ const { writeRDFXML } = require('../src/io/RDFXMLWriter'); // RDF/XML 序列化器:导出病历
45
+ const { TurtleParser } = require('../src/io/TurtleParser'); // Turtle 解析器:解析临床数据
46
+ const { triplesToOntology } = require('../src/io/RDFGraphToOntology'); // TripleStore → OWLOntology
47
+ const { TripleStore } = require('../src/inference/TripleStore'); // 三元组存储:合并真实+临床
48
+ const { OWL2RLReasoner } = require('../src/inference/OWL2RLReasoner'); // OWL 2 RL 推理机:物化
49
+ const { NS } = require('../src/inference/rdf'); // 命名空间常量
50
+
51
+ // 简化命名空间引用
52
+ const RDF = NS.RDF, RDFS = NS.RDFS;
53
+ // 真实 OWL 文件所在目录:sample/ontologies/
54
+ const ONT_DIR = path.join(__dirname, 'ontologies');
55
+ // rdfs:label 完整 IRI(用于过滤 label 注解)
56
+ const RDFS_LABEL = RDFS + 'label';
57
+ // 真实标准类 IRI(来自 OBO Foundry OGMS/BFO/IDO 发布文件)
58
+ const OGMS_SYMPTOM = 'http://purl.obolibrary.org/obo/OGMS_0000020'; // symptom 症状
59
+ const OGMS_PHYSICAL_SIGN = 'http://purl.obolibrary.org/obo/OGMS_0000129'; // physical sign 体征
60
+ const OGMS_DIAGNOSIS = 'http://purl.obolibrary.org/obo/OGMS_0000073'; // diagnosis 诊断
61
+ const OGMS_TREATMENT = 'http://purl.obolibrary.org/obo/OGMS_0000090'; // treatment 治疗
62
+ const OGMS_THERAPEUTIC = 'http://purl.obolibrary.org/obo/OGMS_0000112'; // therapeutic procedure 治疗操作
63
+ const OGMS_ENCOUNTER = 'http://purl.obolibrary.org/obo/OGMS_0000097'; // health care encounter 就诊
64
+ const OGMS_CLINICAL_FINDING = 'http://purl.obolibrary.org/obo/OGMS_0000014'; // clinical finding 临床发现
65
+ const OGMS_ACUTE_COURSE = 'http://purl.obolibrary.org/obo/OGMS_0000094'; // acute disease course 急性病程
66
+ const IDO_INFECTIOUS = 'http://purl.obolibrary.org/obo/IDO_0000504'; // infectious disorder 感染性疾病
67
+ const BFO_PROCESS = 'http://purl.obolibrary.org/obo/BFO_0000015'; // process 过程
68
+
69
+ // 从实体/类表达式中取 IRI 字符串(模型中 iri 为 {_iri} 嵌套对象)
70
+ function iriOf(x) {
71
+ if (!x) return null; // 空值直接返回
72
+ if (typeof x === 'string') return x; // 已经是字符串 IRI
73
+ const i = x.iri; // 取嵌套的 iri 字段
74
+ if (typeof i === 'string') return i; // iri 本身是字符串
75
+ if (i && typeof i._iri === 'string') return i._iri; // iri 是 {_iri} 对象
76
+ if (typeof x._iri === 'string') return x._iri; // 兜底:x 本身是 {_iri} 对象
77
+ return null; // 无法提取
78
+ }
79
+
80
+ // 真实本体的类层级 + rdfs:label → IRI 映射
81
+ function extractOntologyFacts(onts) {
82
+ const store = new TripleStore(); // 存放类层级边
83
+ const label2iri = {}; // label 文本 → 类 IRI 映射
84
+ let edges = 0; // 统计层级边数
85
+ for (const ont of onts) { // 遍历每个本体
86
+ for (const ax of ont.getAxioms()) { // 遍历每条公理
87
+ const t = ax.constructor && ax.constructor.name; // 公理类型名
88
+ if (t === 'OWLSubClassOfAxiom') { // SubClassOf 公理
89
+ const sub = iriOf(ax.subClass); // 子类 IRI
90
+ const sup = iriOf(ax.superClass); // 父类 IRI
91
+ if (sub && sup && sub.startsWith('http') && sup.startsWith('http')) {
92
+ store.add(sub, RDFS + 'subClassOf', sup); // 写入 TripleStore
93
+ edges++; // 边数 +1
94
+ }
95
+ } else if (t === 'OWLAnnotationAssertionAxiom') { // 注解断言公理
96
+ const p = ax.property && iriOf(ax.property); // 注解属性 IRI
97
+ const s = typeof ax.subject === 'string' ? ax.subject : iriOf(ax.subject); // 主体 IRI
98
+ const v = ax.value && ax.value.lexicalValue; // label 文本
99
+ // 只保留 rdfs:label,且首次出现(避免同名 label 覆盖)
100
+ if (p === RDFS_LABEL && s && v && !(v in label2iri)) label2iri[v] = s;
101
+ }
102
+ }
103
+ }
104
+ return { store, label2iri, edges }; // 返回层级存储、label 映射、边数
105
+ }
106
+
107
+ // 感冒临床诊疗数据(挂到真实 OGMS/BFO 标准父类)
108
+ function buildColdTreatmentTurtle() {
109
+ return [
110
+ '@prefix clin: <http://clinic.example.com/cold#> .', // 定义 clin 前缀(临床门诊)
111
+ '@prefix owl: <http://www.w3.org/2002/07/owl#> .', // 定义 owl 前缀
112
+ '@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .', // 定义 rdfs 前缀
113
+ '@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .', // 定义 xsd 前缀(数据类型)
114
+ '@prefix obo: <http://purl.obolibrary.org/obo/> .', // 定义 obo 前缀(OBO 标准 IRI)
115
+ '',
116
+
117
+ '# ========== 患者与就诊 ==========',
118
+ 'clin:Patient a owl:Class .', // 患者类
119
+ 'clin:hasSymptom a owl:ObjectProperty ; rdfs:domain clin:Patient ; rdfs:range obo:OGMS_0000020 .', // 患者→症状
120
+ 'clin:hasSign a owl:ObjectProperty ; rdfs:domain clin:Patient ; rdfs:range obo:OGMS_0000129 .', // 患者→体征
121
+ 'clin:hasDiagnosis a owl:ObjectProperty ; rdfs:domain clin:Patient ; rdfs:range obo:OGMS_0000073 .', // 患者→诊断
122
+ 'clin:receivesTreatment a owl:ObjectProperty ; rdfs:domain clin:Patient ; rdfs:range obo:OGMS_0000090 .', // 患者→治疗
123
+ '',
124
+
125
+ '# ========== 症状定义(挂到真实 OGMS symptom) ==========',
126
+ 'clin:Fever a owl:Class ; rdfs:subClassOf obo:OGMS_0000020 .', // 发热 ⊑ symptom
127
+ 'clin:Cough a owl:Class ; rdfs:subClassOf obo:OGMS_0000020 .', // 咳嗽 ⊑ symptom
128
+ 'clin:SoreThroat a owl:Class ; rdfs:subClassOf obo:OGMS_0000020 .', // 咽痛 ⊑ symptom
129
+ 'clin:RunnyNose a owl:Class ; rdfs:subClassOf obo:OGMS_0000020 .', // 流涕 ⊑ symptom
130
+ '',
131
+
132
+ '# ========== 体征定义(挂到真实 OGMS physical sign) ==========',
133
+ 'clin:PharyngealCongestion a owl:Class ; rdfs:subClassOf obo:OGMS_0000129 .', // 咽部充血 ⊑ physical sign
134
+ 'clin:TonsilSwelling a owl:Class ; rdfs:subClassOf obo:OGMS_0000129 .', // 扁桃体肿大 ⊑ physical sign
135
+ '',
136
+
137
+ '# ========== 诊断定义(挂到真实 OGMS diagnosis + IDO infectious disorder) ==========',
138
+ 'clin:UpperRespiratoryInfection a owl:Class ;', // 上呼吸道感染
139
+ ' rdfs:subClassOf obo:OGMS_0000073 ;', // ⊑ diagnosis
140
+ ' rdfs:subClassOf obo:IDO_0000504 ;', // ⊑ infectious disorder
141
+ ' rdfs:subClassOf obo:OGMS_0000094 .', // ⊑ acute disease course
142
+ '',
143
+
144
+ '# ========== 治疗方案定义(挂到真实 OGMS treatment) ==========',
145
+ 'clin:SymptomaticTreatment a owl:Class ; rdfs:subClassOf obo:OGMS_0000090 .', // 对症治疗 ⊑ treatment
146
+ 'clin:AntiviralTreatment a owl:Class ; rdfs:subClassOf obo:OGMS_0000090 .', // 抗病毒治疗 ⊑ treatment
147
+ '',
148
+
149
+ '# ========== 药物定义 ==========',
150
+ 'clin:Drug a owl:Class .', // 药物类
151
+ 'clin:hasMedication a owl:ObjectProperty ; rdfs:domain obo:OGMS_0000090 ; rdfs:range clin:Drug .', // 治疗→药物
152
+ 'clin:dosage a owl:DatatypeProperty ; rdfs:domain clin:Drug ; rdfs:range xsd:string .', // 剂量
153
+ 'clin:frequency a owl:DatatypeProperty ; rdfs:domain clin:Drug ; rdfs:range xsd:string .', // 频次
154
+ '',
155
+
156
+ '# ========== 具体实例:患者张三的感冒诊疗 ==========',
157
+ '# 患者实例',
158
+ 'clin:Patient-ZhangSan a clin:Patient ; rdfs:label "患者-张三" .',
159
+ '',
160
+ '# 症状实例',
161
+ 'clin:Fever-ZS a clin:Fever ; rdfs:label "发热38.5°C" .', // 发热实例
162
+ 'clin:Cough-ZS a clin:Cough ; rdfs:label "干咳" .', // 咳嗽实例
163
+ 'clin:SoreThroat-ZS a clin:SoreThroat ; rdfs:label "咽痛" .', // 咽痛实例
164
+ 'clin:RunnyNose-ZS a clin:RunnyNose ; rdfs:label "流涕" .', // 流涕实例
165
+ '',
166
+ '# 体征实例',
167
+ 'clin:PharyngealCongestion-ZS a clin:PharyngealCongestion ; rdfs:label "咽部充血" .', // 咽部充血实例
168
+ 'clin:TonsilSwelling-ZS a clin:TonsilSwelling ; rdfs:label "扁桃体I度肿大" .', // 扁桃体肿大实例
169
+ '',
170
+ '# 诊断实例',
171
+ 'clin:Diagnosis-ZS a clin:UpperRespiratoryInfection ; rdfs:label "急性上呼吸道感染(普通感冒)" .', // 诊断实例
172
+ '',
173
+ '# 治疗方案实例',
174
+ 'clin:Treatment-ZS a clin:SymptomaticTreatment ; rdfs:label "对症治疗方案" .', // 对症治疗实例
175
+ 'clin:Antiviral-ZS a clin:AntiviralTreatment ; rdfs:label "抗病毒治疗方案" .', // 抗病毒治疗实例
176
+ '',
177
+ '# 药物实例',
178
+ 'clin:Paracetamol a clin:Drug ; rdfs:label "对乙酰氨基酚" ; clin:dosage "500mg" ; clin:frequency "每6小时一次" .', // 退热药
179
+ 'clin:Dextromethorphan a clin:Drug ; rdfs:label "右美沙芬" ; clin:dosage "15mg" ; clin:frequency "每日三次" .', // 止咳药
180
+ 'clin:Oseltamivir a clin:Drug ; rdfs:label "奥司他韦" ; clin:dosage "75mg" ; clin:frequency "每日两次" .', // 抗病毒药
181
+ '',
182
+ '# 患者-症状关联',
183
+ 'clin:Patient-ZhangSan clin:hasSymptom clin:Fever-ZS .', // 张三有发热
184
+ 'clin:Patient-ZhangSan clin:hasSymptom clin:Cough-ZS .', // 张三有咳嗽
185
+ 'clin:Patient-ZhangSan clin:hasSymptom clin:SoreThroat-ZS .', // 张三有咽痛
186
+ 'clin:Patient-ZhangSan clin:hasSymptom clin:RunnyNose-ZS .', // 张三有流涕
187
+ '',
188
+ '# 患者-体征关联',
189
+ 'clin:Patient-ZhangSan clin:hasSign clin:PharyngealCongestion-ZS .', // 张三咽部充血
190
+ 'clin:Patient-ZhangSan clin:hasSign clin:TonsilSwelling-ZS .', // 张三扁桃体肿大
191
+ '',
192
+ '# 患者-诊断关联',
193
+ 'clin:Patient-ZhangSan clin:hasDiagnosis clin:Diagnosis-ZS .', // 张三诊断为感冒
194
+ '',
195
+ '# 患者-治疗关联',
196
+ 'clin:Patient-ZhangSan clin:receivesTreatment clin:Treatment-ZS .', // 张三接受对症治疗
197
+ 'clin:Patient-ZhangSan clin:receivesTreatment clin:Antiviral-ZS .', // 张三接受抗病毒治疗
198
+ '',
199
+ '# 治疗-药物关联',
200
+ 'clin:Treatment-ZS clin:hasMedication clin:Paracetamol .', // 对症治疗含退热药
201
+ 'clin:Treatment-ZS clin:hasMedication clin:Dextromethorphan .', // 对症治疗含止咳药
202
+ 'clin:Antiviral-ZS clin:hasMedication clin:Oseltamivir .', // 抗病毒治疗含奥司他韦
203
+ '',
204
+
205
+ '# ========== 就诊记录(挂到真实 OGMS health care encounter) ==========',
206
+ 'clin:OutpatientVisit a owl:Class ; rdfs:subClassOf obo:OGMS_0000097 .', // 门诊就诊 ⊑ health care encounter
207
+ 'clin:Visit-20240901 a clin:OutpatientVisit ; rdfs:label "2024-09-01门诊就诊" .', // 就诊实例
208
+ 'clin:recordsPatient a owl:ObjectProperty ; rdfs:domain clin:OutpatientVisit ; rdfs:range clin:Patient .', // 就诊→患者
209
+ 'clin:recordsDiagnosis a owl:ObjectProperty ; rdfs:domain clin:OutpatientVisit ; rdfs:range obo:OGMS_0000073 .', // 就诊→诊断
210
+ 'clin:recordsTreatment a owl:ObjectProperty ; rdfs:domain clin:OutpatientVisit ; rdfs:range obo:OGMS_0000090 .', // 就诊→治疗
211
+ 'clin:Visit-20240901 clin:recordsPatient clin:Patient-ZhangSan .', // 就诊关联患者
212
+ 'clin:Visit-20240901 clin:recordsDiagnosis clin:Diagnosis-ZS .', // 就诊关联诊断
213
+ 'clin:Visit-20240901 clin:recordsTreatment clin:Treatment-ZS .', // 就诊关联对症治疗
214
+ 'clin:Visit-20240901 clin:recordsTreatment clin:Antiviral-ZS .', // 就诊关联抗病毒治疗
215
+ ''
216
+ ].join('\n');
217
+ }
218
+
219
+ // 执行真实本体加载、临床数据合并、RL 推理与导出
220
+ function run() {
221
+ // 1) 加载真实公开本体
222
+ const bfo = parseRDFXML(fs.readFileSync(path.join(ONT_DIR, 'bfo.owl'), 'utf8')); // BFO 顶层本体
223
+ const ogms = parseRDFXML(fs.readFileSync(path.join(ONT_DIR, 'ogms.owl'), 'utf8')); // OGMS 医学本体
224
+ const counts = { bfo: bfo.getAxiomCount(), ogms: ogms.getAxiomCount() }; // 统计公理数
225
+
226
+ // 2) 提取真实类层级 + label 映射;校验 OGMS 标准类
227
+ const { store, label2iri, edges } = extractOntologyFacts([bfo, ogms]);
228
+ const ogmsStdClasses = {
229
+ 'symptom': label2iri['symptom'] || null, // 症状
230
+ 'physical sign': label2iri['physical sign'] || null, // 体征
231
+ 'diagnosis': label2iri['diagnosis'] || null, // 诊断
232
+ 'treatment': label2iri['treatment'] || null, // 治疗
233
+ 'therapeutic procedure': label2iri['therapeutic procedure'] || null, // 治疗操作
234
+ 'health care encounter': label2iri['health care encounter'] || null, // 就诊
235
+ 'infectious disorder': label2iri['infectious disorder'] || null, // 感染性疾病
236
+ 'acute disease course': label2iri['acute disease course'] || null // 急性病程
237
+ };
238
+ const hasStdClasses =
239
+ ogmsStdClasses['symptom'] === OGMS_SYMPTOM &&
240
+ ogmsStdClasses['physical sign'] === OGMS_PHYSICAL_SIGN &&
241
+ ogmsStdClasses['diagnosis'] === OGMS_DIAGNOSIS &&
242
+ ogmsStdClasses['treatment'] === OGMS_TREATMENT &&
243
+ ogmsStdClasses['therapeutic procedure'] === OGMS_THERAPEUTIC &&
244
+ ogmsStdClasses['health care encounter'] === OGMS_ENCOUNTER;
245
+
246
+ // 3) 真实层级 + 感冒临床数据合并 → RL 物化
247
+ const clinStore = new TurtleParser().parse(buildColdTreatmentTurtle()); // 解析临床数据 Turtle
248
+ for (const [s, p, o] of clinStore.match(null, null, null)) { // 遍历临床数据三元组
249
+ store.add(s, p, o); // 合并到真实本体 store
250
+ }
251
+ const reasoner = new OWL2RLReasoner(store);
252
+ reasoner.materialize(); // 执行 RL 物化
253
+
254
+ // 4) 治疗记录 OGMS 层级归因验证
255
+ const TREATMENT_ZS = 'http://clinic.example.com/cold#Treatment-ZS'; // 对症治疗实例 IRI
256
+ const c = 'http://clinic.example.com/cold#'; // 临床前缀
257
+ const isSymptomaticTreatment = store.has(TREATMENT_ZS, RDF + 'type', c + 'SymptomaticTreatment'); // 归为对症治疗
258
+ const isTreatment = store.has(TREATMENT_ZS, RDF + 'type', OGMS_TREATMENT); // 归为 treatment
259
+ const isTherapeutic = store.has(TREATMENT_ZS, RDF + 'type', OGMS_THERAPEUTIC); // 归为 therapeutic procedure(兄弟类,非父子)
260
+ const isProcess = store.has(TREATMENT_ZS, RDF + 'type', BFO_PROCESS); // 归为 BFO process
261
+ const treatmentAttributed = isSymptomaticTreatment && isTreatment && isProcess; // 完整归因链(treatment⊑process)
262
+
263
+ // 5) 诊断 IDO 层级归因验证
264
+ const DIAG_ZS = 'http://clinic.example.com/cold#Diagnosis-ZS'; // 诊断实例 IRI
265
+ const isURI = store.has(DIAG_ZS, RDF + 'type', c + 'UpperRespiratoryInfection'); // 归为上呼吸道感染
266
+ const isDiagnosis = store.has(DIAG_ZS, RDF + 'type', OGMS_DIAGNOSIS); // 归为 diagnosis
267
+ const isInfectious = store.has(DIAG_ZS, RDF + 'type', IDO_INFECTIOUS); // 归为 infectious disorder
268
+ const isAcute = store.has(DIAG_ZS, RDF + 'type', OGMS_ACUTE_COURSE); // 归为 acute disease course
269
+ const diagnosisAttributed = isURI && isDiagnosis && isInfectious && isAcute; // 完整归因链
270
+
271
+ // 6) 症状/体征/就诊归因验证
272
+ const FEVER_ZS = 'http://clinic.example.com/cold#Fever-ZS'; // 发热实例 IRI
273
+ const isFever = store.has(FEVER_ZS, RDF + 'type', c + 'Fever'); // 归为发热
274
+ const isSymptom = store.has(FEVER_ZS, RDF + 'type', OGMS_SYMPTOM); // 归为 symptom
275
+ const isClinicalFinding = store.has(FEVER_ZS, RDF + 'type', OGMS_CLINICAL_FINDING); // 归为 clinical finding
276
+
277
+ const VISIT = 'http://clinic.example.com/cold#Visit-20240901'; // 就诊实例 IRI
278
+ const isOutpatient = store.has(VISIT, RDF + 'type', c + 'OutpatientVisit'); // 归为门诊就诊
279
+ const isEncounter = store.has(VISIT, RDF + 'type', OGMS_ENCOUNTER); // 归为 health care encounter
280
+
281
+ // 7) 临床数据关联验证
282
+ const patient = 'http://clinic.example.com/cold#Patient-ZhangSan'; // 患者实例 IRI
283
+ const hasFever = store.has(patient, c + 'hasSymptom', FEVER_ZS); // 患者有发热
284
+ const hasDiagnosis = store.has(patient, c + 'hasDiagnosis', DIAG_ZS); // 患者有诊断
285
+ const receivesTreatment = store.has(patient, c + 'receivesTreatment', TREATMENT_ZS); // 患者接受治疗
286
+ const treatmentHasParacetamol = store.has(TREATMENT_ZS, c + 'hasMedication', c + 'Paracetamol'); // 治疗含退热药
287
+ const visitRecordsPatient = store.has(VISIT, c + 'recordsPatient', patient); // 就诊记录患者
288
+ const visitRecordsDiagnosis = store.has(VISIT, c + 'recordsDiagnosis', DIAG_ZS); // 就诊记录诊断
289
+
290
+ const consistent = reasoner.isConsistent(); // 本体一致性
291
+
292
+ // 8) 导出病历本体为 RDF/XML
293
+ const clinOnt = triplesToOntology(new TurtleParser().parse(buildColdTreatmentTurtle())); // 桥接为 OWLOntology
294
+ const xmlOut = writeRDFXML(clinOnt); // 导出 RDF/XML
295
+ const exported = xmlOut.trim().startsWith('<?xml'); // 是合法 XML
296
+
297
+ return {
298
+ counts, edges, ogmsStdClasses, hasStdClasses,
299
+ isSymptomaticTreatment, isTreatment, isTherapeutic, isProcess, treatmentAttributed,
300
+ isURI, isDiagnosis, isInfectious, isAcute, diagnosisAttributed,
301
+ isFever, isSymptom, isClinicalFinding,
302
+ isOutpatient, isEncounter,
303
+ hasFever, hasDiagnosis, receivesTreatment, treatmentHasParacetamol,
304
+ visitRecordsPatient, visitRecordsDiagnosis,
305
+ consistent, exported
306
+ };
307
+ }
308
+
309
+ // 导出供测试与复用
310
+ module.exports = { run };
311
+
312
+ // 直接运行时打印业务结论
313
+ if (require.main === module) {
314
+ const r = run();
315
+ console.log('================ 真实标准本体加载 ================');
316
+ console.log('BFO 公理数 :', r.counts.bfo); // > 0
317
+ console.log('OGMS 公理数 :', r.counts.ogms); // > 0
318
+ console.log('真实类层级边数 :', r.edges); // > 100
319
+ console.log('含全部 OGMS 临床标准类 :', r.hasStdClasses); // true
320
+ console.log('');
321
+ console.log('================ 治疗方案 OGMS 层级归因 ================');
322
+ console.log('对症治疗归为 SymptomaticTreatment:', r.isSymptomaticTreatment); // true
323
+ console.log(' → treatment :', r.isTreatment); // true
324
+ console.log(' → therapeutic procedure(兄弟类):', r.isTherapeutic); // false(兄弟类非父子)
325
+ console.log(' → BFO process :', r.isProcess); // true
326
+ console.log('沿真实 OGMS 层级完整归因 :', r.treatmentAttributed); // true
327
+ console.log('');
328
+ console.log('================ 诊断 IDO 层级归因 ================');
329
+ console.log('诊断归为上呼吸道感染 :', r.isURI); // true
330
+ console.log(' → diagnosis :', r.isDiagnosis); // true
331
+ console.log(' → infectious disorder :', r.isInfectious); // true
332
+ console.log(' → acute disease course :', r.isAcute); // true
333
+ console.log('沿真实 IDO 层级完整归因 :', r.diagnosisAttributed); // true
334
+ console.log('');
335
+ console.log('================ 症状与就诊归因 ================');
336
+ console.log('发热归为 Fever :', r.isFever); // true
337
+ console.log(' → symptom :', r.isSymptom); // true
338
+ console.log(' → clinical finding(兄弟类) :', r.isClinicalFinding); // false(兄弟类非父子)
339
+ console.log('门诊就诊归为 OutpatientVisit :', r.isOutpatient); // true
340
+ console.log(' → health care encounter :', r.isEncounter); // true
341
+ console.log('');
342
+ console.log('================ 临床数据关联 ================');
343
+ console.log('患者有发热症状 :', r.hasFever); // true
344
+ console.log('患者有诊断 :', r.hasDiagnosis); // true
345
+ console.log('患者接受治疗 :', r.receivesTreatment); // true
346
+ console.log('对症治疗含退热药 :', r.treatmentHasParacetamol); // true
347
+ console.log('就诊记录关联患者 :', r.visitRecordsPatient); // true
348
+ console.log('就诊记录关联诊断 :', r.visitRecordsDiagnosis); // true
349
+ console.log('');
350
+ console.log('================ 一致性与导出 ================');
351
+ console.log('本体一致性 :', r.consistent); // true
352
+ console.log('病历可导出为 RDF/XML :', r.exported); // true
353
+ }