@nahisaho/satori 0.20.0 → 0.22.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 (30) hide show
  1. package/README.md +70 -39
  2. package/package.json +1 -1
  3. package/src/.github/skills/scientific-biothings-idmapping/SKILL.md +4 -0
  4. package/src/.github/skills/scientific-cellxgene-census/SKILL.md +257 -0
  5. package/src/.github/skills/scientific-clingen-curation/SKILL.md +258 -0
  6. package/src/.github/skills/scientific-clinical-nlp/SKILL.md +250 -0
  7. package/src/.github/skills/scientific-clinical-pharmacology/SKILL.md +361 -0
  8. package/src/.github/skills/scientific-clinical-standards/SKILL.md +444 -0
  9. package/src/.github/skills/scientific-crispr-design/SKILL.md +369 -0
  10. package/src/.github/skills/scientific-drug-repurposing/SKILL.md +4 -0
  11. package/src/.github/skills/scientific-environmental-ecology/SKILL.md +5 -0
  12. package/src/.github/skills/scientific-epidemiology-public-health/SKILL.md +5 -0
  13. package/src/.github/skills/scientific-epigenomics-chromatin/SKILL.md +5 -0
  14. package/src/.github/skills/scientific-glycomics/SKILL.md +274 -0
  15. package/src/.github/skills/scientific-gtex-tissue-expression/SKILL.md +5 -2
  16. package/src/.github/skills/scientific-hgnc-nomenclature/SKILL.md +282 -0
  17. package/src/.github/skills/scientific-human-cell-atlas/SKILL.md +3 -0
  18. package/src/.github/skills/scientific-human-protein-atlas/SKILL.md +4 -0
  19. package/src/.github/skills/scientific-immunoinformatics/SKILL.md +9 -0
  20. package/src/.github/skills/scientific-lipidomics/SKILL.md +284 -0
  21. package/src/.github/skills/scientific-metabolomics/SKILL.md +3 -0
  22. package/src/.github/skills/scientific-metabolomics-network/SKILL.md +311 -0
  23. package/src/.github/skills/scientific-metagenome-assembled-genomes/SKILL.md +299 -0
  24. package/src/.github/skills/scientific-model-organism-db/SKILL.md +8 -0
  25. package/src/.github/skills/scientific-pharmacogenomics/SKILL.md +4 -0
  26. package/src/.github/skills/scientific-pharos-targets/SKILL.md +276 -0
  27. package/src/.github/skills/scientific-protein-structure-analysis/SKILL.md +4 -0
  28. package/src/.github/skills/scientific-public-health-data/SKILL.md +11 -0
  29. package/src/.github/skills/scientific-systems-biology/SKILL.md +11 -0
  30. package/src/.github/skills/scientific-variant-effect-prediction/SKILL.md +7 -0
