bfflearn 0.1.0.dev1__py3-none-any.whl

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 (55) hide show
  1. bff/__init__.py +30 -0
  2. bff/bayes/__init__.py +11 -0
  3. bff/bayes/gaussian_process.py +285 -0
  4. bff/bayes/kernels.py +71 -0
  5. bff/bayes/learning.py +484 -0
  6. bff/bayes/likelihoods.py +142 -0
  7. bff/bayes/posterior.py +62 -0
  8. bff/bayes/priors.py +179 -0
  9. bff/bayes/results.py +327 -0
  10. bff/bayes/utils.py +333 -0
  11. bff/cli.py +254 -0
  12. bff/data.py +93 -0
  13. bff/domain/__init__.py +12 -0
  14. bff/domain/bias.py +149 -0
  15. bff/domain/specs.py +347 -0
  16. bff/domain/trainset.py +201 -0
  17. bff/io/__init__.py +12 -0
  18. bff/io/colvars.py +186 -0
  19. bff/io/commands.py +20 -0
  20. bff/io/cp2k.py +330 -0
  21. bff/io/logs.py +213 -0
  22. bff/io/mdp.py +98 -0
  23. bff/io/plumed.py +184 -0
  24. bff/io/progress.py +74 -0
  25. bff/io/schedulers.py +118 -0
  26. bff/io/utils.py +208 -0
  27. bff/mcmc/__init__.py +3 -0
  28. bff/mcmc/convergence.py +168 -0
  29. bff/mcmc/proposal.py +254 -0
  30. bff/mcmc/sampler.py +481 -0
  31. bff/plotting.py +362 -0
  32. bff/qoi/__init__.py +9 -0
  33. bff/qoi/analysis.py +209 -0
  34. bff/qoi/data.py +169 -0
  35. bff/qoi/hbonds.py +255 -0
  36. bff/qoi/rdf.py +108 -0
  37. bff/qoi/routines.py +272 -0
  38. bff/tools.py +168 -0
  39. bff/topology.py +581 -0
  40. bff/workflows/__init__.py +0 -0
  41. bff/workflows/configs.py +1147 -0
  42. bff/workflows/learn.py +77 -0
  43. bff/workflows/md.py +326 -0
  44. bff/workflows/prepare.py +788 -0
  45. bff/workflows/qoi.py +260 -0
  46. bff/workflows/runsims.py +620 -0
  47. bff/workflows/simulate.py +28 -0
  48. bff/workflows/train.py +69 -0
  49. bff/workflows/validate.py +29 -0
  50. bfflearn-0.1.0.dev1.dist-info/METADATA +913 -0
  51. bfflearn-0.1.0.dev1.dist-info/RECORD +55 -0
  52. bfflearn-0.1.0.dev1.dist-info/WHEEL +5 -0
  53. bfflearn-0.1.0.dev1.dist-info/entry_points.txt +2 -0
  54. bfflearn-0.1.0.dev1.dist-info/licenses/LICENSE +674 -0
  55. bfflearn-0.1.0.dev1.dist-info/top_level.txt +1 -0
