adaptivepy-sampling 0.1.1__tar.gz → 0.1.2__tar.gz

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 (43) hide show
  1. adaptivepy_sampling-0.1.2/PKG-INFO +108 -0
  2. adaptivepy_sampling-0.1.2/README.md +88 -0
  3. {adaptivepy_sampling-0.1.1 → adaptivepy_sampling-0.1.2}/adaptivepy/__init__.py +1 -1
  4. {adaptivepy_sampling-0.1.1 → adaptivepy_sampling-0.1.2}/adaptivepy/api.py +3 -4
  5. {adaptivepy_sampling-0.1.1 → adaptivepy_sampling-0.1.2}/adaptivepy/config/schema.py +1 -1
  6. {adaptivepy_sampling-0.1.1 → adaptivepy_sampling-0.1.2}/adaptivepy/io/__init__.py +4 -0
  7. {adaptivepy_sampling-0.1.1 → adaptivepy_sampling-0.1.2}/adaptivepy/io/loader.py +68 -9
  8. adaptivepy_sampling-0.1.2/adaptivepy_sampling.egg-info/PKG-INFO +108 -0
  9. {adaptivepy_sampling-0.1.1 → adaptivepy_sampling-0.1.2}/adaptivepy_sampling.egg-info/requires.txt +4 -0
  10. {adaptivepy_sampling-0.1.1 → adaptivepy_sampling-0.1.2}/pyproject.toml +5 -1
  11. {adaptivepy_sampling-0.1.1 → adaptivepy_sampling-0.1.2}/tests/test_adaptivepy.py +18 -0
  12. adaptivepy_sampling-0.1.1/PKG-INFO +0 -52
  13. adaptivepy_sampling-0.1.1/README.md +0 -35
  14. adaptivepy_sampling-0.1.1/adaptivepy_sampling.egg-info/PKG-INFO +0 -52
  15. {adaptivepy_sampling-0.1.1 → adaptivepy_sampling-0.1.2}/adaptivepy/cli/__init__.py +0 -0
  16. {adaptivepy_sampling-0.1.1 → adaptivepy_sampling-0.1.2}/adaptivepy/cli/run.py +0 -0
  17. {adaptivepy_sampling-0.1.1 → adaptivepy_sampling-0.1.2}/adaptivepy/clustering/__init__.py +0 -0
  18. {adaptivepy_sampling-0.1.1 → adaptivepy_sampling-0.1.2}/adaptivepy/clustering/base.py +0 -0
  19. {adaptivepy_sampling-0.1.1 → adaptivepy_sampling-0.1.2}/adaptivepy/clustering/regular_space.py +0 -0
  20. {adaptivepy_sampling-0.1.1 → adaptivepy_sampling-0.1.2}/adaptivepy/clustering/sklearn_kmeans.py +0 -0
  21. {adaptivepy_sampling-0.1.1 → adaptivepy_sampling-0.1.2}/adaptivepy/clustering/sklearn_minibatch.py +0 -0
  22. {adaptivepy_sampling-0.1.1 → adaptivepy_sampling-0.1.2}/adaptivepy/config/__init__.py +0 -0
  23. {adaptivepy_sampling-0.1.1 → adaptivepy_sampling-0.1.2}/adaptivepy/io/trajectory.py +0 -0
  24. {adaptivepy_sampling-0.1.1 → adaptivepy_sampling-0.1.2}/adaptivepy/models.py +0 -0
  25. {adaptivepy_sampling-0.1.1 → adaptivepy_sampling-0.1.2}/adaptivepy/output/__init__.py +0 -0
  26. {adaptivepy_sampling-0.1.1 → adaptivepy_sampling-0.1.2}/adaptivepy/output/pdb_writer.py +0 -0
  27. {adaptivepy_sampling-0.1.1 → adaptivepy_sampling-0.1.2}/adaptivepy/output/writer.py +0 -0
  28. {adaptivepy_sampling-0.1.1 → adaptivepy_sampling-0.1.2}/adaptivepy/policies/__init__.py +0 -0
  29. {adaptivepy_sampling-0.1.1 → adaptivepy_sampling-0.1.2}/adaptivepy/policies/base.py +0 -0
  30. {adaptivepy_sampling-0.1.1 → adaptivepy_sampling-0.1.2}/adaptivepy/policies/least_counts.py +0 -0
  31. {adaptivepy_sampling-0.1.1 → adaptivepy_sampling-0.1.2}/adaptivepy/policies/random.py +0 -0
  32. {adaptivepy_sampling-0.1.1 → adaptivepy_sampling-0.1.2}/adaptivepy/selection/__init__.py +0 -0
  33. {adaptivepy_sampling-0.1.1 → adaptivepy_sampling-0.1.2}/adaptivepy/selection/frame_selector.py +0 -0
  34. {adaptivepy_sampling-0.1.1 → adaptivepy_sampling-0.1.2}/adaptivepy/stats/__init__.py +0 -0
  35. {adaptivepy_sampling-0.1.1 → adaptivepy_sampling-0.1.2}/adaptivepy/stats/cluster_stats.py +0 -0
  36. {adaptivepy_sampling-0.1.1 → adaptivepy_sampling-0.1.2}/adaptivepy/utils/__init__.py +0 -0
  37. {adaptivepy_sampling-0.1.1 → adaptivepy_sampling-0.1.2}/adaptivepy/utils/io_utils.py +0 -0
  38. {adaptivepy_sampling-0.1.1 → adaptivepy_sampling-0.1.2}/adaptivepy/utils/logging.py +0 -0
  39. {adaptivepy_sampling-0.1.1 → adaptivepy_sampling-0.1.2}/adaptivepy_sampling.egg-info/SOURCES.txt +0 -0
  40. {adaptivepy_sampling-0.1.1 → adaptivepy_sampling-0.1.2}/adaptivepy_sampling.egg-info/dependency_links.txt +0 -0
  41. {adaptivepy_sampling-0.1.1 → adaptivepy_sampling-0.1.2}/adaptivepy_sampling.egg-info/entry_points.txt +0 -0
  42. {adaptivepy_sampling-0.1.1 → adaptivepy_sampling-0.1.2}/adaptivepy_sampling.egg-info/top_level.txt +0 -0
  43. {adaptivepy_sampling-0.1.1 → adaptivepy_sampling-0.1.2}/setup.cfg +0 -0
