batplot 1.7.25__tar.gz → 1.7.27__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.

Potentially problematic release.


This version of batplot might be problematic. Click here for more details.

Files changed (60) hide show
  1. {batplot-1.7.25/batplot.egg-info → batplot-1.7.27}/PKG-INFO +1 -1
  2. {batplot-1.7.25 → batplot-1.7.27}/batplot/__init__.py +1 -1
  3. {batplot-1.7.25 → batplot-1.7.27}/batplot/batplot.py +62 -31
  4. {batplot-1.7.25 → batplot-1.7.27}/batplot/color_utils.py +13 -6
  5. {batplot-1.7.25 → batplot-1.7.27}/batplot/cpc_interactive.py +515 -320
  6. {batplot-1.7.25 → batplot-1.7.27}/batplot/electrochem_interactive.py +24 -2
  7. {batplot-1.7.25 → batplot-1.7.27}/batplot/interactive.py +12 -4
  8. {batplot-1.7.25 → batplot-1.7.27}/batplot/operando.py +3 -3
  9. {batplot-1.7.25 → batplot-1.7.27}/batplot/operando_ec_interactive.py +22 -1
  10. {batplot-1.7.25 → batplot-1.7.27}/batplot/session.py +29 -3
  11. {batplot-1.7.25 → batplot-1.7.27}/batplot/style.py +4 -0
  12. {batplot-1.7.25 → batplot-1.7.27}/batplot/ui.py +13 -29
  13. {batplot-1.7.25 → batplot-1.7.27}/batplot/utils.py +48 -0
  14. {batplot-1.7.25 → batplot-1.7.27/batplot.egg-info}/PKG-INFO +1 -1
  15. {batplot-1.7.25 → batplot-1.7.27}/pyproject.toml +1 -1
  16. {batplot-1.7.25 → batplot-1.7.27}/LICENSE +0 -0
  17. {batplot-1.7.25 → batplot-1.7.27}/MANIFEST.in +0 -0
  18. {batplot-1.7.25 → batplot-1.7.27}/README.md +0 -0
  19. {batplot-1.7.25 → batplot-1.7.27}/USER_MANUAL.md +0 -0
  20. {batplot-1.7.25 → batplot-1.7.27}/batplot/args.py +0 -0
  21. {batplot-1.7.25 → batplot-1.7.27}/batplot/batch.py +0 -0
  22. {batplot-1.7.25 → batplot-1.7.27}/batplot/cif.py +0 -0
  23. {batplot-1.7.25 → batplot-1.7.27}/batplot/cli.py +0 -0
  24. {batplot-1.7.25 → batplot-1.7.27}/batplot/config.py +0 -0
  25. {batplot-1.7.25 → batplot-1.7.27}/batplot/converters.py +0 -0
  26. {batplot-1.7.25 → batplot-1.7.27}/batplot/data/USER_MANUAL.md +0 -0
  27. {batplot-1.7.25 → batplot-1.7.27}/batplot/manual.py +0 -0
  28. {batplot-1.7.25 → batplot-1.7.27}/batplot/modes.py +0 -0
  29. {batplot-1.7.25 → batplot-1.7.27}/batplot/plotting.py +0 -0
  30. {batplot-1.7.25 → batplot-1.7.27}/batplot/readers.py +0 -0
  31. {batplot-1.7.25 → batplot-1.7.27}/batplot/version_check.py +0 -0
  32. {batplot-1.7.25 → batplot-1.7.27}/batplot.egg-info/SOURCES.txt +0 -0
  33. {batplot-1.7.25 → batplot-1.7.27}/batplot.egg-info/dependency_links.txt +0 -0
  34. {batplot-1.7.25 → batplot-1.7.27}/batplot.egg-info/entry_points.txt +0 -0
  35. {batplot-1.7.25 → batplot-1.7.27}/batplot.egg-info/requires.txt +0 -0
  36. {batplot-1.7.25 → batplot-1.7.27}/batplot.egg-info/top_level.txt +0 -0
  37. {batplot-1.7.25 → batplot-1.7.27}/batplot_backup_20251121_223043/__init__.py +0 -0
  38. {batplot-1.7.25 → batplot-1.7.27}/batplot_backup_20251121_223043/args.py +0 -0
  39. {batplot-1.7.25 → batplot-1.7.27}/batplot_backup_20251121_223043/batch.py +0 -0
  40. {batplot-1.7.25 → batplot-1.7.27}/batplot_backup_20251121_223043/batplot.py +0 -0
  41. {batplot-1.7.25 → batplot-1.7.27}/batplot_backup_20251121_223043/cif.py +0 -0
  42. {batplot-1.7.25 → batplot-1.7.27}/batplot_backup_20251121_223043/cli.py +0 -0
  43. {batplot-1.7.25 → batplot-1.7.27}/batplot_backup_20251121_223043/color_utils.py +0 -0
  44. {batplot-1.7.25 → batplot-1.7.27}/batplot_backup_20251121_223043/config.py +0 -0
  45. {batplot-1.7.25 → batplot-1.7.27}/batplot_backup_20251121_223043/converters.py +0 -0
  46. {batplot-1.7.25 → batplot-1.7.27}/batplot_backup_20251121_223043/cpc_interactive.py +0 -0
  47. {batplot-1.7.25 → batplot-1.7.27}/batplot_backup_20251121_223043/electrochem_interactive.py +0 -0
  48. {batplot-1.7.25 → batplot-1.7.27}/batplot_backup_20251121_223043/interactive.py +0 -0
  49. {batplot-1.7.25 → batplot-1.7.27}/batplot_backup_20251121_223043/modes.py +0 -0
  50. {batplot-1.7.25 → batplot-1.7.27}/batplot_backup_20251121_223043/operando.py +0 -0
  51. {batplot-1.7.25 → batplot-1.7.27}/batplot_backup_20251121_223043/operando_ec_interactive.py +0 -0
  52. {batplot-1.7.25 → batplot-1.7.27}/batplot_backup_20251121_223043/plotting.py +0 -0
  53. {batplot-1.7.25 → batplot-1.7.27}/batplot_backup_20251121_223043/readers.py +0 -0
  54. {batplot-1.7.25 → batplot-1.7.27}/batplot_backup_20251121_223043/session.py +0 -0
  55. {batplot-1.7.25 → batplot-1.7.27}/batplot_backup_20251121_223043/style.py +0 -0
  56. {batplot-1.7.25 → batplot-1.7.27}/batplot_backup_20251121_223043/ui.py +0 -0
  57. {batplot-1.7.25 → batplot-1.7.27}/batplot_backup_20251121_223043/utils.py +0 -0
  58. {batplot-1.7.25 → batplot-1.7.27}/batplot_backup_20251121_223043/version_check.py +0 -0
  59. {batplot-1.7.25 → batplot-1.7.27}/setup.cfg +0 -0
  60. {batplot-1.7.25 → batplot-1.7.27}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: batplot
