scitex 2.4.3__py3-none-any.whl → 2.5.0__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.
Files changed (45) hide show
  1. scitex/__version__.py +1 -1
  2. scitex/io/_load.py +5 -0
  3. scitex/io/_load_modules/_canvas.py +171 -0
  4. scitex/io/_save.py +8 -0
  5. scitex/io/_save_modules/_canvas.py +356 -0
  6. scitex/plt/_subplots/_export_as_csv_formatters/_format_plot.py +77 -22
  7. scitex/plt/docs/FIGURE_ARCHITECTURE.md +257 -0
  8. scitex/plt/utils/__init__.py +10 -0
  9. scitex/plt/utils/_collect_figure_metadata.py +14 -12
  10. scitex/plt/utils/_csv_column_naming.py +237 -0
  11. scitex/session/_decorator.py +13 -1
  12. scitex/vis/README.md +246 -615
  13. scitex/vis/__init__.py +138 -78
  14. scitex/vis/canvas.py +423 -0
  15. scitex/vis/docs/CANVAS_ARCHITECTURE.md +307 -0
  16. scitex/vis/editor/__init__.py +1 -1
  17. scitex/vis/editor/_dearpygui_editor.py +1830 -0
  18. scitex/vis/editor/_defaults.py +40 -1
  19. scitex/vis/editor/_edit.py +54 -18
  20. scitex/vis/editor/_flask_editor.py +37 -0
  21. scitex/vis/editor/_qt_editor.py +865 -0
  22. scitex/vis/editor/flask_editor/__init__.py +21 -0
  23. scitex/vis/editor/flask_editor/bbox.py +216 -0
  24. scitex/vis/editor/flask_editor/core.py +152 -0
  25. scitex/vis/editor/flask_editor/plotter.py +130 -0
  26. scitex/vis/editor/flask_editor/renderer.py +184 -0
  27. scitex/vis/editor/flask_editor/templates/__init__.py +33 -0
  28. scitex/vis/editor/flask_editor/templates/html.py +295 -0
  29. scitex/vis/editor/flask_editor/templates/scripts.py +614 -0
  30. scitex/vis/editor/flask_editor/templates/styles.py +549 -0
  31. scitex/vis/editor/flask_editor/utils.py +81 -0
  32. scitex/vis/io/__init__.py +84 -21
  33. scitex/vis/io/canvas.py +226 -0
  34. scitex/vis/io/data.py +204 -0
  35. scitex/vis/io/directory.py +202 -0
  36. scitex/vis/io/export.py +460 -0
  37. scitex/vis/io/panel.py +424 -0
  38. {scitex-2.4.3.dist-info → scitex-2.5.0.dist-info}/METADATA +9 -2
  39. {scitex-2.4.3.dist-info → scitex-2.5.0.dist-info}/RECORD +42 -21
  40. scitex/vis/DJANGO_INTEGRATION.md +0 -677
  41. scitex/vis/editor/_web_editor.py +0 -1440
  42. scitex/vis/tmp.txt +0 -239
  43. {scitex-2.4.3.dist-info → scitex-2.5.0.dist-info}/WHEEL +0 -0
  44. {scitex-2.4.3.dist-info → scitex-2.5.0.dist-info}/entry_points.txt +0 -0
  45. {scitex-2.4.3.dist-info → scitex-2.5.0.dist-info}/licenses/LICENSE +0 -0
@@ -197,9 +197,48 @@ def extract_defaults_from_metadata(metadata):
197
197
  if legend:
198
198
  defaults['legend_visible'] = legend.get('visible', True)
199
199
  defaults['legend_frameon'] = legend.get('frameon', False)
200
- defaults['legend_loc'] = legend.get('loc', 'best')
200
+ loc = legend.get('loc', 'best')
201
+ # Convert numeric legend loc to string (matplotlib accepts both but GUI needs string)
202
+ defaults['legend_loc'] = _normalize_legend_loc(loc)
201
203
 
202
204
  return defaults
203
205
 
204
206
 
