batplot 1.1.8__tar.gz → 1.3.0__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.
- {batplot-1.1.8 → batplot-1.3.0}/PKG-INFO +7 -1
- {batplot-1.1.8 → batplot-1.3.0}/README.md +6 -0
- {batplot-1.1.8 → batplot-1.3.0}/batplot/__init__.py +1 -1
- {batplot-1.1.8 → batplot-1.3.0}/batplot/args.py +10 -1
- {batplot-1.1.8 → batplot-1.3.0}/batplot/batch.py +184 -1
- {batplot-1.1.8 → batplot-1.3.0}/batplot/batplot.py +43 -4
- {batplot-1.1.8 → batplot-1.3.0}/batplot/cpc_interactive.py +178 -25
- {batplot-1.1.8 → batplot-1.3.0}/batplot/electrochem_interactive.py +253 -49
- {batplot-1.1.8 → batplot-1.3.0}/batplot/interactive.py +116 -22
- {batplot-1.1.8 → batplot-1.3.0}/batplot/operando_ec_interactive.py +324 -60
- {batplot-1.1.8 → batplot-1.3.0}/batplot/session.py +44 -0
- {batplot-1.1.8 → batplot-1.3.0}/batplot/style.py +179 -20
- {batplot-1.1.8 → batplot-1.3.0}/batplot/ui.py +2 -2
- {batplot-1.1.8 → batplot-1.3.0}/batplot.egg-info/PKG-INFO +7 -1
- {batplot-1.1.8 → batplot-1.3.0}/batplot.egg-info/SOURCES.txt +1 -0
- {batplot-1.1.8 → batplot-1.3.0}/pyproject.toml +1 -1
- batplot-1.3.0/setup.py +3 -0
- {batplot-1.1.8 → batplot-1.3.0}/LICENSE +0 -0
- {batplot-1.1.8 → batplot-1.3.0}/batplot/batplot_new.py +0 -0
- {batplot-1.1.8 → batplot-1.3.0}/batplot/cif.py +0 -0
- {batplot-1.1.8 → batplot-1.3.0}/batplot/cli.py +0 -0
- {batplot-1.1.8 → batplot-1.3.0}/batplot/converters.py +0 -0
- {batplot-1.1.8 → batplot-1.3.0}/batplot/modes.py +0 -0
- {batplot-1.1.8 → batplot-1.3.0}/batplot/operando.py +0 -0
- {batplot-1.1.8 → batplot-1.3.0}/batplot/plotting.py +0 -0
- {batplot-1.1.8 → batplot-1.3.0}/batplot/readers.py +0 -0
- {batplot-1.1.8 → batplot-1.3.0}/batplot/utils.py +0 -0
- {batplot-1.1.8 → batplot-1.3.0}/batplot.egg-info/dependency_links.txt +0 -0
- {batplot-1.1.8 → batplot-1.3.0}/batplot.egg-info/entry_points.txt +0 -0
- {batplot-1.1.8 → batplot-1.3.0}/batplot.egg-info/requires.txt +0 -0
- {batplot-1.1.8 → batplot-1.3.0}/batplot.egg-info/top_level.txt +0 -0
- {batplot-1.1.8 → batplot-1.3.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: batplot
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.0
|
|
4
4
|
Summary: Interactive plotting for XRD, PDF, and XAS data (.xye, .xy, .qye, .dat, .csv, .gr, .nor, .chik, .chir)
|
|
5
5
|
Author-email: Tian Dai <tianda@uio.no>
|
|
6
6
|
License: MIT License
|
|
@@ -107,6 +107,12 @@ batplot --gc all # All .mpt/.csv files (.mpt needs --mass, .csv doesn't)
|
|
|
107
107
|
batplot --cv all # All .mpt files (CV mode)
|
|
108
108
|
batplot --dqdv all # All .csv files (dQdV mode)
|
|
109
109
|
batplot --cpc all --mass 6.2 # All .mpt/.csv files (.mpt needs --mass, .csv doesn't)
|
|
110
|
+
|
|
111
|
+
# Batch processing with style/geometry: apply consistent formatting to all files
|
|
112
|
+
batplot --all mystyle.bps --gc --mass 7.0 # Apply .bps style to all GC files
|
|
113
|
+
batplot --all config.bpsg --cv # Apply .bpsg style+geometry to all CV files
|
|
114
|
+
batplot --all style.bps --dqdv # Apply style to all dQdV files
|
|
115
|
+
batplot --all geom.bpsg --cpc --mass 5.4 # Apply style+geometry to all CPC files
|
|
110
116
|
```
|
|
111
117
|
|
|
112
118
|
### Operando Analysis
|
|
@@ -58,6 +58,12 @@ batplot --gc all # All .mpt/.csv files (.mpt needs --mass, .csv doesn't)
|
|
|
58
58
|
batplot --cv all # All .mpt files (CV mode)
|
|
59
59
|
batplot --dqdv all # All .csv files (dQdV mode)
|
|
60
60
|
batplot --cpc all --mass 6.2 # All .mpt/.csv files (.mpt needs --mass, .csv doesn't)
|
|
61
|
+
|
|
62
|
+
# Batch processing with style/geometry: apply consistent formatting to all files
|
|
63
|
+
batplot --all mystyle.bps --gc --mass 7.0 # Apply .bps style to all GC files
|
|
64
|
+
batplot --all config.bpsg --cv # Apply .bpsg style+geometry to all CV files
|
|
65
|
+
batplot --all style.bps --dqdv # Apply style to all dQdV files
|
|
66
|
+
batplot --all geom.bpsg --cpc --mass 5.4 # Apply style+geometry to all CPC files
|
|
61
67
|
```
|
|
62
68
|
|
|
63
69
|
### Operando Analysis
|
|
@@ -23,6 +23,8 @@ def _print_general_help() -> None:
|
|
|
23
23
|
" batplot --gc FILE.mpt --mass 7.0 # EC GC from .mpt (requires --mass mg)\n"
|
|
24
24
|
" batplot --gc FILE.csv # EC GC from supported .csv (no mass required)\n"
|
|
25
25
|
" batplot --gc all --mass 7.0 # Batch: all .mpt/.csv in directory (.mpt needs --mass)\n"
|
|
26
|
+
" batplot --all --gc style.bps --mass 7 # Batch with style: apply style.bps to all GC files\n"
|
|
27
|
+
" batplot --all --cv config.bpsg # Batch with style+geom: apply to all CV files\n"
|
|
26
28
|
" batplot --dqdv FILE.csv # EC dQ/dV from supported .csv\n"
|
|
27
29
|
" batplot --dqdv all # Batch: all .csv in directory (dQdV mode)\n"
|
|
28
30
|
" batplot --cv FILE.mpt # EC CV (cyclic voltammetry) from .mpt\n"
|
|
@@ -34,7 +36,8 @@ def _print_general_help() -> None:
|
|
|
34
36
|
" • Quick plotting with sensible defaults, no config files needed\n"
|
|
35
37
|
" • Supports many common file formats (see -h xy/ec/op)\n"
|
|
36
38
|
" • Interactive menus (--interactive): styling, ranges, fonts, export, sessions\n"
|
|
37
|
-
" • Batch processing: use 'all' or directory path with any mode\n
|
|
39
|
+
" • Batch processing: use 'all' or directory path with any mode\n"
|
|
40
|
+
" • Batch styling: apply .bps/.bpsg files to all exports (use --all flag)\n\n"
|
|
38
41
|
|
|
39
42
|
"More help:\n"
|
|
40
43
|
" batplot -h xy # XY file plotting guide\n"
|
|
@@ -93,6 +96,11 @@ def _print_ec_help() -> None:
|
|
|
93
96
|
" batplot --dqdv all # All .csv files (dQdV mode)\n"
|
|
94
97
|
" batplot --cpc all --mass 5.4 # All .mpt/.csv files (.mpt requires --mass)\n"
|
|
95
98
|
" batplot --gc /path/to/folder --mass 6 # Process specific directory\n\n"
|
|
99
|
+
"Batch mode with style/geometry: Apply .bps/.bpsg files to all batch exports.\n"
|
|
100
|
+
" batplot --all --gc style.bps --mass 7 # Apply style to all GC plots\n"
|
|
101
|
+
" batplot --all --cv config.bpsg # Apply style+geometry to all CV plots\n"
|
|
102
|
+
" batplot --all --dqdv my.bps # Apply style to all dQdV plots\n"
|
|
103
|
+
" batplot --all --cpc geom.bpsg --mass 6 # Apply style+geom to all CPC plots\n\n"
|
|
96
104
|
"Interactive (--interactive): choose cycles, colors/palettes, line widths, axis scales (linear/log/symlog),\n"
|
|
97
105
|
"rename axes, toggle ticks/titles/spines, print/export/import style (.bpcfg), save session (.pkl).\n"
|
|
98
106
|
"Note: Batch mode exports SVG files automatically; --interactive is for single-file plotting only.\n"
|
|
@@ -139,6 +147,7 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
139
147
|
parser.add_argument("--dqdv", action="store_true", help=argparse.SUPPRESS)
|
|
140
148
|
parser.add_argument("--cv", action="store_true", help=argparse.SUPPRESS)
|
|
141
149
|
parser.add_argument("--cpc", action="store_true", help=argparse.SUPPRESS)
|
|
150
|
+
parser.add_argument("--all", type=str, nargs='?', const='all', help=argparse.SUPPRESS)
|
|
142
151
|
return parser
|
|
143
152
|
|
|
144
153
|
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import os
|
|
6
|
+
import json
|
|
6
7
|
import numpy as np
|
|
7
8
|
import matplotlib.pyplot as plt
|
|
8
9
|
|
|
@@ -16,6 +17,152 @@ from .readers import (
|
|
|
16
17
|
from .utils import _confirm_overwrite
|
|
17
18
|
|
|
18
19
|
|
|
20
|
+
def _load_style_file(style_path: str) -> dict | None:
|
|
21
|
+
"""Load a .bps, .bpsg, or .bpcfg style file.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
style_path: Path to style configuration file
|
|
25
|
+
|
|
26
|
+
Returns:
|
|
27
|
+
Style configuration dict or None if loading fails
|
|
28
|
+
"""
|
|
29
|
+
try:
|
|
30
|
+
with open(style_path, 'r', encoding='utf-8') as f:
|
|
31
|
+
cfg = json.load(f)
|
|
32
|
+
return cfg
|
|
33
|
+
except Exception as e:
|
|
34
|
+
print(f"Warning: Could not load style file {style_path}: {e}")
|
|
35
|
+
return None
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _apply_ec_style(fig, ax, cfg: dict):
|
|
39
|
+
"""Apply style configuration to an EC batch plot.
|
|
40
|
+
|
|
41
|
+
Applies formatting from .bps/.bpsg files including fonts, colors,
|
|
42
|
+
tick parameters, and geometry (if present in .bpsg files).
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
fig: Matplotlib figure object
|
|
46
|
+
ax: Matplotlib axes object
|
|
47
|
+
cfg: Style configuration dictionary
|
|
48
|
+
"""
|
|
49
|
+
try:
|
|
50
|
+
# Apply fonts
|
|
51
|
+
font_cfg = cfg.get('font', {})
|
|
52
|
+
if font_cfg:
|
|
53
|
+
family = font_cfg.get('family')
|
|
54
|
+
size = font_cfg.get('size')
|
|
55
|
+
if family:
|
|
56
|
+
plt.rcParams['font.sans-serif'] = [family] if isinstance(family, str) else family
|
|
57
|
+
if size is not None:
|
|
58
|
+
plt.rcParams['font.size'] = size
|
|
59
|
+
|
|
60
|
+
# Apply figure size if present
|
|
61
|
+
fig_cfg = cfg.get('figure', {})
|
|
62
|
+
if fig_cfg:
|
|
63
|
+
canvas_size = fig_cfg.get('canvas_size')
|
|
64
|
+
if canvas_size and isinstance(canvas_size, (list, tuple)) and len(canvas_size) == 2:
|
|
65
|
+
try:
|
|
66
|
+
fig.set_size_inches(canvas_size[0], canvas_size[1])
|
|
67
|
+
except Exception:
|
|
68
|
+
pass
|
|
69
|
+
|
|
70
|
+
# Apply tick parameters
|
|
71
|
+
ticks_cfg = cfg.get('ticks', {})
|
|
72
|
+
if ticks_cfg:
|
|
73
|
+
# Tick widths
|
|
74
|
+
widths = ticks_cfg.get('widths', {})
|
|
75
|
+
if widths.get('x_major') is not None:
|
|
76
|
+
ax.tick_params(axis='x', which='major', width=widths['x_major'])
|
|
77
|
+
if widths.get('x_minor') is not None:
|
|
78
|
+
ax.tick_params(axis='x', which='minor', width=widths['x_minor'])
|
|
79
|
+
if widths.get('y_major') is not None or widths.get('ly_major') is not None:
|
|
80
|
+
w = widths.get('y_major') or widths.get('ly_major')
|
|
81
|
+
ax.tick_params(axis='y', which='major', width=w)
|
|
82
|
+
if widths.get('y_minor') is not None or widths.get('ly_minor') is not None:
|
|
83
|
+
w = widths.get('y_minor') or widths.get('ly_minor')
|
|
84
|
+
ax.tick_params(axis='y', which='minor', width=w)
|
|
85
|
+
|
|
86
|
+
# Tick lengths
|
|
87
|
+
lengths = ticks_cfg.get('lengths', {})
|
|
88
|
+
if lengths.get('major') is not None:
|
|
89
|
+
ax.tick_params(axis='both', which='major', length=lengths['major'])
|
|
90
|
+
if lengths.get('minor') is not None:
|
|
91
|
+
ax.tick_params(axis='both', which='minor', length=lengths['minor'])
|
|
92
|
+
|
|
93
|
+
# Tick direction
|
|
94
|
+
direction = ticks_cfg.get('direction')
|
|
95
|
+
if direction:
|
|
96
|
+
ax.tick_params(axis='both', which='both', direction=direction)
|
|
97
|
+
|
|
98
|
+
# Apply geometry if present (for .bpsg files)
|
|
99
|
+
kind = cfg.get('kind', '')
|
|
100
|
+
if 'geom' in kind.lower() and 'geometry' in cfg:
|
|
101
|
+
geom = cfg.get('geometry', {})
|
|
102
|
+
if geom.get('xlabel'):
|
|
103
|
+
ax.set_xlabel(geom['xlabel'])
|
|
104
|
+
if geom.get('ylabel'):
|
|
105
|
+
ax.set_ylabel(geom['ylabel'])
|
|
106
|
+
if 'xlim' in geom and isinstance(geom['xlim'], (list, tuple)) and len(geom['xlim']) == 2:
|
|
107
|
+
try:
|
|
108
|
+
ax.set_xlim(geom['xlim'][0], geom['xlim'][1])
|
|
109
|
+
except Exception:
|
|
110
|
+
pass
|
|
111
|
+
if 'ylim' in geom and isinstance(geom['ylim'], (list, tuple)) and len(geom['ylim']) == 2:
|
|
112
|
+
try:
|
|
113
|
+
ax.set_ylim(geom['ylim'][0], geom['ylim'][1])
|
|
114
|
+
except Exception:
|
|
115
|
+
pass
|
|
116
|
+
|
|
117
|
+
# Apply line colors if available (for GC/CV/dQdV modes)
|
|
118
|
+
lines_cfg = cfg.get('lines', [])
|
|
119
|
+
if lines_cfg and len(ax.lines) > 0:
|
|
120
|
+
for entry in lines_cfg:
|
|
121
|
+
idx = entry.get('index')
|
|
122
|
+
if idx is not None and 0 <= idx < len(ax.lines):
|
|
123
|
+
ln = ax.lines[idx]
|
|
124
|
+
if 'color' in entry:
|
|
125
|
+
try:
|
|
126
|
+
ln.set_color(entry['color'])
|
|
127
|
+
except Exception:
|
|
128
|
+
pass
|
|
129
|
+
if 'linewidth' in entry:
|
|
130
|
+
try:
|
|
131
|
+
ln.set_linewidth(entry['linewidth'])
|
|
132
|
+
except Exception:
|
|
133
|
+
pass
|
|
134
|
+
if 'linestyle' in entry:
|
|
135
|
+
try:
|
|
136
|
+
ln.set_linestyle(entry['linestyle'])
|
|
137
|
+
except Exception:
|
|
138
|
+
pass
|
|
139
|
+
|
|
140
|
+
# Apply spine configuration
|
|
141
|
+
spines_cfg = cfg.get('spines', {})
|
|
142
|
+
for spine_name, spine_props in spines_cfg.items():
|
|
143
|
+
if spine_name in ax.spines:
|
|
144
|
+
sp = ax.spines[spine_name]
|
|
145
|
+
if 'lw' in spine_props or 'linewidth' in spine_props:
|
|
146
|
+
try:
|
|
147
|
+
lw = spine_props.get('lw') or spine_props.get('linewidth')
|
|
148
|
+
sp.set_linewidth(lw)
|
|
149
|
+
except Exception:
|
|
150
|
+
pass
|
|
151
|
+
if 'color' in spine_props:
|
|
152
|
+
try:
|
|
153
|
+
sp.set_edgecolor(spine_props['color'])
|
|
154
|
+
except Exception:
|
|
155
|
+
pass
|
|
156
|
+
if 'visible' in spine_props:
|
|
157
|
+
try:
|
|
158
|
+
sp.set_visible(spine_props['visible'])
|
|
159
|
+
except Exception:
|
|
160
|
+
pass
|
|
161
|
+
|
|
162
|
+
except Exception as e:
|
|
163
|
+
print(f"Warning: Error applying style: {e}")
|
|
164
|
+
|
|
165
|
+
|
|
19
166
|
def batch_process(directory: str, args):
|
|
20
167
|
print(f"Batch mode: scanning {directory}")
|
|
21
168
|
supported_ext = {'.xye', '.xy', '.qye', '.dat', '.csv', '.gr', '.nor', '.chik', '.chir', '.txt'}
|
|
@@ -168,15 +315,44 @@ def batch_process_ec(directory: str, args):
|
|
|
168
315
|
Supports GC (.mpt/.csv), CV (.mpt), dQdV (.csv), and CPC (.mpt/.csv) modes.
|
|
169
316
|
Exports SVG plots to batplot_svg subdirectory.
|
|
170
317
|
|
|
318
|
+
Can apply style/geometry from .bps/.bpsg files using --all flag:
|
|
319
|
+
batplot --all --gc style.bps # Apply style.bps to all .mpt/.csv GC files
|
|
320
|
+
batplot --all --cv style.bpsg # Apply style+geom to all CV files
|
|
321
|
+
batplot --all --dqdv mystyle.bps # Apply style to all dQdV files
|
|
322
|
+
batplot --all --cpc config.bpsg # Apply to all CPC files
|
|
323
|
+
|
|
171
324
|
Note: For GC and CPC modes with .csv files, --mass is not required as the
|
|
172
325
|
capacity data is already in the file. For .mpt files, --mass is required.
|
|
173
326
|
|
|
174
327
|
Args:
|
|
175
328
|
directory: Directory containing EC files
|
|
176
|
-
args: Argument namespace with mode flags (gc, cv, dqdv, cpc) and
|
|
329
|
+
args: Argument namespace with mode flags (gc, cv, dqdv, cpc), mass, and all
|
|
177
330
|
"""
|
|
178
331
|
print(f"EC Batch mode: scanning {directory}")
|
|
179
332
|
|
|
333
|
+
# Check if --all flag was used with a style file
|
|
334
|
+
style_cfg = None
|
|
335
|
+
style_file_arg = getattr(args, 'all', None)
|
|
336
|
+
if style_file_arg and style_file_arg != 'all':
|
|
337
|
+
# User provided a style file path
|
|
338
|
+
style_path = style_file_arg if os.path.isabs(style_file_arg) else os.path.join(directory, style_file_arg)
|
|
339
|
+
if os.path.exists(style_path) and style_path.lower().endswith(('.bps', '.bpsg', '.bpcfg')):
|
|
340
|
+
style_cfg = _load_style_file(style_path)
|
|
341
|
+
if style_cfg:
|
|
342
|
+
print(f"Using style file: {os.path.basename(style_path)}")
|
|
343
|
+
else:
|
|
344
|
+
# Try to find the file in current directory
|
|
345
|
+
for ext in ['.bps', '.bpsg', '.bpcfg']:
|
|
346
|
+
test_path = style_file_arg if style_file_arg.endswith(ext) else style_file_arg + ext
|
|
347
|
+
test_full = os.path.join(directory, test_path)
|
|
348
|
+
if os.path.exists(test_full):
|
|
349
|
+
style_cfg = _load_style_file(test_full)
|
|
350
|
+
if style_cfg:
|
|
351
|
+
print(f"Using style file: {os.path.basename(test_full)}")
|
|
352
|
+
break
|
|
353
|
+
if not style_cfg:
|
|
354
|
+
print(f"Warning: Could not find style file '{style_file_arg}'")
|
|
355
|
+
|
|
180
356
|
# Determine which EC mode is active
|
|
181
357
|
mode = None
|
|
182
358
|
if getattr(args, 'gc', False):
|
|
@@ -490,6 +666,13 @@ def batch_process_ec(directory: str, args):
|
|
|
490
666
|
ax_b.legend()
|
|
491
667
|
ax_b.set_title(f"{fname}")
|
|
492
668
|
|
|
669
|
+
# Apply style/geometry if provided via --all flag
|
|
670
|
+
if style_cfg:
|
|
671
|
+
try:
|
|
672
|
+
_apply_ec_style(fig_b, ax_b, style_cfg)
|
|
673
|
+
except Exception as e:
|
|
674
|
+
print(f" Warning: Could not apply style to {fname}: {e}")
|
|
675
|
+
|
|
493
676
|
# Adjust layout and save
|
|
494
677
|
fig_b.subplots_adjust(left=0.18, right=0.97, bottom=0.16, top=0.90)
|
|
495
678
|
out_name = os.path.splitext(fname)[0] + f"_{mode}.svg"
|
|
@@ -98,6 +98,11 @@ def batplot_main() -> int:
|
|
|
98
98
|
getattr(args, 'cpc', False)
|
|
99
99
|
])
|
|
100
100
|
|
|
101
|
+
# Check for --all flag (with or without style file)
|
|
102
|
+
if ec_mode_active and getattr(args, 'all', None) is not None:
|
|
103
|
+
batch_process_ec(os.getcwd(), args)
|
|
104
|
+
exit()
|
|
105
|
+
|
|
101
106
|
if ec_mode_active and len(args.files) == 1:
|
|
102
107
|
sole = args.files[0]
|
|
103
108
|
if sole.lower() == 'all':
|
|
@@ -1362,6 +1367,23 @@ def batplot_main() -> int:
|
|
|
1362
1367
|
ax.tick_params(axis='y', which='minor', width=tw['y_minor'])
|
|
1363
1368
|
except Exception:
|
|
1364
1369
|
pass
|
|
1370
|
+
# Tick lengths restore
|
|
1371
|
+
try:
|
|
1372
|
+
tl = sess.get('tick_lengths', {})
|
|
1373
|
+
if tl.get('x_major') is not None or tl.get('y_major') is not None:
|
|
1374
|
+
major_len = tl.get('x_major') or tl.get('y_major')
|
|
1375
|
+
ax.tick_params(axis='both', which='major', length=major_len)
|
|
1376
|
+
if not hasattr(fig, '_tick_lengths'):
|
|
1377
|
+
fig._tick_lengths = {}
|
|
1378
|
+
fig._tick_lengths['major'] = major_len
|
|
1379
|
+
if tl.get('x_minor') is not None or tl.get('y_minor') is not None:
|
|
1380
|
+
minor_len = tl.get('x_minor') or tl.get('y_minor')
|
|
1381
|
+
ax.tick_params(axis='both', which='minor', length=minor_len)
|
|
1382
|
+
if not hasattr(fig, '_tick_lengths'):
|
|
1383
|
+
fig._tick_lengths = {}
|
|
1384
|
+
fig._tick_lengths['minor'] = minor_len
|
|
1385
|
+
except Exception:
|
|
1386
|
+
pass
|
|
1365
1387
|
# Rebuild label texts
|
|
1366
1388
|
for i, lab in enumerate(labels_list):
|
|
1367
1389
|
txt = ax.text(1.0, 1.0, f"{i+1}: {lab}", ha='right', va='top', transform=ax.transAxes,
|
|
@@ -1374,6 +1396,7 @@ def batplot_main() -> int:
|
|
|
1374
1396
|
cif_numbering_enabled = True
|
|
1375
1397
|
cif_extend_suspended = False
|
|
1376
1398
|
show_cif_hkl = sess.get('show_cif_hkl', False)
|
|
1399
|
+
show_cif_titles = sess.get('show_cif_titles', True)
|
|
1377
1400
|
# Provide minimal stubs to satisfy interactive menu dependencies
|
|
1378
1401
|
# Axis mode restoration informs downstream toggles (e.g., CIF conversions, crosshair availability)
|
|
1379
1402
|
axis_mode_restored = sess.get('axis_mode', 'unknown')
|
|
@@ -1652,6 +1675,8 @@ def batplot_main() -> int:
|
|
|
1652
1675
|
if args.xaxis and args.xaxis.lower() in ("2theta","two_theta","tth"):
|
|
1653
1676
|
axis_mode = "2theta"
|
|
1654
1677
|
else:
|
|
1678
|
+
# If wavelength is provided, user wants to convert to Q
|
|
1679
|
+
# CIF files are in Q space
|
|
1655
1680
|
axis_mode = "Q"
|
|
1656
1681
|
elif args.xaxis:
|
|
1657
1682
|
axis_mode = args.xaxis
|
|
@@ -1665,6 +1690,16 @@ def batplot_main() -> int:
|
|
|
1665
1690
|
use_k = axis_mode == "k" # NEW
|
|
1666
1691
|
use_rft = axis_mode == "rft" # NEW
|
|
1667
1692
|
|
|
1693
|
+
# Validate: if using 2theta mode with CIF files, wavelength is required
|
|
1694
|
+
if use_2th and any_cif and not wavelength_file:
|
|
1695
|
+
raise ValueError(
|
|
1696
|
+
"Cannot display CIF files in 2θ mode without wavelength.\n"
|
|
1697
|
+
"Please provide wavelength using:\n"
|
|
1698
|
+
" --wl <wavelength_in_angstrom>\n"
|
|
1699
|
+
" or include wavelength in filename (e.g., data_wl1.5406.xy)\n"
|
|
1700
|
+
" or use Q mode (remove --xaxis 2theta)"
|
|
1701
|
+
)
|
|
1702
|
+
|
|
1668
1703
|
# ---------------- Read and plot files ----------------
|
|
1669
1704
|
# Helper to extract discrete peak positions from a simulated CIF pattern by local maxima picking
|
|
1670
1705
|
def _extract_peak_positions(Q_array, I_array, min_rel_height=0.05):
|
|
@@ -1702,6 +1737,7 @@ def batplot_main() -> int:
|
|
|
1702
1737
|
# Cached wavelength for CIF tick conversion (prevents interactive blocking prompts)
|
|
1703
1738
|
cif_cached_wavelength = None
|
|
1704
1739
|
show_cif_hkl = False
|
|
1740
|
+
show_cif_titles = True # show CIF filename labels by default
|
|
1705
1741
|
|
|
1706
1742
|
for idx_file, file_entry in enumerate(args.files):
|
|
1707
1743
|
parts = file_entry.split(":")
|
|
@@ -2058,10 +2094,12 @@ def batplot_main() -> int:
|
|
|
2058
2094
|
ln, = ax.plot([p,p],[y_line, y_line+0.02*yr], color=color, lw=1.0, alpha=0.9, zorder=3)
|
|
2059
2095
|
new_art.append(ln)
|
|
2060
2096
|
# Removed numbering; keep space padding (placed per CIF row)
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2097
|
+
# Only add title label if show_cif_titles is True
|
|
2098
|
+
if globals().get('show_cif_titles', True):
|
|
2099
|
+
label_text = f" {lab}"
|
|
2100
|
+
txt = ax.text(ax.get_xlim()[0], y_line + 0.005*yr, label_text,
|
|
2101
|
+
ha='left', va='bottom', fontsize=max(8,int(0.55*plt.rcParams.get('font.size',12))), color=color)
|
|
2102
|
+
new_art.append(txt)
|
|
2065
2103
|
ax._cif_tick_art = new_art
|
|
2066
2104
|
# Store simplified metadata for hover: list of dicts with 'x','y','label'
|
|
2067
2105
|
hover_meta = []
|
|
@@ -2264,6 +2302,7 @@ def batplot_main() -> int:
|
|
|
2264
2302
|
'cif_hkl_map': cif_hkl_map,
|
|
2265
2303
|
'cif_hkl_label_map': cif_hkl_label_map,
|
|
2266
2304
|
'show_cif_hkl': show_cif_hkl,
|
|
2305
|
+
'show_cif_titles': show_cif_titles,
|
|
2267
2306
|
'cif_extend_suspended': cif_extend_suspended,
|
|
2268
2307
|
'keep_canvas_fixed': keep_canvas_fixed,
|
|
2269
2308
|
}
|