3
- Version: 1.7.25
3
+ Version: 1.7.27
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
6
  License: MIT License
@@ -1,5 +1,5 @@
1
1
  """batplot: Interactive plotting for battery data visualization."""
2
2
 
3
- __version__ = "1.7.25"
3
+ __version__ = "1.7.27"
4
4
 
5
5
  __all__ = ["__version__"]
@@ -76,9 +76,32 @@ except ImportError:
76
76
  operando_ec_interactive_menu = None
77
77
 
78
78
  try:
79
- from .cpc_interactive import cpc_interactive_menu
79
+ from .cpc_interactive import cpc_interactive_menu, _generate_similar_color
80
80
  except ImportError:
81
81
  cpc_interactive_menu = None
82
+ # Fallback function if import fails
83
+ def _generate_similar_color(base_color):
84
+ """Generate a similar but distinguishable color for discharge from charge color."""
85
+ try:
86
+ from matplotlib.colors import to_rgb, rgb_to_hsv, hsv_to_rgb
87
+ rgb = to_rgb(base_color)
88
+ hsv = rgb_to_hsv(rgb)
89
+ h, s, v = hsv
90
+ h_new = (h + 0.04) % 1.0
91
+ s_new = max(0.3, s * 0.85)
92
+ v_new = max(0.4, v * 0.9)
93
+ rgb_new = hsv_to_rgb([h_new, s_new, v_new])
94
+ # Convert numpy array to tuple to avoid truth value ambiguity
95
+ if hasattr(rgb_new, 'tolist'):
96
+ return tuple(rgb_new.tolist())
97
+ return tuple(rgb_new)
98
+ except Exception:
99
+ try:
100
+ from matplotlib.colors import to_rgb
101
+ rgb = to_rgb(base_color)
102
+ return tuple(max(0, c * 0.7) for c in rgb)
103
+ except Exception:
104
+ return base_color
82
105
 
83
106
  # Global state variables (used by interactive menus and style system)
84
107
  keep_canvas_fixed = False
@@ -1040,20 +1063,23 @@ def batplot_main() -> int:
1040
1063
 
1041
1064
  # Process multiple files
1042
1065
  file_data = [] # List of dicts with file info and data
1043
- # Use perceptually-uniform palettes for capacity (viridis) and efficiency (plasma)
1066
+ # Use tab10 for capacity and viridis for efficiency
1044
1067
  import matplotlib.cm as cm