207
+ def _normalize_legend_loc(loc):
208
+ """Convert legend location to string format for GUI compatibility.
209
+
210
+ Matplotlib accepts both numeric codes and string locations for legends.
211
+ This function ensures consistency by converting numeric codes to strings.
212
+
213
+ Parameters
214
+ ----------
215
+ loc : int or str
216
+ Legend location (numeric or string)
217
+
218
+ Returns
219
+ -------
220
+ str
221
+ String representation of legend location
222
+ """
223
+ if isinstance(loc, str):
224
+ return loc
225
+
226
+ # Numeric to string mapping (matplotlib legend location codes)
227
+ loc_map = {
228
+ 0: 'best',
229
+ 1: 'upper right',
230
+ 2: 'upper left',
231
+ 3: 'lower left',
232
+ 4: 'lower right',
233
+ 5: 'right',
234
+ 6: 'center left',
235
+ 7: 'center right',
236
+ 8: 'lower center',
237
+ 9: 'upper center',
238
+ 10: 'center',
239
+ }
240
+
241
+ return loc_map.get(loc, 'best')
242
+
243
+
205
244
  # EOF
@@ -7,11 +7,46 @@ from pathlib import Path
7
7
  from typing import Union, Optional, Literal
8
8
  import hashlib
9
9
  import json
10
+ import warnings
11
+
12
+
13
+ def _print_available_backends():
14
+ """Print available backends status."""
15
+ backends = {
16
+ "flask": ["flask"],
17
+ "dearpygui": ["dearpygui"],
18
+ "qt": ["PyQt6", "PyQt5", "PySide6", "PySide2"],
19
+ "tkinter": ["tkinter"],
20
+ "mpl": ["matplotlib"],
21
+ }
22
+
23
+ print("\n" + "=" * 50)
24
+ print("SciTeX Visual Editor - Available Backends")
25
+ print("=" * 50)
26
+
27
+ for backend, packages in backends.items():
28
+ available = False
29
+ available_pkg = None
30
+ for pkg in packages:
31
+ try:
32
+ __import__(pkg)
33
+ available = True
34
+ available_pkg = pkg
35
+ break
36
+ except ImportError:
37
+ pass
38
+
39
+ status = f"[OK] {available_pkg}" if available else "[NOT INSTALLED]"
40
+ print(f" {backend:12s}: {status}")
41
+
42
+ print("=" * 50)
43
+ print("Install: pip install scitex[gui]")
44
+ print("=" * 50 + "\n")
10
45
 
11
46
 
12
47
  def edit(
13
48
  path: Union[str, Path],
14
- backend: Literal["auto", "web", "dearpygui", "qt", "tkinter", "mpl"] = "auto",
49
+ backend: Literal["auto", "flask", "dearpygui", "qt", "tkinter", "mpl"] = "auto",
15
50
  apply_manual: bool = True,
16
51
  ) -> None:
17
52
  """
@@ -28,8 +63,8 @@ def edit(
28
63
  backend : str, optional
29
64
  GUI backend to use (default: "auto"):
30
65
  - "auto": Pick best available with graceful degradation
31
- (web -> dearpygui -> qt -> tkinter -> mpl)
32
- - "web": Browser-based editor (Flask/FastAPI, modern UI)
66
+ (flask -> dearpygui -> qt -> tkinter -> mpl)
67
+ - "flask": Browser-based editor (Flask, modern UI)
33
68
  - "dearpygui": GPU-accelerated modern GUI (fast, requires dearpygui)
34
69
  - "qt": Rich desktop editor (requires PyQt5/6 or PySide2/6)
35
70
  - "tkinter": Built-in Python GUI (works everywhere)
@@ -46,7 +81,7 @@ def edit(
46
81
  --------
47
82
  >>> import scitex as stx
48
83
  >>> stx.vis.edit("output/figure.json") # Auto-select best backend
49
- >>> stx.vis.edit("output/figure.png", backend="web") # Force web editor
84
+ >>> stx.vis.edit("output/figure.png", backend="flask") # Force flask editor
50
85
  >>> stx.vis.edit("output/figure.json", backend="tkinter") # Force tkinter
51
86
 
52
87
  Notes
@@ -54,7 +89,7 @@ def edit(
54
89
  - Changes are saved to `{basename}.manual.json` alongside the original
55
90
  - Manual JSON includes hash of base JSON for staleness detection
56
91
  - Original JSON/CSV files are never modified
57
- - Backend auto-detection order: web > dearpygui > qt > tkinter > mpl
92
+ - Backend auto-detection order: flask > dearpygui > qt > tkinter > mpl
58
93
  """
