Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions .claude/skills/new-subcmd/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
---
name: new-subcmd
description: mdtbxに新しいargparseサブコマンドを追加する
---

# new-subcmd スキル

mdtbxに新しいargparseサブコマンドを追加するスキル。

## ワークフロー

### ステップ1: ユーザーへの確認

以下をユーザーに確認する:
1. **サブコマンド名** (例: `calc_rmsd`, `gen_topology`) — CLIで `mdtbx <名前>` として呼ぶ
2. **配置場所**: 機能に応じて選択
- `src/build/` — 系構築 (addace, amb2gro, gen_posres等と同種)
- `src/trajectory/` — 軌跡処理 (fit, trjcat等と同種)
- `src/analysis/` — 解析 (extract_str等と同種)
- `src/cv/` — Collective Variable計算
- `src/utils/` — 汎用ユーティリティ (mod_mdp, convert等と同種)
3. **引数**: 必須引数・オプション引数の名前と型
4. **処理内容**: 何をするコマンドか

### ステップ2: サブコマンドファイルの作成

`${SKILL_ROOT}/template.py` を参考に新ファイルを作成する。

必須パターン:
- `add_subcmd(subparsers)` の末尾に必ず `parser.set_defaults(func=run)` を置く
- `run(args)` が実装本体
- ロガーは `from ..logger import generate_logger` / `LOGGER = generate_logger(__name__)`
- `argparse.ArgumentDefaultsHelpFormatter` を使う
- `src/utils/` のパーサーを使う場合は `from ..utils.atom_selection_parser import AtomSelector` のように参照する

### ステップ3: cli.py への登録

`src/cli.py` に2箇所追加:

1. **importブロック** (対応するカテゴリのブロックに追加):
```python
from .build import <name> # build の場合
from .trajectory import <name> # trajectory の場合
from .analysis import <name> # analysis の場合
from .cv import <name> # cv の場合
from .utils import <name> # utils の場合
```

2. **add_subcmdの呼び出し** (同カテゴリのブロックに追加):
```python
<name>.add_subcmd(subparsers)
```

### ステップ4: テストファイルの作成

`tests/test_<category>/test_<name>.py` にユニットテストを追加する:
- 外部ツール不要な純粋計算関数は直接テスト
- ファイルI/Oは `tmp_path` fixture を使用
- 軌跡が必要な場合は `conftest.py` の `trajectory_files` fixture を使用
- PyMOL/subprocess 依存は `unittest.mock.patch` でモック

### ステップ5: Lintチェック・テスト実行

```bash
pixi run r # ruff format + lint
pixi run test # 全テスト
```

エラーがあれば修正する。
24 changes: 24 additions & 0 deletions .claude/skills/new-subcmd/template.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import argparse

from ..logger import generate_logger

LOGGER = generate_logger(__name__)


def add_subcmd(subparsers):
parser = subparsers.add_parser(
"SUBCMD_NAME",
help="HELP_TEXT",
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
)
# 必須引数
parser.add_argument("input", type=str, help="Input file")
# オプション引数
parser.add_argument("--output", type=str, default="output.dat", help="Output file")

parser.set_defaults(func=run)


def run(args):
LOGGER.info(f"input: {args.input}")
# TODO: 実装
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -196,3 +196,6 @@ cython_debug/
.pixi

!/sample/build
!/src/build

TODO.md
122 changes: 122 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Overview

`mdtbx` はMDシミュレーション用のツールボックス。系の構築・シミュレーション実行・軌跡解析・自由エネルギー計算をサポートするCLIツール。

依存ツール: AMBER, PyMOL, OpenBabel, Gromacs, Gaussian16
力場: ff14SB, TIP3P, GAFF2, Lipid21, GLYCAM06-j

## 開発コマンド

```bash
# 環境構築
pixi install

# CLIの実行
pixi run mdtbx <subcommand>
pixi run gmx ... # mdtbx cmd gmx ... の短縮形

# テスト
pixi run test # 全テスト実行
pixi run test-fast # 最初の失敗で停止 (-x)

# コードフォーマット・Lint
pixi run r # ruff format + ruff check を一括実行
pixi run ruff-format # フォーマットのみ
pixi run ruff-lint # Lintのみ

# 更新
pixi run update # git pull && pixi install

# PyMOL設定
pixi run pymolrc # ~/.pymolrcを生成

# JupyterLab (リモート)
pixi run jupyter_remote
```

## アーキテクチャ