1045
1068
  import matplotlib.colors as mcolors
1046
1069
  n_files = len(data_files)
1047
1070
 
1048
- capacity_cmap = cm.get_cmap('viridis')
1049
- efficiency_cmap = cm.get_cmap('plasma')
1071
+ # Use tab10 hardcoded colors for capacity (matching interactive menu)
1072
+ default_tab10_colors = ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', '#9467bd',
1073
+ '#8c564b', '#e377c2', '#7f7f7f', '#bcbd22', '#17becf']
1050
1074
  if n_files <= 1:
1051
- cap_positions = [0.55]
1052
- eff_positions = [0.35]
1075
+ capacity_colors = [default_tab10_colors[0]]
1076
+ eff_positions = [0.55]
1053
1077
  else:
1054
- cap_positions = np.linspace(0.15, 0.85, n_files)
1055
- eff_positions = np.linspace(0.2, 0.9, n_files)
1056
- capacity_colors = [mcolors.rgb2hex(capacity_cmap(pos)[:3]) for pos in cap_positions]
1078
+ capacity_colors = [default_tab10_colors[i % len(default_tab10_colors)] for i in range(n_files)]
1079
+ eff_positions = np.linspace(0.08, 0.88, n_files)
1080
+
1081
+ # Use viridis for efficiency
1082
+ efficiency_cmap = cm.get_cmap('viridis')
1057
1083
  efficiency_colors = [mcolors.rgb2hex(efficiency_cmap(pos)[:3]) for pos in eff_positions]
1058
1084
 
1059
1085
  for file_idx, ec_file in enumerate(data_files):
@@ -1137,6 +1163,8 @@ def batplot_main() -> int:
1137
1163
  # Assign colors: distinct hue for each file
1138
1164
  capacity_color = capacity_colors[file_idx % len(capacity_colors)]
1139
1165
  efficiency_color = efficiency_colors[file_idx % len(efficiency_colors)]
1166
+ # Generate discharge color using the same function as interactive menu
1167
+ discharge_color = _generate_similar_color(capacity_color)
1140
1168
 
1141
1169
  file_data.append({
1142
1170
  'filename': file_basename,
@@ -1146,6 +1174,7 @@ def batplot_main() -> int:
1146
1174
  'cap_discharge': cap_discharge,
1147
1175
  'eff': eff,
1148
1176
  'color': capacity_color,
1177
+ 'discharge_color': discharge_color,
1149
1178
  'eff_color': efficiency_color,
1150
1179
  'visible': True
1151
1180
  })
@@ -1187,15 +1216,11 @@ def batplot_main() -> int:
1187
1216
  label_dch = f'{label} (Dch)'
1188
1217
  label_eff = f'{label} (Eff)'
1189
1218
 
1190
- # Use slightly different shades for charge/discharge from same file
1191
- from matplotlib.colors import to_rgb, rgb_to_hsv, hsv_to_rgb
1192
- rgb = to_rgb(color)
1193
- # Discharge: shift hue slightly and reduce brightness for clear distinction
1194
- hsv = rgb_to_hsv(rgb)
1195
- h, s, v = hsv
1196
- h_new = (h - 0.05) % 1.0 # Shift hue slightly (more red/brown)
1197
- v_new = max(0.3, v * 0.75) # Darker but not too dark
1198
- discharge_color = hsv_to_rgb([h_new, s, v_new])
1219
+ # Use stored discharge color if available, otherwise generate it
1220
+ if 'discharge_color' in file_info and file_info['discharge_color'] is not None:
1221
+ discharge_color = file_info['discharge_color']
1222
+ else:
1223
+ discharge_color = _generate_similar_color(color)
1199
1224
 
1200
1225
  sc_charge = ax.scatter(cyc_nums, cap_charge, color=color, label=label_chg,
1201
1226
  s=32, zorder=3, alpha=0.8, marker='o')
@@ -1216,10 +1241,24 @@ def batplot_main() -> int:
1216
1241
  try:
1217
1242
  h1, l1 = ax.get_legend_handles_labels()
1218
1243
  h2, l2 = ax2.get_legend_handles_labels()
1219
- leg = ax.legend(h1 + h2, l1 + l2, loc='best', borderaxespad=1.0)
1244
+ combined_handles = h1 + h2
1245
+ leg = ax.legend(
1246
+ combined_handles, l1 + l2,
1247
+ loc='best',
1248
+ frameon=False,
1249
+ handlelength=1.0,
1250
+ handletextpad=0.35,
1251
+ labelspacing=0.25,
1252
+ borderaxespad=0.5,
1253
+ borderpad=0.3,
1254
+ columnspacing=0.6,
1255
+ labelcolor='linecolor',
1256
+ )
1220
1257
  if leg is not None:
1221
1258
  try:
1222
1259
  leg.set_frame_on(False)
1260
+ leg.set_edgecolor('none')
1261
+ leg.set_facecolor('none')
1223
1262
  except Exception:
1224
1263
  pass
1225
1264
  except Exception:
@@ -1278,15 +1317,7 @@ def batplot_main() -> int:
1278
1317
  pass
1279
1318
  plt.show(block=False)
1280
1319
  try:
1281
- # Pass file_data for multi-file support, but keep backward compatibility
1282
- if len(file_data) == 1:
1283
- # Single file: use original signature
1284
- cpc_interactive_menu(fig, ax, ax2,
1285
- file_data[0]['sc_charge'],
1286
- file_data[0]['sc_discharge'],
1287
- file_data[0]['sc_eff'])
1288
- else:
1289
- # Multiple files: pass file_data list
1320
+ # Always pass file_data so filename is available
1290
1321
  cpc_interactive_menu(fig, ax, ax2,
1291
1322
  file_data[0]['sc_charge'],
1292
1323
  file_data[0]['sc_discharge'],
@@ -2129,7 +2160,7 @@ def batplot_main() -> int:
2129
2160
  # Rebuild label texts
2130
2161
  for i, lab in enumerate(labels_list):
2131
2162
  txt = ax.text(1.0, 1.0, f"{i+1}: {lab}", ha='right', va='top', transform=ax.transAxes,
2132
- fontsize=plt.rcParams.get('font.size', 12))
2163
+ fontsize=plt.rcParams.get('font.size', 16))
2133
2164
  label_text_objects.append(txt)
2134
2165
  # Restore curve names visibility
2135
2166
  try:
@@ -2311,7 +2342,7 @@ def batplot_main() -> int:
2311
2342
  if show_titles_local:
2312
2343
  label_text = f" {lab}"
2313
2344
  txt = ax.text(prev_xlim[0], y_line+0.005*yr, label_text,
2314
- ha='left', va='bottom', fontsize=max(8,int(0.55*plt.rcParams.get('font.size',12))), color=color)
2345
+ ha='left', va='bottom', fontsize=max(8,int(0.55*plt.rcParams.get('font.size',16))), color=color)
2315
2346
  new_art.append(txt)
2316
2347
  ax._cif_tick_art = new_art
2317
2348
  # Restore both x and y-axis limits to prevent movement
@@ -2939,7 +2970,7 @@ def batplot_main() -> int:
2939
2970
  # ---------------- Initial label creation (REPLACED BLOCK) ----------------
2940
2971
  # Remove the old simple per-curve placement loop and use:
2941
2972
  label_text_objects = []
2942
- tick_fs = sample_tick.get_fontsize() if sample_tick else plt.rcParams.get('font.size', 12)
2973
+ tick_fs = sample_tick.get_fontsize() if sample_tick else plt.rcParams.get('font.size', 16)
2943
2974
  # get_fontname() may not exist on some backends; use family from rcParams if missing
2944
2975
  try:
2945
2976
  tick_fn = sample_tick.get_fontname() if sample_tick else plt.rcParams.get('font.sans-serif', ['DejaVu Sans'])[0]
@@ -246,12 +246,19 @@ def palette_preview(name: str, steps: int = 8) -> str:
246
246
  if steps < 1:
247
247
  steps = 1
248
248
 
249
- # Sample colors at evenly spaced positions along the colormap
250
- # Position ranges from 0.0 (start) to 1.0 (end)
251
- samples = [
252
- mcolors.to_hex(cmap(i / max(steps - 1, 1))) # Convert to hex color code
253
- for i in range(steps)
254
- ]
249
+ # Special handling for tab10 to use hardcoded colors (matching EC and CPC interactive)
250
+ if name.lower() == 'tab10':
251
+ default_tab10_colors = ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', '#9467bd',
252
+ '#8c564b', '#e377c2', '#7f7f7f', '#bcbd22', '#17becf']
253
+ # Use first 'steps' colors from tab10
254
+ samples = [default_tab10_colors[i % len(default_tab10_colors)] for i in range(steps)]
255
+ else:
256
+ # Sample colors at evenly spaced positions along the colormap
257
+ # Position ranges from 0.0 (start) to 1.0 (end)
258
+ samples = [
259
+ mcolors.to_hex(cmap(i / max(steps - 1, 1))) # Convert to hex color code
260
+ for i in range(steps)
261
+ ]
255
262
 
256
263
  # Convert color codes to visual blocks and return as string
257
264
  return color_bar(samples)