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.
- scitex/__version__.py +1 -1
- scitex/io/_load.py +5 -0
- scitex/io/_load_modules/_canvas.py +171 -0
- scitex/io/_save.py +8 -0
- scitex/io/_save_modules/_canvas.py +356 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot.py +77 -22
- scitex/plt/docs/FIGURE_ARCHITECTURE.md +257 -0
- scitex/plt/utils/__init__.py +10 -0
- scitex/plt/utils/_collect_figure_metadata.py +14 -12
- scitex/plt/utils/_csv_column_naming.py +237 -0
- scitex/session/_decorator.py +13 -1
- scitex/vis/README.md +246 -615
- scitex/vis/__init__.py +138 -78
- scitex/vis/canvas.py +423 -0
- scitex/vis/docs/CANVAS_ARCHITECTURE.md +307 -0
- scitex/vis/editor/__init__.py +1 -1
- scitex/vis/editor/_dearpygui_editor.py +1830 -0
- scitex/vis/editor/_defaults.py +40 -1
- scitex/vis/editor/_edit.py +54 -18
- scitex/vis/editor/_flask_editor.py +37 -0
- scitex/vis/editor/_qt_editor.py +865 -0
- scitex/vis/editor/flask_editor/__init__.py +21 -0
- scitex/vis/editor/flask_editor/bbox.py +216 -0
- scitex/vis/editor/flask_editor/core.py +152 -0
- scitex/vis/editor/flask_editor/plotter.py +130 -0
- scitex/vis/editor/flask_editor/renderer.py +184 -0
- scitex/vis/editor/flask_editor/templates/__init__.py +33 -0
- scitex/vis/editor/flask_editor/templates/html.py +295 -0
- scitex/vis/editor/flask_editor/templates/scripts.py +614 -0
- scitex/vis/editor/flask_editor/templates/styles.py +549 -0
- scitex/vis/editor/flask_editor/utils.py +81 -0
- scitex/vis/io/__init__.py +84 -21
- scitex/vis/io/canvas.py +226 -0
- scitex/vis/io/data.py +204 -0
- scitex/vis/io/directory.py +202 -0
- scitex/vis/io/export.py +460 -0
- scitex/vis/io/panel.py +424 -0
- {scitex-2.4.3.dist-info → scitex-2.5.0.dist-info}/METADATA +9 -2
- {scitex-2.4.3.dist-info → scitex-2.5.0.dist-info}/RECORD +42 -21
- scitex/vis/DJANGO_INTEGRATION.md +0 -677
- scitex/vis/editor/_web_editor.py +0 -1440
- scitex/vis/tmp.txt +0 -239
- {scitex-2.4.3.dist-info → scitex-2.5.0.dist-info}/WHEEL +0 -0
- {scitex-2.4.3.dist-info → scitex-2.5.0.dist-info}/entry_points.txt +0 -0
- {scitex-2.4.3.dist-info → scitex-2.5.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
<!-- ---
|
|
2
|
+
!-- Timestamp: 2025-12-08 16:05:39
|
|
3
|
+
!-- Author: ywatanabe
|
|
4
|
+
!-- File: /home/ywatanabe/proj/scitex-code/src/scitex/vis/docs/CANVAS_ARCHITECTURE.md
|
|
5
|
+
!-- --- -->
|
|
6
|
+
|
|
7
|
+
# Canvas Architecture for scitex.vis
|
|
8
|
+
|
|
9
|
+
## Terminology
|
|
10
|
+
|
|
11
|
+
| Term | Meaning | Example |
|
|
12
|
+
|------------|---------------------------------------------|-----------------------------|
|
|
13
|
+
| **Canvas** | A paper figure workspace managed by `/vis/` | "Figure 1" in a publication |
|
|
14
|
+
| **Panel** | A single component placed on canvas | Panel A, B, C... |
|
|
15
|
+
| **Figure** | Reserved for matplotlib's `fig` object | `stx.plt` output |
|
|
16
|
+
|
|
17
|
+
## Directory Structure
|
|
18
|
+
|
|
19
|
+
Canvas directories use `.canvas` extension and are standalone (no nested structure required):
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
project/
|
|
23
|
+
├── fig1_neural_results.canvas/ # Standalone .canvas directory
|
|
24
|
+
│ ├── canvas.json # Layout, panels, composition settings
|
|
25
|
+
│ ├── canvas.png # Composed output (auto-generated)
|
|
26
|
+
│ ├── canvas.pdf
|
|
27
|
+
│ ├── canvas.svg
|
|
28
|
+
│ └── panels/
|
|
29
|
+
│ ├── panel_a/ # type: scitex (symlinks by default)
|
|
30
|
+
│ │ ├── panel.json -> ../../plots/plot.json
|
|
31
|
+
│ │ ├── panel.csv -> ../../plots/plot.csv
|
|
32
|
+
│ │ └── panel.png -> ../../plots/plot.png
|
|
33
|
+
│ └── panel_b/ # type: image
|
|
34
|
+
│ └── panel.png -> ../../images/diagram.png
|
|
35
|
+
├── fig2_supplementary.canvas/ # Another standalone canvas
|
|
36
|
+
│ └── ...
|
|
37
|
+
└── plots/ # Source files (symlink targets)
|
|
38
|
+
├── plot.png
|
|
39
|
+
├── plot.json
|
|
40
|
+
└── plot.csv
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Panel files use symlinks by default (`bundle=False`). Use `bundle=True` to copy files for portable archives.
|
|
44
|
+
|
|
45
|
+
The `.canvas` extension:
|
|
46
|
+
- Makes directories self-documenting (clearly a canvas bundle)
|
|
47
|
+
- Enables portability (can be moved/copied as a unit)
|
|
48
|
+
- Is detectable by `scitex.io` for automated handling
|
|
49
|
+
|
|
50
|
+
## Panel Types
|
|
51
|
+
|
|
52
|
+
| Type | Contents | Editable | Re-renderable |
|
|
53
|
+
|----------|------------------|-------------------------|---------------|
|
|
54
|
+
| `scitex` | JSON + CSV + PNG | Full (data, style) | Yes |
|
|
55
|
+
| `image` | PNG/JPG/SVG only | Position/size/transform | No |
|
|
56
|
+
|
|
57
|
+
## canvas.json Schema
|
|
58
|
+
|
|
59
|
+
```json
|
|
60
|
+
{
|
|
61
|
+
"schema_version": "2.0.0",
|
|
62
|
+
"canvas_name": "fig1_neural_results",
|
|
63
|
+
|
|
64
|
+
"size": {
|
|
65
|
+
"width_mm": 180,
|
|
66
|
+
"height_mm": 240
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
"background": {
|
|
70
|
+
"color": "#ffffff",
|
|
71
|
+
"grid": false
|
|
72
|
+
},
|
|
73
|
+
|
|
74
|
+
"panels": [
|
|
75
|
+
{
|
|
76
|
+
"name": "panel_a",
|
|
77
|
+
"type": "scitex",
|
|
78
|
+
"position": {"x_mm": 10, "y_mm": 10},
|
|
79
|
+
"size": {"width_mm": 70, "height_mm": 50},
|
|
80
|
+
"z_index": 0,
|
|
81
|
+
"rotation_deg": 0,
|
|
82
|
+
"clip": {
|
|
83
|
+
"enabled": false,
|
|
84
|
+
"x_mm": 0,
|
|
85
|
+
"y_mm": 0,
|
|
86
|
+
"width_mm": null,
|
|
87
|
+
"height_mm": null
|
|
88
|
+
},
|
|
89
|
+
"opacity": 1.0,
|
|
90
|
+
"flip_h": false,
|
|
91
|
+
"flip_v": false,
|
|
92
|
+
"visible": true,
|
|
93
|
+
"label": {
|
|
94
|
+
"text": "A",
|
|
95
|
+
"position": "top-left",
|
|
96
|
+
"fontsize": 12,
|
|
97
|
+
"fontweight": "bold"
|
|
98
|
+
},
|
|
99
|
+
"border": {
|
|
100
|
+
"visible": false,
|
|
101
|
+
"color": "#000000",
|
|
102
|
+
"width_mm": 0.2
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
"name": "panel_b",
|
|
107
|
+
"type": "image",
|
|
108
|
+
"source": "panel.png",
|
|
109
|
+
"position": {"x_mm": 100, "y_mm": 10},
|
|
110
|
+
"size": {"width_mm": 70, "height_mm": 50},
|
|
111
|
+
"z_index": 1,
|
|
112
|
+
"rotation_deg": 0,
|
|
113
|
+
"clip": {"enabled": false},
|
|
114
|
+
"opacity": 1.0,
|
|
115
|
+
"flip_h": false,
|
|
116
|
+
"flip_v": false,
|
|
117
|
+
"visible": true,
|
|
118
|
+
"label": {"text": "B", "position": "top-left"}
|
|
119
|
+
}
|
|
120
|
+
],
|
|
121
|
+
|
|
122
|
+
"annotations": [
|
|
123
|
+
{
|
|
124
|
+
"type": "text",
|
|
125
|
+
"content": "p < 0.05",
|
|
126
|
+
"position": {"x_mm": 50, "y_mm": 60},
|
|
127
|
+
"fontsize": 8
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
"type": "arrow",
|
|
131
|
+
"start": {"x_mm": 30, "y_mm": 70},
|
|
132
|
+
"end": {"x_mm": 50, "y_mm": 55}
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
"type": "bracket",
|
|
136
|
+
"start": {"x_mm": 10, "y_mm": 80},
|
|
137
|
+
"end": {"x_mm": 80, "y_mm": 80}
|
|
138
|
+
}
|
|
139
|
+
],
|
|
140
|
+
|
|
141
|
+
"title": {
|
|
142
|
+
"text": "",
|
|
143
|
+
"position": {"x_mm": 90, "y_mm": 5},
|
|
144
|
+
"fontsize": 14
|
|
145
|
+
},
|
|
146
|
+
|
|
147
|
+
"data_files": [
|
|
148
|
+
{
|
|
149
|
+
"path": "panels/panel_a/panel.csv",
|
|
150
|
+
"hash": "sha256:abc123..."
|
|
151
|
+
}
|
|
152
|
+
],
|
|
153
|
+
|
|
154
|
+
"metadata": {
|
|
155
|
+
"created_at": "2025-12-08T12:00:00Z",
|
|
156
|
+
"updated_at": "2025-12-08T15:30:00Z",
|
|
157
|
+
"author": "user",
|
|
158
|
+
"description": "Neural activity results for Figure 1"
|
|
159
|
+
},
|
|
160
|
+
|
|
161
|
+
"manual_overrides": {}
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## Panel Properties
|
|
166
|
+
|
|
167
|
+
### Transform Properties
|
|
168
|
+
|
|
169
|
+
| Property | Type | Default | Purpose |
|
|
170
|
+
|----------------|-----------------------|----------|------------------------------------|
|
|
171
|
+
| `position` | {x_mm, y_mm} | required | Position on canvas |
|
|
172
|
+
| `size` | {width_mm, height_mm} | required | Panel dimensions |
|
|
173
|
+
| `z_index` | int | 0 | Stacking order (higher = on top) |
|
|
174
|
+
| `rotation_deg` | float | 0 | Rotation around center (clockwise) |
|
|
175
|
+
| `opacity` | float | 1.0 | Transparency (0.0 - 1.0) |
|
|
176
|
+
| `flip_h` | bool | false | Horizontal flip |
|
|
177
|
+
| `flip_v` | bool | false | Vertical flip |
|
|
178
|
+
| `visible` | bool | true | Show/hide panel |
|
|
179
|
+
|
|
180
|
+
### Clip Properties
|
|
181
|
+
|
|
182
|
+
| Property | Type | Default | Purpose |
|
|
183
|
+
|------------------|-------|---------|----------------------------------|
|
|
184
|
+
| `clip.enabled` | bool | false | Enable cropping |
|
|
185
|
+
| `clip.x_mm` | float | 0 | Crop start X (from panel origin) |
|
|
186
|
+
| `clip.y_mm` | float | 0 | Crop start Y |
|
|
187
|
+
| `clip.width_mm` | float | null | Crop width (null = to edge) |
|
|
188
|
+
| `clip.height_mm` | float | null | Crop height (null = to edge) |
|
|
189
|
+
|
|
190
|
+
### Label Properties
|
|
191
|
+
|
|
192
|
+
| Property | Type | Default | Purpose |
|
|
193
|
+
|--------------------|--------|------------|----------------------------|
|
|
194
|
+
| `label.text` | string | "" | Label text (A, B, C...) |
|
|
195
|
+
| `label.position` | string | "top-left" | Position relative to panel |
|
|
196
|
+
| `label.fontsize` | int | 12 | Font size in points |
|
|
197
|
+
| `label.fontweight` | string | "bold" | Font weight |
|
|
198
|
+
|
|
199
|
+
### Border Properties
|
|
200
|
+
|
|
201
|
+
| Property | Type | Default | Purpose |
|
|
202
|
+
|-------------------|--------|-----------|------------------|
|
|
203
|
+
| `border.visible` | bool | false | Show border |
|
|
204
|
+
| `border.color` | string | "#000000" | Border color |
|
|
205
|
+
| `border.width_mm` | float | 0.2 | Border thickness |
|
|
206
|
+
|
|
207
|
+
## Annotation Types
|
|
208
|
+
|
|
209
|
+
| Type | Properties | Purpose |
|
|
210
|
+
|-------------|------------------------------------|------------------|
|
|
211
|
+
| `text` | content, position, fontsize, color | Text overlay |
|
|
212
|
+
| `arrow` | start, end, color, width | Arrow annotation |
|
|
213
|
+
| `bracket` | start, end, color, width | Bracket/brace |
|
|
214
|
+
| `line` | start, end, color, width, style | Line annotation |
|
|
215
|
+
| `rectangle` | position, size, color, fill | Rectangle shape |
|
|
216
|
+
|
|
217
|
+
## Core API (scitex.vis)
|
|
218
|
+
|
|
219
|
+
### Primary API (minimal, reusable, flexible)
|
|
220
|
+
|
|
221
|
+
```python
|
|
222
|
+
# Canvas operations
|
|
223
|
+
stx.vis.create_canvas(parent_dir, canvas_name) -> Path
|
|
224
|
+
stx.vis.get_canvas_path(parent_dir, canvas_name) -> Path
|
|
225
|
+
stx.vis.canvas_exists(parent_dir, canvas_name) -> bool
|
|
226
|
+
stx.vis.list_canvases(parent_dir) -> List[str]
|
|
227
|
+
stx.vis.delete_canvas(parent_dir, canvas_name) -> bool
|
|
228
|
+
|
|
229
|
+
# Panel operations (symlinks by default, bundle=True for copies)
|
|
230
|
+
stx.vis.add_panel(parent_dir, canvas_name, panel_name, source,
|
|
231
|
+
position=(x, y), size=(w, h), label="A",
|
|
232
|
+
bundle=False, **kwargs) -> Path
|
|
233
|
+
stx.vis.update_panel(parent_dir, canvas_name, panel_name, updates) -> Dict
|
|
234
|
+
stx.vis.remove_panel(parent_dir, canvas_name, panel_name) -> bool
|
|
235
|
+
stx.vis.list_panels(parent_dir, canvas_name) -> List[Dict]
|
|
236
|
+
|
|
237
|
+
# Export (auto-called by stx.io.save)
|
|
238
|
+
stx.vis.export_canvas(parent_dir, canvas_name, output_format="png") -> Path
|
|
239
|
+
|
|
240
|
+
# Data integrity
|
|
241
|
+
stx.vis.verify_data(parent_dir, canvas_name) -> Dict[str, bool]
|
|
242
|
+
|
|
243
|
+
# Editor
|
|
244
|
+
stx.vis.edit(json_path)
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
### Advanced API (via submodules)
|
|
248
|
+
|
|
249
|
+
```python
|
|
250
|
+
# stx.vis.io - Low-level I/O operations
|
|
251
|
+
# stx.vis.model - Data models (FigureModel, AxesModel, etc.)
|
|
252
|
+
# stx.vis.backend - JSON → matplotlib rendering
|
|
253
|
+
# stx.vis.utils - Templates and validation
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
## Django Integration (scitex-cloud)
|
|
257
|
+
|
|
258
|
+
Django views are thin wrappers:
|
|
259
|
+
|
|
260
|
+
```python
|
|
261
|
+
# apps/vis_app/views.py
|
|
262
|
+
import scitex as stx
|
|
263
|
+
|
|
264
|
+
def list_canvases(request, project_id):
|
|
265
|
+
project_path = get_project_path(project_id)
|
|
266
|
+
canvases = stx.vis.io.list_canvas_directories(project_path)
|
|
267
|
+
return JsonResponse({"canvases": canvases})
|
|
268
|
+
|
|
269
|
+
def get_canvas(request, project_id, canvas_name):
|
|
270
|
+
project_path = get_project_path(project_id)
|
|
271
|
+
canvas_json = stx.vis.io.load_canvas_json(project_path, canvas_name)
|
|
272
|
+
return JsonResponse(canvas_json)
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
## Integration with stx.io
|
|
276
|
+
|
|
277
|
+
Canvas directories are first-class citizens in the scitex I/O system:
|
|
278
|
+
|
|
279
|
+
```python
|
|
280
|
+
import scitex as stx
|
|
281
|
+
|
|
282
|
+
# Save canvas to a portable directory
|
|
283
|
+
stx.io.save(canvas_dict, "/path/to/fig1_results.canvas")
|
|
284
|
+
|
|
285
|
+
# Load canvas from directory
|
|
286
|
+
canvas = stx.io.load("/path/to/fig1_results.canvas")
|
|
287
|
+
# Returns dict with canvas.json content + '_canvas_dir' reference
|
|
288
|
+
|
|
289
|
+
# Load canvas with panel images in memory
|
|
290
|
+
canvas = stx.io.load("/path/to/fig1_results.canvas", load_panels=True)
|
|
291
|
+
# Each panel dict now has '_image' key with numpy array
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
## Summary
|
|
295
|
+
|
|
296
|
+
| Aspect | Decision |
|
|
297
|
+
|------------------|------------------------------------------------------------|
|
|
298
|
+
| Directory path | `{parent_dir}/{canvas_name}.canvas/` |
|
|
299
|
+
| Directory ext | `.canvas` extension for portability and distinguishability |
|
|
300
|
+
| Naming | Descriptive names (e.g., `fig1_neural_results`) |
|
|
301
|
+
| Panel types | `scitex` (full) or `image` (static) |
|
|
302
|
+
| Data integrity | SHA256 hash verification |
|
|
303
|
+
| Export structure | Flat (`exports/canvas.png`, `exports/canvas.pdf`) |
|
|
304
|
+
| Manual overrides | Stored in `canvas.json` under `manual_overrides` key |
|
|
305
|
+
| I/O integration | `stx.io.save/load` supports `.canvas` directories |
|
|
306
|
+
|
|
307
|
+
<!-- EOF -->
|
scitex/vis/editor/__init__.py
CHANGED
|
@@ -6,7 +6,7 @@ SciTeX Visual Editor Module
|
|
|
6
6
|
|
|
7
7
|
Provides interactive GUI for editing figure styles and annotations.
|
|
8
8
|
Supports multiple backends with graceful degradation:
|
|
9
|
-
-
|
|
9
|
+
- flask: Browser-based (Flask) - modern UI
|
|
10
10
|
- dearpygui: GPU-accelerated desktop (fast)
|
|
11
11
|
- qt: Rich desktop (PyQt/PySide)
|
|
12
12
|
- tkinter: Built-in Python (works everywhere)
|