```
src/
__main__.py # エントリポイント: main() -> cli()
cli.py # argparseサブコマンドの登録・ディスパッチ
config.py # グローバル定数(水密度、Gaussian設定、MAXWARN等)
logger.py # ロガー生成ユーティリティ
utils/ # 汎用ユーティリティ(mod_mdp, convert, rmfile, cmd, shell_hook, show_mdtraj, show_npy, partial_tempering)
# ※ atom_selection_parser.py, parse_top.py はサブコマンドでなくライブラリユーティリティ
build/ # 系構築サブコマンド(addace, addnme, add_ndx, mv_crds_mol2, calc_ion_conc, centering_gro,
# find_bond, gen_am1bcc, gen_resp, gen_modres_am1bcc, gen_modres_resp, gen_posres,
# gen_distres, modeling_cf, amb2gro, build_solution, gen_temperatures)
# ※ addh.py, mutate.py, place_solvent.py は未登録(cli.pyへの追加が必要)
trajectory/ # 軌跡処理サブコマンド(fit, trjcat, pacs_trjcat, print_perf)
# ※ opt_perf.py は未登録
analysis/ # 解析サブコマンド(extract_str, extract_ave_str)
# ※ contactmap.py, distmat.py は未登録
cv/ # Collective Variable計算(comdist, comvec, densmap, mindist, rmsd, rmsf, xyz, pca)

tests/
conftest.py # 共有fixture・PyMOLモック設定
fixtures/ # テストデータ(sample.mdp, sample.top, sample.pdb)
test_utils/ # src/utils/ のテスト
test_build/ # src/build/ のテスト
test_trajectory/ # src/trajectory/ のテスト
test_analysis/ # src/analysis/ のテスト
test_cv/ # src/cv/ のテスト
test_cli.py # 全サブコマンドのCLI登録確認

pymol-plugins/
pymol_plugins/ # PyMOLプラグイン(builder, visualizer, selector等)

example/ # 用途別のサンプルノートブック・スクリプト
install_scripts/ # Gromacs/PLUMED等の手動インストールスクリプト
```

### サブコマンドの追加パターン

各モジュール(`src/build/*.py`, `src/trajectory/*.py`, `src/analysis/*.py`, `src/cv/*.py`, `src/utils/*.py`)は以下の2関数を実装する:

```python
def add_subcmd(subparsers):
# argparse サブコマンドの引数定義

def run(args):
# 実装本体
```

`cli.py` に以下の2箇所を追加して登録する:

```python
# 1. importブロック (カテゴリに応じて選択)
from .build import <name> # 系構築
from .trajectory import <name> # 軌跡処理
from .analysis import <name> # 解析
from .cv import <name> # CV計算
from .utils import <name> # 汎用

# 2. add_subcmdの呼び出し
<name>.add_subcmd(subparsers)
```

モジュール内で `src/utils/` のパーサーを使う場合は `..utils.` で参照する:
```python
from ..utils.atom_selection_parser import AtomSelector
from ..utils.parse_top import GromacsTopologyParser
```

### 設定 (`src/config.py`)

- `MAXWARN`: grompp の最大警告数
- `GAUSSIAN_CMD`, `STRUCTURE_OPTIMIZATION`, `SINGLE_POINT_CALCULATION`: Gaussian設定
- 各水モデル(TIP3P/TIP4P/TIP5P/OPC)の密度・体積定数
- 起動時に `.pixi/envs/default/bin` をPATHに追加する

## 環境管理

- パッケージ管理: `pixi`(conda + pip の混在)
- Python: 3.10固定
- `pixi.lock` で再現性を保証
- Docker対応: `Dockerfile` でコンテナビルドも可能
2 changes: 2 additions & 0 deletions TODO.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# TODO

26 changes: 26 additions & 0 deletions example/build/all_atom/protein.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,30 @@
#!/bin/bash
set -e

input_structure="input.pdb"

mdtbx addh -s ${input_structure} -o input_h

mdtbx addace -s input_h.pdb -o ace

mdtbx addnme -s ace.pdb -o ace_nme

mdtbx find_bond -s ace_nme.pdb -o bonds.txt -op cym.pdb

# SS-bond有無で入力PDBとpostcmdを切り替え
if [ -s bonds.txt ]; then
input_pdb="cym.pdb"
mdtbx build_vacuum \
-i ${input_pdb} \
-o ./ \
--addpostcmd "$(cat bonds.txt)"
else
input_pdb="ace_nme.pdb"
mdtbx build_vacuum \
-i ${input_pdb} \
-o ./
fi

