or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

analysis-tools.mdauxiliary-data.mdconverters.mdcoordinate-transformations.mdcore-functionality.mdindex.mdio-formats.mdselection-language.mdtopology-handling.mdunits-utilities.md

analysis-tools.mddocs/

0

# Analysis Tools

1

2

MDAnalysis provides a comprehensive suite of analysis tools for studying molecular dynamics trajectories. These tools follow a consistent interface based on the `AnalysisBase` class and provide standardized results storage.

3

4

## Analysis Framework

5

6

### AnalysisBase Class

7

8

All analysis classes inherit from `AnalysisBase`, providing a consistent workflow:

9

10

```python { .api }

11

from MDAnalysis.analysis.base import AnalysisBase

12

13

class AnalysisBase:

14

"""

15

Base class for trajectory analysis with standardized workflow.

16

17

Provides common functionality for frame iteration, progress reporting,

18

and results storage.

19

"""

20

21

def __init__(self, trajectory, verbose=False, **kwargs):

22

"""

23

Initialize analysis base.

24

25

Parameters

26

----------

27

trajectory : Universe or AtomGroup

28

MDAnalysis Universe or AtomGroup with trajectory information.

29

verbose : bool, optional

30

Whether to show progress bar during analysis (default False).

31

**kwargs

32

Additional arguments for specific analysis.

33

"""

34

35

def run(self, start=None, stop=None, step=None, frames=None, verbose=None):

36

"""

37

Execute the analysis over specified trajectory frames.

38

39

Parameters

40

----------

41

start : int, optional

42

First frame to analyze (default None for beginning).

43

stop : int, optional

44

Last frame to analyze (default None for end).

45

step : int, optional

46

Step size for frame iteration (default None for 1).

47

frames : array-like, optional

48

Specific frame indices to analyze.

49

verbose : bool, optional

50

Override verbose setting for this run.

51

52

Returns

53

-------

54

self

55

Returns self to allow method chaining.

56

57

Examples

58

--------

59

>>> analysis = SomeAnalysis(u, selection1, selection2)

60

>>> analysis.run(start=100, stop=500, step=10)

61

>>> results = analysis.results

62

"""

63

64

def _prepare(self):

65

"""

66

Prepare analysis before trajectory iteration.

67

68

Override in subclasses to initialize data structures

69

and validate input parameters.

70

"""

71

72

def _single_frame(self):

73

"""

74

Analyze a single trajectory frame.

75

76

Override in subclasses to implement per-frame calculations.

77

This method is called for each frame during run().

78

"""

79

80

def _conclude(self):

81

"""

82

Finalize analysis after trajectory iteration.

83

84

Override in subclasses to perform post-processing

85

and populate final results.

86

"""

87

88

# Standard usage pattern

89

analysis = SomeAnalysis(universe, parameters...)

90

analysis.run()

91

results = analysis.results

92

```

93

94

### Results Storage

95

96

```python { .api }

97

from MDAnalysis.analysis.results import Results

98

99

class Results:

100

"""

101

Container for analysis results with attribute access.

102

103

Provides dictionary-like access to results with additional

104

functionality for data management.

105

"""

106

107

def __init__(self, *args, **kwargs):

108

"""

109

Create results container.

110

111

Parameters can be provided as dictionaries or keyword arguments.

112

"""

113

114

def __getattr__(self, name):

115

"""

116

Access results as attributes.

117

118

Examples

119

--------

120

>>> results.rmsd # Access RMSD array

121

>>> results.times # Access time points

122

"""

123

124

def __setattr__(self, name, value):

125

"""

126

Set result values as attributes.

127

"""

128

129

def __contains__(self, name):

130

"""

131

Check if result exists.

132

"""

133

```

134

135

## Structural Analysis

136

137

### Alignment and RMSD

138

139