@@ -0,0 +1,108 @@
1
+ Metadata-Version: 2.4
2
+ Name: adaptivepy-sampling
3
+ Version: 0.1.2
4
+ Summary: Adaptive sampling on MD trajectories via clustering and policy-driven seed selection
5
+ Author: AdaptivePy Contributors
6
+ License: MIT
7
+ Requires-Python: >=3.9
8
+ Description-Content-Type: text/markdown
9
+ Requires-Dist: numpy>=1.20
10
+ Requires-Dist: scikit-learn>=1.0
11
+ Requires-Dist: pyyaml>=6.0
12
+ Requires-Dist: click>=8.0
13
+ Requires-Dist: joblib>=1.0
14
+ Requires-Dist: mdtraj>=1.9
15
+ Provides-Extra: dev
16
+ Requires-Dist: pytest>=7.0; extra == "dev"
17
+ Provides-Extra: docs
18
+ Requires-Dist: mkdocs-material>=9.0; extra == "docs"
19
+ Requires-Dist: mkdocstrings[python]>=0.24; extra == "docs"
20
+
21
+ # AdaptivePy
22
+
23
+ **Adaptive sampling for molecular dynamics trajectories**
24
+
25
+ Clustering-based state space partitioning and policy-driven seed selection for MD workflows.
26
+
27
+ [![Documentation](https://img.shields.io/badge/docs-GitHub%20Pages-blue?style=for-the-badge)](https://hnadeem2.github.io/AdaptivePy/)
28
+ [![PyPI](https://img.shields.io/badge/PyPI-adaptivepy--sampling-orange?style=for-the-badge)](https://pypi.org/project/adaptivepy-sampling/)
29
+ [![Python](https://img.shields.io/badge/python-3.9+-green?style=for-the-badge)](https://www.python.org/)
30
+
31
+ ---
32
+
33
+ ## Overview
34
+
35
+ AdaptivePy helps you identify under-sampled regions of conformational space and select seed frames for new simulations. It loads per-trajectory feature arrays, clusters frames, applies adaptive policies, and writes reproducible metadata and optional PDB structures.
36
+
37
+ **Full documentation:** [https://hnadeem2.github.io/AdaptivePy/](https://hnadeem2.github.io/AdaptivePy/)
38
+
39
+ | | |
40
+ |---|---|
41
+ | **Input** | Feature arrays (`.npy` / `.pkl`), optional coordinate trajectories |
42
+ | **Clustering** | KMeans, MiniBatch KMeans, regular-space |
43
+ | **Policies** | Least counts, random (extensible) |
44
+ | **Output** | Seeds, cluster assignments, model, logs, optional PDBs |
45
+
46
+ ## Installation
47
+
48
+ ```bash
49
+ pip install adaptivepy-sampling
50
+ ```
51
+
52
+ For development:
53
+
54
+ ```bash
55
+ git clone https://github.com/hnadeem2/AdaptivePy.git
56
+ cd AdaptivePy
57
+ pip install -e ".[dev,docs]"
58
+ ```
59
+
60
+ ## Quick start
61
+
62
+ 1. **Prepare features** — one file per trajectory, shape `(n_frames, n_features)`:
63
+
64
+ ```text
65
+ features/
66
+ ├── traj_0.npy
67
+ └── traj_1.pkl
68
+ ```
69
+
70
+ 2. **Configure** — edit `examples/config.yaml` (or create your own).
71
+
72
+ 3. **Run**:
73
+
74
+ ```bash
75
+ adaptivepy run examples/config.yaml
76
+ ```
77
+
78
+ See the [Getting Started guide](https://hnadeem2.github.io/AdaptivePy/getting-started/) for a complete walkthrough.
79
+
80
+ ## CLI
81
+
82
+ ```bash
83
+ adaptivepy run config.yaml # run adaptive sampling
84
+ adaptivepy validate config.yaml # validate inputs only
85
+ adaptivepy list-policies # list available policies
86
+ ```
87
+
88
+ ## Python API
89
+
90
+ ```python
91
+ from adaptivepy import run_adaptive_sampling
92
+
93
+ results = run_adaptive_sampling("config.yaml")
94
+ ```
95
+
96
+ ## Documentation
97
+
98
+ | Guide | Description |
99
+ |-------|-------------|
100
+ | [Getting Started](https://hnadeem2.github.io/AdaptivePy/getting-started/) | First run in minutes |
101
+ | [Configuration](https://hnadeem2.github.io/AdaptivePy/configuration/) | YAML options and defaults |
102
+ | [Feature Inputs](https://hnadeem2.github.io/AdaptivePy/features/) | File formats and layout |
103
+ | [Policies](https://hnadeem2.github.io/AdaptivePy/policies/) | Seed selection strategies |
104
+ | [API Reference](https://hnadeem2.github.io/AdaptivePy/reference/api/) | Module documentation |
105
+
106
+ ## License
107
+
108
+ MIT
@@ -0,0 +1,88 @@
1
+ # AdaptivePy
2
+
3
+ **Adaptive sampling for molecular dynamics trajectories**
4
+
5
+ Clustering-based state space partitioning and policy-driven seed selection for MD workflows.
6
+
7
+ [![Documentation](https://img.shields.io/badge/docs-GitHub%20Pages-blue?style=for-the-badge)](https://hnadeem2.github.io/AdaptivePy/)
8
+ [![PyPI](https://img.shields.io/badge/PyPI-adaptivepy--sampling-orange?style=for-the-badge)](https://pypi.org/project/adaptivepy-sampling/)
9
+ [![Python](https://img.shields.io/badge/python-3.9+-green?style=for-the-badge)](https://www.python.org/)
10
+
11
+ ---
12
+
13
+ ## Overview
14
+
15
+ AdaptivePy helps you identify under-sampled regions of conformational space and select seed frames for new simulations. It loads per-trajectory feature arrays, clusters frames, applies adaptive policies, and writes reproducible metadata and optional PDB structures.
16
+
17
+ **Full documentation:** [https://hnadeem2.github.io/AdaptivePy/](https://hnadeem2.github.io/AdaptivePy/)
18
+
19
+ | | |
20
+ |---|---|
21
+ | **Input** | Feature arrays (`.npy` / `.pkl`), optional coordinate trajectories |
22
+ | **Clustering** | KMeans, MiniBatch KMeans, regular-space |
23
+ | **Policies** | Least counts, random (extensible) |
24
+ | **Output** | Seeds, cluster assignments, model, logs, optional PDBs |
25
+
26
+ ## Installation
27
+
28
+ ```bash
29
+ pip install adaptivepy-sampling
30
+ ```
31
+
32
+ For development:
33
+
34
+ ```bash
35
+ git clone https://github.com/hnadeem2/AdaptivePy.git
36
+ cd AdaptivePy
37
+ pip install -e ".[dev,docs]"
38
+ ```
39
+
40
+ ## Quick start
41
+
42
+ 1. **Prepare features** — one file per trajectory, shape `(n_frames, n_features)`:
43
+
44
+ ```text
45
+ features/
46
+ ├── traj_0.npy
47
+ └── traj_1.pkl
48
+ ```
49
+
50
+ 2. **Configure** — edit `examples/config.yaml` (or create your own).
51
+
52
+ 3. **Run**:
53
+
54
+ ```bash
55
+ adaptivepy run examples/config.yaml
56
+ ```
57
+
58
+ See the [Getting Started guide](https://hnadeem2.github.io/AdaptivePy/getting-started/) for a complete walkthrough.
59
+
60
+ ## CLI
61
+
62
+ ```bash
63
+ adaptivepy run config.yaml # run adaptive sampling
64
+ adaptivepy validate config.yaml # validate inputs only
65
+ adaptivepy list-policies # list available policies
66
+ ```
67
+
68
+ ## Python API
69
+
70
+ ```python
71
+ from adaptivepy import run_adaptive_sampling
72
+
73
+ results = run_adaptive_sampling("config.yaml")
74
+ ```
75
+
76
+ ## Documentation
77
+
78
+ | Guide | Description |
79
+ |-------|-------------|
80
+ | [Getting Started](https://hnadeem2.github.io/AdaptivePy/getting-started/) | First run in minutes |
81
+ | [Configuration](https://hnadeem2.github.io/AdaptivePy/configuration/) | YAML options and defaults |
82
+ | [Feature Inputs](https://hnadeem2.github.io/AdaptivePy/features/) | File formats and layout |
83
+ | [Policies](https://hnadeem2.github.io/AdaptivePy/policies/) | Seed selection strategies |
84
+ | [API Reference](https://hnadeem2.github.io/AdaptivePy/reference/api/) | Module documentation |
85
+
86
+ ## License
87
+
88
+ MIT
@@ -1,6 +1,6 @@
1
1
  """AdaptivePy: adaptive sampling for molecular dynamics trajectories."""
2
2
 
3
- __version__ = "0.1.1"
3
+ __version__ = "0.1.2"
4
4
 
5
5
  from adaptivepy.api import run_adaptive_sampling
6
6
 
@@ -11,6 +11,7 @@ import numpy as np
11
11
  from adaptivepy.clustering import create_clusterer, fit_clusterer
12
12
  from adaptivepy.config.schema import RunConfig, load_config
13
13
  from adaptivepy.io.loader import (
14
+ list_feature_files,
14
15
  list_trajectory_files,
15
16
  load_features,
16
17
  validate_dataset,
@@ -84,7 +85,7 @@ def run_adaptive_sampling(
84
85
  np.random.seed(config.random_seed)
85
86
 
86
87
  # --- Load and validate data ---
87
- feature_files = sorted(Path(config.features_dir).glob("*.npy"))
88
+ feature_files = list_feature_files(config.features_dir)
88
89
  trajectory_files: Optional[List[Path]] = None
89
90
  trajectory_map: Optional[Dict[int, Path]] = None
90
91
 
@@ -199,9 +200,7 @@ def validate_config(config_path: str | Path) -> RunConfig:
199
200
  config_path = Path(config_path)
200
201
  config = load_config(config_path)
201
202
 
202
- feature_files = sorted(Path(config.features_dir).glob("*.npy"))
203
- if not feature_files:
204
- raise ValueError(f"No feature files in {config.features_dir}")
203
+ feature_files = list_feature_files(config.features_dir)
205
204
 
206
205
  trajectory_files = None
207
206
  if config.trajectories_dir is not None:
@@ -55,7 +55,7 @@ class RunConfig:
55
55
  Attributes
56
56
  ----------
57
57
  features_dir : Path
58
- Directory containing ``*.npy`` feature files.
58
+ Directory containing ``*.npy`` or ``*.pkl`` feature files.
59
59
  output_dir : Path
60
60
  Directory where results are written.
61
61
  trajectories_dir : Path or None
@@ -1,8 +1,10 @@
1
1
  """Input/output utilities for AdaptivePy."""
2
2
 
3
3
  from adaptivepy.io.loader import (
4
+ FEATURE_EXTENSIONS,
4
5
  list_feature_files,
5
6
  list_trajectory_files,
7
+ load_feature_array,
6
8
  load_features,
7
9
  validate_dataset,
8
10
  validate_feature_trajectory_mapping,
@@ -15,10 +17,12 @@ from adaptivepy.io.trajectory import (
15
17
  )
16
18
 
17
19
  __all__ = [
20
+ "FEATURE_EXTENSIONS",
18
21
  "build_trajectory_map",
19
22
  "extract_frame",
20
23
  "list_feature_files",
21
24
  "list_trajectory_files",
25
+ "load_feature_array",
22
26
  "load_features",
23
27
  "load_trajectory",
24
28
  "validate_dataset",
@@ -6,15 +6,18 @@ import logging
6
6
  from pathlib import Path
7
7
  from typing import Dict, List, Optional, Tuple
8
8
 
9
+ import joblib
9
10
  import numpy as np
10
11
 
11
12
  from adaptivepy.models import Dataset, FrameRecord
12
13
 
13
14
  logger = logging.getLogger(__name__)
14
15
 
16
+ FEATURE_EXTENSIONS = (".npy", ".pkl")
17
+
15
18
 
16
19
  def list_feature_files(features_dir: Path) -> List[Path]:
17
- """List ``*.npy`` feature files in a directory, sorted by name.
20
+ """List ``*.npy`` and ``*.pkl`` feature files in a directory, sorted by stem.
18
21
 
19
22
  Parameters
20
23
  ----------
@@ -24,25 +27,80 @@ def list_feature_files(features_dir: Path) -> List[Path]:
24
27
  Returns
25
28
  -------
26
29
  list of Path
27
- Sorted paths to feature files.
30
+ Sorted paths to feature files (one file per trajectory stem).
28
31
 
29
32
  Raises
30
33
  ------
31
34
  FileNotFoundError
32
35
  If the directory does not exist.
33
36
  ValueError
34
- If no ``*.npy`` files are found.
37
+ If no supported feature files are found or duplicate stems exist.
35
38
  """
36
39
  features_dir = Path(features_dir)
37
40
  if not features_dir.is_dir():
38
41
  raise FileNotFoundError(f"Features directory not found: {features_dir}")
39
42
 
40
- files = sorted(features_dir.glob("*.npy"))
43
+ files_by_stem: Dict[str, Path] = {}
44
+ for path in sorted(features_dir.iterdir()):
45
+ if not path.is_file():
46
+ continue
47
+ suffix = path.suffix.lower()
48
+ if suffix not in FEATURE_EXTENSIONS:
49
+ continue
50
+ stem = path.stem
51
+ if stem in files_by_stem:
52
+ raise ValueError(
53
+ f"Duplicate feature files for '{stem}': "
54
+ f"{files_by_stem[stem].name} and {path.name}"
55
+ )
56
+ files_by_stem[stem] = path
57
+
58
+ files = [files_by_stem[stem] for stem in sorted(files_by_stem)]
41
59
  if not files:
42
- raise ValueError(f"No .npy feature files found in {features_dir}")
60
+ raise ValueError(
61
+ f"No .npy or .pkl feature files found in {features_dir}"
62
+ )
43
63
  return files
44
64
 
45
65
 
66
+ def load_feature_array(path: Path) -> np.ndarray:
67
+ """Load a feature array from a ``.npy`` or ``.pkl`` file.
68
+
69
+ Parameters
70
+ ----------
71
+ path : Path
72
+ Path to a feature file.
73
+
74
+ Returns
75
+ -------
76
+ np.ndarray
77
+ Loaded feature array.
78
+
79
+ Raises
80
+ ------
81
+ ValueError
82
+ If the file extension is unsupported or the loaded object cannot be
83
+ converted to an array.
84
+ """
85
+ suffix = path.suffix.lower()
86
+ if suffix == ".npy":
87
+ data = np.load(path)
88
+ elif suffix == ".pkl":
89
+ data = joblib.load(path)
90
+ else:
91
+ raise ValueError(
92
+ f"Unsupported feature file extension '{suffix}' in {path}. "
93
+ f"Use one of: {', '.join(FEATURE_EXTENSIONS)}"
94
+ )
95
+
96
+ try:
97
+ return np.asarray(data)
98
+ except (TypeError, ValueError) as exc:
99
+ raise ValueError(
100
+ f"Feature file {path} does not contain a numeric array."
101
+ ) from exc
102
+
103
+
46
104
  def list_trajectory_files(trajectories_dir: Path) -> List[Path]:
47
105
  """List coordinate trajectory files supported by mdtraj.
48
106
 
@@ -96,7 +154,7 @@ def validate_feature_trajectory_mapping(
96
154
  Parameters
97
155
  ----------
98
156
  feature_files : list of Path
99
- Feature ``.npy`` file paths.
157
+ Feature ``.npy`` or ``.pkl`` file paths.
100
158
  trajectory_files : list of Path or None
101
159
  Optional coordinate trajectory file paths.
102
160
 
@@ -130,8 +188,9 @@ def validate_feature_trajectory_mapping(
130
188
  def load_features(features_dir: Path) -> Dataset:
131
189
  """Load feature arrays from disk and build a :class:`Dataset`.
132
190
 
133
- Each ``*.npy`` file must have shape ``(n_frames, n_features)``. Per-frame
134
- ``FrameRecord`` objects are created while preserving trajectory identity.
191
+ Each ``*.npy`` or ``*.pkl`` file must have shape ``(n_frames, n_features)``.
192
+ Per-frame ``FrameRecord`` objects are created while preserving trajectory
193
+ identity.
135
194
 
136
195
  Parameters
137
196
  ----------
@@ -157,7 +216,7 @@ def load_features(features_dir: Path) -> Dataset:
157
216
  n_features: Optional[int] = None
158
217
 
159
218
  for traj_id, feature_path in enumerate(feature_files):
160
- features = np.load(feature_path)
219
+ features = load_feature_array(feature_path)
161
220
  if features.ndim != 2:
162
221
  raise ValueError(
163
222
  f"Feature file {feature_path} must be 2D (n_frames, n_features), "
@@ -0,0 +1,108 @@
1
+ Metadata-Version: 2.4
2
+ Name: adaptivepy-sampling
3
+ Version: 0.1.2
4
+ Summary: Adaptive sampling on MD trajectories via clustering and policy-driven seed selection
5
+ Author: AdaptivePy Contributors
6
+ License: MIT
7
+ Requires-Python: >=3.9
8
+ Description-Content-Type: text/markdown
9
+ Requires-Dist: numpy>=1.20
10
+ Requires-Dist: scikit-learn>=1.0
11
+ Requires-Dist: pyyaml>=6.0
12
+ Requires-Dist: click>=8.0
13
+ Requires-Dist: joblib>=1.0
14
+ Requires-Dist: mdtraj>=1.9
15
+ Provides-Extra: dev
16
+ Requires-Dist: pytest>=7.0; extra == "dev"
17
+ Provides-Extra: docs
18
+ Requires-Dist: mkdocs-material>=9.0; extra == "docs"
19
+ Requires-Dist: mkdocstrings[python]>=0.24; extra == "docs"
20
+
21
+ # AdaptivePy
22
+
23
+ **Adaptive sampling for molecular dynamics trajectories**
24
+
25
+ Clustering-based state space partitioning and policy-driven seed selection for MD workflows.
26
+
27
+ [![Documentation](https://img.shields.io/badge/docs-GitHub%20Pages-blue?style=for-the-badge)](https://hnadeem2.github.io/AdaptivePy/)
28
+ [![PyPI](https://img.shields.io/badge/PyPI-adaptivepy--sampling-orange?style=for-the-badge)](https://pypi.org/project/adaptivepy-sampling/)
29
+ [![Python](https://img.shields.io/badge/python-3.9+-green?style=for-the-badge)](https://www.python.org/)
30
+
31
+ ---
32
+
33
+ ## Overview
34
+
35
+ AdaptivePy helps you identify under-sampled regions of conformational space and select seed frames for new simulations. It loads per-trajectory feature arrays, clusters frames, applies adaptive policies, and writes reproducible metadata and optional PDB structures.
36
+
37
+ **Full documentation:** [https://hnadeem2.github.io/AdaptivePy/](https://hnadeem2.github.io/AdaptivePy/)
38
+
39
+ | | |
40
+ |---|---|
41
+ | **Input** | Feature arrays (`.npy` / `.pkl`), optional coordinate trajectories |
42
+ | **Clustering** | KMeans, MiniBatch KMeans, regular-space |
43
+ | **Policies** | Least counts, random (extensible) |
44
+ | **Output** | Seeds, cluster assignments, model, logs, optional PDBs |
45
+
46
+ ## Installation
47
+
48
+ ```bash
49
+ pip install adaptivepy-sampling
50
+ ```
51
+
52
+ For development:
53
+
54
+ ```bash
55
+ git clone https://github.com/hnadeem2/AdaptivePy.git
56
+ cd AdaptivePy
57
+ pip install -e ".[dev,docs]"
58
+ ```
59
+
60
+ ## Quick start
61
+
62
+ 1. **Prepare features** — one file per trajectory, shape `(n_frames, n_features)`:
63
+
64
+ ```text
65
+ features/
66
+ ├── traj_0.npy
67
+ └── traj_1.pkl
68
+ ```
69
+
70
+ 2. **Configure** — edit `examples/config.yaml` (or create your own).
71
+
72
+ 3. **Run**:
73
+
74
+ ```bash
75
+ adaptivepy run examples/config.yaml
76
+ ```
77
+
78
+ See the [Getting Started guide](https://hnadeem2.github.io/AdaptivePy/getting-started/) for a complete walkthrough.
79
+
80
+ ## CLI
81
+
82
+ ```bash
83
+ adaptivepy run config.yaml # run adaptive sampling
84
+ adaptivepy validate config.yaml # validate inputs only
85
+ adaptivepy list-policies # list available policies
86
+ ```
87
+
88
+ ## Python API
89
+
90
+ ```python
91
+ from adaptivepy import run_adaptive_sampling
92
+
93
+ results = run_adaptive_sampling("config.yaml")
94
+ ```
95
+
96
+ ## Documentation
97
+
98
+ | Guide | Description |
99
+ |-------|-------------|
100
+ | [Getting Started](https://hnadeem2.github.io/AdaptivePy/getting-started/) | First run in minutes |
101
+ | [Configuration](https://hnadeem2.github.io/AdaptivePy/configuration/) | YAML options and defaults |
102
+ | [Feature Inputs](https://hnadeem2.github.io/AdaptivePy/features/) | File formats and layout |
103
+ | [Policies](https://hnadeem2.github.io/AdaptivePy/policies/) | Seed selection strategies |
104
+ | [API Reference](https://hnadeem2.github.io/AdaptivePy/reference/api/) | Module documentation |
105
+
106
+ ## License
107
+
108
+ MIT
@@ -7,3 +7,7 @@ mdtraj>=1.9
7
7
 
8
8
  [dev]
9
9
  pytest>=7.0
10
+
11
+ [docs]
12
+ mkdocs-material>=9.0
13
+ mkdocstrings[python]>=0.24
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "adaptivepy-sampling"
7
- version = "0.1.1"
7
+ version = "0.1.2"
8
8
  description = "Adaptive sampling on MD trajectories via clustering and policy-driven seed selection"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -21,6 +21,10 @@ dependencies = [
21
21
 
22
22
  [project.optional-dependencies]
23
23
  dev = ["pytest>=7.0"]
24
+ docs = [
25
+ "mkdocs-material>=9.0",
26
+ "mkdocstrings[python]>=0.24",
27
+ ]
24
28
 
25
29
  [project.scripts]
26
30
  adaptivepy = "adaptivepy.cli.run:main"
@@ -4,10 +4,12 @@ from __future__ import annotations
4
4
 
5
5
  from pathlib import Path
6
6
 
7
+ import joblib
7
8
  import numpy as np
8
9
  import pytest
9
10
 
10
11
  from adaptivepy.api import run_adaptive_sampling, validate_config
12
+ from adaptivepy.io.loader import load_feature_array, load_features
11
13
  from adaptivepy.policies import list_policies
12
14
 
13
15
 
@@ -61,6 +63,22 @@ write_pdbs: false
61
63
  assert (output_dir / "combined_metadata.csv").is_file()
62
64
 
63
65
 
66
+ def test_load_pkl_features(tmp_path: Path) -> None:
67
+ """Feature loading supports .pkl files with the same shape contract."""
68
+ features_dir = tmp_path / "features"
69
+ features_dir.mkdir()
70
+ rng = np.random.default_rng(1)
71
+ array = rng.normal(size=(25, 6))
72
+ joblib.dump(array, features_dir / "traj_0.pkl")
73
+
74
+ loaded = load_feature_array(features_dir / "traj_0.pkl")
75
+ np.testing.assert_array_equal(loaded, array)
76
+
77
+ dataset = load_features(features_dir)
78
+ assert dataset.feature_matrix.shape == (25, 6)
79
+ assert dataset.traj_names == ["traj_0"]
80
+
81
+
64
82
  def test_validate_config(tmp_path: Path, synthetic_features: Path) -> None:
65
83
  """Validation succeeds for a well-formed configuration."""
66
84
  config_path = tmp_path / "config.yaml"
@@ -1,52 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: adaptivepy-sampling
3
- Version: 0.1.1
4
- Summary: Adaptive sampling on MD trajectories via clustering and policy-driven seed selection
5
- Author: AdaptivePy Contributors
6
- License: MIT
7
- Requires-Python: >=3.9
8
- Description-Content-Type: text/markdown
9
- Requires-Dist: numpy>=1.20
10
- Requires-Dist: scikit-learn>=1.0
11
- Requires-Dist: pyyaml>=6.0
12
- Requires-Dist: click>=8.0
13
- Requires-Dist: joblib>=1.0
14
- Requires-Dist: mdtraj>=1.9
15
- Provides-Extra: dev
16
- Requires-Dist: pytest>=7.0; extra == "dev"
17
-
18
- # AdaptivePy
19
-
20
- Adaptive sampling on molecular dynamics trajectories using clustering-based state space partitioning and policy-driven seed selection.
21
-
22
- ## Installation
23
-
24
- ```bash
25
- pip install adaptivepy-sampling
26
- ```
27
-
28
- ## Quick start
29
-
30
- 1. Prepare feature files (`features/traj_0.npy`, ...) with shape `(n_frames, n_features)`.
31
- 2. Optionally add matching coordinate trajectories (`trajectories/traj_0.xtc`, ...) and a topology file.
32
- 3. Edit `examples/config.yaml` and run:
33
-
34
- ```bash
35
- adaptivepy run examples/config.yaml
36
- ```
37
-
38
- ## CLI
39
-
40
- ```bash
41
- adaptivepy run config.yaml
42
- adaptivepy validate config.yaml
43
- adaptivepy list-policies
44
- ```
45
-
46
- ## Python API
47
-
48
- ```python
49
- from adaptivepy import run_adaptive_sampling
50
-
51
- results = run_adaptive_sampling("config.yaml")
52
- ```
@@ -1,35 +0,0 @@
1
- # AdaptivePy
2
-
3
- Adaptive sampling on molecular dynamics trajectories using clustering-based state space partitioning and policy-driven seed selection.
4
-
5
- ## Installation
6
-
7
- ```bash
8
- pip install adaptivepy-sampling
9
- ```
10
-
11
- ## Quick start
12
-
13
- 1. Prepare feature files (`features/traj_0.npy`, ...) with shape `(n_frames, n_features)`.
14
- 2. Optionally add matching coordinate trajectories (`trajectories/traj_0.xtc`, ...) and a topology file.
15
- 3. Edit `examples/config.yaml` and run:
16
-
17
- ```bash
18
- adaptivepy run examples/config.yaml
19
- ```
20
-
21
- ## CLI
22
-
23
- ```bash
24
- adaptivepy run config.yaml
25
- adaptivepy validate config.yaml
26
- adaptivepy list-policies
27
- ```
28
-
29
- ## Python API
30
-
31
- ```python
32
- from adaptivepy import run_adaptive_sampling
33
-
34
- results = run_adaptive_sampling("config.yaml")
35
- ```
@@ -1,52 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: adaptivepy-sampling
3
- Version: 0.1.1
4
- Summary: Adaptive sampling on MD trajectories via clustering and policy-driven seed selection
5
- Author: AdaptivePy Contributors
6
- License: MIT
7
- Requires-Python: >=3.9
8
- Description-Content-Type: text/markdown
9
- Requires-Dist: numpy>=1.20
10
- Requires-Dist: scikit-learn>=1.0
11
- Requires-Dist: pyyaml>=6.0
12
- Requires-Dist: click>=8.0
13
- Requires-Dist: joblib>=1.0
14
- Requires-Dist: mdtraj>=1.9
15
- Provides-Extra: dev
16
- Requires-Dist: pytest>=7.0; extra == "dev"
17
-
18
- # AdaptivePy
19
-
20
- Adaptive sampling on molecular dynamics trajectories using clustering-based state space partitioning and policy-driven seed selection.
21
-
22
- ## Installation
23
-
24
- ```bash
25
- pip install adaptivepy-sampling
26
- ```
27
-
28
- ## Quick start
29
-
30
- 1. Prepare feature files (`features/traj_0.npy`, ...) with shape `(n_frames, n_features)`.
31
- 2. Optionally add matching coordinate trajectories (`trajectories/traj_0.xtc`, ...) and a topology file.
32
- 3. Edit `examples/config.yaml` and run:
33
-
34
- ```bash
35
- adaptivepy run examples/config.yaml
36
- ```
37
-
38
- ## CLI
39
-
40
- ```bash
41
- adaptivepy run config.yaml
42
- adaptivepy validate config.yaml
43
- adaptivepy list-policies
44
- ```
45
-
46
- ## Python API
47
-
48
- ```python
49
- from adaptivepy import run_adaptive_sampling
50
-
51
- results = run_adaptive_sampling("config.yaml")
52
- ```