rm -f input_h.pdb ace.pdb ace_nme.pdb cym.pdb bonds.txt

echo done
54 changes: 54 additions & 0 deletions example/build/all_atom/protein_water.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,58 @@
#!/bin/bash
set -e

input_structure="input.pdb"
out_dir="${PWD}/gmx"

mdtbx addh -s ${input_structure} -o input_h

mdtbx addace -s input_h.pdb -o ace

mdtbx addnme -s ace.pdb -o ace_nme

mdtbx find_bond -s ace_nme.pdb -o bonds.txt -op cym.pdb

# SS-bond有無で入力PDBとpostcmdを切り替え
if [ -s bonds.txt ]; then
input_pdb="cym.pdb"
mdtbx build_solution \
-i ${input_pdb} \
-o ./ \
--ion_conc 0.15 \
--cation Na+ \
--anion Cl- \
--boxsize 100 100 100 \
--addpostcmd "$(cat bonds.txt)"
else
input_pdb="ace_nme.pdb"
mdtbx build_solution \
-i ${input_pdb} \
-o ./ \
--ion_conc 0.15 \
--cation Na+ \
--anion Cl- \
--boxsize 100 100 100
fi

mdtbx amb2gro -p leap.parm7 -x leap.rst7 --type parmed

mdtbx add_ndx -g gmx.gro

mdtbx centering_gro -f gmx.gro -p gmx.top -c Protein

mdtbx gen_posres -p gmx.top -s "protein and backbone" -o posres

mdtbx rmfile

mkdir ${out_dir}
mv gmx.gro ${out_dir}/
mv gmx.top ${out_dir}/
mv *itp ${out_dir}/
mv *.ndx ${out_dir}/
cp mdps/*.mdp ${out_dir}/
cp mdrun_slurm.sh ${out_dir}/

rm -f leap.parm7 leap.rst7 leap.pdb gmx.pdb
rm -f input_h.pdb ace.pdb ace_nme.pdb cym.pdb bonds.txt

echo done
62 changes: 62 additions & 0 deletions example/build/all_atom/protein_water_ligand_membrane_glycan.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,66 @@
#!/bin/bash
set -e

# グリカンがタンパク質と同一PDBに含まれている前提
input_structure="prot_lig.pdb"
out_dir="${PWD}/gmx"
lig_frcmod="./LIG.frcmod"
lig_lib="./LIG.lib"

mdtbx addh -s ${input_structure} -o input_h

mdtbx addace -s input_h.pdb -o ace

mdtbx addnme -s ace.pdb -o ace_nme

mdtbx find_bond -s ace_nme.pdb -o bonds.txt -op cym.pdb

# SS-bond有無で入力PDBを切り替え
if [ -s bonds.txt ]; then
input_pdb="cym.pdb"
else
input_pdb="ace_nme.pdb"
fi

# --keepligs でグリカン座標を保持、--gaff2 は使わずGLYCAM06-jをtleapでロード
mdtbx cmd packmol-memgen \
--pdb ${input_pdb} \
--lipids POPC:CHL1 \
--ratio 4:1 \
--salt \
--salt_c Na+ \
--salt_a Cl- \
--saltcon 0.15 \
--keepligs \
--notprotonate \
--dims 120 120 200 \
--ffwat tip3p \
--ffprot ff14SB \
--fflip lipid21 \
--ligand_param ${lig_frcmod}:${lig_lib} \
--leapline "source leaprc.GLYCAM_06j-1"

mdtbx amb2gro -p bilayer_${input_pdb%.pdb}_lipid.top -x bilayer_${input_pdb%.pdb}_lipid.crd --type parmed

mdtbx add_ndx -g gmx.gro

mdtbx centering_gro -f gmx.gro -p gmx.top -c Protein

mdtbx gen_posres -p gmx.top -s "protein and backbone" -o posres

mdtbx rmfile

mkdir ${out_dir}
mv gmx.gro ${out_dir}/
mv gmx.top ${out_dir}/
mv *itp ${out_dir}/
mv *.ndx ${out_dir}/
cp mdps/*.mdp ${out_dir}/
cp mdrun_slurm.sh ${out_dir}/

rm -f input_h.pdb ace.pdb ace_nme.pdb cym.pdb bonds.txt \
bilayer_*.pdb bilayer_*.pdb_FORCED bilayer_*.crd bilayer_*.top \
*in_EMBED.pdb *in_memembed.log \
leap_.log packmol-memgen.log packmol.inp packmol.log gmx.pdb

echo done
Loading