batplot 1.3.5__tar.gz → 1.3.7__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.3.5 → batplot-1.3.7}/PKG-INFO +4 -1
- {batplot-1.3.5 → batplot-1.3.7}/README.md +2 -0
- {batplot-1.3.5 → batplot-1.3.7}/batplot/__init__.py +1 -1
- {batplot-1.3.5 → batplot-1.3.7}/batplot/args.py +68 -6
- {batplot-1.3.5 → batplot-1.3.7}/batplot/batplot.py +17 -1
- {batplot-1.3.5 → batplot-1.3.7}/batplot/operando.py +20 -4
- {batplot-1.3.5 → batplot-1.3.7}/batplot/operando_ec_interactive.py +11 -1
- {batplot-1.3.5 → batplot-1.3.7}/batplot/readers.py +47 -6
- {batplot-1.3.5 → batplot-1.3.7}/batplot.egg-info/PKG-INFO +4 -1
- {batplot-1.3.5 → batplot-1.3.7}/batplot.egg-info/requires.txt +1 -0
- {batplot-1.3.5 → batplot-1.3.7}/pyproject.toml +3 -2
- {batplot-1.3.5 → batplot-1.3.7}/LICENSE +0 -0
- {batplot-1.3.5 → batplot-1.3.7}/batplot/batch.py +0 -0
- {batplot-1.3.5 → batplot-1.3.7}/batplot/batplot_new.py +0 -0
- {batplot-1.3.5 → batplot-1.3.7}/batplot/cif.py +0 -0
- {batplot-1.3.5 → batplot-1.3.7}/batplot/cli.py +0 -0
- {batplot-1.3.5 → batplot-1.3.7}/batplot/converters.py +0 -0
- {batplot-1.3.5 → batplot-1.3.7}/batplot/cpc_interactive.py +0 -0
- {batplot-1.3.5 → batplot-1.3.7}/batplot/electrochem_interactive.py +0 -0
- {batplot-1.3.5 → batplot-1.3.7}/batplot/interactive.py +0 -0
- {batplot-1.3.5 → batplot-1.3.7}/batplot/modes.py +0 -0
- {batplot-1.3.5 → batplot-1.3.7}/batplot/plotting.py +0 -0
- {batplot-1.3.5 → batplot-1.3.7}/batplot/session.py +0 -0
- {batplot-1.3.5 → batplot-1.3.7}/batplot/style.py +0 -0
- {batplot-1.3.5 → batplot-1.3.7}/batplot/ui.py +0 -0
- {batplot-1.3.5 → batplot-1.3.7}/batplot/utils.py +0 -0
- {batplot-1.3.5 → batplot-1.3.7}/batplot.egg-info/SOURCES.txt +0 -0
- {batplot-1.3.5 → batplot-1.3.7}/batplot.egg-info/dependency_links.txt +0 -0
- {batplot-1.3.5 → batplot-1.3.7}/batplot.egg-info/entry_points.txt +0 -0
- {batplot-1.3.5 → batplot-1.3.7}/batplot.egg-info/top_level.txt +0 -0
- {batplot-1.3.5 → batplot-1.3.7}/setup.cfg +0 -0
- {batplot-1.3.5 → batplot-1.3.7}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: batplot
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.7
|
|
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
|
|
@@ -45,6 +45,7 @@ Description-Content-Type: text/markdown
|
|
|
45
45
|
License-File: LICENSE
|
|
46
46
|
Requires-Dist: numpy
|
|
47
47
|
Requires-Dist: matplotlib
|
|
48
|
+
Requires-Dist: rich>=10.0.0
|
|
48
49
|
Dynamic: license-file
|
|
49
50
|
|
|
50
51
|
# batplot
|
|
@@ -179,3 +180,5 @@ Tian Dai (tianda@uio.no)
|
|
|
179
180
|
University of Oslo
|
|
180
181
|
|
|
181
182
|
**GitHub**: https://github.com/tiandai-chem/batplot
|
|
183
|
+
|
|
184
|
+
**Subscribe for Updates**: Join batplot-lab@kjemi.uio.no for updates, feature announcements, and community feedback
|
|
@@ -4,6 +4,64 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import argparse
|
|
6
6
|
import sys
|
|
7
|
+
import re
|
|
8
|
+
|
|
9
|
+
# Try to import rich for colored output
|
|
10
|
+
try:
|
|
11
|
+
from rich.console import Console
|
|
12
|
+
from rich.markup import escape
|
|
13
|
+
_console = Console()
|
|
14
|
+
_HAS_RICH = True
|
|
15
|
+
except ImportError:
|
|
16
|
+
_console = None
|
|
17
|
+
_HAS_RICH = False
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _colorize_help(text: str) -> str:
|
|
21
|
+
"""Add colors to help text by highlighting flags and special elements.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
text: Plain help text
|
|
25
|
+
|
|
26
|
+
Returns:
|
|
27
|
+
Text with rich markup for colored output
|
|
28
|
+
"""
|
|
29
|
+
if not _HAS_RICH:
|
|
30
|
+
return text
|
|
31
|
+
|
|
32
|
+
# Escape any existing markup
|
|
33
|
+
text = escape(text)
|
|
34
|
+
|
|
35
|
+
# Color all flags (--flag or -f)
|
|
36
|
+
text = re.sub(r'(--[\w-]+)', r'[cyan]\1[/cyan]', text)
|
|
37
|
+
text = re.sub(r'(\s-[a-zA-Z]\b)', r'[cyan]\1[/cyan]', text)
|
|
38
|
+
|
|
39
|
+
# Color file extensions
|
|
40
|
+
text = re.sub(r'(\.\w{2,4}\b)', r'[yellow]\1[/yellow]', text)
|
|
41
|
+
|
|
42
|
+
# Color example commands (batplot at start of line or after whitespace)
|
|
43
|
+
text = re.sub(r'(batplot\s+[^\n]+)', r'[green]\1[/green]', text)
|
|
44
|
+
|
|
45
|
+
# Color section headers (lines ending with :)
|
|
46
|
+
text = re.sub(r'^([A-Z][\w\s/()]+:)$', r'[bold blue]\1[/bold blue]', text, flags=re.MULTILINE)
|
|
47
|
+
|
|
48
|
+
# Color special markers
|
|
49
|
+
text = text.replace('•', '[bold]•[/bold]')
|
|
50
|
+
|
|
51
|
+
return text
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def _print_help(text: str) -> None:
|
|
55
|
+
"""Print help text with optional coloring.
|
|
56
|
+
|
|
57
|
+
Args:
|
|
58
|
+
text: Help text to print
|
|
59
|
+
"""
|
|
60
|
+
if _HAS_RICH and _console:
|
|
61
|
+
colored_text = _colorize_help(text)
|
|
62
|
+
_console.print(colored_text)
|
|
63
|
+
else:
|
|
64
|
+
print(text)
|
|
7
65
|
|
|
8
66
|
|
|
9
67
|
def _print_general_help() -> None:
|
|
@@ -46,11 +104,12 @@ def _print_general_help() -> None:
|
|
|
46
104
|
" batplot -h xy # XY file plotting guide\n"
|
|
47
105
|
" batplot -h ec # Electrochemistry (GC/dQdV/CV/CPC) guide\n"
|
|
48
106
|
" batplot -h op # Operando guide\n\n"
|
|
49
|
-
"Contact:\n"
|
|
107
|
+
"Contact & Updates:\n"
|
|
108
|
+
" Subscribe to batplot-lab@kjemi.uio.no for updates and feedback\n"
|
|
50
109
|
" GitHub: https://github.com/tiandai-chem/batplot\n"
|
|
51
110
|
" Email: tianda@uio.no\n"
|
|
52
111
|
)
|
|
53
|
-
|
|
112
|
+
_print_help(msg)
|
|
54
113
|
|
|
55
114
|
|
|
56
115
|
def _print_xy_help() -> None:
|
|
@@ -87,7 +146,7 @@ def _print_xy_help() -> None:
|
|
|
87
146
|
" --fullprof <args> : FullProf overlay options\n"
|
|
88
147
|
" --stack : stack curves vertically (auto-enables normalization)\n"
|
|
89
148
|
)
|
|
90
|
-
|
|
149
|
+
_print_help(msg)
|
|
91
150
|
|
|
92
151
|
|
|
93
152
|
def _print_ec_help() -> None:
|
|
@@ -123,7 +182,7 @@ def _print_ec_help() -> None:
|
|
|
123
182
|
"rename axes, toggle ticks/titles/spines, print/export/import style (.bps/.bpsg), save session (.pkl).\n"
|
|
124
183
|
"Note: Batch mode (--all) exports SVG files automatically; --interactive is for single-file plotting only.\n"
|
|
125
184
|
)
|
|
126
|
-
|
|
185
|
+
_print_help(msg)
|
|
127
186
|
|
|
128
187
|
|
|
129
188
|
def _print_op_help() -> None:
|
|
@@ -141,7 +200,7 @@ def _print_op_help() -> None:
|
|
|
141
200
|
"EC y-axis options (time ↔ ions), geometry tweaks, toggle spines/ticks/labels,\n"
|
|
142
201
|
"print/export/import style, save session.\n"
|
|
143
202
|
)
|
|
144
|
-
|
|
203
|
+
_print_help(msg)
|
|
145
204
|
|
|
146
205
|
|
|
147
206
|
def build_parser() -> argparse.ArgumentParser:
|
|
@@ -191,7 +250,10 @@ def parse_args(argv=None):
|
|
|
191
250
|
_print_op_help()
|
|
192
251
|
else:
|
|
193
252
|
_print_general_help()
|
|
194
|
-
|
|
253
|
+
if _HAS_RICH and _console:
|
|
254
|
+
_console.print("\n[yellow]Unknown help topic. Use: xy, ec, op[/yellow]")
|
|
255
|
+
else:
|
|
256
|
+
print("\nUnknown help topic. Use: xy, ec, op")
|
|
195
257
|
sys.exit(0)
|
|
196
258
|
# No help requested: parse fully
|
|
197
259
|
return parser.parse_args(argv)
|
|
@@ -79,6 +79,22 @@ except ImportError:
|
|
|
79
79
|
keep_canvas_fixed = False
|
|
80
80
|
|
|
81
81
|
|
|
82
|
+
def _natural_sort_key(filename: str) -> list:
|
|
83
|
+
"""Generate a natural sorting key for filenames with numbers.
|
|
84
|
+
|
|
85
|
+
Converts 'file_10.xy' to ['file_', 10, '.xy'] so numerical parts are sorted numerically.
|
|
86
|
+
This ensures file_2.xy comes before file_10.xy (natural order).
|
|
87
|
+
"""
|
|
88
|
+
parts = []
|
|
89
|
+
for match in re.finditer(r'(\d+|\D+)', filename):
|
|
90
|
+
text = match.group(0)
|
|
91
|
+
if text.isdigit():
|
|
92
|
+
parts.append(int(text))
|
|
93
|
+
else:
|
|
94
|
+
parts.append(text.lower())
|
|
95
|
+
return parts
|
|
96
|
+
|
|
97
|
+
|
|
82
98
|
def batplot_main() -> int:
|
|
83
99
|
"""Main entry point for batplot CLI.
|
|
84
100
|
|
|
@@ -1131,7 +1147,7 @@ def batplot_main() -> int:
|
|
|
1131
1147
|
all_xy_files = []
|
|
1132
1148
|
unknown_ext_files = []
|
|
1133
1149
|
|
|
1134
|
-
for f in sorted(os.listdir(os.getcwd())):
|
|
1150
|
+
for f in sorted(os.listdir(os.getcwd()), key=_natural_sort_key):
|
|
1135
1151
|
if not os.path.isfile(os.path.join(os.getcwd(), f)):
|
|
1136
1152
|
continue
|
|
1137
1153
|
ext = os.path.splitext(f)[1].lower()
|
|
@@ -32,6 +32,21 @@ KNOWN_DIFFRACTION_EXT = {".xy", ".xye", ".qye", ".dat"}
|
|
|
32
32
|
_two_theta_re = re.compile(r"2[tT]heta|2th", re.IGNORECASE)
|
|
33
33
|
_q_re = re.compile(r"^q$", re.IGNORECASE)
|
|
34
34
|
|
|
35
|
+
def _natural_sort_key(path: Path) -> list:
|
|
36
|
+
"""Generate a natural sorting key for filenames with numbers.
|
|
37
|
+
|
|
38
|
+
Converts 'file_10.xy' to ['file_', 10, '.xy'] so numerical parts are sorted numerically.
|
|
39
|
+
This ensures file_2.xy comes before file_10.xy (natural order).
|
|
40
|
+
"""
|
|
41
|
+
parts = []
|
|
42
|
+
for match in re.finditer(r'(\d+|\D+)', path.name):
|
|
43
|
+
text = match.group(0)
|
|
44
|
+
if text.isdigit():
|
|
45
|
+
parts.append(int(text))
|
|
46
|
+
else:
|
|
47
|
+
parts.append(text.lower())
|
|
48
|
+
return parts
|
|
49
|
+
|
|
35
50
|
def _infer_axis_mode(args, any_qye: bool, has_unknown_ext: bool):
|
|
36
51
|
# Priority: explicit --xaxis, else .qye presence (Q), else wavelength (Q), else default 2theta with warning
|
|
37
52
|
# If unknown extensions are present, use "user defined" mode
|
|
@@ -83,12 +98,12 @@ def plot_operando_folder(folder: str, args) -> Tuple[plt.Figure, plt.Axes, Dict[
|
|
|
83
98
|
p = Path(folder)
|
|
84
99
|
if not p.is_dir():
|
|
85
100
|
raise FileNotFoundError(f"Not a directory: {folder}")
|
|
86
|
-
# First try to find known diffraction files
|
|
87
|
-
files = sorted([f for f in p.iterdir() if f.suffix.lower() in KNOWN_DIFFRACTION_EXT])
|
|
101
|
+
# First try to find known diffraction files (filter out macOS resource fork files starting with ._)
|
|
102
|
+
files = sorted([f for f in p.iterdir() if f.suffix.lower() in KNOWN_DIFFRACTION_EXT and not f.name.startswith("._")], key=_natural_sort_key)
|
|
88
103
|
has_unknown_ext = False
|
|
89
104
|
# If no known files found, accept any file extension (except .mpt which is for electrochemistry)
|
|
90
105
|
if not files:
|
|
91
|
-
files = sorted([f for f in p.iterdir() if f.is_file() and f.suffix.lower() != ".mpt"])
|
|
106
|
+
files = sorted([f for f in p.iterdir() if f.is_file() and f.suffix.lower() != ".mpt" and not f.name.startswith("._")], key=_natural_sort_key)
|
|
92
107
|
has_unknown_ext = True
|
|
93
108
|
if not files:
|
|
94
109
|
raise FileNotFoundError("No data files found in folder (excluding .mpt files)")
|
|
@@ -137,7 +152,8 @@ def plot_operando_folder(folder: str, args) -> Tuple[plt.Figure, plt.Axes, Dict[
|
|
|
137
152
|
Z = np.vstack(stack) # shape (n_scans, n_x)
|
|
138
153
|
|
|
139
154
|
# Detect an electrochemistry .mpt file in the same folder (if any)
|
|
140
|
-
|
|
155
|
+
# Filter out macOS resource fork files (starting with ._)
|
|
156
|
+
mpt_files = sorted([f for f in p.iterdir() if f.suffix.lower() == ".mpt" and not f.name.startswith("._")], key=_natural_sort_key) # pick first if present
|
|
141
157
|
has_ec = len(mpt_files) > 0
|
|
142
158
|
ec_ax = None
|
|
143
159
|
|
|
@@ -2628,6 +2628,12 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax):
|
|
|
2628
2628
|
current_mA = getattr(ec_ax, '_ec_current_mA', None)
|
|
2629
2629
|
voltage_v = getattr(ec_ax, '_ec_voltage_v', None)
|
|
2630
2630
|
|
|
2631
|
+
if current_mA is None:
|
|
2632
|
+
print("Error: Current data is required for ion counting but is not available in the .mpt file.")
|
|
2633
|
+
print("The .mpt file must contain the '<I>/mA' column to use this feature.")
|
|
2634
|
+
print_menu()
|
|
2635
|
+
continue
|
|
2636
|
+
|
|
2631
2637
|
if time_h is not None and current_mA is not None:
|
|
2632
2638
|
t = np.asarray(time_h, float)
|
|
2633
2639
|
i_mA = np.asarray(current_mA, float)
|
|
@@ -2983,9 +2989,13 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax):
|
|
|
2983
2989
|
voltage_v = getattr(ec_ax, '_ec_voltage_v', None)
|
|
2984
2990
|
current_mA = getattr(ec_ax, '_ec_current_mA', None)
|
|
2985
2991
|
ln = getattr(ec_ax, '_ec_line', None)
|
|
2986
|
-
if time_h is None or
|
|
2992
|
+
if time_h is None or ln is None:
|
|
2987
2993
|
print("EC data not available for ion calculation.")
|
|
2988
2994
|
print_menu(); continue
|
|
2995
|
+
if current_mA is None:
|
|
2996
|
+
print("Error: Current data is required for ion counting but is not available in the .mpt file.")
|
|
2997
|
+
print("The .mpt file must contain the '<I>/mA' column to use this feature.")
|
|
2998
|
+
print_menu(); continue
|
|
2989
2999
|
sub = input("ey submenu: n=ions, t=time, q=back: ").strip().lower()
|
|
2990
3000
|
if not sub or sub == 'q':
|
|
2991
3001
|
print_menu(); continue
|
|
@@ -95,12 +95,50 @@ def read_mpt_file(fname: str, mode: str = 'gc', mass_mg: float = None):
|
|
|
95
95
|
"""
|
|
96
96
|
import re
|
|
97
97
|
|
|
98
|
+
# Check if this is a full EC-Lab format or a simple 2-column export
|
|
99
|
+
is_eclab_format = False
|
|
100
|
+
with open(fname, 'r', encoding='utf-8', errors='ignore') as f:
|
|
101
|
+
first_line = f.readline().strip()
|
|
102
|
+
if first_line.startswith('EC-Lab ASCII FILE'):
|
|
103
|
+
is_eclab_format = True
|
|
104
|
+
|
|
105
|
+
# Handle simple 2-column time/voltage export format (for operando time mode)
|
|
106
|
+
if not is_eclab_format and mode == 'time':
|
|
107
|
+
try:
|
|
108
|
+
# Read with tab delimiter and handle European comma decimal separator
|
|
109
|
+
with open(fname, 'r', encoding='utf-8', errors='ignore') as f:
|
|
110
|
+
# Skip header line
|
|
111
|
+
f.readline()
|
|
112
|
+
time_vals = []
|
|
113
|
+
voltage_vals = []
|
|
114
|
+
for line in f:
|
|
115
|
+
line = line.strip()
|
|
116
|
+
if not line:
|
|
117
|
+
continue
|
|
118
|
+
parts = line.split('\t')
|
|
119
|
+
if len(parts) >= 2:
|
|
120
|
+
# Replace comma with period for European locale
|
|
121
|
+
time_vals.append(float(parts[0].replace(',', '.')))
|
|
122
|
+
voltage_vals.append(float(parts[1].replace(',', '.')))
|
|
123
|
+
|
|
124
|
+
if not time_vals:
|
|
125
|
+
raise ValueError("No data found in file")
|
|
126
|
+
|
|
127
|
+
time_s = np.array(time_vals)
|
|
128
|
+
voltage_v = np.array(voltage_vals)
|
|
129
|
+
current_mA = np.zeros_like(time_s) # No current data in simple format
|
|
130
|
+
return time_s, voltage_v, current_mA
|
|
131
|
+
except Exception as e:
|
|
132
|
+
raise ValueError(f"Failed to read simple .mpt format: {e}")
|
|
133
|
+
|
|
134
|
+
# For non-time modes or EC-Lab format, require full EC-Lab format
|
|
135
|
+
if not is_eclab_format:
|
|
136
|
+
raise ValueError(f"Not a valid EC-Lab .mpt file: {fname}")
|
|
137
|
+
|
|
98
138
|
# Read header to find number of header lines
|
|
99
139
|
header_lines = 0
|
|
100
140
|
with open(fname, 'r', encoding='utf-8', errors='ignore') as f:
|
|
101
141
|
first_line = f.readline().strip()
|
|
102
|
-
if not first_line.startswith('EC-Lab ASCII FILE'):
|
|
103
|
-
raise ValueError(f"Not a valid EC-Lab .mpt file: {fname}")
|
|
104
142
|
|
|
105
143
|
# Find header lines count
|
|
106
144
|
for line in f:
|
|
@@ -289,13 +327,16 @@ def read_mpt_file(fname: str, mode: str = 'gc', mass_mg: float = None):
|
|
|
289
327
|
if voltage_col is None:
|
|
290
328
|
available = ', '.join(f"'{c}'" for c in column_names)
|
|
291
329
|
raise ValueError(f"Could not find 'Ewe/V' or 'Ewe' column.\nAvailable columns: {available}")
|
|
292
|
-
if current_col is None:
|
|
293
|
-
available = ', '.join(f"'{c}'" for c in column_names)
|
|
294
|
-
raise ValueError(f"Could not find '<I>/mA' column.\nAvailable columns: {available}")
|
|
295
330
|
|
|
296
331
|
time_data = data[:, time_col]
|
|
297
332
|
voltage_data = data[:, voltage_col]
|
|
298
|
-
|
|
333
|
+
|
|
334
|
+
# Current column is optional (only needed for advanced features like ion counting)
|
|
335
|
+
if current_col is None:
|
|
336
|
+
# Return None for current_data if column not found
|
|
337
|
+
current_data = None
|
|
338
|
+
else:
|
|
339
|
+
current_data = data[:, current_col]
|
|
299
340
|
|
|
300
341
|
return (time_data, voltage_data, current_data)
|
|
301
342
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: batplot
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.7
|
|
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
|
|
@@ -45,6 +45,7 @@ Description-Content-Type: text/markdown
|
|
|
45
45
|
License-File: LICENSE
|
|
46
46
|
Requires-Dist: numpy
|
|
47
47
|
Requires-Dist: matplotlib
|
|
48
|
+
Requires-Dist: rich>=10.0.0
|
|
48
49
|
Dynamic: license-file
|
|
49
50
|
|
|
50
51
|
# batplot
|
|
@@ -179,3 +180,5 @@ Tian Dai (tianda@uio.no)
|
|
|
179
180
|
University of Oslo
|
|
180
181
|
|
|
181
182
|
**GitHub**: https://github.com/tiandai-chem/batplot
|
|
183
|
+
|
|
184
|
+
**Subscribe for Updates**: Join batplot-lab@kjemi.uio.no for updates, feature announcements, and community feedback
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "batplot"
|
|
7
|
-
version = "1.3.
|
|
7
|
+
version = "1.3.7"
|
|
8
8
|
description = "Interactive plotting for XRD, PDF, and XAS data (.xye, .xy, .qye, .dat, .csv, .gr, .nor, .chik, .chir)"
|
|
9
9
|
authors = [
|
|
10
10
|
{ name = "Tian Dai", email = "tianda@uio.no" }
|
|
@@ -13,7 +13,8 @@ readme = "README.md"
|
|
|
13
13
|
requires-python = ">=3.7"
|
|
14
14
|
dependencies = [
|
|
15
15
|
"numpy",
|
|
16
|
-
"matplotlib"
|
|
16
|
+
"matplotlib",
|
|
17
|
+
"rich>=10.0.0"
|
|
17
18
|
]
|
|
18
19
|
license = { file = "LICENSE" }
|
|
19
20
|
classifiers = [
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|