forked from Rhizobium-gits/seq2pipe
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathqiime2_agent.py
More file actions
executable file
·3267 lines (2905 loc) · 144 KB
/
qiime2_agent.py
File metadata and controls
executable file
·3267 lines (2905 loc) · 144 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#!/usr/bin/env python3
# coding: utf-8
"""
seq2pipe — sequence → pipeline
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
ローカルLLM(Ollama)を使ったマイクロバイオーム解析 AI エージェント
生配列データを読み取り、QIIME2 パイプラインを自動生成します
依存ライブラリ: Python 標準ライブラリのみ(外部パッケージ不要)
必要ツール : Ollama (setup.sh でインストール), Docker Desktop
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
"""
import datetime
import json
import os
import re
import shutil
import socket
import subprocess
import sys
import tempfile
import urllib.error
import urllib.request
from pathlib import Path
from typing import Optional
# 🍺 ======================================================================
# 🐱 設定
# 🍺 ======================================================================
OLLAMA_URL = "http://localhost:11434/api/chat"
DEFAULT_MODEL = os.environ.get("QIIME2_AI_MODEL", "qwen2.5-coder:7b")
# 🐱 CPU 専用環境(Codespaces 等)での初回推論に対応するため 600 秒に設定
# 🐱 環境変数 OLLAMA_TIMEOUT で上書き可能
OLLAMA_TIMEOUT = int(os.environ.get("OLLAMA_TIMEOUT", "600"))
# 🐱 execute_python のタイムアウト(issue #32: 300s → 600s に延長, 環境変数で上書き可)
PYTHON_EXEC_TIMEOUT = int(os.environ.get("SEQ2PIPE_PYTHON_TIMEOUT", "600"))
# 🐱 エージェントループの最大ステップ数(100 → 200: QIIME2 + 複数図生成で消費が多い)
MAX_AGENT_STEPS = int(os.environ.get("SEQ2PIPE_MAX_STEPS", "200"))
# 🐱 自律モード: SEQ2PIPE_AUTO_YES=1 でコマンド確認をスキップ(issue #31)
AUTO_YES = os.environ.get("SEQ2PIPE_AUTO_YES", "0") == "1"
SCRIPT_DIR = Path(__file__).parent.resolve()
# 🐱 QIIME2 conda 環境の自動検出
def _find_qiime2_conda_bin() -> str:
"""QIIME2 conda 環境の bin ディレクトリを自動検出する"""
# 環境変数で上書き可(最優先)
env_override = os.environ.get("QIIME2_CONDA_BIN", "")
if env_override and Path(env_override).exists():
return env_override
# conda のベースディレクトリ候補
conda_bases = [
Path.home() / "miniforge3",
Path.home() / "miniconda3",
Path.home() / "anaconda3",
Path.home() / "mambaforge",
Path.home() / "opt/miniconda3",
Path.home() / "opt/miniforge3",
Path("/opt/miniconda3"),
Path("/opt/miniforge3"),
Path("/usr/local/miniconda3"),
]
# まず名前が "qiime2" で始まる環境を優先して探す(バージョン付きも対象)
for base in conda_bases:
envs_dir = base / "envs"
if not envs_dir.exists():
continue
# "qiime2" で始まる環境を新しい順(バージョン番号降順)に試す
matches = sorted(
[d for d in envs_dir.iterdir() if d.name.startswith("qiime2") and (d / "bin" / "qiime").exists()],
key=lambda d: d.name,
reverse=True,
)
if matches:
return str(matches[0] / "bin")
# フォールバック: 全 conda 環境から qiime 実行ファイルを持つものを探す
for base in conda_bases:
envs_dir = base / "envs"
if not envs_dir.exists():
continue
for env_dir in sorted(envs_dir.iterdir(), reverse=True):
if (env_dir / "bin" / "qiime").exists():
return str(env_dir / "bin")
return ""
QIIME2_CONDA_BIN: str = _find_qiime2_conda_bin()
QIIME2_PYTHON: str = str(Path(QIIME2_CONDA_BIN) / "python3") if QIIME2_CONDA_BIN else sys.executable
# 🍺 ======================================================================
# 🐱 セッション状態(ダウンストリーム解析トラッキング)
# 🍺 ======================================================================
ANALYSIS_LOG: list = [] # 実行した解析の記録
SESSION_OUTPUT_DIR: str = "" # セッション全体の出力ルートディレクトリ(起動時に作成)
SESSION_FIGURE_DIR: str = "" # 図の出力先(SESSION_OUTPUT_DIR/figures/ に同期)
PLOT_CONFIG: dict = { # 図のデフォルトスタイル設定
"style": "seaborn-v0_8-whitegrid",
"palette": "Set2",
"figsize": [10, 6],
"dpi": 150,
"font_size": 12,
"title_font_size": 14,
"format": "pdf", # 保存フォーマット: pdf / png / svg
}
# 🍺 ======================================================================
# 🐱 言語設定(select_language() で起動時に設定)
# 🍺 ======================================================================
LANG: str = "ja" # "ja" | "en"
_UI: dict = {
"ja": {
"model_selected": "✅ 使用モデル: {}",
"hint_exit": "ヒント: 終了するには Ctrl+C を押してください。",
"prompt": "あなた",
"tool_exec": "🔧 ツール実行: {}",
"tool_result": "📋 実行結果:",
"goodbye": "👋 終了します。お疲れ様でした!",
"ollama_error": "❌ Ollama が起動していません。",
"ollama_hint": "以下のコマンドを別ターミナルで実行してから再試行してください:",
"ollama_hint2": "Ollama が未インストールの場合:",
"no_model": "⚠️ Ollama にモデルがインストールされていません。",
"no_model_hint": "推奨モデル: {}",
"no_model_hint2": "軽量版 : {}",
"runtime_error": "エラーが発生しました: {}",
"cmd_request": "⚡ コマンド実行リクエスト",
"cmd_desc": "説明",
"cmd_cmd": "コマンド",
"cmd_confirm": "[y] 実行する [n] キャンセル",
"cmd_cancelled_ki": "❌ キャンセルされました(キーボード割り込み)",
"cmd_cancelled": "❌ ユーザーによりキャンセルされました。",
"agent_limit": "⚠️ 最大ステップ数 ({}) に達しました。ループを終了します。",
"deps_ok": "✅ Pythonパッケージ確認済み(numpy/pandas/matplotlib/seaborn)",
"deps_warn": "⚠️ Pythonパッケージが不足しています: {}",
"deps_hint": "execute_python ツールが正しく動作しないことがあります。",
"deps_hint2": "インストール方法: {}",
"auto_approve": "[自律モード] コマンドを自動承認します",
"empty_response": "⚠️ AI からの応答が空でした。再試行します...",
"pkg_warning": "[警告] パッケージ不足: {}",
"pkg_hint": "pip install numpy pandas matplotlib seaborn を実行してください",
"select_error": "1 か 2 を入力してください",
"qiime2_python": "QIIME2 conda Python を使用: {}",
"session_dir": "📁 出力先ディレクトリ: {}",
"session_dir_hint": " 解析結果・図・レポートはすべてこのディレクトリに保存されます",
},
"en": {
"model_selected": "✅ Model: {}",
"hint_exit": "Tip: Press Ctrl+C to exit.",
"prompt": "You",
"tool_exec": "🔧 Tool: {}",
"tool_result": "📋 Result:",
"goodbye": "👋 Goodbye!",
"ollama_error": "❌ Ollama is not running.",
"ollama_hint": "Run the following command in another terminal:",
"ollama_hint2": "If Ollama is not installed:",
"no_model": "⚠️ No models installed in Ollama.",
"no_model_hint": "Recommended model: {}",
"no_model_hint2": "Lightweight: {}",
"runtime_error": "An error occurred: {}",
"cmd_request": "⚡ Command Execution Request",
"cmd_desc": "Description",
"cmd_cmd": "Command",
"cmd_confirm": "[y] Execute [n] Cancel",
"cmd_cancelled_ki": "❌ Cancelled (keyboard interrupt)",
"cmd_cancelled": "❌ Cancelled by user.",
"agent_limit": "⚠️ Max steps ({}) reached. Stopping loop.",
"deps_ok": "✅ Python packages verified (numpy/pandas/matplotlib/seaborn)",
"deps_warn": "⚠️ Missing Python packages: {}",
"deps_hint": "The execute_python tool may not work correctly.",
"deps_hint2": "To install: {}",
"auto_approve": "[Auto mode] Command approved automatically",
"empty_response": "⚠️ Empty response from AI. Retrying...",
"pkg_warning": "[WARNING] Missing package: {}",
"pkg_hint": "Please run: pip install numpy pandas matplotlib seaborn",
"select_error": "Please enter 1 or 2",
"qiime2_python": "Using QIIME2 conda Python: {}",
"session_dir": "📁 Output directory: {}",
"session_dir_hint": " All analysis results, figures, and reports will be saved here",
},
}
def ui(key: str, *args) -> str:
"""現在の LANG に対応する UI 文字列を返す"""
tmpl = _UI.get(LANG, _UI["ja"]).get(key, key)
return tmpl.format(*args) if args else tmpl
# 🍺 ======================================================================
# 🐱 ANSI カラー
# 🍺 ======================================================================
RESET = "\033[0m"
BOLD = "\033[1m"
GREEN = "\033[32m"
CYAN = "\033[36m"
YELLOW = "\033[33m"
RED = "\033[31m"
BLUE = "\033[34m"
MAGENTA = "\033[35m"
DIM = "\033[2m"
def c(text, color):
return f"{color}{text}{RESET}"
# 🍺 ======================================================================
# 🐱 システムプロンプト(QIIME2 ドメイン知識を埋め込み)
# 🍺 ======================================================================
SYSTEM_PROMPT = """あなたは QIIME2(Quantitative Insights Into Microbial Ecology 2)の専門 AI アシスタントです。
ユーザーのマイクロバイオームデータを解析し、最適な QIIME2 パイプラインを自動構築します。
━━━ 行動原則(最優先) ━━━
1. ツール・ファースト: ユーザーの発言を受けたら、長い説明より先にツールを呼び出す。
2. データ確認から始める: パスが提示されたら必ず inspect_directory → read_file でデータを把握してから提案する。
3. 実験情報をパラメータに反映: ユーザーが提供するアンプリコン領域・プライマー・比較グループを
DADA2 パラメータ・分類器・差次解析の設定に直接使う。
4. エラーは自力で診断・修正: ツールが失敗したら原因を分析し、別のアプローチを即座に試みる。
5. 生成スクリプトには日本語コメントを付ける。
6. QIIME2 は conda 環境で直接実行する(Docker 不要)。qiime コマンドはそのまま run_command に渡す。
7. 解析は一度に1ステップずつ実行し、各ステップのツール結果を確認してから次へ進む。
8. ツール名は下記リストにある正確な名前のみ使用すること。
━━━ 利用可能なツール(この名前のみ有効) ━━━
- inspect_directory : ディレクトリ内容を一覧表示
- read_file : テキスト/TSV/CSVファイルを読み込む
- check_system : QIIME2・システム環境を確認
- write_file : ファイルを書き出す(スクリプト・マニフェスト等)
- generate_manifest : FASTQファイルからQIIME2マニフェストTSVを自動生成
- edit_file : 既存ファイルを文字列置換で編集
- run_command : 単発シェルコマンドを実行(追加・修正が必要な場合のみ)
- run_qiime2_pipeline : ★ QIIME2解析パイプライン全体を一括自動実行(メインツール)
- set_plot_config : 図のスタイル・DPI・フォントサイズを設定
- execute_python : Pythonコードを実行(pandas/matplotlib/seabornで可視化)
- log_analysis_step : 解析ステップをログに記録
- build_report_tex : 解析結果をまとめたPDFレポートを生成(最終ステップ)
⚠️ 「generate_report」「compile_report」「create_report」などは存在しない。レポートは必ず「build_report_tex」を使うこと。
━━━ 解析パイプライン実行手順(この順に実行) ━━━
STEP 1: inspect_directory → FASTQディレクトリを調査
STEP 2: read_file → sample-metadata.tsv を読んでサンプル情報・列名を把握
STEP 3: set_plot_config → 論文向け設定(dpi=300, style=whitegrid等)を適用
STEP 4: run_qiime2_pipeline → QIIME2パイプライン全体を一括実行
(インポート→DADA2→系統発生ツリー→分類→多様性解析を全て自動実行)
STEP 5: execute_python → 属レベル組成・α多様性グラフを生成(FIGURE_DIR に保存)
STEP 6: build_report_tex → 全解析をまとめたPDFレポートを生成
★ run_qiime2_pipeline は QIIME2の全コアステップを内部で自動実行する。
個別に run_command で qiime コマンドを呼ぶ必要はない。
inspector の結果とメタデータを読んだらすぐに run_qiime2_pipeline を呼ぶこと。
━━━ あなたの役割 ━━━
1. ユーザーが指定したディレクトリのデータ構造を調査する
2. データの形式(FASTQ・マニフェスト・メタデータ等)を自動判定する
3. 実験系の説明(領域・プライマー・群構成)からパラメータを決定する
4. データに合わせた最適な QIIME2 解析パイプラインを自動実行する
5. 実行可能なシェルスクリプト・マニフェスト・メタデータを生成する
6. 解析結果の可視化を Python で行い、PDF レポートを生成する
━━━ 実験情報 → パラメータ対応 ━━━
ユーザーが実験系の説明を提供した場合、以下に従ってパラメータを決定する:
| ユーザーが示す情報 | 反映するパラメータ |
|---|---|
| V1-V3 / 27F/338R | trim-left-f=19, trim-left-r=20, trunc-f≈260, trunc-r≈200 |
| V3-V4 / 341F/806R | trim-left-f=17, trim-left-r=21, trunc-f≈270, trunc-r≈220 |
| V4 / 515F/806R | trim-left-f=19, trim-left-r=20, trunc-f≈250, trunc-r≈220 |
| ペアエンド 2×250bp | denoise-paired を使用 |
| シングルエンド 150bp | denoise-single, trunc≈140 |
| コントロール vs 処理群 | グループ列名を beta-group-significance と ancombc に渡す |
| 全長分類器でよい | setup_classifier.sh をスキップ、pre-trained 分類器を wget |
※ trunc-len の最終値は demux-summary.qzv のクオリティドロップ位置で調整が必要。
ユーザーに「demux-summary.qzv を view.qiime2.org で確認し、品質が急落する位置を教えてください」と必ず伝えること。
━━━ QIIME2 解析の完全ワークフロー ━━━
## データ形式の判定基準
- `*_R1*.fastq.gz` + `*_R2*.fastq.gz` → ペアエンドFASTQ
- `*.fastq.gz` のみ → シングルエンドFASTQ
- `*.qza` → 既存の QIIME2 アーティファクト(途中再開可能)
- `manifest.tsv` / `manifest.csv` → マニフェストファイル
- `metadata.tsv` / `sample_info.tsv` → メタデータファイル
- バーコードファイルがある → マルチプレックスデータ
## STEP 1: データのインポート
### ペアエンド FASTQ(マニフェスト方式、推奨)
```bash
qiime tools import \
--type 'SampleData[PairedEndSequencesWithQuality]' \
--input-path manifest.tsv \
--output-path paired-end-demux.qza \
--input-format PairedEndFastqManifestPhred33V2
```
マニフェストファイルの形式(manifest.tsv):
```
sample-id forward-absolute-filepath reverse-absolute-filepath
sample1 /data/output/raw/sample1_R1.fastq.gz /data/output/raw/sample1_R2.fastq.gz
```
### シングルエンド FASTQ
```bash
qiime tools import \
--type 'SampleData[SequencesWithQuality]' \
--input-path manifest.tsv \
--output-path single-end-demux.qza \
--input-format SingleEndFastqManifestPhred33V2
```
マニフェストファイルの形式(シングルエンド):
```
sample-id absolute-filepath
sample1 /data/output/raw/sample1_R1.fastq.gz
```
### マルチプレックスデータ(未デマルチプレックス)
```bash
qiime tools import \
--type EMPPairedEndSequences \
--input-path raw-sequences/ \
--output-path emp-paired-end-sequences.qza
```
## STEP 2: クオリティ確認
```bash
qiime demux summarize \
--i-data paired-end-demux.qza \
--o-visualization demux-summary.qzv
```
→ demux-summary.qzv を https://view.qiime2.org で開き、
クオリティが急落する位置を確認して DADA2 のパラメータを決定する
## STEP 3: DADA2 によるデノイジング(ノイズ除去・OTU/ASV 生成)
### ペアエンドの場合
```bash
# --p-trim-left-f/r: プライマー長(V1-V3: 19、V3-V4: 17)
# --p-trunc-len-f/r: demux-summary.qzv でクオリティが落ちる位置を確認して設定
qiime dada2 denoise-paired \
--i-demultiplexed-seqs paired-end-demux.qza \
--p-trim-left-f 19 \
--p-trim-left-r 20 \
--p-trunc-len-f 260 \
--p-trunc-len-r 200 \
--p-n-threads 4 \
--o-table table.qza \
--o-representative-sequences rep-seqs.qza \
--o-denoising-stats denoising-stats.qza
```
### シングルエンドの場合
```bash
qiime dada2 denoise-single \
--i-demultiplexed-seqs single-end-demux.qza \
--p-trim-left 19 \
--p-trunc-len 250 \
--p-n-threads 4 \
--o-table table.qza \
--o-representative-sequences rep-seqs.qza \
--o-denoising-stats denoising-stats.qza
```
領域別推奨パラメータ(目安):
- V1-V3 (27F/338R): f_primer=19bp, r_primer=20bp, trunc-f=260, trunc-r=200
- V3-V4 (341F/806R): f_primer=17bp, r_primer=21bp, trunc-f=270, trunc-r=220
- V4 (515F/806R) : f_primer=19bp, r_primer=20bp, trunc-f=250, trunc-r=220
## STEP 4: フィーチャーテーブルの確認
```bash
qiime feature-table summarize \
--i-table table.qza \
--m-sample-metadata-file metadata.tsv \
--o-visualization table.qzv
qiime feature-table tabulate-seqs \
--i-data rep-seqs.qza \
--o-visualization rep-seqs.qzv
```
## STEP 5: 系統樹の構築(多様性解析に必須)
```bash
qiime phylogeny align-to-tree-mafft-fasttree \
--i-sequences rep-seqs.qza \
--o-alignment aligned-rep-seqs.qza \
--o-masked-alignment masked-aligned-rep-seqs.qza \
--o-tree unrooted-tree.qza \
--o-rooted-tree rooted-tree.qza \
--p-n-threads 4
```
## STEP 6: 分類学的解析(SILVA 138)
### 分類器のセットアップ(初回のみ、約2-5時間)
V1-V3 領域専用(推奨):
```bash
# 参照配列のダウンロード
wget https://data.qiime2.org/2024.10/common/silva-138-99-seqs.qza
wget https://data.qiime2.org/2024.10/common/silva-138-99-tax.qza
# V1-V3 領域の抽出(27F/338R プライマー、1-2時間)
qiime feature-classifier extract-reads \
--i-sequences silva-138-99-seqs.qza \
--p-f-primer AGAGTTTGATCMTGGCTCAG \
--p-r-primer TGCTGCCTCCCGTAGGAGT \
--p-min-length 100 --p-max-length 400 --p-n-jobs 4 \
--o-reads silva-138-99-seqs-V1-V3.qza
# Naive Bayes 分類器の学習(1-3時間)
qiime feature-classifier fit-classifier-naive-bayes \
--i-reference-reads silva-138-99-seqs-V1-V3.qza \
--i-reference-taxonomy silva-138-99-tax.qza \
--o-classifier silva-138-99-classifier-V1-V3.qza
```
全長分類器(最速、精度は低め):
```bash
wget https://data.qiime2.org/classifiers/sklearn-1.4.2/silva/silva-138-99-nb-classifier.qza
```
### 分類の実行
```bash
qiime feature-classifier classify-sklearn \
--i-classifier silva-138-99-classifier-V1-V3.qza \
--i-reads rep-seqs.qza \
--p-n-jobs 4 \
--o-classification taxonomy.qza
# 分類ラベル一覧
qiime metadata tabulate \
--m-input-file taxonomy.qza \
--o-visualization taxonomy.qzv
# 分類組成バーチャート(最重要可視化)
qiime taxa barplot \
--i-table table.qza \
--i-taxonomy taxonomy.qza \
--m-metadata-file metadata.tsv \
--o-visualization taxa-bar-plots.qzv
```
## STEP 7: 多様性解析
```bash
# α・β多様性(sampling-depth は table.qzv で最小リード数を確認後に設定)
qiime diversity core-metrics-phylogenetic \
--i-phylogeny rooted-tree.qza \
--i-table table.qza \
--p-sampling-depth 1000 \
--m-metadata-file metadata.tsv \
--output-dir core-metrics-results/
# α多様性の統計検定(Shannon 多様性)
qiime diversity alpha-group-significance \
--i-alpha-diversity core-metrics-results/shannon_vector.qza \
--m-metadata-file metadata.tsv \
--o-visualization core-metrics-results/shannon-significance.qzv
# β多様性の PERMANOVA(Unweighted UniFrac)
qiime diversity beta-group-significance \
--i-distance-matrix core-metrics-results/unweighted_unifrac_distance_matrix.qza \
--m-metadata-file metadata.tsv \
--m-metadata-column <グループ列名> \
--o-visualization core-metrics-results/unweighted-unifrac-significance.qzv
```
## STEP 8: 差次解析(オプション)
```bash
# ANCOM-BC(グループ間の差次豊富種)
qiime composition ancombc \
--i-table table.qza \
--m-metadata-file metadata.tsv \
--p-formula <グループ列名> \
--o-differentials ancombc-results.qza
qiime composition da-barplot \
--i-data ancombc-results.qza \
--o-visualization ancombc-results.qzv
```
## Docker での実行コマンド雛形
```bash
docker run --rm \
-v <ホスト側解析ディレクトリ>:/data/output \
quay.io/qiime2/amplicon:2026.1 \
qiime <サブコマンド> \
--i-<入力引数> /data/output/<ファイル名> \
--o-<出力引数> /data/output/results/<ファイル名>
```
## メタデータファイル形式(metadata.tsv)
```
sample-id group age treatment
#q2:types categorical numeric categorical
sample1 control 25 placebo
sample2 treatment 30 drug_A
```
- 1行目: ヘッダー(必ず `sample-id` から始める)
- 2行目: データ型(`categorical` または `numeric`)省略可
## SILVA 138 分類階層
```
d__Bacteria; p__Firmicutes; c__Bacilli; o__Lactobacillales; f__Lactobacillaceae; g__Lactobacillus; s__Lactobacillus_acidophilus
```
レベル1: d__(ドメイン), 2: p__(門), 3: c__(綱), 4: o__(目), 5: f__(科), 6: g__(属), 7: s__(種)
※ 種レベルは精度が低い場合が多いため属レベル(g__)推奨
## トラブルシューティング
- extract-reads で配列が残らない → プライマー配列確認(縮重塩基 M, R, W 等)
- classify-sklearn でメモリエラー → Docker メモリ上限を 8GB 以上に、--p-n-jobs 1 に
- 全て Unassigned → リバースコンプリメント確認、--p-confidence 0.5 に下げる
- DADA2 後のリード数が激減 → trunc-len を短く(品質が低い位置を避ける)
━━━ 出力ファイルの説明 ━━━
- `*.qza` = QIIME2 アーティファクト(内部データ)
- `*.qzv` = QIIME2 ビジュアライゼーション → https://view.qiime2.org で開く
- `results/` = すべての出力先ディレクトリ
- `taxa-bar-plots.qzv` = 分類組成の積み上げ棒グラフ(最もよく使われる可視化)
- `core-metrics-results/` = 多様性解析の全出力
━━━ ダウンストリーム Python 解析 ━━━
QIIME2 が出力した結果ファイルに対して、Python(pandas / scipy / sklearn / matplotlib / seaborn)
を使った高度な統計・可視化・機械学習解析ができる。execute_python ツールを使うこと。
## execute_python で使えるビルトイン変数
以下の変数はコード実行前に自動で設定される(コード内でそのまま使用可):
```python
FIGURE_DIR # 図の保存先ディレクトリ(必ず plt.savefig(f"{FIGURE_DIR}/xxx.{FIGURE_FORMAT}") で保存すること)
OUTPUT_DIR # 解析出力の保存先ディレクトリ
PLOT_STYLE # matplotlib スタイル名(例: "seaborn-v0_8-whitegrid")
PLOT_PALETTE # seaborn カラーパレット(例: "Set2")
PLOT_FIGSIZE # figsize タプル(例: (10, 6))
PLOT_DPI # 解像度(例: 150)
FONT_SIZE # 通常フォントサイズ
TITLE_FONT_SIZE # タイトルフォントサイズ
FIGURE_FORMAT # 保存フォーマット(デフォルト: "pdf"、他: "png", "svg")
```
## 主な解析パターン
| 解析 | 必要な QIIME2 出力 | Python パッケージ |
|------|------|------|
| OTU/ASV 組成解析(biplot, stacked bar) | table.qza を解凍した feature-table.biom | biom-format, pandas, matplotlib |
| α多様性可視化・統計 | shannon_vector.qza 等を解凍した alpha-diversity.tsv | pandas, scipy, seaborn |
| β多様性 PCoA 図 | unweighted_unifrac_pcoa_results.qza 解凍 | pandas, matplotlib |
| ランダムフォレスト群判別 | feature-table.biom + metadata.tsv | sklearn, pandas |
| 分類組成ヒートマップ | taxonomy.tsv + feature-table.biom | pandas, seaborn |
| 差次解析補完(LEfSe 風) | feature-table.biom + metadata.tsv | scipy, statsmodels |
| ネットワーク解析(co-occurrence) | feature-table.biom | scipy, networkx |
## QIIME2 アーティファクトの解凍方法
.qza は ZIP ファイルなので Python でそのまま読める:
```python
import zipfile, json
with zipfile.ZipFile("/path/to/file.qza") as z:
# data/ 以下の実データを取り出す
for name in z.namelist():
if name.endswith('.tsv') or name.endswith('.biom'):
z.extract(name, OUTPUT_DIR)
```
## 図の保存ルール(必ず守ること)
```python
fig, ax = plt.subplots(figsize=PLOT_FIGSIZE)
# ... 描画 ...
plt.tight_layout()
# FIGURE_FORMAT はデフォルト "pdf"(変数がそのまま使える)
plt.savefig(f"{FIGURE_DIR}/figure_name.{FIGURE_FORMAT}", dpi=PLOT_DPI, bbox_inches='tight')
plt.close()
```
- FIGURE_FORMAT を使うことで、ユーザーの設定(pdf/png/svg)が自動反映される
- デフォルトは PDF なので view.qiime2.org を使わずにそのまま論文・レポートで使用可能
- savefig を呼ばないと図がトラッキングされないので必ず保存すること
## レポート生成
ユーザーが「レポートを作成して」と言ったら **build_report_tex** ツールを使う。
- `build_report_tex` は ANALYSIS_LOG を読んで Python で TeX を自動生成する(LLM が TeX を書く必要がない)
- `compile_report` は旧ツール(LLM が TeX 全文を書く方式)で非推奨。使わないこと。
build_report_tex には以下を渡すこと:
1. `title_ja` / `title_en`: レポートタイトル(日英)
2. `experiment_summary`: ユーザーから得た実験系の説明
3. `lang`: "both"(デフォルト)/ "ja" / "en"
## TeX レポートのテンプレート
### 日本語(XeLaTeX + xeCJK)
```latex
\\documentclass[a4paper,12pt]{article}
\\usepackage{xeCJK}
\\setCJKmainfont{Hiragino Mincho ProN}
\\usepackage{graphicx}
\\usepackage{booktabs}
\\usepackage{geometry}
\\geometry{margin=2.5cm}
\\title{マイクロバイオーム解析レポート}
\\author{seq2pipe}
\\date{\\today}
\\begin{document}
\\maketitle
% ここに内容
\\end{document}
```
### 英語(標準 LaTeX)
```latex
\\documentclass[a4paper,12pt]{article}
\\usepackage{graphicx}
\\usepackage{booktabs}
\\usepackage{geometry}
\\geometry{margin=2.5cm}
\\title{Microbiome Analysis Report}
\\author{seq2pipe}
\\date{\\today}
\\begin{document}
\\maketitle
% content here
\\end{document}
```
図を埋め込む: \\includegraphics[width=0.8\\textwidth]{<FIGURE_DIR>/figure_name.png}
━━━ 自律探索モード ━━━
ユーザーが「自動で解析して」「どんどん探索して」「いろいろ試して」と言ったとき(または
QIIME2 コア解析が完了した後)、以下のプロトコルを自律的に実行する。
ユーザーの確認を待たずに Phase 1 〜 5 を順番に実行すること。
## 探索フェーズ一覧
### Phase 1: α多様性探索 (subfolder="alpha_diversity")
- Shannon, Simpson, Chao1 を計算して violin/boxplot で可視化
- グループ間の統計検定(Mann-Whitney U / Kruskal-Wallis)
- 有意性を標準出力に print すること(例: `print(f"Shannon p={p:.4f}")`)
### Phase 2: β多様性探索 (subfolder="beta_diversity")
- Bray-Curtis dissimilarity を計算して PCoA を描画
- グループごとに色を変え、95% 信頼楕円を描く
- PERMANOVA を scipy で実装して p 値を出力(permutation_test または距離行列 + ランダム置換)
### Phase 3: 分類組成探索 (subfolder="taxonomy")
- 門・属レベルで relative abundance を集計
- stacked bar chart と heatmap(属レベル top 20)を作成
- グループ間で平均組成が異なる属を目視確認できるようにする
### Phase 4: 差次解析 (subfolder="differential_abundance")
- 全 ASV / 属に対して Mann-Whitney U / Kruskal-Wallis 検定を実施
- Benjamini-Hochberg 法で多重検定補正(statsmodels.stats.multitest.multipletests)
- 有意(FDR < 0.05)な taxa を dot plot / volcano plot で可視化
- 有意な taxa の数を print する
### Phase 5: 機械学習判別 (subfolder="machine_learning") ※2群以上の場合
- feature-table から ASV 相対存在量を特徴量として Random Forest を学習
- 5-fold cross-validation で accuracy と AUC を評価
- Feature importance 上位 20 種を棒グラフで表示
## .qza ファイルの読み込みコード雛形
```python
import zipfile, os, io
def extract_qza_data(qza_path):
# qza から data/ フォルダ内のデータファイルを読み込む
files = {}
with zipfile.ZipFile(qza_path) as z:
for name in z.namelist():
if '/data/' in name and not name.endswith('/'):
basename = os.path.basename(name)
if basename:
files[basename] = z.read(name)
return files
# 使用例: feature-table.biom の読み込み
# data = extract_qza_data('/path/to/table.qza')
# biom_bytes = data.get('feature-table.biom')
# if biom_bytes:
# import biom
# table = biom.load_table(io.BytesIO(biom_bytes))
# df = pd.DataFrame(table.to_dataframe()).T # サンプル×ASV
# メタデータの読み込み
# import pandas as pd
# metadata = pd.read_csv('/path/to/metadata.tsv', sep='\t', index_col=0)
# metadata = metadata[metadata.index != '#q2:types'] # q2:types 行を除外
```
## 探索中のコミュニケーションルール
- 各フェーズ開始時: 「Phase X: ○○解析を開始します」と伝える
- 各フェーズ終了時: 主要な発見(有意差の有無・特徴的な taxa 等)を要約する
- 全フェーズ完了後: `build_report_tex` を呼び出してレポートを自動生成する
- エラーが出たフェーズは原因を診断してスキップし、次のフェーズに進む
## IMPORTANT: run_command 実行後の ANALYSIS_LOG 登録
run_command で QIIME2 コマンドを実行したら、必ず直後に `log_analysis_step` を呼び出して
ANALYSIS_LOG に記録すること。こうしないと build_report_tex がそのステップを認識できない。
例:
```
log_analysis_step(
description="DADA2 デノイジング完了: ASV×サンプル table.qza 生成",
subfolder="qiime2_pipeline",
summary="処理リード: 平均 85%保持, ASV数: 約300"
)
```
## 探索完了後のレポート生成
全フェーズ完了後、必ず以下を実行する:
```
build_report_tex(
title_ja="<実験タイトル> 自律探索解析レポート",
title_en="<Experiment Title> Autonomous Exploration Report",
experiment_summary="<ユーザーから得た実験系の説明>",
lang="both"
)
```
このツールは ANALYSIS_LOG を読んで図・統計結果を自動的に TeX に埋め込み、PDF を生成する。"""
# 🍺 ======================================================================
# 🐱 ツール定義(Ollama function calling 形式)
# 🍺 ======================================================================
TOOLS = [
{
"type": "function",
"function": {
"name": "inspect_directory",
"description": "指定されたディレクトリの内容を調査する。ファイル名・サイズ・種類を一覧表示。",
"parameters": {
"type": "object",
"properties": {
"path": {
"type": "string",
"description": "調査するディレクトリの絶対パス"
},
"recursive": {
"type": "boolean",
"description": "サブディレクトリも含めて再帰的に調査するか(デフォルト: false)"
}
},
"required": ["path"]
}
}
},
{
"type": "function",
"function": {
"name": "read_file",
"description": "テキストファイル(TSV, CSV, TXT, MD 等)の内容を読み込む。ファイル冒頭 100 行まで表示。",
"parameters": {
"type": "object",
"properties": {
"path": {
"type": "string",
"description": "読み込むファイルの絶対パス"
},
"max_lines": {
"type": "integer",
"description": "最大読み込み行数(デフォルト: 50)"
}
},
"required": ["path"]
}
}
},
{
"type": "function",
"function": {
"name": "check_system",
"description": "Docker・Ollama・QIIME2 の利用可否とバージョンを確認する",
"parameters": {
"type": "object",
"properties": {}
}
}
},
{
"type": "function",
"function": {
"name": "write_file",
"description": "解析スクリプト・README・マニフェストなどのファイルを書き出す",
"parameters": {
"type": "object",
"properties": {
"path": {
"type": "string",
"description": "書き込むファイルの絶対パス"
},
"content": {
"type": "string",
"description": "書き込む内容(シェルスクリプト、Markdown 等)"
}
},
"required": ["path", "content"]
}
}
},
{
"type": "function",
"function": {
"name": "generate_manifest",
"description": "FASTQファイルからQIIME2マニフェストTSVを自動生成する",
"parameters": {
"type": "object",
"properties": {
"fastq_dir": {
"type": "string",
"description": "FASTQファイルが入ったディレクトリの絶対パス"
},
"output_path": {
"type": "string",
"description": "生成するマニフェストファイルの絶対パス"
},
"paired_end": {
"type": "boolean",
"description": "ペアエンドデータか(true: ペアエンド, false: シングルエンド)"
},
"container_data_dir": {
"type": "string",
"description": "Docker コンテナ内でのデータディレクトリパス(デフォルト: /data/output)"
}
},
"required": ["fastq_dir", "output_path", "paired_end"]
}
}
},
{
"type": "function",
"function": {
"name": "edit_file",
"description": "生成済みシェルスクリプトや設定ファイルの一部を文字列置換で編集する。old_str はファイル内で一意に存在する文字列を指定すること。",
"parameters": {
"type": "object",
"properties": {
"path": {
"type": "string",
"description": "編集するファイルの絶対パス"
},
"old_str": {
"type": "string",
"description": "置換前の文字列(ファイル内で一意に特定できる部分を含めること)"
},
"new_str": {
"type": "string",
"description": "置換後の文字列"
}
},
"required": ["path", "old_str", "new_str"]
}
}
},
{
"type": "function",
"function": {
"name": "run_command",
"description": "シェルコマンドを実行する。ユーザーに確認を求めてから実行する。",
"parameters": {
"type": "object",
"properties": {
"command": {
"type": "string",
"description": "実行するシェルコマンド"
},
"description": {
"type": "string",
"description": "このコマンドが何をするかの説明(ユーザーに表示)"
},
"working_dir": {
"type": "string",
"description": "コマンドを実行するディレクトリ(省略時はカレントディレクトリ)"
}
},
"required": ["command", "description"]
}
}
},
{
"type": "function",
"function": {
"name": "set_plot_config",
"description": "図(グラフ)のスタイル・色・サイズを設定する。ユーザーが見た目の好みを指定したときに呼び出す。",
"parameters": {
"type": "object",
"properties": {
"style": {
"type": "string",
"description": "matplotlib スタイル名(例: seaborn-v0_8-whitegrid, seaborn-v0_8-darkgrid, ggplot, dark_background)"
},
"palette": {
"type": "string",
"description": "seaborn/matplotlib カラーパレット名(例: Set2, tab10, husl, muted, deep, pastel)"
},
"figsize_w": {
"type": "number",
"description": "図の幅(インチ)"
},
"figsize_h": {
"type": "number",
"description": "図の高さ(インチ)"
},
"dpi": {
"type": "integer",
"description": "解像度 DPI(72=低, 150=中, 300=高品質)"
},
"font_size": {
"type": "integer",
"description": "通常テキストのフォントサイズ(pt)"
},
"title_font_size": {
"type": "integer",
"description": "タイトルのフォントサイズ(pt)"
},
"fig_format": {
"type": "string",
"description": "保存フォーマット(pdf / png / svg)。デフォルトは pdf。"
}
},
"required": []
}
}
},
{
"type": "function",
"function": {
"name": "execute_python",
"description": "Pythonコードを実行してダウンストリーム解析・統計・可視化を行う。QIIME2の出力(.qza/.tsv/.biom)を読み込み、pandas/scipy/sklearn/matplotlib/seabornで処理する。図は必ず FIGURE_DIR に savefig で保存すること。",
"parameters": {
"type": "object",
"properties": {
"code": {
"type": "string",
"description": "実行する Python コード。FIGURE_DIR, OUTPUT_DIR, PLOT_STYLE, PLOT_PALETTE, PLOT_FIGSIZE, PLOT_DPI, FONT_SIZE 変数が自動注入される。"
},
"description": {
"type": "string",
"description": "この解析の説明(レポートに記録される)"
},
"output_dir": {
"type": "string",
"description": "解析結果・図の保存先ディレクトリ(省略時はセッションのデフォルト出力先)"
},
"subfolder": {
"type": "string",
"description": "図を保存するサブフォルダ名。解析種別ごとに分ける(例: alpha_diversity, beta_diversity, taxonomy, differential_abundance, machine_learning)。省略時は figures/ 直下。"
}
},
"required": ["code", "description"]
}
}
},
{
# 🐱 issue #35: run_command 経由の QIIME2 ステップを ANALYSIS_LOG に手動登録するツール
"type": "function",
"function": {
"name": "log_analysis_step",
"description": (
"run_command で実行した QIIME2 操作や外部コマンドを ANALYSIS_LOG に記録する。"
"build_report_tex はこのログを参照するため、run_command 成功後に必ず呼び出す。"
),
"parameters": {
"type": "object",
"properties": {
"description": {
"type": "string",
"description": "解析ステップの説明(例: DADA2 デノイジング完了, taxonomy 分類完了)"
},
"subfolder": {
"type": "string",
"description": "解析カテゴリ(alpha_diversity / beta_diversity / taxonomy / differential_abundance / machine_learning / qiime2_pipeline など)"
},
"figures": {
"type": "array",
"items": {"type": "string"},
"description": "このステップで生成された図ファイルの絶対パスリスト(なければ省略)"
},
"summary": {
"type": "string",
"description": "解析結果の要約テキスト(統計値・ASV数・taxonomy ヒット率など)"
}
},
"required": ["description"]
}
}
},
{
"type": "function",
"function": {
"name": "build_report_tex",
"description": "ANALYSIS_LOG を読み取り、全解析ステップ・図・統計結果を含む TeX レポートを自動生成して PDF にコンパイルする。探索が完了したとき、またはユーザーがレポートを求めたときに呼び出す。",
"parameters": {
"type": "object",
"properties": {
"title_ja": {
"type": "string",
"description": "日本語レポートのタイトル(例: ヒト腸内マイクロバイオーム 自律探索解析レポート)"
},
"title_en": {
"type": "string",
"description": "英語レポートのタイトル(例: Human Gut Microbiome Autonomous Exploration Report)"