bff/workflows/qoi.py ADDED
@@ -0,0 +1,260 @@
1
+ import numpy as np
2
+
3
+ from ..domain.trainset import TrainSetInfo, TrajectorySet
4
+ from ..io.logs import Logger
5
+ from ..io.utils import save_json
6
+ from ..qoi.analysis import analyze_trajectory_sets
7
+ from ..qoi.data import QoI, QoIDataset
8
+ from ..qoi.routines import build_analysis_routines
9
+ from .configs import QoIConfig
10
+
11
+
12
+ def _qoi_output_path(path, qoi_name: str | None = None, *, raw: bool = False):
13
+ if raw:
14
+ return path.with_name(path.name + ".raw.json")
15
+ if qoi_name is None:
16
+ raise ValueError("qoi_name is required unless raw=True.")
17
+ return path.with_name(f"{path.name}-{qoi_name}.pt")
18
+
19
+
20
+ def _validate_qoi_blocks(
21
+ blocks: list[QoI],
22
+ *,
23
+ context: str,
24
+ ) -> tuple[str, ...] | None:
25
+ if not blocks:
26
+ return None
27
+
28
+ first = blocks[0]
29
+ labels = first.labels
30
+ values_per_label = first.values_per_label
31
+ n_values = first.n_values
32
+ for block in blocks[1:]:
33
+ if block.values_per_label != values_per_label:
34
+ raise ValueError(
35
+ f"QoI schema mismatch in {context}: expected values_per_label="
36
+ f"{values_per_label}, got {block.values_per_label}."
37
+ )
38
+ if block.labels != labels:
39
+ raise ValueError(
40
+ f"QoI label mismatch in {context}: expected {labels}, "
41
+ f"got {block.labels}."
42
+ )
43
+ if block.n_values != n_values:
44
+ raise ValueError(
45
+ f"QoI value-count mismatch in {context}: expected {n_values}, "
46
+ f"got {block.n_values}."
47
+ )
48
+ return labels
49
+
50
+
51
+ def _stack_qoi_blocks(
52
+ blocks: list[QoI],
53
+ *,
54
+ context: str,
55
+ ) -> np.ndarray:
56
+ if not blocks:
57
+ return np.empty(0, dtype=float)
58
+ _validate_qoi_blocks(blocks, context=context)
59
+ return np.concatenate([block.values for block in blocks])
60
+
61
+
62
+ def _dataset_labels(
63
+ ref_blocks: list[QoI],
64
+ system_indices: list[int],
65
+ ) -> tuple[str, ...] | None:
66
+ if not ref_blocks:
67
+ return None
68
+
69
+ labels = ref_blocks[0].labels
70
+ if labels is None:
71
+ return None
72
+ if len(ref_blocks) == 1:
73
+ return labels
74
+
75
+ return tuple(
76
+ f"window-{system_index:03d}:{label}"
77
+ for system_index, block in zip(system_indices, ref_blocks)
78
+ for label in block.labels or ()
79
+ )
80
+
81
+
82
+ def _write_qoi_datasets(
83
+ *,
84
+ fn_out,
85
+ inputs,
86
+ qoi_train: list[list[dict[str, QoI]]],
87
+ qoi_ref: list[dict[str, QoI]],
88
+ ) -> None:
89
+ qoi_names = sorted({name for sample in qoi_ref for name in sample})
90
+
91
+ for qoi_name in qoi_names:
92
+ fn_qoi = _qoi_output_path(fn_out, qoi_name)
93
+ system_indices = [i for i, sample in enumerate(qoi_ref) if qoi_name in sample]
94
+ ref_blocks = [qoi_ref[i][qoi_name] for i in system_indices]
95
+ train_blocks = [
96
+ [sample[i][qoi_name] for i in system_indices]
97
+ for sample in qoi_train
98
+ ]
99
+
100
+ _validate_qoi_blocks(
101
+ ref_blocks,
102
+ context="reference QoI blocks",
103
+ )
104
+ reference = ref_blocks[0] if ref_blocks else None
105
+ outputs_ref = _stack_qoi_blocks(
106
+ ref_blocks,
107
+ context="reference QoI blocks",
108
+ )
109
+ outputs = []
110
+ for i, blocks in enumerate(train_blocks):
111
+ if reference is not None and blocks:
112
+ _validate_qoi_blocks(
113
+ [reference, *blocks],
114
+ context=f"training QoI blocks for sample {i}",
115
+ )
116
+ outputs.append(
117
+ _stack_qoi_blocks(
118
+ blocks,
119
+ context=f"training QoI blocks for sample {i}",
120
+ )
121
+ )
122
+
123
+ if outputs_ref.size == 0:
124
+ if fn_qoi.exists():
125
+ fn_qoi.unlink()
126
+ continue
127
+
128
+ settings: dict[str, object] = {}
129
+ metadata: dict[str, object] = {"system_indices": system_indices}
130
+ values_per_label = 1
131
+ if reference is not None:
132
+ settings_by_block = [dict(block.settings) for block in ref_blocks]
133
+ if settings_by_block:
134
+ shared_settings = settings_by_block[0]
135
+ if all(
136
+ block_settings == shared_settings
137
+ for block_settings in settings_by_block[1:]
138
+ ):
139
+ settings = dict(shared_settings)
140
+ else:
141
+ metadata["settings_by_block"] = settings_by_block
142
+
143
+ metadata_by_block = [dict(block.metadata) for block in ref_blocks]
144
+ if metadata_by_block:
145
+ shared_metadata = metadata_by_block[0]
146
+ if all(
147
+ block_metadata == shared_metadata
148
+ for block_metadata in metadata_by_block[1:]
149
+ ):
150
+ metadata = dict(shared_metadata) | metadata
151
+ else:
152
+ metadata["metadata_by_block"] = metadata_by_block
153
+
154
+ labels = _dataset_labels(ref_blocks, system_indices)
155
+ values_per_label = reference.values_per_label
156
+
157
+ dataset = QoIDataset(
158
+ name=qoi_name,
159
+ inputs=inputs,
160
+ outputs=outputs,
161
+ outputs_ref=outputs_ref,
162
+ labels=labels,
163
+ values_per_label=values_per_label,
164
+ nuisance=None,
165
+ settings=settings,
166
+ metadata=metadata,
167
+ )
168
+ dataset.write(fn_qoi)
169
+
170
+
171
+ def main(fn_config: str) -> None:
172
+ """Run QoI analysis for a training set and its reference trajectories.
173
+
174
+ Parameters
175
+ ----------
176
+ fn_config
177
+ Path to the YAML workflow configuration.
178
+ """
179
+ config = QoIConfig.load(fn_config)
180
+ train_cfg = config.trainset
181
+ ref_cfg = config.refset
182
+ run_cfg = config.run
183
+ output_cfg = config.output
184
+
185
+ routines_by_system = build_analysis_routines(
186
+ [system.routines for system in ref_cfg.systems]
187
+ )
188
+ logger = Logger(name="qoi", fn_log=str(output_cfg.log), mode="w")
189
+ trainset = TrainSetInfo.from_dir(train_cfg.dir)
190
+ if len(routines_by_system) != len(trainset.systems):
191
+ raise ValueError(
192
+ "Analysis system count must match the number of staged trainset systems."
193
+ )
194
+
195
+ reference_set = TrajectorySet(
196
+ sample_id="reference",
197
+ fn_topol=tuple(system.fn_topol for system in ref_cfg.systems),
198
+ fn_coord=tuple(system.fn_coord for system in ref_cfg.systems),
199
+ fn_trj=tuple(system.fn_trj for system in ref_cfg.systems),
200
+ )
201
+
202
+ logger.info("=== Quantities of Interest (QoI) Analysis ===\n", level=0)
203
+
204
+ qoi_ref = analyze_trajectory_sets(
205
+ [reference_set],
206
+ routines_by_system=routines_by_system,
207
+ start=ref_cfg.start,
208
+ stop=ref_cfg.stop,
209
+ step=ref_cfg.step,
210
+ workers=1,
211
+ progress_stride=1,
212
+ progress_label="Reference QoI",
213
+ logger=logger,
214
+ in_memory=run_cfg.in_memory,
215
+ gc_collect=run_cfg.gc_collect,
216
+ )[0]
217
+
218
+ logger.info("", level=0)
219
+
220
+ qoi_train = analyze_trajectory_sets(
221
+ trainset.samples,
222
+ routines_by_system=routines_by_system,
223
+ start=train_cfg.start,
224
+ stop=train_cfg.stop,
225
+ step=train_cfg.step,
226
+ workers=train_cfg.workers,
227
+ progress_stride=train_cfg.progress_stride,
228
+ progress_label="Training QoI",
229
+ logger=logger,
230
+ in_memory=run_cfg.in_memory,
231
+ gc_collect=run_cfg.gc_collect,
232
+ maxtasksperchild=run_cfg.maxtasksperchild,
233
+ )
234
+
235
+ logger.info("", level=0)
236
+ logger.info("Saving QoI data: in progress...", level=1, overwrite=True)
237
+ _write_qoi_datasets(
238
+ fn_out=output_cfg.path,
239
+ inputs=trainset.inputs,
240
+ qoi_train=qoi_train,
241
+ qoi_ref=qoi_ref,
242
+ )
243
+ logger.info("Saving QoI data: Done.", level=1, overwrite=True)
244
+ logger.info("", level=0)
245
+
246
+ if output_cfg.write_raw:
247
+ logger.info("Saving raw QoI data: in progress...", level=1, overwrite=True)
248
+ fn_out = _qoi_output_path(output_cfg.path, raw=True)
249
+ raw_data = {
250
+ "train": [
251
+ [{name: qoi.to_dict() for name, qoi in trj.items()} for trj in sample]
252
+ for sample in qoi_train
253
+ ],
254
+ "ref": [
255
+ {name: qoi.to_dict() for name, qoi in trj.items()}
256
+ for trj in qoi_ref
257
+ ],
258
+ }
259
+ save_json(raw_data, fn_out)
260
+ logger.info("Saving raw QoI data: Done.", level=1, overwrite=True)