MCP HubMCP Hub
SKILL·F062E0

molecular-dynamics

K-Dense-AI
업데이트됨 9 days ago
10 조회
48,722
4,378
48,722
GitHub에서 보기
기타general

정보

이 스킬은 OpenMM을 사용한 분자 동역학 시뮬레이션 실행과 MDAnalysis를 활용한 분석을 가능하게 합니다. 시스템 설정, 힘장 정의, 에너지 최소화, 그리고 궤적 분석(RMSD, RMSF, 접촉 지도)을 처리합니다. 구조 생물학, 약물 결합 연구, 그리고 계산 모델링이 필요한 생물물리학 연구에 사용하세요.

빠른 설치

Claude Code

추천
기본
npx skills add K-Dense-AI/claude-scientific-skills -a claude-code
플러그인 명령대체
/plugin add https://github.com/K-Dense-AI/claude-scientific-skills
Git 클론대체
git clone https://github.com/K-Dense-AI/claude-scientific-skills.git ~/.claude/skills/molecular-dynamics

Claude Code에서 이 명령을 복사하여 붙여넣어 스킬을 설치하세요

문서

Molecular Dynamics

Overview

Molecular dynamics (MD) simulation computationally models the time evolution of molecular systems by integrating Newton's equations of motion. This skill covers two complementary tools:

  • OpenMM (https://openmm.org/): High-performance MD simulation engine with GPU support, Python API, and flexible force field support
  • MDAnalysis (https://mdanalysis.org/): Python library for reading, writing, and analyzing MD trajectories from all major simulation packages

Reviewed versions: OpenMM 8.6.1 and MDAnalysis 2.10.0. Reference-platform smoke checks use small synthetic systems; GPU performance and scientific convergence are not established by them. OpenMM latest API pages identify a development build, so the installed 8.6.1 API is the executable reference.

Installation into a dedicated environment:

uv venv --python 3.12 .venv-md
uv pip install --python .venv-md/bin/python "openmm==8.6.1" "MDAnalysis==2.10.0" matplotlib pandas
# Windows: use .venv-md/Scripts/python.exe instead

When to Use This Skill

Use molecular dynamics when:

  • Protein stability analysis: How does a mutation affect protein dynamics?
  • Drug binding simulations: Characterize binding mode and residence time of a ligand
  • Conformational sampling: Explore protein flexibility and conformational changes
  • Protein-protein interaction: Model interface dynamics and binding energetics
  • RMSD/RMSF analysis: Quantify structural fluctuations from a reference structure
  • Free energy estimation: Compute binding free energy or conformational free energy
  • Membrane simulations: Model proteins in lipid bilayers
  • Intrinsically disordered proteins: Study IDR conformational ensembles

Core Workflow: OpenMM Simulation

Examples require system-specific preparation and validation. Review biological assembly, alternate locations, missing loops, termini, protonation, disulfides, ligands and cofactors before parameterization. An MD trajectory alone does not establish binding free energy or residence time.

The functions below form one Python module: execute their import blocks together. Use a new output prefix for every stage to avoid overwriting earlier results.

1. System Preparation

from openmm.app import *
from openmm import *
from openmm.unit import *

def prepare_system_from_pdb(pdb_file, forcefield_name="amber14-all.xml",
                              water_model="amber14/tip3pfb.xml", ph=7.0):
    """
    Prepare an OpenMM system from a PDB file.

    Args:
        pdb_file: Path to cleaned PDB file (use PDBFixer for raw PDB files)
        forcefield_name: Force field XML file
        water_model: Water model XML file

    Returns:
        modeller, system
    """
    # Load PDB
    pdb = PDBFile(pdb_file)

    # Load force field
    forcefield = ForceField(forcefield_name, water_model)

    # Add hydrogens and solvate
    modeller = Modeller(pdb.topology, pdb.positions)
    modeller.addHydrogens(forcefield, pH=ph)

    # TIP3P geometry also serves TIP3P-FB; XML supplies the parameters.
    # 10 Å padding; added salt excludes neutralizing counterions.
    modeller.addSolvent(
        forcefield,
        model='tip3p',
        padding=10*angstroms,
        ionicStrength=0.15*molar, neutralize=True
    )

    print(f"System: {modeller.topology.getNumAtoms()} atoms, "
          f"{modeller.topology.getNumResidues()} residues")

    # Create system
    system = forcefield.createSystem(
        modeller.topology,
        nonbondedMethod=PME,         # Particle Mesh Ewald for long-range electrostatics
        nonbondedCutoff=1.0*nanometer,
        constraints=HBonds,           # Constrain bonds involving H (not intermolecular H-bonds)
        rigidWater=True,
        ewaldErrorTolerance=0.0005
    )

    return modeller, system

2. Energy Minimization

from openmm.app import *
from openmm import *
from openmm.unit import *

def minimize_energy(modeller, system, output_pdb="minimized.pdb",
                     max_iterations=1000, tolerance=10.0, platform_name=None):
    """
    Energy minimize the system to remove steric clashes.

    Args:
        modeller: Modeller object with topology and positions
        system: OpenMM System
        output_pdb: Path to save minimized structure
        max_iterations: Maximum minimization steps
        tolerance: Convergence criterion in kJ/mol/nm

    Returns:
        simulation object with minimized positions
    """
    # Keep the integrator at 2 fs for the subsequent NVT/NPT examples.
    integrator = LangevinMiddleIntegrator(300*kelvin, 1/picosecond, 0.002*picoseconds)

    # Automatic platform selection, or an explicit tested platform (e.g. CPU).
    # A registered GPU plugin does not prove a working device or driver.
    platform = Platform.getPlatformByName(platform_name) if platform_name else None
    simulation = Simulation(modeller.topology, system, integrator, platform)
    simulation.context.setPositions(modeller.positions)

    # Check initial energy
    state = simulation.context.getState(getEnergy=True)
    print(f"Initial energy: {state.getPotentialEnergy()}")

    # Minimize
    simulation.minimizeEnergy(
        tolerance=tolerance*kilojoules_per_mole/nanometer,
        maxIterations=max_iterations
    )

    state = simulation.context.getState(getEnergy=True, getPositions=True)
    print(f"Minimized energy: {state.getPotentialEnergy()}")

    # Save minimized structure
    with open(output_pdb, 'w') as f:
        PDBFile.writeFile(simulation.topology, state.getPositions(), f)

    return simulation

3. NVT Equilibration

from openmm.app import *
from openmm import *
from openmm.unit import *

def run_nvt_equilibration(simulation, n_steps=50000, temperature=300,
                            report_interval=1000, output_prefix="nvt"):
    """
    NVT equilibration: constant N, V, T.
    Equilibrate velocities to target temperature.

    Args:
        simulation: OpenMM Simulation (after minimization)
        n_steps: Number of MD steps (50000 × 2fs = 100 ps)
        temperature: Temperature in Kelvin
        report_interval: Steps between data reports
        output_prefix: File prefix for trajectory and log
    """
    # This example is unrestrained; add validated restraints before Context creation.
    if any("Barostat" in type(f).__name__ and f.getFrequency() > 0
           for f in simulation.system.getForces()):
        raise ValueError("NVT requires all barostats disabled or absent")

    # Set both the thermostat target and initial velocities.
    simulation.integrator.setTemperature(temperature*kelvin)
    simulation.context.setVelocitiesToTemperature(temperature*kelvin)

    # Add reporters
    simulation.reporters = []

    # Log file
    simulation.reporters.append(
        StateDataReporter(
            f"{output_prefix}_log.txt",
            report_interval,
            step=True,
            potentialEnergy=True,
            kineticEnergy=True,
            temperature=True,
            volume=True,
            speed=True
        )
    )

    # DCD trajectory (compact binary format)
    simulation.reporters.append(
        DCDReporter(f"{output_prefix}_traj.dcd", report_interval)
    )

    duration = (n_steps * simulation.integrator.getStepSize()).value_in_unit(picoseconds)
    print(f"Running NVT equilibration: {n_steps} steps ({duration:.1f} ps)")
    simulation.step(n_steps)
    print("NVT equilibration complete")

    return simulation

4. NPT Equilibration and Production

Call this function first with a dedicated NPT equilibration prefix. Inspect density, energy, structure and replicate stability before a separate production call; the default duration is an example, not an equilibration or convergence criterion.

def run_npt_production(simulation, n_steps=500000, temperature=300, pressure=1.0,
                        report_interval=5000, output_prefix="npt"):
    """
    NPT production run: constant N, P, T.

    Args:
        n_steps: Production steps (500000 × 2fs = 1 ns)
        temperature: Temperature in Kelvin
        pressure: Pressure in bar
        report_interval: Steps between reports
    """
    # Keep the Langevin thermostat and barostat at the same temperature.
    simulation.integrator.setTemperature(temperature*kelvin)
    system = simulation.system
    barostats = [f for f in system.getForces() if "Barostat" in type(f).__name__]
    if not system.usesPeriodicBoundaryConditions():
        raise ValueError("NPT requires a periodic system")
    if not barostats:
        system.addForce(MonteCarloBarostat(pressure*bar, temperature*kelvin, 25))
        simulation.context.reinitialize(preserveState=True)
    elif len(barostats) != 1 or not isinstance(barostats[0], MonteCarloBarostat):
        raise ValueError("This example supports one isotropic MonteCarloBarostat")
    else:
        barostats[0].setDefaultPressure(pressure*bar)
        barostats[0].setDefaultTemperature(temperature*kelvin)
        barostats[0].setFrequency(25)
    # Existing Context parameters must also be updated on repeated calls.
    simulation.context.setParameter(MonteCarloBarostat.Pressure(), pressure)
    simulation.context.setParameter(MonteCarloBarostat.Temperature(), temperature)

    # Update reporters
    simulation.reporters = []
    simulation.reporters.append(
        StateDataReporter(
            f"{output_prefix}_log.txt",
            report_interval,
            step=True,
            potentialEnergy=True,
            temperature=True,
            density=True,
            speed=True
        )
    )
    simulation.reporters.append(
        DCDReporter(f"{output_prefix}_traj.dcd", report_interval)
    )

    # Save checkpoints
    simulation.reporters.append(
        CheckpointReporter(f"{output_prefix}_checkpoint.chk", 50000)
    )

    duration = (n_steps * simulation.integrator.getStepSize()).value_in_unit(nanoseconds)
    print(f"Running NPT stage: {n_steps} steps ({duration:.3f} ns)")
    simulation.step(n_steps)
    simulation.saveCheckpoint(f"{output_prefix}_checkpoint.chk")
    simulation.saveState(f"{output_prefix}_state.xml")
    print("NPT stage complete")
    return simulation

Trajectory Analysis with MDAnalysis

1. Load Trajectory

Use the solvated topology with exactly the DCD atom count and order (e.g. the minimized.pdb above), not the original unsolvated input. MDAnalysis converts lengths to Å and time to ps by default; OpenMM bare coordinates use nm. Preserve frame box vectors and actual timestamps; do not infer time from frame number.

import MDAnalysis as mda
from MDAnalysis.analysis import rms, align, contacts
import numpy as np
import matplotlib.pyplot as plt

def load_trajectory(topology_file, trajectory_file):
    """
    Load an MD trajectory with MDAnalysis.

    Args:
        topology_file: PDB, PSF, or other topology file
        trajectory_file: DCD, XTC, TRR, or other trajectory
    """
    u = mda.Universe(topology_file, trajectory_file)
    print(f"Universe: {u.atoms.n_atoms} atoms, {u.trajectory.n_frames} frames")
    first, last = u.trajectory[0].time, u.trajectory[-1].time
    print(f"Time range: {first:g} to {last:g} ps")
    u.trajectory[0]
    return u

2. RMSD Analysis

def compute_rmsd(u, selection="backbone", reference_frame=0):
    """
    Compute RMSD of selected atoms relative to reference frame.

    Args:
        u: MDAnalysis Universe
        selection: Atom selection string (MDAnalysis syntax)
        reference_frame: Frame index for reference structure

    Returns:
        numpy array with columns [frame index, time in ps, RMSD in Angstroms]
    """
    # RMSD performs its own fit; avoid rotating the stored trajectory here.
    # Make the selected molecule whole before analysis of periodic trajectories.
    R = rms.RMSD(u, select=selection, ref_frame=reference_frame)
    R.run()

    rmsd_data = R.results.rmsd  # columns: frame, time, RMSD
    return rmsd_data

def plot_rmsd(rmsd_data, title="RMSD over time", output_file="rmsd.png"):
    """Plot RMSD over simulation time."""
    fig, ax = plt.subplots(figsize=(10, 4))
    ax.plot(rmsd_data[:, 1] / 1000, rmsd_data[:, 2], 'b-', linewidth=0.5)
    ax.set_xlabel("Time (ns)")
    ax.set_ylabel("RMSD (Å)")
    ax.set_title(title)
    ax.axhline(rmsd_data[:, 2].mean(), color='r', linestyle='--',
               label=f'Mean: {rmsd_data[:, 2].mean():.2f} Å')
    ax.legend()
    plt.tight_layout()
    plt.savefig(output_file, dpi=150)
    return fig

3. RMSF Analysis (Per-Residue Flexibility)

Make molecules whole and align a separate structural-analysis copy before RMSF; RMSF does not align. Do not run periodic contacts on a rotated trajectory whose box was not rotated. See analysis reference for alignment, PCA, DSSP, hydrogen bonds and population-derived free energy.

def compute_rmsf(u, selection="protein and name CA", start_frame=0):
    """
    Compute per-residue RMSF (flexibility).

    Returns:
        residue_keys, rmsf_values; keys are (resindex, segid, resid, resname)
    """
    # Select atoms
    atoms = u.select_atoms(selection)

    if not len(atoms):
        raise ValueError("RMSF selection is empty")
    # A multi-atom selection returns mean atomic RMSF, not COM RMSF.
    R = rms.RMSF(atoms)
    R.run(start=start_frame)

    # Average by residue
    resids = []
    rmsf_per_res = []
    for res in u.select_atoms(selection).residues:
        res_atoms = res.atoms.intersection(atoms)
        if len(res_atoms) > 0:
            resids.append((res.ix, res.segid, res.resid, res.resname))
            # RMSF is indexed within the selected AtomGroup, not the Universe.
            rmsf_per_res.append(R.results.rmsf[atoms.resindices == res.ix].mean())

    return resids, np.array(rmsf_per_res)

4. Protein-Ligand Contacts

def analyze_contacts(u, protein_sel="protein", ligand_sel="resname LIG",
                      radius=4.5, start_frame=0, periodic=True):
    """
    Track protein-ligand contacts over trajectory.

    Args:
        radius: Atom-pair cutoff in Angstroms; any pair defines a residue contact.
        periodic: Require box data and use minimum-image distances.
    Returns sets of (resindex, segid, resid, resname), one per analyzed frame.
    """
    from MDAnalysis.lib.distances import distance_array

    protein = u.select_atoms(protein_sel)
    ligand = u.select_atoms(ligand_sel)

    if not len(protein) or not len(ligand):
        raise ValueError("Protein and ligand selections must both be nonempty")
    if not np.isfinite(radius) or radius <= 0:
        raise ValueError("radius must be finite and positive")
    contact_frames = []
    for ts in u.trajectory[start_frame:]:
        if periodic and (ts.dimensions is None or not np.all(np.isfinite(ts.dimensions))
                         or np.any(ts.dimensions[:3] <= 0)):
            raise ValueError("Periodic contacts require valid frame box dimensions")
        # This includes hydrogen atoms unless the caller selects heavy atoms.
        distances = contacts.contact_matrix(
            distance_array(protein.positions, ligand.positions, box=ts.dimensions if periodic else None),
            radius,
        )
        contact_residues = set()
        for i in range(distances.shape[0]):
            if distances[i].any():
                res = protein[i].residue
                contact_residues.add((res.ix, res.segid, res.resid, res.resname))
        contact_frames.append(contact_residues)

    return contact_frames

Force Fields and Preparation

Choose a validated protein/ligand/water/ion combination for the scientific system. The working example retains AMBER14/TIP3P-FB; it is not a universal recommendation. Current OpenMM also bundles amber19-all.xml (ff19SB, DNA OL21, RNA OL3, lipid21), and charmm36_2024.xml with its own charmm36_2024/water.xml. Generic TIP3P and CHARMM-modified TIP3P are not interchangeable. IDP ensembles are especially sensitive to protein-water balance. Four-site waters need extra particles and a matching Modeller geometry, unlike the three-site example above.

AMBER protein XML does not parameterize arbitrary ligands. Use a reviewed GAFF2 or OpenFF route with explicit stereochemistry, protonation, bond orders, atom mapping and charge method. A ligand-only Interchange is not a protein-ligand system. See preparation reference for conservative PDBFixer and OpenFF examples, installation requirements and current release details.

Validation and Provenance

  • Start with minimization; finite energy does not establish a valid structure.
  • Use staged NVT → NPT equilibration → production. This example has no restraints.
  • A 2 fs step with constrained H-containing bonds is a starting choice. Larger steps/HMR require integrator, stability and observable validation for that system.
  • Use per-frame boxes for periodic distances. Make molecules whole for structural observables using trusted bond topology; unwrapping cannot infer missing bonds.
  • Assess burn-in, autocorrelation, effective samples, replicas and uncertainties. Short stable temperature/density traces do not establish conformational sampling.
  • Save topology/atom order, System/Integrator XML, force-field files/versions, seeds, platform/precision, parameters and analysis selections. Checkpoints are platform/hardware/version specific; XML states are more portable but do not retain all internal random-generator state. Test restarting the actual setup.

Additional Resources

GitHub 저장소

K-Dense-AI/claude-scientific-skills
경로: skills/molecular-dynamics
0
agent-skillsai-scientistbioinformaticschemoinformaticsclaudeclaude-skills
FAQ

자주 묻는 질문

molecular-dynamics Skill이란 무엇인가요?

molecular-dynamics은(는) K-Dense-AI이(가) 만든 Claude Skill입니다. Skill은 Claude가 필요할 때 불러오는 지침과 리소스를 묶어 추가 프롬프트 없이 molecular-dynamics 관련 작업을 수행할 수 있게 합니다.

molecular-dynamics은(는) 어떻게 설치하나요?

이 페이지의 설치 명령을 사용하세요. molecular-dynamics을(를) Claude Code 플러그인으로 추가하거나 저장소를 skills 디렉터리에 복제한 다음 Claude를 다시 시작해 Skill을 불러옵니다.

molecular-dynamics은(는) 어떤 카테고리에 속하나요?

molecular-dynamics은(는) 기타 카테고리에 속합니다.

molecular-dynamics은(는) 무료로 사용할 수 있나요?

네. molecular-dynamics은(는) AIMCP에 등록되어 있으며 무료로 설치할 수 있습니다.

연관 스킬

sports-betting-analyzer
기타

이 Claude Skill은 스프레드, 오버/언더, 프로프 베트를 포함한 스포츠 베팅 시장을 분석합니다. 역사적 추이와 상황별 통계를 검토하여 가치 베트를 발견하고, 교육적 목적으로 실행 가능한 권장 사항이 담긴 구조화된 마크다운 결과를 제공합니다. 개발자는 이 기능을 스포츠 베팅 분석 도구에 활용할 수 있으며, 단순히 엔터테인먼트/교육 목적으로만 설계되었음을 유의해야 합니다.

스킬 보기
llamaguard
기타

LlamaGuard는 폭력 및 혐오 발언 등 6가지 안전 범주에서 LLM 입력과 출력을 조정하기 위한 Meta의 70-80억 파라미터 모델입니다. 94-95% 정확도를 제공하며 vLLM, Hugging Face 또는 Amazon SageMaker를 사용해 배포할 수 있습니다. 이 기술을 사용하여 AI 애플리케이션에 콘텐츠 필터링 및 안전 가드레일을 손쉽게 통합하세요.

스킬 보기
cost-optimization
기타

이 Claude Skill은 리소스 적정화, 태깅 전략, 지출 분석을 통해 개발자들이 클라우드 비용을 최적화할 수 있도록 지원합니다. AWS, Azure, GCP에서 클라우드 비용을 절감하고 비용 거버넌스를 구현하기 위한 프레임워크를 제공합니다. 인프라 비용을 분석하거나, 리소스를 적정화하거나, 예산 제약을 충족해야 할 때 사용하세요.

스킬 보기
quantizing-models-bitsandbytes
기타

이 스킬은 bitsandbytes를 사용하여 LLM을 8비트 또는 4비트 정밀도로 양자화하며, 최소한의 정확도 손실로 50-75%의 메모리 감소를 달성합니다. 제한된 GPU 메모리에서 더 큰 모델을 실행하거나 추론을 가속화하는 데 이상적이며, INT8, NF4, FP4와 같은 형식을 지원합니다. 이 스킬은 HuggingFace Transformers와 통합되어 QLoRA 학습 및 8비트 옵티마이저를 가능하게 합니다.

스킬 보기