59
94
  path = Path(path)
60
95
 
@@ -82,10 +117,14 @@ def edit(
82
117
  if backend == "auto":
83
118
  backend = _detect_best_backend()
84
119
 
120
+ # Print status
121
+ _print_available_backends()
122
+ print(f"Launching {backend} editor for: {json_path}")
123
+
85
124
  # Launch appropriate backend
86
- if backend == "web":
125
+ if backend == "flask":
87
126
  try:
88
- from ._web_editor import WebEditor
127
+ from ._flask_editor import WebEditor
89
128
  editor = WebEditor(
90
129
  json_path=json_path,
91
130
  metadata=metadata,
@@ -96,7 +135,7 @@ def edit(
96
135
  editor.run()
97
136
  except ImportError as e:
98
137
  raise ImportError(
99
- "Web backend requires Flask or FastAPI. "
138
+ "Flask backend requires Flask. "
100
139
  "Install with: pip install flask"
101
140
  ) from e
102
141
  elif backend == "dearpygui":
@@ -106,6 +145,7 @@ def edit(
106
145
  json_path=json_path,
107
146
  metadata=metadata,
108
147
  csv_data=csv_data,
148
+ png_path=png_path,
109
149
  manual_overrides=manual_overrides,
110
150
  )
111
151
  editor.run()
@@ -121,6 +161,7 @@ def edit(
121
161
  json_path=json_path,
122
162
  metadata=metadata,
123
163
  csv_data=csv_data,
164
+ png_path=png_path,
124
165
  manual_overrides=manual_overrides,
125
166
  )
126
167
  editor.run()
@@ -150,7 +191,7 @@ def edit(
150
191
  else:
151
192
  raise ValueError(
152
193
  f"Unknown backend: {backend}. "
153
- "Use 'auto', 'web', 'dearpygui', 'qt', 'tkinter', or 'mpl'."
194
+ "Use 'auto', 'flask', 'dearpygui', 'qt', 'tkinter', or 'mpl'."
154
195
  )
155
196
 
156
197
 
@@ -158,20 +199,15 @@ def _detect_best_backend() -> str:
158
199
  """
159
200
  Detect the best available GUI backend with graceful degradation.
160
201
 
161
- Order: web > dearpygui > qt > tkinter > mpl
202
+ Order: flask > dearpygui > qt > tkinter > mpl
162
203
  Shows warnings when falling back to less capable backends.
163
204
  """
164
205
  import warnings
165
206
 
166
- # Try Web (Flask/FastAPI) - best for modern UI
207
+ # Try Flask - best for modern UI
167
208
  try:
168
209
  import flask
169
- return "web"
170
- except ImportError:
171
- pass
172
- try:
173
- import fastapi
174
- return "web"
210
+ return "flask"
175
211
  except ImportError:
176
212
  pass
177
213
 
@@ -181,7 +217,7 @@ def _detect_best_backend() -> str:
181
217
  return "dearpygui"
182
218
  except ImportError:
183
219
  warnings.warn(
184
- "Web/Flask not available. Consider: pip install flask\n"
220
+ "Flask not available. Consider: pip install flask\n"
185
221
  "Trying DearPyGui..."
186
222
  )
187
223
 
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ # File: ./src/scitex/vis/editor/_flask_editor.py
4
+ """Web-based figure editor using Flask.
5
+
6
+ This module re-exports from the flask_editor package for backward compatibility.
7
+ The actual implementation is in the flask_editor/ subpackage.
8
+ """
9
+
10
+ from .flask_editor import (
11
+ WebEditor,
12
+ find_available_port,
13
+ kill_process_on_port,
14
+ check_port_available,
15
+ render_preview_with_bboxes,
16
+ plot_from_csv,
17
+ )
18
+
19
+ # Legacy aliases for backward compatibility
20
+ _find_available_port = find_available_port
21
+ _kill_process_on_port = kill_process_on_port
22
+
23
+
24
+ __all__ = [
25
+ 'WebEditor',
26
+ 'find_available_port',
27
+ 'kill_process_on_port',
28
+ 'check_port_available',
29
+ 'render_preview_with_bboxes',
30
+ 'plot_from_csv',
31
+ # Legacy aliases
32
+ '_find_available_port',
33
+ '_kill_process_on_port',
34
+ ]
35
+
36
+
37
+ # EOF