```python { .api }

140

from MDAnalysis.analysis import align, rms

141

142

# Structural alignment

143

def alignto(mobile, reference, select="all", weights=None, subsetA=None,

144

subsetB=None, **kwargs):

145

"""

146

Align mobile AtomGroup to reference AtomGroup.

147

148

Parameters

149

----------

150

mobile : Universe or AtomGroup

151

Structure to be aligned (modified in place).

152

reference : Universe or AtomGroup

153

Reference structure for alignment.

154

select : str, optional

155

Selection string for atoms to use in alignment (default "all").

156

weights : str or array-like, optional

157

Weights for alignment fitting. Can be "mass" or array of weights.

158

subsetA : AtomGroup, optional

159

Specific atoms from mobile to use for fitting.

160

subsetB : AtomGroup, optional

161

Specific atoms from reference to use for fitting.

162

**kwargs

163

Additional arguments for fitting algorithm.

164

165

Returns

166

-------

167

dict

168

Dictionary containing transformation matrix and RMSD.

169

170

Examples

171

--------

172

>>> # Align protein backbone

173

>>> align.alignto(mobile_u, reference_u, select="backbone")

174

175

>>> # Mass-weighted alignment

176

>>> align.alignto(mobile_u, reference_u, select="name CA", weights="mass")

177

"""

178

179

class AlignTraj:

180

"""

181

Align trajectory to reference structure.

182

183

Performs structural alignment of each trajectory frame to a reference,

184

optionally writing aligned trajectory to file.

185

"""

186

187

def __init__(self, mobile, reference, select="all", filename=None,

188

weights=None, **kwargs):

189

"""

190

Initialize trajectory alignment.

191

192

Parameters

193

----------

194

mobile : Universe

195

Universe with trajectory to align.

196

reference : Universe or AtomGroup

197

Reference structure for alignment.

198

select : str, optional

199

Selection for alignment atoms (default "all").

200

filename : str, optional

201

Output file for aligned trajectory.

202

weights : str or array-like, optional

203

Weights for alignment ("mass" or custom weights).

204

**kwargs

205

Additional parameters.

206

207

Examples

208

--------

209

>>> aligner = align.AlignTraj(u, reference, select="backbone",

210

... filename="aligned.xtc")

211

>>> aligner.run()

212

"""

213

214

class RMSD:

215

"""

216

Calculate RMSD between trajectory and reference structure.

217

"""

218

219

def __init__(self, atomgroup, reference=None, select="all",

220

groupselections=None, **kwargs):

221

"""

222

Initialize RMSD calculation.

223

224

Parameters

225

----------

226

atomgroup : AtomGroup or Universe

227

Atoms for RMSD calculation.

228

reference : AtomGroup or Universe, optional

229

Reference structure (default first frame).

230

select : str, optional

231

Selection string for RMSD atoms (default "all").

232

groupselections : list, optional

233

List of selection strings for multiple group RMSD.

234

**kwargs

235

Additional parameters including mass weighting options.

236

237

Examples

238

--------

239

>>> R = rms.RMSD(u, select="backbone")

240

>>> R.run()

241

>>> rmsd_data = R.results.rmsd # Shape: (n_frames, 3) [frame, time, RMSD]

242

243

>>> # Multiple group RMSD

244

>>> R = rms.RMSD(u, groupselections=["backbone", "sidechain"])

245

>>> R.run()

246

>>> backbone_rmsd = R.results.rmsd[:, 2] # Backbone RMSD values

247

"""

248

249

@property

250

def results(self):

251

"""

252

RMSD results after running analysis.

253

254

Returns

255

-------

256

Results

257

Results object with rmsd attribute containing array of

258

shape (n_frames, 3 + n_groups) with columns:

259

[frame, time, rmsd_total, rmsd_group1, rmsd_group2, ...]

260

"""

261

```

262

263

### Root Mean Square Fluctuation

264

265

```python { .api }

266

class RMSF:

267

"""

268

Calculate root mean square fluctuation (RMSF) of atoms.

269

270

RMSF measures atomic positional fluctuations around average positions.

271

"""

272

273

def __init__(self, atomgroup, **kwargs):

274

"""

275

Initialize RMSF calculation.

276

277

Parameters

278

----------

279

atomgroup : AtomGroup

280

Atoms for RMSF calculation.

281

**kwargs

282

Additional parameters for analysis setup.

283

284

Examples

285

--------

286

>>> ca_atoms = u.select_atoms("name CA")

287

>>> rmsf_analysis = rms.RMSF(ca_atoms)

288

>>> rmsf_analysis.run()

289

>>> rmsf_values = rmsf_analysis.results.rmsf

290

"""

291

292

@property

293

def results(self):

294

"""

295

RMSF results after running analysis.

296

297

Returns

298

-------

299

Results

300

Results object with rmsf attribute containing per-atom

301

RMSF values in Angstrom units.

302

"""

303

```

304

305

## Distance Analysis

306

307

### Distance Calculations

308

309

