batplot 1.7.22__py3-none-any.whl → 1.7.24__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.
Potentially problematic release.
This version of batplot might be problematic. Click here for more details.
- batplot/__init__.py +1 -1
- batplot/args.py +1 -0
- batplot/cpc_interactive.py +168 -11
- batplot/electrochem_interactive.py +152 -14
- batplot/interactive.py +156 -30
- batplot/operando_ec_interactive.py +198 -21
- batplot/session.py +92 -1
- batplot/style.py +109 -47
- {batplot-1.7.22.dist-info → batplot-1.7.24.dist-info}/METADATA +26 -3
- {batplot-1.7.22.dist-info → batplot-1.7.24.dist-info}/RECORD +14 -14
- {batplot-1.7.22.dist-info → batplot-1.7.24.dist-info}/WHEEL +0 -0
- {batplot-1.7.22.dist-info → batplot-1.7.24.dist-info}/entry_points.txt +0 -0
- {batplot-1.7.22.dist-info → batplot-1.7.24.dist-info}/licenses/LICENSE +0 -0
- {batplot-1.7.22.dist-info → batplot-1.7.24.dist-info}/top_level.txt +0 -0
batplot/style.py
CHANGED
|
@@ -500,7 +500,8 @@ def export_style_config(
|
|
|
500
500
|
label_text_objects: Optional[List] = None,
|
|
501
501
|
base_path: Optional[str] = None,
|
|
502
502
|
show_cif_titles: Optional[bool] = None,
|
|
503
|
-
|
|
503
|
+
overwrite_path: Optional[str] = None,
|
|
504
|
+
) -> Optional[str]:
|
|
504
505
|
"""Export style configuration after displaying a summary and prompting the user.
|
|
505
506
|
|
|
506
507
|
This function now matches the EC menu workflow: display summary, then prompt for export.
|
|
@@ -635,6 +636,14 @@ def export_style_config(
|
|
|
635
636
|
"has_left_y": bool(ax.yaxis.label.get_visible()),
|
|
636
637
|
}
|
|
637
638
|
cfg["axis_title_texts"] = axis_title_texts
|
|
639
|
+
cfg["title_offsets"] = {
|
|
640
|
+
"top_y": float(getattr(ax, '_top_xlabel_manual_offset_y_pts', 0.0) or 0.0),
|
|
641
|
+
"top_x": float(getattr(ax, '_top_xlabel_manual_offset_x_pts', 0.0) or 0.0),
|
|
642
|
+
"bottom_y": float(getattr(ax, '_bottom_xlabel_manual_offset_y_pts', 0.0) or 0.0),
|
|
643
|
+
"left_x": float(getattr(ax, '_left_ylabel_manual_offset_x_pts', 0.0) or 0.0),
|
|
644
|
+
"right_x": float(getattr(ax, '_right_ylabel_manual_offset_x_pts', 0.0) or 0.0),
|
|
645
|
+
"right_y": float(getattr(ax, '_right_ylabel_manual_offset_y_pts', 0.0) or 0.0),
|
|
646
|
+
}
|
|
638
647
|
# Save rotation angle
|
|
639
648
|
cfg["rotation_angle"] = getattr(ax, '_rotation_angle', 0)
|
|
640
649
|
|
|
@@ -674,14 +683,27 @@ def export_style_config(
|
|
|
674
683
|
if serialized_palettes:
|
|
675
684
|
cfg['curve_palettes'] = serialized_palettes
|
|
676
685
|
|
|
677
|
-
#
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
686
|
+
# If overwrite_path is provided, determine export type from existing file
|
|
687
|
+
if overwrite_path:
|
|
688
|
+
try:
|
|
689
|
+
with open(overwrite_path, 'r', encoding='utf-8') as f:
|
|
690
|
+
old_cfg = json.load(f)
|
|
691
|
+
old_kind = old_cfg.get('kind', '')
|
|
692
|
+
if old_kind == 'xy_style_geom':
|
|
693
|
+
exp_choice = 'psg'
|
|
694
|
+
else:
|
|
695
|
+
exp_choice = 'ps'
|
|
696
|
+
except Exception:
|
|
697
|
+
exp_choice = 'ps' # Default to style-only if can't read
|
|
698
|
+
else:
|
|
699
|
+
# Ask user for style-only or style+geometry
|
|
700
|
+
print("\nExport options:")
|
|
701
|
+
print(" ps = style only (.bps)")
|
|
702
|
+
print(" psg = style + geometry (.bpsg)")
|
|
703
|
+
exp_choice = input("Export choice (ps/psg, q=cancel): ").strip().lower()
|
|
704
|
+
if not exp_choice or exp_choice == 'q':
|
|
705
|
+
print("Style export canceled.")
|
|
706
|
+
return None
|
|
685
707
|
|
|
686
708
|
# Determine file extension and add geometry if requested
|
|
687
709
|
if exp_choice == 'ps':
|
|
@@ -704,55 +726,74 @@ def export_style_config(
|
|
|
704
726
|
print(f"Unknown option: {exp_choice}")
|
|
705
727
|
return
|
|
706
728
|
|
|
707
|
-
#
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
print(f"\nExisting {default_ext} files in {styles_dir}:")
|
|
720
|
-
for i, f in enumerate(style_files, 1):
|
|
721
|
-
print(f" {i}: {f}")
|
|
729
|
+
# If overwrite_path is provided, use it directly
|
|
730
|
+
if overwrite_path:
|
|
731
|
+
target_path = overwrite_path
|
|
732
|
+
else:
|
|
733
|
+
# List existing files for user convenience (from Styles subdirectory)
|
|
734
|
+
import os
|
|
735
|
+
from .utils import list_files_in_subdirectory, get_organized_path
|
|
736
|
+
|
|
737
|
+
if base_path:
|
|
738
|
+
print(f"\nChosen path: {base_path}")
|
|
739
|
+
file_list = list_files_in_subdirectory((default_ext, '.bpcfg'), 'style', base_path=base_path)
|
|
740
|
+
style_files = [f[0] for f in file_list]
|
|
722
741
|
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
742
|
+
if style_files:
|
|
743
|
+
styles_root = base_path if base_path else os.getcwd()
|
|
744
|
+
styles_dir = os.path.join(styles_root, 'Styles')
|
|
745
|
+
print(f"\nExisting {default_ext} files in {styles_dir}:")
|
|
746
|
+
for i, f in enumerate(style_files, 1):
|
|
747
|
+
print(f" {i}: {f}")
|
|
727
748
|
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
else:
|
|
732
|
-
# Add default extension if no extension provided
|
|
733
|
-
if not any(choice.lower().endswith(ext) for ext in ['.bps', '.bpsg', '.bpcfg']):
|
|
734
|
-
filename_with_ext = f"{choice}{default_ext}"
|
|
749
|
+
last_style_path = getattr(fig, '_last_style_export_path', None)
|
|
750
|
+
if last_style_path:
|
|
751
|
+
choice = input("Export to file? Enter filename, number to overwrite, or o to overwrite last (q=cancel): ").strip()
|
|
735
752
|
else:
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
753
|
+
choice = input("Export to file? Enter filename or number to overwrite (q=cancel): ").strip()
|
|
754
|
+
if not choice or choice.lower() == 'q':
|
|
755
|
+
print("Style export canceled.")
|
|
756
|
+
return None
|
|
757
|
+
if choice.lower() == 'o':
|
|
758
|
+
# Overwrite last exported style file - handled by caller
|
|
759
|
+
if not last_style_path:
|
|
760
|
+
print("No previous export found.")
|
|
761
|
+
return None
|
|
762
|
+
if not os.path.exists(last_style_path):
|
|
763
|
+
print(f"Previous export file not found: {last_style_path}")
|
|
764
|
+
return None
|
|
765
|
+
target_path = last_style_path
|
|
741
766
|
else:
|
|
742
|
-
|
|
767
|
+
# Determine the target path
|
|
768
|
+
if choice.isdigit() and style_files and 1 <= int(choice) <= len(style_files):
|
|
769
|
+
target_path = file_list[int(choice) - 1][1] # Full path from list
|
|
770
|
+
else:
|
|
771
|
+
# Add default extension if no extension provided
|
|
772
|
+
if not any(choice.lower().endswith(ext) for ext in ['.bps', '.bpsg', '.bpcfg']):
|
|
773
|
+
filename_with_ext = f"{choice}{default_ext}"
|
|
774
|
+
else:
|
|
775
|
+
filename_with_ext = choice
|
|
776
|
+
|
|
777
|
+
# Use organized path unless it's an absolute path
|
|
778
|
+
if os.path.isabs(filename_with_ext):
|
|
779
|
+
target_path = filename_with_ext
|
|
780
|
+
else:
|
|
781
|
+
target_path = get_organized_path(filename_with_ext, 'style', base_path=base_path)
|
|
743
782
|
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
783
|
+
# Only prompt ONCE for overwrite if the file exists
|
|
784
|
+
if os.path.exists(target_path):
|
|
785
|
+
yn = input(f"Overwrite '{os.path.basename(target_path)}'? (y/n): ").strip().lower()
|
|
786
|
+
if yn != 'y':
|
|
787
|
+
print("Style export canceled.")
|
|
788
|
+
return None
|
|
750
789
|
|
|
751
790
|
with open(target_path, "w", encoding="utf-8") as f:
|
|
752
791
|
json.dump(cfg, f, indent=2)
|
|
753
792
|
print(f"Exported style to {target_path}")
|
|
793
|
+
return target_path
|
|
754
794
|
except Exception as e:
|
|
755
795
|
print(f"Error exporting style: {e}")
|
|
796
|
+
return None
|
|
756
797
|
|
|
757
798
|
|
|
758
799
|
def apply_style_config(
|
|
@@ -1204,6 +1245,27 @@ def apply_style_config(
|
|
|
1204
1245
|
except Exception as e:
|
|
1205
1246
|
print(f"Warning: Could not restore rotation angle: {e}")
|
|
1206
1247
|
|
|
1248
|
+
# Restore title offsets BEFORE positioning titles
|
|
1249
|
+
title_offsets = cfg.get("title_offsets", {})
|
|
1250
|
+
if title_offsets:
|
|
1251
|
+
try:
|
|
1252
|
+
if 'top_y' in title_offsets:
|
|
1253
|
+
ax._top_xlabel_manual_offset_y_pts = float(title_offsets.get('top_y', 0.0) or 0.0)
|
|
1254
|
+
else:
|
|
1255
|
+
# Backward compatibility: old format used 'top' for y-offset
|
|
1256
|
+
ax._top_xlabel_manual_offset_y_pts = float(title_offsets.get('top', 0.0) or 0.0)
|
|
1257
|
+
ax._top_xlabel_manual_offset_x_pts = float(title_offsets.get('top_x', 0.0) or 0.0)
|
|
1258
|
+
ax._bottom_xlabel_manual_offset_y_pts = float(title_offsets.get('bottom_y', 0.0) or 0.0)
|
|
1259
|
+
ax._left_ylabel_manual_offset_x_pts = float(title_offsets.get('left_x', 0.0) or 0.0)
|
|
1260
|
+
if 'right_x' in title_offsets:
|
|
1261
|
+
ax._right_ylabel_manual_offset_x_pts = float(title_offsets.get('right_x', 0.0) or 0.0)
|
|
1262
|
+
else:
|
|
1263
|
+
# Backward compatibility: old format used 'right' for x-offset
|
|
1264
|
+
ax._right_ylabel_manual_offset_x_pts = float(title_offsets.get('right', 0.0) or 0.0)
|
|
1265
|
+
ax._right_ylabel_manual_offset_y_pts = float(title_offsets.get('right_y', 0.0) or 0.0)
|
|
1266
|
+
except Exception as e:
|
|
1267
|
+
print(f"Warning: Could not restore title offsets: {e}")
|
|
1268
|
+
|
|
1207
1269
|
# Restore grid state
|
|
1208
1270
|
if "grid" in cfg:
|
|
1209
1271
|
try:
|
|
@@ -1,9 +1,30 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: batplot
|
|
3
|
-
Version: 1.7.
|
|
3
|
+
Version: 1.7.24
|
|
4
4
|
Summary: Interactive plotting tool for material science (1D plot) and electrochemistry (GC, CV, dQ/dV, CPC, operando) with batch processing
|
|
5
5
|
Author-email: Tian Dai <tianda@uio.no>
|
|
6
|
-
License
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2025 Tian Dai
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
7
28
|
Project-URL: Homepage, https://github.com/TianDai1729/batplot
|
|
8
29
|
Project-URL: Repository, https://github.com/TianDai1729/batplot
|
|
9
30
|
Project-URL: Issues, https://github.com/TianDai1729/batplot/issues
|
|
@@ -171,7 +192,9 @@ See [LICENSE](LICENSE)
|
|
|
171
192
|
|
|
172
193
|
## Author & Contact
|
|
173
194
|
|
|
174
|
-
Tian Dai
|
|
195
|
+
Tian Dai
|
|
196
|
+
tianda@uio.no
|
|
175
197
|
University of Oslo
|
|
198
|
+
https://www.mn.uio.no/kjemi/english/people/aca/tianda/
|
|
176
199
|
|
|
177
200
|
**Subscribe for Updates**: Join batplot-lab@kjemi.uio.no for updates, feature announcements, and community feedback. If you are not from UiO, send an email to sympa@kjemi.uio.no with the exact subject line with your name: "subscribe batplot-lab@kjemi.uio.no your-name"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
batplot/__init__.py,sha256=
|
|
2
|
-
batplot/args.py,sha256=
|
|
1
|
+
batplot/__init__.py,sha256=vcxX_RWa2zNjGw0VeGmJHavkp3EFX9_6FzqOzyahxOI,119
|
|
2
|
+
batplot/args.py,sha256=6g1eHVsycDSAenwrXuCTcyuXCy_-30zy1lWtdguBG2s,34983
|
|
3
3
|
batplot/batch.py,sha256=YQ7obCIqLCObwDbM7TXpOBh7g7BO95wZNsa2Fy84c6o,53858
|
|
4
4
|
batplot/batplot.py,sha256=h960XKSmJ825DqI99Xnyomg_gaB0aFDUIKxkovm8BPQ,170691
|
|
5
5
|
batplot/cif.py,sha256=JfHwNf3SHrcpALc_F5NjJmQ3lg71MBRSaIUJjGYPTx8,30120
|
|
@@ -7,22 +7,22 @@ batplot/cli.py,sha256=ScDb2je8VQ0mz_z0SLCHEigiTuFPY5pb1snnzCouKms,5828
|
|
|
7
7
|
batplot/color_utils.py,sha256=ow2ElqjIWFLRdrnLwQvrnfa3w3IEB0FodPFdoDQR_Dc,19990
|
|
8
8
|
batplot/config.py,sha256=6nGY7fKN4T5KZUGQS2ArUBgEkLAL0j37XwG5SCVQgKA,6420
|
|
9
9
|
batplot/converters.py,sha256=rR2WMPM0nR5E3eZI3gWbaJf_AfbdQx3urVSbJmZXNzo,8237
|
|
10
|
-
batplot/cpc_interactive.py,sha256=
|
|
11
|
-
batplot/electrochem_interactive.py,sha256=
|
|
12
|
-
batplot/interactive.py,sha256=
|
|
10
|
+
batplot/cpc_interactive.py,sha256=zeMIoPt8fNEi-PcxkMf2PnU7k8owoU6SUfsruohIAsM,195690
|
|
11
|
+
batplot/electrochem_interactive.py,sha256=ig9I-bQelTIRxSdXMppdA9RBqrR9vJ1lbkyNtwTC7-A,217226
|
|
12
|
+
batplot/interactive.py,sha256=R9ipqK4ZN5wwe6L1mcvWt1TbmGXwPU87V5jm1BWvgeM,203584
|
|
13
13
|
batplot/manual.py,sha256=pbRI6G4Pm12pOW8LrOLWWu7IEOtqWN3tRHtgge50LlA,11556
|
|
14
14
|
batplot/modes.py,sha256=qE2OsOQQKhwOWene5zxJeuuewTrZxubtahQuz5je7ok,37252
|
|
15
15
|
batplot/operando.py,sha256=CdTZJa6Cr1wNczFEbwAido2mc7C_h1xxoQ5b045ktSk,28105
|
|
16
|
-
batplot/operando_ec_interactive.py,sha256=
|
|
16
|
+
batplot/operando_ec_interactive.py,sha256=wMuWMz96TeJcKp52iUEqsWy6_NTxAagva4NvCALG0GI,293064
|
|
17
17
|
batplot/plotting.py,sha256=hG2_EdDhF1Qpn1XfZKdCQ5-w_m9gUYFbr804UQ5QjsU,10841
|
|
18
18
|
batplot/readers.py,sha256=kAI0AvYrdfGRZkvADJ4riN96IWtrH24aAoZpBtONTbw,112960
|
|
19
|
-
batplot/session.py,sha256=
|
|
20
|
-
batplot/style.py,sha256=
|
|
19
|
+
batplot/session.py,sha256=fuUCRdZ2Trl_RKuFgF_m4BUfplhhzOHJ16vtetLC2T0,126312
|
|
20
|
+
batplot/style.py,sha256=ZeRJ15fneSQqCYN_SGap-9Y2J8UkzRxYmf6qLJA6zMo,62058
|
|
21
21
|
batplot/ui.py,sha256=MIY2x_ghCYxjdYhjMUZsMMnQEUBLgrIT37hfPGZf_cs,36320
|
|
22
22
|
batplot/utils.py,sha256=3dBZALWiCu5c6uc5MBII7n8329BZjieTEw4qithTlow,33939
|
|
23
23
|
batplot/version_check.py,sha256=OG4LuHo5-rSqLLHQo5nWbX9lbNq6NyxRdvVUUcJRBqQ,6219
|
|
24
24
|
batplot/data/USER_MANUAL.md,sha256=VYPvNZt3Fy8Z4Izr2FnQBw9vEaFTPkybhHDnF-OuKws,17694
|
|
25
|
-
batplot-1.7.
|
|
25
|
+
batplot-1.7.24.dist-info/licenses/LICENSE,sha256=2PAnHeCiTfgI7aKZLWr0G56HI9fGKQ0CEbQ02H-yExQ,1065
|
|
26
26
|
batplot_backup_20251121_223043/__init__.py,sha256=3s2DUQuTbWs65hoN9cQQ8IiJbaFJY8fNxiCpwRBYoOA,118
|
|
27
27
|
batplot_backup_20251121_223043/args.py,sha256=OH-h84QhN-IhMS8sPAsSEqccHD3wpeMgmXa_fqv5xtg,21215
|
|
28
28
|
batplot_backup_20251121_223043/batch.py,sha256=oI7PONJyciHDOqNPq-8fnOQMyn9CpAdVznKaEdsy0ig,48650
|
|
@@ -45,8 +45,8 @@ batplot_backup_20251121_223043/style.py,sha256=xg-tj6bEbFUVjjxYMokiLehS4tSfKanLI
|
|
|
45
45
|
batplot_backup_20251121_223043/ui.py,sha256=K0XZWyiuBRNkFod9mgZyJ9CLN78GR1-hh6EznnIb5S8,31208
|
|
46
46
|
batplot_backup_20251121_223043/utils.py,sha256=jydA0JxsCWWAudXEwSjlxTG17y2F8U6hIAukAzi1P0g,32526
|
|
47
47
|
batplot_backup_20251121_223043/version_check.py,sha256=vlHkGkgUJcD_Z4KZmwonxZvKZh0MwHLaBSxaLPc66AQ,4555
|
|
48
|
-
batplot-1.7.
|
|
49
|
-
batplot-1.7.
|
|
50
|
-
batplot-1.7.
|
|
51
|
-
batplot-1.7.
|
|
52
|
-
batplot-1.7.
|
|
48
|
+
batplot-1.7.24.dist-info/METADATA,sha256=dJA_9A2XGrZlSltD6KplJokAvn02C88tY4LYxc9A1mg,7407
|
|
49
|
+
batplot-1.7.24.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
50
|
+
batplot-1.7.24.dist-info/entry_points.txt,sha256=73GgH3Zs-qGIvgiyQLgGsSW-ryOwPPKHveOW6TDIR5Q,82
|
|
51
|
+
batplot-1.7.24.dist-info/top_level.txt,sha256=CgqK4RpsYnUFAcqO4bLOnEhCoPY4IPEGLPkiDlzLIxg,39
|
|
52
|
+
batplot-1.7.24.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|