ialdev-vis 0.2.2__tar.gz → 0.2.4__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.
- ialdev_vis-0.2.4/IMVIEW.md +223 -0
- {ialdev_vis-0.2.2 → ialdev_vis-0.2.4}/PKG-INFO +43 -5
- ialdev_vis-0.2.4/README.md +75 -0
- ialdev_vis-0.2.4/js/build.mjs +30 -0
- ialdev_vis-0.2.4/js/package-lock.json +454 -0
- ialdev_vis-0.2.4/js/package.json +12 -0
- ialdev_vis-0.2.4/js/src/canvas.ts +44 -0
- ialdev_vis-0.2.4/js/src/colormap.ts +42 -0
- ialdev_vis-0.2.4/js/src/controls.ts +298 -0
- ialdev_vis-0.2.4/js/src/grid.ts +137 -0
- ialdev_vis-0.2.4/js/src/index.ts +152 -0
- ialdev_vis-0.2.4/js/src/inspect.ts +192 -0
- ialdev_vis-0.2.4/js/src/labels.ts +208 -0
- ialdev_vis-0.2.4/js/src/model.ts +178 -0
- ialdev_vis-0.2.4/js/src/renderer/Canvas2DRenderer.ts +329 -0
- ialdev_vis-0.2.4/js/src/renderer/Renderer.ts +16 -0
- ialdev_vis-0.2.4/js/src/selection.ts +46 -0
- ialdev_vis-0.2.4/js/src/types.ts +58 -0
- ialdev_vis-0.2.4/js/tsconfig.json +12 -0
- {ialdev_vis-0.2.2 → ialdev_vis-0.2.4}/pyproject.toml +15 -4
- {ialdev_vis-0.2.2/src/iad/vis/colormaps → ialdev_vis-0.2.4/src/iad/vis}/__init__.py +0 -0
- ialdev_vis-0.2.4/src/iad/vis/gridcore.py +500 -0
- ialdev_vis-0.2.4/src/iad/vis/imview/__init__.py +9 -0
- ialdev_vis-0.2.4/src/iad/vis/imview/api.py +284 -0
- ialdev_vis-0.2.4/src/iad/vis/imview/colormaps.py +50 -0
- ialdev_vis-0.2.4/src/iad/vis/imview/data.py +614 -0
- ialdev_vis-0.2.4/src/iad/vis/imview/static/imgrid.css +201 -0
- ialdev_vis-0.2.4/src/iad/vis/imview/static/imgrid.js +1 -0
- ialdev_vis-0.2.4/src/iad/vis/imview/widget.py +178 -0
- {ialdev_vis-0.2.2 → ialdev_vis-0.2.4}/src/iad/vis/insight.py +44 -452
- ialdev_vis-0.2.4/src/iad/vis/mutils.py +311 -0
- ialdev_vis-0.2.4/src/iad/vis/plgrid.py +837 -0
- ialdev_vis-0.2.4/src/iad/vis/poly_to_mask/__init__.py +0 -0
- ialdev_vis-0.2.4/tests/test_imview.py +392 -0
- ialdev_vis-0.2.4/tests/test_plgrid.py +139 -0
- ialdev_vis-0.2.2/README.md +0 -45
- ialdev_vis-0.2.2/src/iad/vis/__init__.py +0 -6
- {ialdev_vis-0.2.2/src/iad/vis/poly_to_mask → ialdev_vis-0.2.4/src/iad/vis/colormaps}/__init__.py +0 -0
- {ialdev_vis-0.2.2 → ialdev_vis-0.2.4}/src/iad/vis/colormaps/blush_cm.py +0 -0
- {ialdev_vis-0.2.2 → ialdev_vis-0.2.4}/src/iad/vis/colormaps/glow_cm.py +0 -0
- {ialdev_vis-0.2.2 → ialdev_vis-0.2.4}/src/iad/vis/colormaps/rain.jscm +0 -0
- {ialdev_vis-0.2.2 → ialdev_vis-0.2.4}/src/iad/vis/colormaps/rain_cm.py +0 -0
- {ialdev_vis-0.2.2 → ialdev_vis-0.2.4}/src/iad/vis/colormaps/smooth_cm.py +0 -0
- {ialdev_vis-0.2.2 → ialdev_vis-0.2.4}/src/iad/vis/colormaps/wide_cm.py +0 -0
- {ialdev_vis-0.2.2 → ialdev_vis-0.2.4}/src/iad/vis/dotstyle.py +0 -0
- {ialdev_vis-0.2.2 → ialdev_vis-0.2.4}/src/iad/vis/embedding_in_qt5.py +0 -0
- {ialdev_vis-0.2.2 → ialdev_vis-0.2.4}/src/iad/vis/imageviewer.py +0 -0
- {ialdev_vis-0.2.2 → ialdev_vis-0.2.4}/src/iad/vis/interact.py +0 -0
- {ialdev_vis-0.2.2 → ialdev_vis-0.2.4}/src/iad/vis/ipv.py +0 -0
- {ialdev_vis-0.2.2 → ialdev_vis-0.2.4}/src/iad/vis/jupyter.py +0 -0
- {ialdev_vis-0.2.2 → ialdev_vis-0.2.4}/src/iad/vis/mpl_styles.py +0 -0
- {ialdev_vis-0.2.2 → ialdev_vis-0.2.4}/src/iad/vis/mpl_utils.py +0 -0
- {ialdev_vis-0.2.2 → ialdev_vis-0.2.4}/src/iad/vis/poly_to_mask/README.org +0 -0
- {ialdev_vis-0.2.2 → ialdev_vis-0.2.4}/src/iad/vis/poly_to_mask/example.py +0 -0
- {ialdev_vis-0.2.2 → ialdev_vis-0.2.4}/src/iad/vis/poly_to_mask/roipoly.py +0 -0
- {ialdev_vis-0.2.2 → ialdev_vis-0.2.4}/src/iad/vis/view3d.py +0 -0
- {ialdev_vis-0.2.2 → ialdev_vis-0.2.4}/tests/test_dotstyle.py +0 -0
- {ialdev_vis-0.2.2 → ialdev_vis-0.2.4}/tests/test_insight.py +0 -0
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
# imview — interactive image grid
|
|
2
|
+
|
|
3
|
+
`iad.vis.imview` is the anywidget-based image grid for marimo and Jupyter. It
|
|
4
|
+
replaces JSON heatmaps with binary pixel transport and client-side rendering.
|
|
5
|
+
|
|
6
|
+
## Capabilities
|
|
7
|
+
|
|
8
|
+
| Feature | Where | Notes |
|
|
9
|
+
|---------|-------|-------|
|
|
10
|
+
| Multi-panel grids | Python layout | Regular `(rows, cols)` or mosaic strings |
|
|
11
|
+
| Scalar + RGB panels | `data.py` | Auto-detect; grayscale RGB collapsed to scalar |
|
|
12
|
+
| Colormaps + clim | Frontend | LUTs built in Python, applied in browser |
|
|
13
|
+
| Pan / zoom | `grid.ts` | Per-panel view window; nearest-neighbor upscale |
|
|
14
|
+
| Pixel inspect | `inspect.ts` | Fixed-width coordinate/value readout |
|
|
15
|
+
| Axis ticks | `labels.ts` | Follow visible window during pan/zoom |
|
|
16
|
+
| Colorbars | Python layout + renderer | Scalar panels only |
|
|
17
|
+
| Static oversampling | `data.py` | One-time integer downsample in Python |
|
|
18
|
+
| `figsize` sizing | `data.py` + CSS | Reference CSS px; 240 px min per dimension |
|
|
19
|
+
| `max_zoom` / `downsample` | `data.py` | Control buffer resolution vs. transfer size |
|
|
20
|
+
| Data budget readout | Toolbar | MB / Mpx sent vs. full; red when over budget |
|
|
21
|
+
| Resolution badge | `labels.ts` | Per-panel `(N:1)` ratio, updates with zoom |
|
|
22
|
+
| In-place updates | `ImageGrid.update_data` | Same shapes; reuses prep kwargs |
|
|
23
|
+
| marimo / Jupyter | `api.py` | Auto backend; `.ui` for layout composition |
|
|
24
|
+
|
|
25
|
+
## Architecture
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
Python Browser (imgrid.js)
|
|
29
|
+
───────────────────────────────── ────────────────────────────────
|
|
30
|
+
imgrid() index.ts (entry)
|
|
31
|
+
└─ prepare_grid / data.py ├─ GridModel (trait bridge)
|
|
32
|
+
layout, downsample, pack ├─ Canvas2DRenderer
|
|
33
|
+
└─ ImageGridWidget.create ├─ LabelsOverlay (ticks, titles)
|
|
34
|
+
traitlets → binary buffers ├─ controls (toolbar)
|
|
35
|
+
└─ ImageGrid wrapper ├─ inspect (hover readout)
|
|
36
|
+
display / update_data └─ grid (pan/zoom)
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
**Static oversampling:** Python chooses an integer downsample factor per panel,
|
|
40
|
+
packs buffers once, and sends them over anywidget binary comm. The frontend
|
|
41
|
+
draws a sub-window of the buffer for pan/zoom. Upscaling past buffer detail
|
|
42
|
+
uses nearest-neighbor interpolation; downscaling stays smooth.
|
|
43
|
+
|
|
44
|
+
**Layout:** All panel rects, colorbar positions, and canvas size are computed
|
|
45
|
+
in Python (`_display_layout`) as reference CSS pixels. The frontend scales
|
|
46
|
+
to the display width (driven by `figsize`) while preserving aspect ratio.
|
|
47
|
+
|
|
48
|
+
## Package layout
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
vis/
|
|
52
|
+
├── IMVIEW.md # this file
|
|
53
|
+
├── README.md # package overview + install
|
|
54
|
+
├── js/ # TypeScript sources (build → static/imgrid.js)
|
|
55
|
+
│ └── src/
|
|
56
|
+
│ ├── index.ts # anywidget render entry, wiring
|
|
57
|
+
│ ├── model.ts # trait getters (panels, view, data_*)
|
|
58
|
+
│ ├── canvas.ts # HiDPI canvas sync
|
|
59
|
+
│ ├── grid.ts # pan/zoom, view state
|
|
60
|
+
│ ├── controls.ts # toolbar, data readout, clim/cmap toggles
|
|
61
|
+
│ ├── inspect.ts # pixel hover readout
|
|
62
|
+
│ ├── labels.ts # titles, axis ticks, resolution badge
|
|
63
|
+
│ ├── selection.ts # panel selection state
|
|
64
|
+
│ ├── colormap.ts # scalar recoloring
|
|
65
|
+
│ ├── types.ts # PanelMeta, ViewState, …
|
|
66
|
+
│ └── renderer/
|
|
67
|
+
│ ├── Renderer.ts # interface
|
|
68
|
+
│ └── Canvas2DRenderer.ts
|
|
69
|
+
├── src/iad/vis/
|
|
70
|
+
│ ├── gridcore.py # shared grid/mosaic/resize helpers
|
|
71
|
+
│ ├── mutils.py # marimo mogrid(); backend='wgt' → imview
|
|
72
|
+
│ └── imview/
|
|
73
|
+
│ ├── __init__.py # exports imgrid, ImageGrid
|
|
74
|
+
│ ├── api.py # imgrid(), ImageGrid
|
|
75
|
+
│ ├── data.py # prepare_grid*, layout, downsample
|
|
76
|
+
│ ├── widget.py # anywidget traits + apply_prepared
|
|
77
|
+
│ ├── colormaps.py # matplotlib LUT → bytes
|
|
78
|
+
│ └── static/
|
|
79
|
+
│ ├── imgrid.js # built bundle
|
|
80
|
+
│ └── imgrid.css
|
|
81
|
+
└── tests/test_imview.py
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Public API
|
|
85
|
+
|
|
86
|
+
### `imgrid(...)`
|
|
87
|
+
|
|
88
|
+
Main entry point. Returns an `ImageGrid` unless `out=` requests a component.
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
from iad.vis.imview import imgrid
|
|
92
|
+
|
|
93
|
+
grid = imgrid(
|
|
94
|
+
left, right, diff,
|
|
95
|
+
titles=["left", "right", "diff"],
|
|
96
|
+
figsize=(900, None),
|
|
97
|
+
max_zoom=2,
|
|
98
|
+
clim="auto",
|
|
99
|
+
)
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### `ImageGrid`
|
|
103
|
+
|
|
104
|
+
| Attribute / method | Description |
|
|
105
|
+
|--------------------|-------------|
|
|
106
|
+
| `.widget` | Raw anywidget instance (traits, buffers) |
|
|
107
|
+
| `.ui` | marimo `mo.ui.anywidget(...)` when backend is marimo |
|
|
108
|
+
| `.value` | `{'cursor', 'selection', 'view'}` reactive state |
|
|
109
|
+
| `.panels` | Python `PanelData` list from preparation |
|
|
110
|
+
| `.update_data(data)` | Replace buffers in place (dict by title or sequence) |
|
|
111
|
+
|
|
112
|
+
### marimo usage
|
|
113
|
+
|
|
114
|
+
```python
|
|
115
|
+
# Single grid — return as last expression
|
|
116
|
+
grid = imgrid(a, b, figsize=(800, None))
|
|
117
|
+
|
|
118
|
+
# Stack multiple grids — use .ui
|
|
119
|
+
mo.vstack([grid1.ui, grid2.ui])
|
|
120
|
+
|
|
121
|
+
# Reactive readout
|
|
122
|
+
grid.value["cursor"] # current hover panel + coords
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Via `mutils`:
|
|
126
|
+
|
|
127
|
+
```python
|
|
128
|
+
from iad.vis.mutils import mogrid, Backend
|
|
129
|
+
|
|
130
|
+
mogrid(a, b, backend=Backend.WGT, figsize=(800, 600), max_zoom=2)
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Preparation API (lower level)
|
|
134
|
+
|
|
135
|
+
```python
|
|
136
|
+
from iad.vis.imview.data import prepare_grid, prepare_grid_from_parsed
|
|
137
|
+
|
|
138
|
+
prepared = prepare_grid(img, titles=["a"], figsize=(600, 400), max_zoom=1.5)
|
|
139
|
+
# prepared.panels, prepared.canvas_size, prepared.sent_bytes, …
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## Key parameters
|
|
143
|
+
|
|
144
|
+
### `figsize=(width, height)`
|
|
145
|
+
|
|
146
|
+
Target grid size in CSS pixels. Either dimension may be `None`:
|
|
147
|
+
|
|
148
|
+
- `(800, None)` — fit width 800, height from aspect ratio + chrome
|
|
149
|
+
- `(None, 600)` — fit height 600
|
|
150
|
+
- `(800, 600)` — fit inside both bounds
|
|
151
|
+
|
|
152
|
+
Panel aspect ratios always match the source images. Each dimension has a
|
|
153
|
+
**240 px minimum** (`_MIN_PANEL_PX`).
|
|
154
|
+
|
|
155
|
+
### `max_zoom` vs `downsample`
|
|
156
|
+
|
|
157
|
+
Mutually exclusive.
|
|
158
|
+
|
|
159
|
+
| Mode | Effect |
|
|
160
|
+
|------|--------|
|
|
161
|
+
| *(default)* | Auto factor from `max_pixels` budget |
|
|
162
|
+
| `max_zoom=2` | Buffer ≥ 2× panel display size (crisp 2× zoom headroom) |
|
|
163
|
+
| `max_zoom='full'` | Factor 1 — full resolution sent |
|
|
164
|
+
| `downsample=4` | Fixed 4× block-mean downsample |
|
|
165
|
+
|
|
166
|
+
When `max_zoom` or `downsample` is set explicitly and total sent pixels exceed
|
|
167
|
+
`max_pixels * n_panels`, the toolbar readout turns red (`data_over_budget`).
|
|
168
|
+
|
|
169
|
+
### `update_data`
|
|
170
|
+
|
|
171
|
+
```python
|
|
172
|
+
grid.update_data({"left": new_left, "right": new_right})
|
|
173
|
+
grid.update_data([arr0, arr1]) # panel order
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Arrays must match original shapes. Uses the same `prep_kwargs` as initial
|
|
177
|
+
creation (cmap, clim, figsize, downsample, …).
|
|
178
|
+
|
|
179
|
+
## Widget traits (Python ↔ JS)
|
|
180
|
+
|
|
181
|
+
| Trait | Direction | Purpose |
|
|
182
|
+
|-------|-----------|---------|
|
|
183
|
+
| `panels` | → JS | Metadata: layout, clim, factor, source dims |
|
|
184
|
+
| `buffers` | → JS | Binary pixel data (float32 scalar / uint8 RGBA) |
|
|
185
|
+
| `luts` | → JS | Colormap byte blobs |
|
|
186
|
+
| `canvas_width/height` | → JS | Reference layout size |
|
|
187
|
+
| `data_sent_*`, `data_full_*` | → JS | Transfer accounting |
|
|
188
|
+
| `view` | ↔ | `{scale, tx, ty}` pan/zoom |
|
|
189
|
+
| `cursor`, `selection` | ← JS | Inspect / selection state |
|
|
190
|
+
| `cbar`, `ticks`, `show_grid`, `adj_clim` | ↔ | Display toggles |
|
|
191
|
+
|
|
192
|
+
## Frontend modules
|
|
193
|
+
|
|
194
|
+
| Module | Role |
|
|
195
|
+
|--------|------|
|
|
196
|
+
| `Canvas2DRenderer` | Draw panels, colorbars, grid overlay; nearest upscale |
|
|
197
|
+
| `LabelsOverlay` | DOM overlay for titles, ticks (pan/zoom-aware), res badge |
|
|
198
|
+
| `attachPanZoom` | Wheel zoom + drag pan; updates `view` trait |
|
|
199
|
+
| `attachInspect` | Hover readout with tabular-nums formatting |
|
|
200
|
+
| `buildToolbar` | Cmap/clim controls, data MB/Mpx readout |
|
|
201
|
+
| `GridModel` | Typed accessors over anywidget model traits |
|
|
202
|
+
|
|
203
|
+
## Build (developers)
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
cd vis/js && npm install && npm run build
|
|
207
|
+
# writes vis/src/iad/vis/imview/static/imgrid.js
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
Run tests:
|
|
211
|
+
|
|
212
|
+
```bash
|
|
213
|
+
pixi run pytest vis/tests/test_imview.py
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
## Related backends
|
|
217
|
+
|
|
218
|
+
| Module | Backend | Use case |
|
|
219
|
+
|--------|---------|----------|
|
|
220
|
+
| `iad.vis.imview` | anywidget | Interactive notebooks (this doc) |
|
|
221
|
+
| `iad.vis.insight` | matplotlib | Desktop / static figures |
|
|
222
|
+
| `iad.vis.plgrid` | Plotly | Lightweight overview plots |
|
|
223
|
+
| `iad.vis.mutils.mogrid` | switchable | marimo helper; `backend='wgt'` → imview |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ialdev-vis
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.4
|
|
4
4
|
Summary: iad.vis — visualization utilities (image grids, viewers, colormaps, matplotlib helpers)
|
|
5
5
|
Author: ipcoder
|
|
6
6
|
Requires-Python: >=3.10
|
|
@@ -12,19 +12,25 @@ Classifier: Programming Language :: Python :: 3
|
|
|
12
12
|
Classifier: Programming Language :: Python :: 3.10
|
|
13
13
|
Classifier: Programming Language :: Python :: 3.11
|
|
14
14
|
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
-
Requires-Dist: ialdev-core>=0.2.
|
|
16
|
-
Requires-Dist: ialdev-io>=0.2.
|
|
15
|
+
Requires-Dist: ialdev-core>=0.2.6
|
|
16
|
+
Requires-Dist: ialdev-io>=0.2.4
|
|
17
17
|
Requires-Dist: matplotlib>=3.5.0
|
|
18
18
|
Requires-Dist: numpy>=1.26.4,<2
|
|
19
19
|
Requires-Dist: regex>=2021.0.0
|
|
20
20
|
Requires-Dist: open3d>=0.15.0 ; extra == "3d"
|
|
21
21
|
Requires-Dist: ipyvolume>=0.6.0 ; extra == "3d"
|
|
22
|
-
Requires-Dist: ialdev-vis[graphviz, qt, jupyter, 3d, dev]>=0.2.
|
|
22
|
+
Requires-Dist: ialdev-vis[graphviz, qt, jupyter, notebook, marimo, 3d, dev]>=0.2.4 ; extra == "all"
|
|
23
23
|
Requires-Dist: pytest>=7.0.0 ; extra == "dev"
|
|
24
24
|
Requires-Dist: pytest-cov>=3.0.0 ; extra == "dev"
|
|
25
25
|
Requires-Dist: pygraphviz>=1.14,<2 ; extra == "graphviz"
|
|
26
26
|
Requires-Dist: ipywidgets>=7.0.0 ; extra == "jupyter"
|
|
27
27
|
Requires-Dist: IPython>=7.0.0 ; extra == "jupyter"
|
|
28
|
+
Requires-Dist: plotly>=5.20 ; extra == "jupyter"
|
|
29
|
+
Requires-Dist: anywidget>=0.9 ; extra == "jupyter"
|
|
30
|
+
Requires-Dist: marimo>=0.23 ; extra == "marimo"
|
|
31
|
+
Requires-Dist: plotly>=5.20 ; extra == "marimo"
|
|
32
|
+
Requires-Dist: pandas>=2.0.0 ; extra == "marimo"
|
|
33
|
+
Requires-Dist: anywidget>=0.9 ; extra == "notebook"
|
|
28
34
|
Requires-Dist: PyQt5>=5.15.0 ; extra == "qt"
|
|
29
35
|
Requires-Dist: scikit-image>=0.19.0 ; extra == "qt"
|
|
30
36
|
Project-URL: Homepage, https://github.com/ipcoder/ialdev/tree/master/vis
|
|
@@ -35,6 +41,8 @@ Provides-Extra: all
|
|
|
35
41
|
Provides-Extra: dev
|
|
36
42
|
Provides-Extra: graphviz
|
|
37
43
|
Provides-Extra: jupyter
|
|
44
|
+
Provides-Extra: marimo
|
|
45
|
+
Provides-Extra: notebook
|
|
38
46
|
Provides-Extra: qt
|
|
39
47
|
|
|
40
48
|
# ialdev-vis
|
|
@@ -54,6 +62,8 @@ Optional extras:
|
|
|
54
62
|
```bash
|
|
55
63
|
pip install "ialdev-vis[qt]"
|
|
56
64
|
pip install "ialdev-vis[jupyter]"
|
|
65
|
+
pip install "ialdev-vis[notebook]" # anywidget interactive image grid (imview)
|
|
66
|
+
pip install "ialdev-vis[marimo]"
|
|
57
67
|
pip install "ialdev-vis[3d]"
|
|
58
68
|
pip install "ialdev-vis[all]"
|
|
59
69
|
```
|
|
@@ -63,6 +73,7 @@ Requires Python `>=3.10`.
|
|
|
63
73
|
## Highlights
|
|
64
74
|
|
|
65
75
|
- `imgrid` and `imhist` for fast inspection of images and distributions.
|
|
76
|
+
- `iad.vis.imview.imgrid` — interactive notebook image grid (marimo / Jupyter) via anywidget; static oversampling, `figsize` layout, client-side colormap/clim/zoom, mosaic layouts, data-budget readout, and cross-panel inspection. See [IMVIEW.md](IMVIEW.md).
|
|
66
77
|
- Matplotlib helpers for figure capture and conversion to arrays/PIL images.
|
|
67
78
|
- Built-in custom colormaps.
|
|
68
79
|
- Polygon-to-mask helpers and interactive ROI tools.
|
|
@@ -71,7 +82,7 @@ Requires Python `>=3.10`.
|
|
|
71
82
|
## Examples
|
|
72
83
|
|
|
73
84
|
```python
|
|
74
|
-
from iad.vis import imgrid, imhist
|
|
85
|
+
from iad.vis.insight import imgrid, imhist
|
|
75
86
|
|
|
76
87
|
imgrid(left_image, right_image, titles=["left", "right"], clim="auto")
|
|
77
88
|
imhist(left_image, right_image, titles=["left", "right"])
|
|
@@ -83,3 +94,30 @@ from iad.vis.mpl_utils import fig2img
|
|
|
83
94
|
pil_image = fig2img(figure)
|
|
84
95
|
```
|
|
85
96
|
|
|
97
|
+
### Interactive image grid in marimo / Jupyter (`imview`)
|
|
98
|
+
|
|
99
|
+
See **[IMVIEW.md](IMVIEW.md)** for architecture, parameters (`figsize`, `max_zoom`, `downsample`), module layout, and marimo stacking patterns.
|
|
100
|
+
|
|
101
|
+
```python
|
|
102
|
+
from iad.vis.imview import imgrid
|
|
103
|
+
import marimo as mo
|
|
104
|
+
|
|
105
|
+
grid = imgrid(left, right, diff, titles=["left", "right", "diff"], figsize=(900, None), max_zoom=2)
|
|
106
|
+
grid.ui # use in mo.vstack / mo.hstack
|
|
107
|
+
grid.value # reactive cursor, selection, view state
|
|
108
|
+
grid.update_data({"left": new_left}) # in-place buffer refresh
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
In marimo, `iad.vis.mutils.mogrid(..., backend='wgt')` routes to the same anywidget backend.
|
|
112
|
+
|
|
113
|
+
Rebuild the frontend after editing TypeScript (widget developers only):
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
cd vis/js && npm install && npm run build
|
|
117
|
+
# or: pixi run build-imview-js (requires pixi feature build-js / nodejs)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
**Roadmap:** WebGL renderer (large images), ROI / line-profile tools, live histogram panel, linked selections into pandas/marimo cells.
|
|
121
|
+
|
|
122
|
+
**Note:** `iad.vis.plgrid` remains a lightweight Plotly overview option; desktop/Qt inspection still uses `iad.vis.insight.imgrid` (matplotlib).
|
|
123
|
+
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# ialdev-vis
|
|
2
|
+
|
|
3
|
+
Visualization utilities for the `iad` toolbox, published as `ialdev-vis` and imported as `iad.vis`.
|
|
4
|
+
|
|
5
|
+
Use this package for quick image grids, histograms, Matplotlib helpers, custom colormaps, interactive annotation widgets, Jupyter logging, and optional Qt/3D visualization tools.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pip install ialdev-vis
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Optional extras:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
pip install "ialdev-vis[qt]"
|
|
17
|
+
pip install "ialdev-vis[jupyter]"
|
|
18
|
+
pip install "ialdev-vis[notebook]" # anywidget interactive image grid (imview)
|
|
19
|
+
pip install "ialdev-vis[marimo]"
|
|
20
|
+
pip install "ialdev-vis[3d]"
|
|
21
|
+
pip install "ialdev-vis[all]"
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Requires Python `>=3.10`.
|
|
25
|
+
|
|
26
|
+
## Highlights
|
|
27
|
+
|
|
28
|
+
- `imgrid` and `imhist` for fast inspection of images and distributions.
|
|
29
|
+
- `iad.vis.imview.imgrid` — interactive notebook image grid (marimo / Jupyter) via anywidget; static oversampling, `figsize` layout, client-side colormap/clim/zoom, mosaic layouts, data-budget readout, and cross-panel inspection. See [IMVIEW.md](IMVIEW.md).
|
|
30
|
+
- Matplotlib helpers for figure capture and conversion to arrays/PIL images.
|
|
31
|
+
- Built-in custom colormaps.
|
|
32
|
+
- Polygon-to-mask helpers and interactive ROI tools.
|
|
33
|
+
- Optional Qt image viewer and optional `ipyvolume`/Open3D 3D views.
|
|
34
|
+
|
|
35
|
+
## Examples
|
|
36
|
+
|
|
37
|
+
```python
|
|
38
|
+
from iad.vis.insight import imgrid, imhist
|
|
39
|
+
|
|
40
|
+
imgrid(left_image, right_image, titles=["left", "right"], clim="auto")
|
|
41
|
+
imhist(left_image, right_image, titles=["left", "right"])
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
```python
|
|
45
|
+
from iad.vis.mpl_utils import fig2img
|
|
46
|
+
|
|
47
|
+
pil_image = fig2img(figure)
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Interactive image grid in marimo / Jupyter (`imview`)
|
|
51
|
+
|
|
52
|
+
See **[IMVIEW.md](IMVIEW.md)** for architecture, parameters (`figsize`, `max_zoom`, `downsample`), module layout, and marimo stacking patterns.
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
from iad.vis.imview import imgrid
|
|
56
|
+
import marimo as mo
|
|
57
|
+
|
|
58
|
+
grid = imgrid(left, right, diff, titles=["left", "right", "diff"], figsize=(900, None), max_zoom=2)
|
|
59
|
+
grid.ui # use in mo.vstack / mo.hstack
|
|
60
|
+
grid.value # reactive cursor, selection, view state
|
|
61
|
+
grid.update_data({"left": new_left}) # in-place buffer refresh
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
In marimo, `iad.vis.mutils.mogrid(..., backend='wgt')` routes to the same anywidget backend.
|
|
65
|
+
|
|
66
|
+
Rebuild the frontend after editing TypeScript (widget developers only):
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
cd vis/js && npm install && npm run build
|
|
70
|
+
# or: pixi run build-imview-js (requires pixi feature build-js / nodejs)
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
**Roadmap:** WebGL renderer (large images), ROI / line-profile tools, live histogram panel, linked selections into pandas/marimo cells.
|
|
74
|
+
|
|
75
|
+
**Note:** `iad.vis.plgrid` remains a lightweight Plotly overview option; desktop/Qt inspection still uses `iad.vis.insight.imgrid` (matplotlib).
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import * as esbuild from 'esbuild';
|
|
2
|
+
import { mkdirSync } from 'node:fs';
|
|
3
|
+
import { dirname, resolve } from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
|
|
6
|
+
const root = dirname(fileURLToPath(import.meta.url));
|
|
7
|
+
const outFile = resolve(root, '../src/iad/vis/imview/static/imgrid.js');
|
|
8
|
+
mkdirSync(dirname(outFile), { recursive: true });
|
|
9
|
+
|
|
10
|
+
const watch = process.argv.includes('--watch');
|
|
11
|
+
|
|
12
|
+
const ctx = await esbuild.context({
|
|
13
|
+
entryPoints: [resolve(root, 'src/index.ts')],
|
|
14
|
+
bundle: true,
|
|
15
|
+
format: 'esm',
|
|
16
|
+
platform: 'browser',
|
|
17
|
+
target: ['es2020'],
|
|
18
|
+
outfile: outFile,
|
|
19
|
+
minify: !watch,
|
|
20
|
+
sourcemap: watch,
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
if (watch) {
|
|
24
|
+
await ctx.watch();
|
|
25
|
+
console.log('watching imview bundle...');
|
|
26
|
+
} else {
|
|
27
|
+
await ctx.rebuild();
|
|
28
|
+
await ctx.dispose();
|
|
29
|
+
console.log('built', outFile);
|
|
30
|
+
}
|