```python { .api }

310

from MDAnalysis.analysis import distances

311

312

def distance_array(reference, configuration, box=None, result=None, backend="serial"):

313

"""

314

Calculate distance array between two coordinate sets.

315

316

Parameters

317

----------

318

reference : array-like

319

Reference coordinates of shape (n, 3).

320

configuration : array-like

321

Configuration coordinates of shape (m, 3).

322

box : array-like, optional

323

Unit cell dimensions for periodic boundary conditions.

324

result : numpy.ndarray, optional

325

Pre-allocated result array of shape (n, m).

326

backend : str, optional

327

Computation backend ("serial" or "OpenMP").

328

329

Returns

330

-------

331

numpy.ndarray

332

Distance array of shape (n, m) containing all pairwise distances.

333

334

Examples

335

--------

336

>>> protein_pos = protein.positions

337

>>> water_pos = waters.positions

338

>>> dist_array = distances.distance_array(protein_pos, water_pos,

339

... box=u.dimensions)

340

"""

341

342

def self_distance_array(reference, box=None, result=None, backend="serial"):

343

"""

344

Calculate self-distance array (all pairwise distances within one set).

345

346

Parameters

347

----------

348

reference : array-like

349

Coordinates of shape (n, 3).

350

box : array-like, optional

351

Unit cell dimensions for periodic boundary conditions.

352

result : numpy.ndarray, optional

353

Pre-allocated result array of shape (n, n).

354

backend : str, optional

355

Computation backend ("serial" or "OpenMP").

356

357

Returns

358

-------

359

numpy.ndarray

360

Symmetric distance matrix of shape (n, n).

361

362

Examples

363

--------

364

>>> ca_positions = ca_atoms.positions

365

>>> ca_distances = distances.self_distance_array(ca_positions,

366

... box=u.dimensions)

367

"""

368

369

def contact_matrix(coordinates, cutoff=8.0, returntype="numpy", box=None):

370

"""

371

Calculate contact matrix based on distance cutoff.

372

373

Parameters

374

----------

375

coordinates : array-like

376

Atomic coordinates of shape (n, 3).

377

cutoff : float, optional

378

Distance cutoff for contacts in Angstrom (default 8.0).

379

returntype : str, optional

380

Return type ("numpy" for dense array, "sparse" for sparse matrix).

381

box : array-like, optional

382

Unit cell dimensions.

383

384

Returns

385

-------

386

numpy.ndarray or sparse matrix

387

Contact matrix where 1 indicates contact, 0 indicates no contact.

388

389

Examples

390

--------

391

>>> contacts = distances.contact_matrix(protein.positions, cutoff=6.0)

392

>>> contact_count = np.sum(contacts)

393

"""

394

395

class InterRDF:

396

"""

397

Calculate intermolecular radial distribution function (RDF).

398

399

Computes g(r) between two atom groups, measuring probability of

400

finding atoms at distance r.

401

"""

402

403

def __init__(self, g1, g2, nbins=75, range=(0.0, 15.0), norm="rdf",

404

exclusion_block=None, **kwargs):

405

"""

406

Initialize RDF calculation.

407

408

Parameters

409

----------

410

g1 : AtomGroup

411

First atom group.

412

g2 : AtomGroup

413

Second atom group.

414

nbins : int, optional

415

Number of histogram bins (default 75).

416

range : tuple, optional

417

Distance range for RDF as (min, max) in Angstrom (default (0, 15)).

418

norm : str, optional

419

Normalization method ("rdf" or "density").

420

exclusion_block : tuple, optional

421

Exclude distances between atoms (n, m) apart in topology.

422

**kwargs

423

Additional parameters.

424

425

Examples

426

--------

427

>>> water_O = u.select_atoms("name OH2")

428

>>> protein = u.select_atoms("protein")

429

>>> rdf = distances.InterRDF(water_O, protein, range=(0, 10))

430

>>> rdf.run()

431

>>> r = rdf.results.bins # Distance bins

432

>>> gr = rdf.results.rdf # RDF values

433

"""

434

435

@property

436

def results(self):

437

"""

438

RDF results after running analysis.

439

440

Returns

441

-------

442

Results

443

Results object with:

444

- bins: distance bin centers

445

- rdf: radial distribution function g(r)

446

- count: raw histogram counts

447

"""

448

```

449

450

### Contact Analysis

451

452