@@ -0,0 +1,444 @@
1
+ ---
2
+ name: scientific-clinical-standards
3
+ description: |
4
+ 臨床標準用語・コードマッピングスキル。LOINC 臨床検査コード・
5
+ ICD-10/ICD-11 疾病分類・FHIR R4 リソースマッピング・
6
+ SNOMED CT 用語変換・臨床用語相互運用パイプライン。
7
+ tu_tools:
8
+ - key: loinc
9
+ name: LOINC
10
+ description: 臨床検査用語標準コード体系
11
+ - key: icd
12
+ name: ICD
13
+ description: WHO 国際疾病分類 ICD-10/ICD-11
14
+ ---
15
+
16
+ # Scientific Clinical Standards
17
+
18
+ LOINC / ICD / FHIR / SNOMED CT を統合した
19
+ 臨床標準用語コード検索・マッピング・相互運用パイプラインを提供する。
20
+
21
+ ## When to Use
22
+
23
+ - LOINC コードで臨床検査項目を標準化するとき
24
+ - ICD-10/ICD-11 で疾病分類コードを検索するとき
25
+ - FHIR R4 リソースに臨床データをマッピングするとき
26
+ - 異なる用語体系間のコード変換を行うとき
27
+ - 電子カルテ (EHR) データの標準化パイプラインを構築するとき
28
+ - 臨床データウェアハウスの用語統一を行うとき
29
+
30
+ ---
31
+
32
+ ## Quick Start
33
+
34
+ ## 1. LOINC コード検索
35
+
36
+ ```python
37
+ import requests
38
+ import pandas as pd
39
+
40
+
41
+ LOINC_FHIR = "https://fhir.loinc.org"
42
+
43
+
44
+ def loinc_search(query, max_results=20):
45
+ """
46
+ LOINC — 臨床検査コード検索 (FHIR API)。
47
+
48
+ Parameters:
49
+ query: str — 検索クエリ (検査名/コード)
50
+ max_results: int — 最大結果数
51
+ """
52
+ url = f"{LOINC_FHIR}/CodeSystem/$lookup"
53
+ params = {
54
+ "system": "http://loinc.org",
55
+ "code": query,
56
+ }
57
+
58
+ # まずコード直接検索
59
+ try:
60
+ resp = requests.get(url, params=params,
61
+ timeout=30)
62
+ if resp.status_code == 200:
63
+ data = resp.json()
64
+ params_list = data.get("parameter", [])
65
+ result = {}
66
+ for p in params_list:
67
+ result[p["name"]] = p.get(
68
+ "valueString",
69
+ p.get("valueCode", ""))
70
+ return pd.DataFrame([result])
71
+ except Exception:
72
+ pass
73
+
74
+ # テキスト検索にフォールバック
75
+ url = f"{LOINC_FHIR}/CodeSystem"
76
+ params = {
77
+ "_text": query,
78
+ "_count": max_results,
79
+ }
80
+ resp = requests.get(url, params=params,
81
+ timeout=30)
82
+ resp.raise_for_status()
83
+ data = resp.json()
84
+
85
+ entries = data.get("entry", [])
86
+ rows = []
87
+ for entry in entries:
88
+ resource = entry.get("resource", {})
89
+ rows.append({
90
+ "code": resource.get("id", ""),
91
+ "name": resource.get("name", ""),
92
+ "title": resource.get("title", ""),
93
+ "status": resource.get("status", ""),
94
+ })
95
+
96
+ df = pd.DataFrame(rows)
97
+ print(f"LOINC: {len(df)} results for "
98
+ f"'{query}'")
99
+ return df
100
+
101
+
102
+ def loinc_code_detail(loinc_code):
103
+ """
104
+ LOINC — コード詳細取得。
105
+
106
+ Parameters:
107
+ loinc_code: str — LOINC コード
108
+ (例: "2160-0" = Creatinine)
109
+ """
110
+ url = (f"{LOINC_FHIR}/CodeSystem/"
111
+ f"$lookup")
112
+ params = {
113
+ "system": "http://loinc.org",
114
+ "code": loinc_code,
115
+ }
116
+ resp = requests.get(url, params=params,
117
+ timeout=30)
118
+ resp.raise_for_status()
119
+ data = resp.json()
120
+
121
+ detail = {"loinc_code": loinc_code}
122
+ for p in data.get("parameter", []):
123
+ name = p.get("name", "")
124
+ value = p.get(
125
+ "valueString",
126
+ p.get("valueCode",
127
+ p.get("valueBoolean", "")))
128
+ detail[name] = value
129
+
130
+ print(f"LOINC {loinc_code}: "
131
+ f"{detail.get('display', 'N/A')}")
132
+ return detail
133
+ ```
134
+
135
+ ## 2. ICD-10/ICD-11 疾病分類検索
136
+
137
+ ```python
138
+ ICD_API = "https://id.who.int"
139
+
140
+
141
+ def icd11_search(query, max_results=20,
142
+ language="en"):
143
+ """
144
+ ICD-11 — WHO 疾病分類検索。
145
+
146
+ Parameters:
147
+ query: str — 検索クエリ (疾病名)
148
+ max_results: int — 最大結果数
149
+ language: str — 言語 (en/ja)
150
+ """
151
+ url = (f"{ICD_API}/icd/release/11/"
152
+ f"2024-01/mms/search")
153
+ headers = {
154
+ "Accept": "application/json",
155
+ "Accept-Language": language,
156
+ "API-Version": "v2",
157
+ }
158
+ params = {
159
+ "q": query,
160
+ "subtreesFilter": "",
161
+ "flatResults": "true",
162
+ }
163
+
164
+ resp = requests.get(url, params=params,
165
+ headers=headers,
166
+ timeout=30)
167
+ resp.raise_for_status()
168
+ data = resp.json()
169
+
170
+ results = []
171
+ for item in data.get(
172
+ "destinationEntities", [])[:max_results]:
173
+ results.append({
174
+ "code": item.get("theCode", ""),
175
+ "title": item.get("title", ""),
176
+ "chapter": item.get("chapter", ""),
177
+ "score": item.get("score", 0),
178
+ "id": item.get("id", ""),
179
+ })
180
+
181
+ df = pd.DataFrame(results)
182
+ print(f"ICD-11: {len(df)} results for "
183
+ f"'{query}'")
184
+ return df
185
+
186
+
187
+ def icd10_to_icd11_mapping(icd10_code):
188
+ """
189
+ ICD-10 → ICD-11 マッピング。
190
+
191
+ Parameters:
192
+ icd10_code: str — ICD-10 コード
193
+ (例: "E11" = Type 2 DM)
194
+ """
195
+ url = (f"{ICD_API}/icd/release/11/"
196
+ f"2024-01/mms/codeinfo/"
197
+ f"{icd10_code}")
198
+ headers = {
199
+ "Accept": "application/json",
200
+ "API-Version": "v2",
201
+ }
202
+ try:
203
+ resp = requests.get(url, headers=headers,
204
+ timeout=30)
205
+ if resp.status_code == 200:
206
+ data = resp.json()
207
+ print(f"ICD mapping: {icd10_code} → "
208
+ f"{data.get('code', 'N/A')}")
209
+ return data
210
+ except Exception:
211
+ pass
212
+
213
+ # フォールバック: テキスト検索
214
+ results = icd11_search(icd10_code)
215
+ if not results.empty:
216
+ return results.iloc[0].to_dict()
217
+
218
+ print(f"ICD mapping: {icd10_code} → not found")
219
+ return {}
220
+ ```
221
+
222
+ ## 3. FHIR R4 リソースマッピング
223
+
224
+ ```python
225
+ def create_fhir_observation(
226
+ loinc_code, value, unit,
227
+ patient_id, effective_date):
228
+ """
229
+ FHIR R4 Observation リソース作成。
230
+
231
+ Parameters:
232
+ loinc_code: str — LOINC コード
233
+ value: float — 測定値
234
+ unit: str — 単位
235
+ patient_id: str — 患者 ID
236
+ effective_date: str — 測定日時 (ISO 8601)
237
+ """
238
+ observation = {
239
+ "resourceType": "Observation",
240
+ "status": "final",
241
+ "code": {
242
+ "coding": [{
243
+ "system": "http://loinc.org",
244
+ "code": loinc_code,
245
+ }]
246
+ },
247
+ "subject": {
248
+ "reference": f"Patient/{patient_id}"
249
+ },
250
+ "effectiveDateTime": effective_date,
251
+ "valueQuantity": {
252
+ "value": value,
253
+ "unit": unit,
254
+ "system": (
255
+ "http://unitsofmeasure.org"),
256
+ },
257
+ }
258
+
259
+ print(f"FHIR Observation: "
260
+ f"LOINC {loinc_code} = {value} {unit}")
261
+ return observation
262
+
263
+
264
+ def create_fhir_condition(
265
+ icd_code, icd_system,
266
+ patient_id, onset_date,
267
+ clinical_status="active"):
268
+ """
269
+ FHIR R4 Condition リソース作成。
270
+
271
+ Parameters:
272
+ icd_code: str — ICD コード
273
+ icd_system: str — "icd10" or "icd11"
274
+ patient_id: str — 患者 ID
275
+ onset_date: str — 発症日 (ISO 8601)
276
+ clinical_status: str — 臨床状態
277
+ """
278
+ system_uri = (
279
+ "http://hl7.org/fhir/sid/icd-10"
280
+ if icd_system == "icd10"
281
+ else "http://id.who.int/icd/release/11/mms"
282
+ )
283
+
284
+ condition = {
285
+ "resourceType": "Condition",
286
+ "clinicalStatus": {
287
+ "coding": [{
288
+ "system": ("http://terminology."
289
+ "hl7.org/CodeSystem/"
290
+ "condition-clinical"),
291
+ "code": clinical_status,
292
+ }]
293
+ },
294
+ "code": {
295
+ "coding": [{
296
+ "system": system_uri,
297
+ "code": icd_code,
298
+ }]
299
+ },
300
+ "subject": {
301
+ "reference": f"Patient/{patient_id}"
302
+ },
303
+ "onsetDateTime": onset_date,
304
+ }
305
+
306
+ print(f"FHIR Condition: {icd_system.upper()} "
307
+ f"{icd_code} ({clinical_status})")
308
+ return condition
309
+ ```
310
+
311
+ ## 4. 用語体系相互変換
312
+
313
+ ```python
314
+ def cross_reference_codes(code, source_system,
315
+ target_systems=None):
316
+ """
317
+ 用語体系間コード相互参照。
318
+
319
+ Parameters:
320
+ code: str — ソースコード
321
+ source_system: str — ソース体系
322
+ ("loinc"/"icd10"/"icd11"/"snomed")
323
+ target_systems: list[str] | None —
324
+ ターゲット体系
325
+ """
326
+ if target_systems is None:
327
+ target_systems = [
328
+ "loinc", "icd10", "icd11", "snomed"]
329
+ target_systems = [
330
+ s for s in target_systems
331
+ if s != source_system]
332
+
333
+ mappings = {"source": code,
334
+ "source_system": source_system}
335
+
336
+ if source_system == "loinc":
337
+ detail = loinc_code_detail(code)
338
+ mappings["display"] = detail.get(
339
+ "display", "")
340
+
341
+ if source_system == "icd10":
342
+ m = icd10_to_icd11_mapping(code)
343
+ if m:
344
+ mappings["icd11"] = m.get("code", "")
345
+ mappings["icd11_title"] = m.get(
346
+ "title", "")
347
+
348
+ print(f"Cross-ref: {source_system}:{code} → "
349
+ f"{len(mappings) - 2} mappings")
350
+ return mappings
351
+ ```
352
+
353
+ ## 5. 臨床標準統合パイプライン
354
+
355
+ ```python
356
+ def clinical_standards_pipeline(
357
+ lab_data, diagnosis_data,
358
+ output_dir="results"):
359
+ """
360
+ 臨床標準用語統合パイプライン。
361
+
362
+ Parameters:
363
+ lab_data: pd.DataFrame — 検査データ
364
+ columns: [test_name, value, unit, date]
365
+ diagnosis_data: pd.DataFrame — 診断データ
366
+ columns: [diagnosis, icd_code, date]
367
+ output_dir: str — 出力ディレクトリ
368
+ """
369
+ from pathlib import Path
370
+ out = Path(output_dir)
371
+ out.mkdir(parents=True, exist_ok=True)
372
+
373
+ # 1) 検査 LOINC マッピング
374
+ loinc_maps = []
375
+ for _, row in lab_data.iterrows():
376
+ result = loinc_search(row["test_name"], 1)
377
+ if not result.empty:
378
+ loinc_maps.append({
379
+ "test_name": row["test_name"],
380
+ "loinc_code": result.iloc[0].get(
381
+ "code", ""),
382
+ "value": row["value"],
383
+ "unit": row["unit"],
384
+ })
385
+ if loinc_maps:
386
+ loinc_df = pd.DataFrame(loinc_maps)
387
+ loinc_df.to_csv(
388
+ out / "loinc_mappings.csv",
389
+ index=False)
390
+
391
+ # 2) 診断 ICD マッピング
392
+ icd_maps = []
393
+ for _, row in diagnosis_data.iterrows():
394
+ result = icd11_search(row["diagnosis"], 1)
395
+ if not result.empty:
396
+ icd_maps.append({
397
+ "diagnosis": row["diagnosis"],
398
+ "icd11_code": result.iloc[0].get(
399
+ "code", ""),
400
+ "icd11_title": result.iloc[0].get(
401
+ "title", ""),
402
+ })
403
+ if icd_maps:
404
+ icd_df = pd.DataFrame(icd_maps)
405
+ icd_df.to_csv(
406
+ out / "icd_mappings.csv",
407
+ index=False)
408
+
409
+ # 3) FHIR Bundle 生成
410
+ fhir_resources = []
411
+ for item in loinc_maps:
412
+ obs = create_fhir_observation(
413
+ item["loinc_code"],
414
+ item["value"], item["unit"],
415
+ "patient-001", "2024-01-01")
416
+ fhir_resources.append(obs)
417
+
418
+ print(f"Clinical standards pipeline → {out}")
419
+ return {
420
+ "loinc_mappings": loinc_maps,
421
+ "icd_mappings": icd_maps,
422
+ "fhir_resources": fhir_resources,
423
+ }
424
+ ```
425
+
426
+ ---
427
+
428
+ ## パイプライン統合
429
+
430
+ ```
431
+ clinical-reporting → clinical-standards → clinical-decision-support
432
+ (臨床レポート) (用語標準化) (臨床意思決定支援)
433
+ │ │ ↓
434
+ public-health-data ───────┘ pharmacogenomics
435
+ (公衆衛生データ) (ゲノム薬理学)
436
+ ```
437
+
438
+ ## パイプライン出力
439
+
440
+ | ファイル | 説明 | 次スキル |
441
+ |---------|------|---------|
442
+ | `loinc_mappings.csv` | LOINC コードマッピング | → clinical-decision |
443
+ | `icd_mappings.csv` | ICD コードマッピング | → epidemiology |
444
+ | `fhir_bundle.json` | FHIR R4 バンドル | → EHR 統合 |