gmxplot 0.2.0__py3-none-any.whl → 0.2.2__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.
- gmxplot/__init__.py +1 -1
- gmxplot/comparison.py +17 -6
- gmxplot/plotting.py +37 -6
- gmxplot/stats.py +5 -5
- {gmxplot-0.2.0.dist-info → gmxplot-0.2.2.dist-info}/METADATA +7 -1
- gmxplot-0.2.2.dist-info/RECORD +16 -0
- gmxplot-0.2.0.dist-info/RECORD +0 -16
- {gmxplot-0.2.0.dist-info → gmxplot-0.2.2.dist-info}/WHEEL +0 -0
- {gmxplot-0.2.0.dist-info → gmxplot-0.2.2.dist-info}/entry_points.txt +0 -0
- {gmxplot-0.2.0.dist-info → gmxplot-0.2.2.dist-info}/licenses/LICENSE +0 -0
gmxplot/__init__.py
CHANGED
gmxplot/comparison.py
CHANGED
|
@@ -57,15 +57,26 @@ def _compare_single(datasets: list, labels: list, style: StyleOptions) -> plt.Fi
|
|
|
57
57
|
multi = len(ds0.y_cols) > 1
|
|
58
58
|
colors = resolve_palette(style.palette, len(datasets))
|
|
59
59
|
fig, ax = plt.subplots(figsize=style.figsize or FIGURE_SIZE_SINGLE)
|
|
60
|
-
|
|
60
|
+
if not multi:
|
|
61
|
+
# One series per file: match by position, not by column name. GROMACS
|
|
62
|
+
# names the legend after the selection, so files that differ only in the
|
|
63
|
+
# selection (ZF1-DNA, ZF2-DNA, ...) carry different column names and
|
|
64
|
+
# only the first file would be drawn.
|
|
61
65
|
for i, ds in enumerate(datasets):
|
|
62
|
-
if
|
|
66
|
+
if not ds.y_cols:
|
|
63
67
|
continue
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
68
|
+
_overlay_line(ax, ds, ds.y_cols[0], colors[i],
|
|
69
|
+
labels[i] if labels else str(i), style,
|
|
70
|
+
_effective_roll(ds, None))
|
|
71
|
+
else:
|
|
72
|
+
for col in ds0.y_cols:
|
|
73
|
+
for i, ds in enumerate(datasets):
|
|
74
|
+
if col not in ds.y_cols:
|
|
75
|
+
continue
|
|
76
|
+
color = colors[i]
|
|
77
|
+
label = labels[i] if labels else str(i)
|
|
67
78
|
label = f'{label} {col}'
|
|
68
|
-
|
|
79
|
+
_overlay_line(ax, ds, col, color, label, style, _effective_roll(ds, None))
|
|
69
80
|
ax.set_xlabel(_x_title(ds0, style))
|
|
70
81
|
ax.set_ylabel(style.ylabel or ds0.meta.y_label or '')
|
|
71
82
|
ax.set_title(style.title or ds0.meta.title)
|
gmxplot/plotting.py
CHANGED
|
@@ -97,16 +97,47 @@ def _make_axes(n_panels: int, figsize: Optional[Tuple[float, float]] = None):
|
|
|
97
97
|
return fig, axes_flat, n_cols
|
|
98
98
|
|
|
99
99
|
|
|
100
|
+
# GROMACS writes ONE y-axis label for a whole multi-column file and merges
|
|
101
|
+
# repeated units: energy.xvg has 6 columns but the label only lists five
|
|
102
|
+
# "(...)" groups. A purely positional assignment therefore shifts every unit
|
|
103
|
+
# after the duplicate (Total Energy gets K, Temperature gets bar, ...), so fall
|
|
104
|
+
# back to per-term units when the counts do not line up.
|
|
105
|
+
_TERM_UNITS = [
|
|
106
|
+
(r'\bdensity\b', 'kg/m^3'),
|
|
107
|
+
(r'\bpressure\b|\bpres\.|\bvir-', 'bar'),
|
|
108
|
+
(r'\btemperature\b|^t-', 'K'),
|
|
109
|
+
(r'\bbox-[xyz]\b', 'nm'),
|
|
110
|
+
(r'\bvolume\b', 'nm^3'),
|
|
111
|
+
(r'\bpotential\b|\bkinetic\b|\btotal energy\b|\benthalpy\b|\bgibbs\b',
|
|
112
|
+
'kJ/mol'),
|
|
113
|
+
(r'\bcoul|\blj-|\bdisper|\bbond|\bangle\b|\bdihedral|\bimproper|\bvdw',
|
|
114
|
+
'kJ/mol'),
|
|
115
|
+
]
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def _unit_for_column(col: str, units: List[str]) -> Optional[str]:
|
|
119
|
+
"""Resolve a unit for one column when the file's unit list is incomplete."""
|
|
120
|
+
label = clean_gromacs_label(col).lower()
|
|
121
|
+
for pattern, unit in _TERM_UNITS:
|
|
122
|
+
if re.search(pattern, label):
|
|
123
|
+
return unit
|
|
124
|
+
# A single unit for the whole file applies to every column.
|
|
125
|
+
return units[0] if len(units) == 1 else None
|
|
126
|
+
|
|
127
|
+
|
|
100
128
|
def _y_titles(ds: Dataset) -> dict:
|
|
101
129
|
"""Map each y column to a display label with units when available."""
|
|
102
|
-
units =
|
|
130
|
+
units = [clean_gromacs_label(u)
|
|
131
|
+
for u in re.findall(r'\(([^()]+)\)', ds.meta.y_label)]
|
|
103
132
|
out = {}
|
|
104
|
-
|
|
133
|
+
if units and len(units) == len(ds.y_cols):
|
|
134
|
+
for col, unit in zip(ds.y_cols, units):
|
|
135
|
+
out[col] = f'{clean_gromacs_label(col)} ({unit})'
|
|
136
|
+
return out
|
|
137
|
+
for col in ds.y_cols:
|
|
105
138
|
base = clean_gromacs_label(col)
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
else:
|
|
109
|
-
out[col] = base
|
|
139
|
+
unit = _unit_for_column(col, units)
|
|
140
|
+
out[col] = f'{base} ({unit})' if unit else base
|
|
110
141
|
return out
|
|
111
142
|
|
|
112
143
|
|
gmxplot/stats.py
CHANGED
|
@@ -8,6 +8,7 @@ count-weighted x statistics; PCA analyzes every column (there is no x column).
|
|
|
8
8
|
import math
|
|
9
9
|
import os
|
|
10
10
|
import re
|
|
11
|
+
from dataclasses import replace
|
|
11
12
|
from pathlib import Path
|
|
12
13
|
from typing import Dict, List, Optional
|
|
13
14
|
|
|
@@ -243,11 +244,10 @@ def generate_stats_csv(
|
|
|
243
244
|
df, meta = read_xvg(fp)
|
|
244
245
|
if df.empty:
|
|
245
246
|
continue
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
if
|
|
250
|
-
o.path = fp
|
|
247
|
+
# Per-file copy: mutating a shared options object would pin every later
|
|
248
|
+
# row to the first file's label/path.
|
|
249
|
+
label = os.path.basename(fp)
|
|
250
|
+
o = replace(opts, label=label, path=fp) if opts else DatasetOptions(label=label, path=fp)
|
|
251
251
|
ds = prepare_dataset(df, meta, o)
|
|
252
252
|
bs = block_size
|
|
253
253
|
if block_time is not None and bs is None and ds.x_col is not None:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: gmxplot
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: GROMACS XVG visualization and statistics with family/kind semantics, physical time axes, windows, replica aggregation, and dashboards
|
|
5
5
|
Project-URL: Homepage, https://github.com/MaybeBio/gmxplot
|
|
6
6
|
Project-URL: Issues, https://github.com/MaybeBio/gmxplot/issues
|
|
@@ -137,6 +137,12 @@ average and drift statistics. Nothing is smoothed by accident.
|
|
|
137
137
|
|
|
138
138
|
## 📦 Installation
|
|
139
139
|
|
|
140
|
+
```bash
|
|
141
|
+
pip install gmxplot
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
or
|
|
145
|
+
|
|
140
146
|
```bash
|
|
141
147
|
git clone https://github.com/MaybeBio/gmxplot.git
|
|
142
148
|
cd gmxplot
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
gmxplot/__init__.py,sha256=TThvsrSaI7Y7g1-8vfoj4C14rtS9TCRlCmfNezKUbSo,91
|
|
2
|
+
gmxplot/cli.py,sha256=Z1rdBQ_5swjaXtWzHoodq9JXe0gp0L9pp8-UmTf9L7o,34304
|
|
3
|
+
gmxplot/comparison.py,sha256=wVFmaUYgph9VjtsD8pTT4c3x35ACHB-UiAoMOFbKFEY,5368
|
|
4
|
+
gmxplot/config.py,sha256=9IGso6QluhPKtP204HJjqUUnpq5LVfZcPJTBgeGo190,2696
|
|
5
|
+
gmxplot/dashboard.py,sha256=8tbqgA-o_pYK8DNMusQUeqSp-29XPxt6kgd8b1zFABI,10766
|
|
6
|
+
gmxplot/dataset.py,sha256=bf-823OkOVo1XGCqadj-J5RaRf9genHIibDqdVDXJMc,9399
|
|
7
|
+
gmxplot/escape_codes.py,sha256=HR9F-sy_Jq4NOb74I7bZgUx6svjy2xYHMYTPQRBxBk4,1831
|
|
8
|
+
gmxplot/parser.py,sha256=oijRpBjucRzlMm8OcI4GAkYA6jQAaQ4lzZQZrRwdz7k,10308
|
|
9
|
+
gmxplot/plotting.py,sha256=ujWfJJYAzSaU9xnSO-G48XZIsJci5ajX5E3SkzBMo88,14653
|
|
10
|
+
gmxplot/replicas.py,sha256=eAp3yFZlg1FiY7YVFY7MFYvoXSIPMznj5GjuonVqmkM,7769
|
|
11
|
+
gmxplot/stats.py,sha256=ZuQbdPj4dV2XQfWD9FJZXBSZPFuc478xG7Efjo70Fnk,11496
|
|
12
|
+
gmxplot-0.2.2.dist-info/METADATA,sha256=kgFqDo-8Dqu_vWG69A71O3yrBGYfXYMFj_pevYQG1tg,21701
|
|
13
|
+
gmxplot-0.2.2.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
|
|
14
|
+
gmxplot-0.2.2.dist-info/entry_points.txt,sha256=ENtnfYYCM2sAELFTNdOc2lhOPna_ndmXImWPONbAKRA,44
|
|
15
|
+
gmxplot-0.2.2.dist-info/licenses/LICENSE,sha256=8-mfygEBYs_zUebQalb4qE5TIk8ni9ERmb9g52GWED0,308
|
|
16
|
+
gmxplot-0.2.2.dist-info/RECORD,,
|
gmxplot-0.2.0.dist-info/RECORD
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
gmxplot/__init__.py,sha256=FGkyYOsuFfy3yx5O9WvX5Q5rSvLfpr7x9Pxp8G3koGg,91
|
|
2
|
-
gmxplot/cli.py,sha256=Z1rdBQ_5swjaXtWzHoodq9JXe0gp0L9pp8-UmTf9L7o,34304
|
|
3
|
-
gmxplot/comparison.py,sha256=gYpIhKin5R7JonYmvC_Bvsaz2pEiV1xYAy6O-ldZaAU,4776
|
|
4
|
-
gmxplot/config.py,sha256=9IGso6QluhPKtP204HJjqUUnpq5LVfZcPJTBgeGo190,2696
|
|
5
|
-
gmxplot/dashboard.py,sha256=8tbqgA-o_pYK8DNMusQUeqSp-29XPxt6kgd8b1zFABI,10766
|
|
6
|
-
gmxplot/dataset.py,sha256=bf-823OkOVo1XGCqadj-J5RaRf9genHIibDqdVDXJMc,9399
|
|
7
|
-
gmxplot/escape_codes.py,sha256=HR9F-sy_Jq4NOb74I7bZgUx6svjy2xYHMYTPQRBxBk4,1831
|
|
8
|
-
gmxplot/parser.py,sha256=oijRpBjucRzlMm8OcI4GAkYA6jQAaQ4lzZQZrRwdz7k,10308
|
|
9
|
-
gmxplot/plotting.py,sha256=nSVjE3M02XLWNhOdpcTaHwtCZ1gotXWqhALJW9KoMpY,13334
|
|
10
|
-
gmxplot/replicas.py,sha256=eAp3yFZlg1FiY7YVFY7MFYvoXSIPMznj5GjuonVqmkM,7769
|
|
11
|
-
gmxplot/stats.py,sha256=2c2V6E6v03PtQEGu6nt3_IdLQO-Q2kGrEnHd6snox6g,11354
|
|
12
|
-
gmxplot-0.2.0.dist-info/METADATA,sha256=RKNLi8WBDf54lLiZTq5OFaoKS8ecT7PFJc_dHrKP-xc,21664
|
|
13
|
-
gmxplot-0.2.0.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
|
|
14
|
-
gmxplot-0.2.0.dist-info/entry_points.txt,sha256=ENtnfYYCM2sAELFTNdOc2lhOPna_ndmXImWPONbAKRA,44
|
|
15
|
-
gmxplot-0.2.0.dist-info/licenses/LICENSE,sha256=8-mfygEBYs_zUebQalb4qE5TIk8ni9ERmb9g52GWED0,308
|
|
16
|
-
gmxplot-0.2.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|