```python { .api }

453

from MDAnalysis.analysis import contacts

454

455

class Contacts:

456

"""

457

Calculate contacts between two atom groups over trajectory.

458

459

Monitors formation and breaking of contacts based on distance cutoff.

460

"""

461

462

def __init__(self, selection_one, selection_two, radius=4.5,

463

method="hard_cut", **kwargs):

464

"""

465

Initialize contact analysis.

466

467

Parameters

468

----------

469

selection_one : AtomGroup

470

First group of atoms.

471

selection_two : AtomGroup

472

Second group of atoms.

473

radius : float, optional

474

Contact distance cutoff in Angstrom (default 4.5).

475

method : str, optional

476

Contact detection method ("hard_cut" or "soft_cut").

477

**kwargs

478

Additional parameters for contact detection.

479

480

Examples

481

--------

482

>>> protein = u.select_atoms("protein")

483

>>> ligand = u.select_atoms("resname LIG")

484

>>> contacts_analysis = contacts.Contacts(protein, ligand, radius=3.5)

485

>>> contacts_analysis.run()

486

>>> contact_matrix = contacts_analysis.results.contact_matrix

487

"""

488

489

@property

490

def results(self):

491

"""

492

Contact analysis results.

493

494

Returns

495

-------

496

Results

497

Results object with:

498

- contact_matrix: binary matrix indicating contacts per frame

499

- timeseries: contact time series data

500

"""

501

```

502

503

## Hydrogen Bond Analysis

504

505

### Modern Hydrogen Bond Analysis

506

507

```python { .api }

508

from MDAnalysis.analysis.hydrogenbonds import HydrogenBondAnalysis

509

510

class HydrogenBondAnalysis:

511

"""

512

Analyze hydrogen bonds in molecular dynamics trajectories.

513

514

Identifies hydrogen bonds based on geometric criteria and tracks

515

their formation/breaking over time.

516

"""

517

518

def __init__(self, universe, donors_sel=None, hydrogens_sel=None,

519

acceptors_sel=None, d_h_cutoff=1.2, d_a_cutoff=3.0,

520

d_h_a_angle_cutoff=150, **kwargs):

521

"""

522

Initialize hydrogen bond analysis.

523

524

Parameters

525

----------

526

universe : Universe

527

MDAnalysis Universe object.

528

donors_sel : str, optional

529

Selection string for hydrogen bond donor atoms.

530

hydrogens_sel : str, optional

531

Selection string for hydrogen atoms.

532

acceptors_sel : str, optional

533

Selection string for hydrogen bond acceptor atoms.

534

d_h_cutoff : float, optional

535

Maximum donor-hydrogen distance in Angstrom (default 1.2).

536

d_a_cutoff : float, optional

537

Maximum donor-acceptor distance in Angstrom (default 3.0).

538

d_h_a_angle_cutoff : float, optional

539

Minimum donor-hydrogen-acceptor angle in degrees (default 150).

540

**kwargs

541

Additional parameters.

542

543

Examples

544

--------

545

>>> # Analyze protein-water hydrogen bonds

546

>>> hbond_analysis = HydrogenBondAnalysis(

547

... universe=u,

548

... donors_sel="protein",

549

... acceptors_sel="resname SOL"

550

... )

551

>>> hbond_analysis.run()

552

>>> hbond_data = hbond_analysis.results.hbonds

553

"""

554

555

def guess_donors(self, selection="protein", max_missing=1):

556

"""

557

Automatically identify hydrogen bond donors.

558

559

Parameters

560

----------

561

selection : str, optional

562

Selection string for donor search (default "protein").

563

max_missing : int, optional

564

Maximum missing hydrogen atoms per donor (default 1).

565

566

Returns

567

-------

568

str

569

Selection string for identified donors.

570

"""

571

572

def guess_acceptors(self, selection="protein"):

573

"""

574

Automatically identify hydrogen bond acceptors.

575

576

Parameters

577

----------

578

selection : str, optional

579

Selection string for acceptor search (default "protein").

580

581

Returns

582

-------

583

str

584

Selection string for identified acceptors.

585

"""

586

587

@property

588

def results(self):

589

"""

590

Hydrogen bond analysis results.

591

592

Returns

593

-------

594

Results

595

Results object with:

596

- hbonds: array of hydrogen bond data per frame

597

- pairs: unique donor-acceptor pairs

598

- times: time points for each frame

599

"""

600

601

class WaterBridgeAnalysis:

602

"""

603

Analyze water-mediated hydrogen bonds between two selections.

604

605

Identifies hydrogen bonds where water molecules bridge interactions

606

between two molecular groups.

607

"""

608

609

def __init__(self, universe, selection1, selection2, water_selection="resname SOL",

610

order=1, **kwargs):

611

"""

612

Initialize water bridge analysis.

613

614

Parameters

615

----------

616

universe : Universe

617

MDAnalysis Universe object.

618

selection1 : str

619

First selection (e.g., "protein").

620

selection2 : str

621

Second selection (e.g., "resname LIG").

622

water_selection : str, optional

623

Selection for water molecules (default "resname SOL").

624

order : int, optional

625

Maximum number of water molecules in bridge (default 1).

626

**kwargs

627

Additional hydrogen bond criteria.

628

629

Examples

630

--------

631

>>> wb_analysis = WaterBridgeAnalysis(

632

... universe=u,

633

... selection1="protein",

634

... selection2="resname LIG",

635

... order=2 # Up to 2 water molecules

636

... )

637

>>> wb_analysis.run()

638

>>> bridges = wb_analysis.results.water_bridges

639

"""

640

```

