nwb-video-widgets 0.1.0__py3-none-any.whl → 0.1.2__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.
- nwb_video_widgets/dandi_video_widget.py +68 -11
- nwb_video_widgets/local_video_widget.py +71 -11
- nwb_video_widgets/video_widget.js +47 -12
- {nwb_video_widgets-0.1.0.dist-info → nwb_video_widgets-0.1.2.dist-info}/METADATA +68 -7
- {nwb_video_widgets-0.1.0.dist-info → nwb_video_widgets-0.1.2.dist-info}/RECORD +7 -7
- {nwb_video_widgets-0.1.0.dist-info → nwb_video_widgets-0.1.2.dist-info}/WHEEL +0 -0
- {nwb_video_widgets-0.1.0.dist-info → nwb_video_widgets-0.1.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -32,9 +32,19 @@ class NWBDANDIVideoPlayer(anywidget.AnyWidget):
|
|
|
32
32
|
nwbfile : pynwb.NWBFile, optional
|
|
33
33
|
Pre-loaded NWB file to avoid re-loading. If not provided, the widget
|
|
34
34
|
will load the NWB file via streaming.
|
|
35
|
+
video_grid : list[list[str]], optional
|
|
36
|
+
A 2D grid layout specifying which videos to display and where.
|
|
37
|
+
Each inner list represents a row of videos. When provided, bypasses
|
|
38
|
+
the interactive settings panel and displays videos in the specified
|
|
39
|
+
grid arrangement. Video names that don't exist are silently skipped.
|
|
40
|
+
video_labels : dict[str, str], optional
|
|
41
|
+
Mapping of video names to custom display labels. If a video name is
|
|
42
|
+
not in the dictionary, the original video name is displayed.
|
|
35
43
|
|
|
36
44
|
Example
|
|
37
45
|
-------
|
|
46
|
+
Interactive mode (default):
|
|
47
|
+
|
|
38
48
|
>>> from dandi.dandiapi import DandiAPIClient
|
|
39
49
|
>>> client = DandiAPIClient()
|
|
40
50
|
>>> dandiset = client.get_dandiset("000409", "draft")
|
|
@@ -48,6 +58,23 @@ class NWBDANDIVideoPlayer(anywidget.AnyWidget):
|
|
|
48
58
|
... asset=asset,
|
|
49
59
|
... nwbfile=already_loaded_nwbfile,
|
|
50
60
|
... )
|
|
61
|
+
|
|
62
|
+
Fixed grid mode (single row):
|
|
63
|
+
|
|
64
|
+
>>> widget = NWBDANDIVideoPlayer(
|
|
65
|
+
... asset=asset,
|
|
66
|
+
... video_grid=[["VideoLeftCamera", "VideoBodyCamera", "VideoRightCamera"]]
|
|
67
|
+
... )
|
|
68
|
+
|
|
69
|
+
Fixed grid mode (2x2 grid):
|
|
70
|
+
|
|
71
|
+
>>> widget = NWBDANDIVideoPlayer(
|
|
72
|
+
... asset=asset,
|
|
73
|
+
... video_grid=[
|
|
74
|
+
... ["VideoLeftCamera", "VideoRightCamera"],
|
|
75
|
+
... ["VideoBodyCamera"],
|
|
76
|
+
... ]
|
|
77
|
+
... )
|
|
51
78
|
"""
|
|
52
79
|
|
|
53
80
|
video_urls = traitlets.Dict({}).tag(sync=True)
|
|
@@ -56,6 +83,8 @@ class NWBDANDIVideoPlayer(anywidget.AnyWidget):
|
|
|
56
83
|
selected_videos = traitlets.List([]).tag(sync=True)
|
|
57
84
|
layout_mode = traitlets.Unicode("row").tag(sync=True)
|
|
58
85
|
settings_open = traitlets.Bool(False).tag(sync=True)
|
|
86
|
+
grid_layout = traitlets.List([]).tag(sync=True)
|
|
87
|
+
video_labels = traitlets.Dict({}).tag(sync=True)
|
|
59
88
|
|
|
60
89
|
_esm = pathlib.Path(__file__).parent / "video_widget.js"
|
|
61
90
|
_css = pathlib.Path(__file__).parent / "video_widget.css"
|
|
@@ -64,6 +93,8 @@ class NWBDANDIVideoPlayer(anywidget.AnyWidget):
|
|
|
64
93
|
self,
|
|
65
94
|
asset: RemoteAsset,
|
|
66
95
|
nwbfile: Optional[NWBFile] = None,
|
|
96
|
+
video_grid: Optional[list[list[str]]] = None,
|
|
97
|
+
video_labels: Optional[dict[str, str]] = None,
|
|
67
98
|
**kwargs,
|
|
68
99
|
):
|
|
69
100
|
# Load NWB file if not provided
|
|
@@ -73,17 +104,43 @@ class NWBDANDIVideoPlayer(anywidget.AnyWidget):
|
|
|
73
104
|
video_urls = self.get_video_urls_from_dandi(nwbfile, asset)
|
|
74
105
|
video_timestamps = get_video_timestamps(nwbfile)
|
|
75
106
|
available_videos = get_video_info(nwbfile)
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
107
|
+
video_labels = video_labels or {}
|
|
108
|
+
|
|
109
|
+
if video_grid is not None and len(video_grid) > 0:
|
|
110
|
+
# Fixed grid mode - bypass settings panel
|
|
111
|
+
# Filter to only include videos that exist in video_urls
|
|
112
|
+
filtered_grid = [
|
|
113
|
+
[v for v in row if v in video_urls]
|
|
114
|
+
for row in video_grid
|
|
115
|
+
]
|
|
116
|
+
# Remove empty rows
|
|
117
|
+
filtered_grid = [row for row in filtered_grid if row]
|
|
118
|
+
# Flatten grid to get selected videos (preserving order)
|
|
119
|
+
selected = [v for row in filtered_grid for v in row]
|
|
120
|
+
super().__init__(
|
|
121
|
+
video_urls=video_urls,
|
|
122
|
+
video_timestamps=video_timestamps,
|
|
123
|
+
available_videos=available_videos,
|
|
124
|
+
selected_videos=selected,
|
|
125
|
+
layout_mode="grid",
|
|
126
|
+
settings_open=False,
|
|
127
|
+
grid_layout=filtered_grid,
|
|
128
|
+
video_labels=video_labels,
|
|
129
|
+
**kwargs,
|
|
130
|
+
)
|
|
131
|
+
else:
|
|
132
|
+
# Interactive mode (current behavior)
|
|
133
|
+
super().__init__(
|
|
134
|
+
video_urls=video_urls,
|
|
135
|
+
video_timestamps=video_timestamps,
|
|
136
|
+
available_videos=available_videos,
|
|
137
|
+
selected_videos=[],
|
|
138
|
+
layout_mode="grid",
|
|
139
|
+
settings_open=True,
|
|
140
|
+
grid_layout=[],
|
|
141
|
+
video_labels=video_labels,
|
|
142
|
+
**kwargs,
|
|
143
|
+
)
|
|
87
144
|
|
|
88
145
|
@staticmethod
|
|
89
146
|
def _load_nwbfile_from_dandi(asset: RemoteAsset) -> NWBFile:
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
"""Local NWB video player widget."""
|
|
2
2
|
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
3
5
|
import pathlib
|
|
4
6
|
from pathlib import Path
|
|
7
|
+
from typing import Optional
|
|
5
8
|
|
|
6
9
|
import anywidget
|
|
7
10
|
import traitlets
|
|
@@ -28,15 +31,42 @@ class NWBLocalVideoPlayer(anywidget.AnyWidget):
|
|
|
28
31
|
nwbfile : pynwb.NWBFile
|
|
29
32
|
NWB file containing video ImageSeries in acquisition. Must have been
|
|
30
33
|
loaded from disk (i.e., nwbfile.read_io must not be None).
|
|
34
|
+
video_grid : list[list[str]], optional
|
|
35
|
+
A 2D grid layout specifying which videos to display and where.
|
|
36
|
+
Each inner list represents a row of videos. When provided, bypasses
|
|
37
|
+
the interactive settings panel and displays videos in the specified
|
|
38
|
+
grid arrangement. Video names that don't exist are silently skipped.
|
|
39
|
+
video_labels : dict[str, str], optional
|
|
40
|
+
Mapping of video names to custom display labels. If a video name is
|
|
41
|
+
not in the dictionary, the original video name is displayed.
|
|
31
42
|
|
|
32
43
|
Example
|
|
33
44
|
-------
|
|
45
|
+
Interactive mode (default):
|
|
46
|
+
|
|
34
47
|
>>> from pynwb import NWBHDF5IO
|
|
35
48
|
>>> with NWBHDF5IO("experiment.nwb", "r") as io:
|
|
36
49
|
... nwbfile = io.read()
|
|
37
50
|
... widget = NWBLocalVideoPlayer(nwbfile)
|
|
38
51
|
... display(widget)
|
|
39
52
|
|
|
53
|
+
Fixed grid mode (single row):
|
|
54
|
+
|
|
55
|
+
>>> widget = NWBLocalVideoPlayer(
|
|
56
|
+
... nwbfile,
|
|
57
|
+
... video_grid=[["VideoLeftCamera", "VideoBodyCamera", "VideoRightCamera"]]
|
|
58
|
+
... )
|
|
59
|
+
|
|
60
|
+
Fixed grid mode (2x2 grid):
|
|
61
|
+
|
|
62
|
+
>>> widget = NWBLocalVideoPlayer(
|
|
63
|
+
... nwbfile,
|
|
64
|
+
... video_grid=[
|
|
65
|
+
... ["VideoLeftCamera", "VideoRightCamera"],
|
|
66
|
+
... ["VideoBodyCamera"],
|
|
67
|
+
... ]
|
|
68
|
+
... )
|
|
69
|
+
|
|
40
70
|
Raises
|
|
41
71
|
------
|
|
42
72
|
ValueError
|
|
@@ -49,6 +79,8 @@ class NWBLocalVideoPlayer(anywidget.AnyWidget):
|
|
|
49
79
|
selected_videos = traitlets.List([]).tag(sync=True)
|
|
50
80
|
layout_mode = traitlets.Unicode("row").tag(sync=True)
|
|
51
81
|
settings_open = traitlets.Bool(False).tag(sync=True)
|
|
82
|
+
grid_layout = traitlets.List([]).tag(sync=True)
|
|
83
|
+
video_labels = traitlets.Dict({}).tag(sync=True)
|
|
52
84
|
|
|
53
85
|
_esm = pathlib.Path(__file__).parent / "video_widget.js"
|
|
54
86
|
_css = pathlib.Path(__file__).parent / "video_widget.css"
|
|
@@ -56,22 +88,50 @@ class NWBLocalVideoPlayer(anywidget.AnyWidget):
|
|
|
56
88
|
def __init__(
|
|
57
89
|
self,
|
|
58
90
|
nwbfile: NWBFile,
|
|
91
|
+
video_grid: Optional[list[list[str]]] = None,
|
|
92
|
+
video_labels: Optional[dict[str, str]] = None,
|
|
59
93
|
**kwargs,
|
|
60
94
|
):
|
|
61
95
|
video_urls = self.get_video_urls_from_local(nwbfile)
|
|
62
96
|
video_timestamps = get_video_timestamps(nwbfile)
|
|
63
97
|
available_videos = get_video_info(nwbfile)
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
98
|
+
video_labels = video_labels or {}
|
|
99
|
+
|
|
100
|
+
if video_grid is not None and len(video_grid) > 0:
|
|
101
|
+
# Fixed grid mode - bypass settings panel
|
|
102
|
+
# Filter to only include videos that exist in video_urls
|
|
103
|
+
filtered_grid = [
|
|
104
|
+
[v for v in row if v in video_urls]
|
|
105
|
+
for row in video_grid
|
|
106
|
+
]
|
|
107
|
+
# Remove empty rows
|
|
108
|
+
filtered_grid = [row for row in filtered_grid if row]
|
|
109
|
+
# Flatten grid to get selected videos (preserving order)
|
|
110
|
+
selected = [v for row in filtered_grid for v in row]
|
|
111
|
+
super().__init__(
|
|
112
|
+
video_urls=video_urls,
|
|
113
|
+
video_timestamps=video_timestamps,
|
|
114
|
+
available_videos=available_videos,
|
|
115
|
+
selected_videos=selected,
|
|
116
|
+
layout_mode="grid",
|
|
117
|
+
settings_open=False,
|
|
118
|
+
grid_layout=filtered_grid,
|
|
119
|
+
video_labels=video_labels,
|
|
120
|
+
**kwargs,
|
|
121
|
+
)
|
|
122
|
+
else:
|
|
123
|
+
# Interactive mode (current behavior)
|
|
124
|
+
super().__init__(
|
|
125
|
+
video_urls=video_urls,
|
|
126
|
+
video_timestamps=video_timestamps,
|
|
127
|
+
available_videos=available_videos,
|
|
128
|
+
selected_videos=[],
|
|
129
|
+
layout_mode="grid",
|
|
130
|
+
settings_open=True,
|
|
131
|
+
grid_layout=[],
|
|
132
|
+
video_labels=video_labels,
|
|
133
|
+
**kwargs,
|
|
134
|
+
)
|
|
75
135
|
|
|
76
136
|
@staticmethod
|
|
77
137
|
def get_video_urls_from_local(nwbfile: NWBFile) -> dict[str, str]:
|
|
@@ -394,6 +394,17 @@ function render({ model, el }) {
|
|
|
394
394
|
const urls = model.get("video_urls");
|
|
395
395
|
const selectedVideos = model.get("selected_videos") || [];
|
|
396
396
|
const layoutMode = model.get("layout_mode") || "row";
|
|
397
|
+
const gridLayout = model.get("grid_layout") || [];
|
|
398
|
+
|
|
399
|
+
// Check if we're in fixed grid mode (grid_layout is non-empty)
|
|
400
|
+
const isFixedGridMode = gridLayout.length > 0;
|
|
401
|
+
|
|
402
|
+
// Hide/show settings button based on mode
|
|
403
|
+
if (isFixedGridMode) {
|
|
404
|
+
settingsBtn.style.display = "none";
|
|
405
|
+
} else {
|
|
406
|
+
settingsBtn.style.display = "";
|
|
407
|
+
}
|
|
397
408
|
|
|
398
409
|
// Filter to only selected videos that have URLs
|
|
399
410
|
const videosToShow = selectedVideos.filter((name) => urls[name]);
|
|
@@ -406,25 +417,47 @@ function render({ model, el }) {
|
|
|
406
417
|
return;
|
|
407
418
|
}
|
|
408
419
|
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
420
|
+
let numRows, numCols;
|
|
421
|
+
let videoPositions = []; // Array of {name, rowIdx, colIdx}
|
|
422
|
+
|
|
423
|
+
if (isFixedGridMode) {
|
|
424
|
+
// Fixed grid mode - use 2D layout directly
|
|
425
|
+
numRows = gridLayout.length;
|
|
426
|
+
numCols = Math.max(...gridLayout.map((row) => row.length));
|
|
427
|
+
|
|
428
|
+
// Build positions from grid_layout
|
|
429
|
+
gridLayout.forEach((row, rowIdx) => {
|
|
430
|
+
row.forEach((name, colIdx) => {
|
|
431
|
+
if (urls[name]) {
|
|
432
|
+
videoPositions.push({ name, rowIdx, colIdx });
|
|
433
|
+
}
|
|
434
|
+
});
|
|
435
|
+
});
|
|
436
|
+
} else {
|
|
437
|
+
// Interactive mode - use selected_videos + layout_mode
|
|
438
|
+
const dims = calculateGridDimensions(layoutMode, videosToShow.length);
|
|
439
|
+
numRows = dims.rows;
|
|
440
|
+
numCols = dims.cols;
|
|
441
|
+
|
|
442
|
+
// Build positions from selected_videos order
|
|
443
|
+
videosToShow.forEach((name, index) => {
|
|
444
|
+
const rowIdx = Math.floor(index / numCols);
|
|
445
|
+
const colIdx = index % numCols;
|
|
446
|
+
videoPositions.push({ name, rowIdx, colIdx });
|
|
447
|
+
});
|
|
448
|
+
}
|
|
414
449
|
|
|
415
450
|
gridContainer.style.gridTemplateColumns = "repeat(" + numCols + ", auto)";
|
|
416
451
|
gridContainer.style.gridTemplateRows = "repeat(" + numRows + ", auto)";
|
|
417
452
|
|
|
418
|
-
// Place videos in grid cells
|
|
419
|
-
|
|
453
|
+
// Place videos in grid cells
|
|
454
|
+
videoPositions.forEach(({ name, rowIdx, colIdx }) => {
|
|
420
455
|
const url = urls[name];
|
|
421
|
-
const rowIdx = Math.floor(index / numCols);
|
|
422
|
-
const colIdx = index % numCols;
|
|
423
456
|
|
|
424
457
|
const videoCell = document.createElement("div");
|
|
425
458
|
videoCell.classList.add("video-widget__video-cell");
|
|
426
|
-
videoCell.style.gridRow = rowIdx + 1;
|
|
427
|
-
videoCell.style.gridColumn = colIdx + 1;
|
|
459
|
+
videoCell.style.gridRow = String(rowIdx + 1);
|
|
460
|
+
videoCell.style.gridColumn = String(colIdx + 1);
|
|
428
461
|
|
|
429
462
|
const videoContainer = document.createElement("div");
|
|
430
463
|
videoContainer.classList.add("video-widget__video-container");
|
|
@@ -463,8 +496,9 @@ function render({ model, el }) {
|
|
|
463
496
|
videoContainer.appendChild(video);
|
|
464
497
|
videoContainer.appendChild(loadingDiv);
|
|
465
498
|
|
|
499
|
+
const videoLabels = model.get("video_labels") || {};
|
|
466
500
|
const label = document.createElement("p");
|
|
467
|
-
label.textContent = name
|
|
501
|
+
label.textContent = videoLabels[name] || name;
|
|
468
502
|
label.classList.add("video-widget__video-label");
|
|
469
503
|
|
|
470
504
|
videoCell.appendChild(videoContainer);
|
|
@@ -544,6 +578,7 @@ function render({ model, el }) {
|
|
|
544
578
|
updateSettingsPanel();
|
|
545
579
|
});
|
|
546
580
|
model.on("change:layout_mode", updateVideos);
|
|
581
|
+
model.on("change:grid_layout", updateVideos);
|
|
547
582
|
model.on("change:settings_open", updateSettingsPanel);
|
|
548
583
|
model.on("change:available_videos", updateSettingsPanel);
|
|
549
584
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nwb-video-widgets
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.2
|
|
4
4
|
Summary: Interactive Jupyter widgets for NWB video and pose visualization
|
|
5
5
|
Project-URL: Homepage, https://github.com/catalystneuro/nwb-video-widgets
|
|
6
6
|
Project-URL: Repository, https://github.com/catalystneuro/nwb-video-widgets
|
|
@@ -12,11 +12,12 @@ Classifier: Development Status :: 4 - Beta
|
|
|
12
12
|
Classifier: Framework :: Jupyter
|
|
13
13
|
Classifier: Intended Audience :: Science/Research
|
|
14
14
|
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: JavaScript
|
|
15
16
|
Classifier: Programming Language :: Python :: 3
|
|
16
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
17
17
|
Classifier: Programming Language :: Python :: 3.11
|
|
18
18
|
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
-
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Requires-Python: <3.14,>=3.10
|
|
20
21
|
Requires-Dist: anywidget>=0.9.0
|
|
21
22
|
Requires-Dist: matplotlib
|
|
22
23
|
Requires-Dist: numpy
|
|
@@ -25,10 +26,6 @@ Provides-Extra: dandi
|
|
|
25
26
|
Requires-Dist: dandi>=0.60.0; extra == 'dandi'
|
|
26
27
|
Requires-Dist: h5py; extra == 'dandi'
|
|
27
28
|
Requires-Dist: remfile>=0.1.13; extra == 'dandi'
|
|
28
|
-
Provides-Extra: test
|
|
29
|
-
Requires-Dist: opencv-python-headless; extra == 'test'
|
|
30
|
-
Requires-Dist: pytest-cov; extra == 'test'
|
|
31
|
-
Requires-Dist: pytest>=7.0; extra == 'test'
|
|
32
29
|
Description-Content-Type: text/markdown
|
|
33
30
|
|
|
34
31
|
# nwb-video-widgets
|
|
@@ -100,6 +97,70 @@ widget = NWBLocalVideoPlayer(nwbfile)
|
|
|
100
97
|
widget
|
|
101
98
|
```
|
|
102
99
|
|
|
100
|
+
### Fixed Grid Layout
|
|
101
|
+
|
|
102
|
+
When you know exactly which videos you want to display and how to arrange them, use the `video_grid` parameter to bypass the interactive settings panel. This is useful for:
|
|
103
|
+
|
|
104
|
+
- Reproducible notebooks where you want consistent output
|
|
105
|
+
- Presentations or demos with predetermined layouts
|
|
106
|
+
- Embedding widgets in dashboards or reports
|
|
107
|
+
|
|
108
|
+
The `video_grid` parameter accepts a 2D list where each inner list represents a row of videos:
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
# Single row of three cameras
|
|
112
|
+
widget = NWBLocalVideoPlayer(
|
|
113
|
+
nwbfile,
|
|
114
|
+
video_grid=[["VideoLeftCamera", "VideoBodyCamera", "VideoRightCamera"]]
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
# 2x2 grid layout
|
|
118
|
+
widget = NWBLocalVideoPlayer(
|
|
119
|
+
nwbfile,
|
|
120
|
+
video_grid=[
|
|
121
|
+
["VideoLeftCamera", "VideoRightCamera"],
|
|
122
|
+
["VideoBodyCamera", "VideoTopCamera"],
|
|
123
|
+
]
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
# Asymmetric grid (2 videos on top, 1 on bottom)
|
|
127
|
+
widget = NWBLocalVideoPlayer(
|
|
128
|
+
nwbfile,
|
|
129
|
+
video_grid=[
|
|
130
|
+
["VideoLeftCamera", "VideoRightCamera"],
|
|
131
|
+
["VideoBodyCamera"],
|
|
132
|
+
]
|
|
133
|
+
)
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
The same parameter works with `NWBDANDIVideoPlayer`:
|
|
137
|
+
|
|
138
|
+
```python
|
|
139
|
+
widget = NWBDANDIVideoPlayer(
|
|
140
|
+
asset=asset,
|
|
141
|
+
video_grid=[["VideoLeftCamera", "VideoRightCamera"]]
|
|
142
|
+
)
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Video names that don't exist in the NWB file are silently skipped.
|
|
146
|
+
|
|
147
|
+
### Custom Video Labels
|
|
148
|
+
|
|
149
|
+
By default, the video name from the NWB file is displayed under each video. Use the `video_labels` parameter to provide custom display names:
|
|
150
|
+
|
|
151
|
+
```python
|
|
152
|
+
widget = NWBLocalVideoPlayer(
|
|
153
|
+
nwbfile,
|
|
154
|
+
video_grid=[["VideoLeftCamera", "VideoRightCamera"]],
|
|
155
|
+
video_labels={
|
|
156
|
+
"VideoLeftCamera": "Left",
|
|
157
|
+
"VideoRightCamera": "Right",
|
|
158
|
+
}
|
|
159
|
+
)
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Videos not in the dictionary will display their original name.
|
|
163
|
+
|
|
103
164
|
---
|
|
104
165
|
|
|
105
166
|
## Pose Estimation Widgets
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
nwb_video_widgets/__init__.py,sha256=4m-AlratOMO31jFrnWQSRqU2duXHMs7ZI3Iogs-hbAs,616
|
|
2
2
|
nwb_video_widgets/_utils.py,sha256=kXcgjbq8mdgR0P4drPRy_Wrag3F5Od_7Ysikrr_VQMk,10566
|
|
3
3
|
nwb_video_widgets/dandi_pose_widget.py,sha256=Tk_ZnqZIRIJzIAghuc1OEh0tmP9tMDP8UVDzZ4CoySg,13511
|
|
4
|
-
nwb_video_widgets/dandi_video_widget.py,sha256=
|
|
4
|
+
nwb_video_widgets/dandi_video_widget.py,sha256=Jnn1-AXjZMNwVf9oL-0pZREjqdO6IS3YT5X_F2-4_Us,7342
|
|
5
5
|
nwb_video_widgets/local_pose_widget.py,sha256=6yrm3qoRf0C1s2CFQXTv9xCUG9NrDm4_mEv2Z8_QYww,12774
|
|
6
|
-
nwb_video_widgets/local_video_widget.py,sha256=
|
|
6
|
+
nwb_video_widgets/local_video_widget.py,sha256=V0JK9C04DLfa1fLFWxrikNML5Xs7vFNP1BC-VKqPeNs,6703
|
|
7
7
|
nwb_video_widgets/pose_widget.css,sha256=nTaPfxr-6TC2IlcjNf0jVHDEqG3dx0i5jF1mtf1tzPo,15172
|
|
8
8
|
nwb_video_widgets/pose_widget.js,sha256=zoXoLI1j63BOvngQ-Riufy7ae297VUidXW1KA7Z2TjI,26888
|
|
9
9
|
nwb_video_widgets/video_widget.css,sha256=h6G67yoRNaVR9obRZWJ8xgo6KBKbzuRfUgDPKCYlBFo,11893
|
|
10
|
-
nwb_video_widgets/video_widget.js,sha256=
|
|
10
|
+
nwb_video_widgets/video_widget.js,sha256=BV0lNXCvA_zIGtgWgL9rEbAJOfS7HCthJmjUl9cB6b0,21401
|
|
11
11
|
nwb_video_widgets/video_widget.py,sha256=glRQOBquOHDFeKC_aW_fMvJGqqh90AsMRWzMGSokonA,6252
|
|
12
|
-
nwb_video_widgets-0.1.
|
|
13
|
-
nwb_video_widgets-0.1.
|
|
14
|
-
nwb_video_widgets-0.1.
|
|
15
|
-
nwb_video_widgets-0.1.
|
|
12
|
+
nwb_video_widgets-0.1.2.dist-info/METADATA,sha256=gtwuUaCbKUTbmdbMCg2paqui5KnQseX480wgRXhFgKc,6751
|
|
13
|
+
nwb_video_widgets-0.1.2.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
14
|
+
nwb_video_widgets-0.1.2.dist-info/licenses/LICENSE,sha256=9Xuwwu2OWDAyD-b0_T2W-E13CysuHPPHYu7aNSOtIMI,1070
|
|
15
|
+
nwb_video_widgets-0.1.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|