641

642

## Principal Component Analysis

643

644

```python { .api }

645

from MDAnalysis.analysis import pca

646

647

class PCA:

648

"""

649

Principal Component Analysis of atomic coordinate fluctuations.

650

651

Performs PCA on coordinate data to identify principal modes of motion.

652

"""

653

654

def __init__(self, universe, select="all", align=False, mean=None,

655

n_components=None, **kwargs):

656

"""

657

Initialize PCA calculation.

658

659

Parameters

660

----------

661

universe : Universe or AtomGroup

662

System for PCA analysis.

663

select : str, optional

664

Selection string for atoms (default "all").

665

align : bool, optional

666

Whether to align structures before PCA (default False).

667

mean : array-like, optional

668

Pre-computed mean structure for centering.

669

n_components : int, optional

670

Number of principal components to compute.

671

**kwargs

672

Additional parameters.

673

674

Examples

675

--------

676

>>> # PCA of backbone motion

677

>>> pca_analysis = pca.PCA(u, select="backbone", align=True)

678

>>> pca_analysis.run()

679

>>> eigenvalues = pca_analysis.results.variance

680

>>> eigenvectors = pca_analysis.results.p_components

681

"""

682

683

def transform(self, atomgroup, n_components=None):

684

"""

685

Project coordinates onto principal components.

686

687

Parameters

688

----------

689

atomgroup : AtomGroup

690

Atoms to project (must match PCA selection).

691

n_components : int, optional

692

Number of components for projection.

693

694

Returns

695

-------

696

numpy.ndarray

697

Projected coordinates in PC space.

698

"""

699

700

@property

701

def results(self):

702

"""

703

PCA analysis results.

704

705

Returns

706

-------

707

Results

708

Results object with:

709

- variance: eigenvalues (variance explained by each PC)

710

- p_components: principal component vectors

711

- variance_ratio: fraction of variance explained

712

"""

713

```

714

715

## Specialized Analysis Tools

716

717

### Membrane Analysis

718

719

```python { .api }

720

from MDAnalysis.analysis import leaflet

721

722

class LeafletFinder:

723

"""

724

Identify membrane leaflets in lipid bilayer systems.

725

726

Uses phosphate positions and connectivity to determine upper

727

and lower leaflets of lipid bilayers.

728

"""

729

730

def __init__(self, universe, select="name P*", cutoff=15.0, pbc=True):

731

"""

732

Initialize leaflet identification.

733

734

Parameters

735

----------

736

universe : Universe

737

Universe containing membrane system.

738

select : str, optional

739

Selection for phosphate atoms (default "name P*").

740

cutoff : float, optional

741

Distance cutoff for leaflet assignment (default 15.0).

742

pbc : bool, optional

743

Whether to use periodic boundary conditions (default True).

744

745

Examples

746

--------

747

>>> leaflets = leaflet.LeafletFinder(u, select="name P", cutoff=12.0)

748

>>> upper_leaflet = leaflets.groups(0)

749

>>> lower_leaflet = leaflets.groups(1)

750

"""

751

752

def groups(self, leaflet_id=None):

753

"""

754

Get atoms belonging to specified leaflet.

755

756

Parameters

757

----------

758

leaflet_id : int, optional

759

Leaflet identifier. If None, returns list of all leaflets.

760

761

Returns

762

-------

763

AtomGroup or list

764

Atoms in specified leaflet or list of leaflet AtomGroups.

765

"""

766

```

767

768

### Polymer Analysis

769

770

```python { .api }

771

from MDAnalysis.analysis import polymer

772

773

class PersistenceLength:

774

"""

775

Calculate persistence length of polymer chains.

776

777

Measures the characteristic length scale over which chain

778

correlations decay exponentially.

779

"""

780

781

def __init__(self, atomgroups, **kwargs):

782

"""

783

Initialize persistence length calculation.

784

785

Parameters

786

----------

787

atomgroups : list of AtomGroup

788

List of AtomGroups representing polymer backbone atoms.

789

**kwargs

790

Additional parameters for calculation.

791

792

Examples

793

--------

794

>>> # DNA backbone analysis

795

>>> backbone_atoms = [u.select_atoms(f"segid {seg} and name P")

796

... for seg in ["DNA1", "DNA2"]]

797

>>> lp_analysis = polymer.PersistenceLength(backbone_atoms)

798

>>> lp_analysis.run()

799

>>> persistence_length = lp_analysis.results.lp

800

"""

801

```

802

803

### Mean Squared Displacement

804

805

```python { .api }

806

from MDAnalysis.analysis import msd

807

808

class MeanSquaredDisplacement:

809

"""

810

Calculate mean squared displacement for diffusion analysis.

811

812

Computes MSD as a function of lag time to analyze diffusive motion.

813

"""

814

815

def __init__(self, universe, select="all", msd_type="xyz", fft=True, **kwargs):

816

"""

817

Initialize MSD calculation.

818

819

Parameters

820

----------

821

universe : Universe

822

Universe with trajectory for MSD analysis.

823

select : str, optional

824

Selection string for atoms (default "all").

825

msd_type : str, optional

826

Type of MSD calculation ("xyz", "xy", "yz", "xz", "x", "y", "z").

827

fft : bool, optional

828

Whether to use FFT-based algorithm for efficiency (default True).

829

**kwargs

830

Additional parameters.

831

832

Examples

833

--------

834

>>> # Water diffusion analysis

835

>>> water_O = u.select_atoms("name OH2")

836

>>> msd_analysis = msd.MeanSquaredDisplacement(u, select="name OH2")

837

>>> msd_analysis.run()

838

>>> msd_data = msd_analysis.results.msd

839

>>> lag_times = msd_analysis.results.lagtimes

840

"""

841

842

@property

843

def results(self):

844

"""

845

MSD analysis results.

846

847

Returns

848

-------

849

Results

850

Results object with:

851

- msd: mean squared displacement values

852

- lagtimes: lag time values

853

"""

854

```

855

856

## Usage Patterns

857

858

### Analysis Workflow

859

860

```python { .api }

861

# Standard analysis workflow

862

def analyze_trajectory(universe, output_prefix="analysis"):

863

"""

864

Comprehensive trajectory analysis example.

865

"""

866

# Structural analysis

867

protein = universe.select_atoms("protein")

868

869

# RMSD analysis

870

rmsd_analysis = rms.RMSD(protein, select="backbone")

871

rmsd_analysis.run()

872

873

# RMSF analysis

874

ca_atoms = protein.select_atoms("name CA")

875

rmsf_analysis = rms.RMSF(ca_atoms)

876

rmsf_analysis.run()

877

878

# Hydrogen bond analysis

879

hb_analysis = HydrogenBondAnalysis(universe)

880

hb_analysis.run()

881

882

# Save results

883

np.savetxt(f"{output_prefix}_rmsd.dat", rmsd_analysis.results.rmsd)

884

np.savetxt(f"{output_prefix}_rmsf.dat", rmsf_analysis.results.rmsf)

885

886

return {

887

'rmsd': rmsd_analysis.results,

888

'rmsf': rmsf_analysis.results,

889

'hbonds': hb_analysis.results

890

}

891

892

# Run analysis

893

results = analyze_trajectory(u, "protein_analysis")

894

```

895

896

### Parallel Analysis

897

898

```python { .api }

899

# Parallel analysis using multiprocessing

900

from MDAnalysis.analysis.base import AnalysisFromFunction

901

import multiprocessing as mp

902

903

def frame_analysis(ag):

904

"""Per-frame analysis function."""

905

return {

906

'rgyr': ag.radius_of_gyration(),

907

'com': ag.center_of_mass()

908

}

909

910

# Run in parallel

911

protein = u.select_atoms("protein")

912

parallel_analysis = AnalysisFromFunction(frame_analysis, protein)

913

parallel_analysis.run(n_jobs=mp.cpu_count())

914

915

results = parallel_analysis.results

916

```