singlebehaviorlab 2.3.2__tar.gz → 2.3.3__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.
- {singlebehaviorlab-2.3.2/singlebehaviorlab.egg-info → singlebehaviorlab-2.3.3}/PKG-INFO +2 -3
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/pyproject.toml +2 -3
- singlebehaviorlab-2.3.3/singlebehaviorlab/backend/embedding_refine.py +158 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/gui/inference_widget.py +40 -2
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/gui/inference_worker.py +1 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/gui/registration_widget.py +1 -10
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3/singlebehaviorlab.egg-info}/PKG-INFO +2 -3
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab.egg-info/SOURCES.txt +1 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab.egg-info/requires.txt +0 -1
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/third_party/videoprism_backend/videoprism/tokenizers.py +4 -6
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/third_party/videoprism_backend/videoprism/utils.py +1 -10
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/LICENSE +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/README.md +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/setup.cfg +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/__init__.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/__main__.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/_paths.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/backend/__init__.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/backend/augmentations.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/backend/clustering.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/backend/contrastive.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/backend/data_store.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/backend/inference.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/backend/model.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/backend/registration.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/backend/segmentation.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/backend/segments.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/backend/train.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/backend/training_runner.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/backend/uncertainty.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/backend/video_processor.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/backend/video_utils.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/cli.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/config.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/data/config/config.yaml +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/data/training_profiles.json +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/demo.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/gui/__init__.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/gui/analysis_widget.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/gui/attention_export.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/gui/clip_extraction_widget.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/gui/clustering_widget.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/gui/inference_popups.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/gui/interactive_timeline.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/gui/labeling_widget.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/gui/main_window.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/gui/metadata_management_widget.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/gui/motion_tracking.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/gui/overlay_export.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/gui/plot_integration.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/gui/qt_helpers.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/gui/review_widget.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/gui/segmentation_tracking_widget.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/gui/tab_tutorial_dialog.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/gui/timeline_themes.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/gui/training_profiles.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/gui/training_widget.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/gui/video_utils.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/licenses/SAM2-LICENSE +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/licenses/VideoPrism-LICENSE +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab.egg-info/dependency_links.txt +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab.egg-info/entry_points.txt +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab.egg-info/top_level.txt +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/tests/test_clustering_smoke.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/tests/test_config.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/tests/test_motion_tracking.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/tests/test_paths.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/tests/test_sam2_smoke.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/tests/test_segments.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/third_party/sam2_backend/sam2/__init__.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/third_party/sam2_backend/sam2/automatic_mask_generator.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/third_party/sam2_backend/sam2/benchmark.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/third_party/sam2_backend/sam2/build_sam.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/third_party/sam2_backend/sam2/configs/sam2/sam2_hiera_b+.yaml +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/third_party/sam2_backend/sam2/configs/sam2/sam2_hiera_l.yaml +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/third_party/sam2_backend/sam2/configs/sam2/sam2_hiera_s.yaml +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/third_party/sam2_backend/sam2/configs/sam2/sam2_hiera_t.yaml +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/third_party/sam2_backend/sam2/configs/sam2.1/sam2.1_hiera_b+.yaml +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/third_party/sam2_backend/sam2/configs/sam2.1/sam2.1_hiera_l.yaml +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/third_party/sam2_backend/sam2/configs/sam2.1/sam2.1_hiera_s.yaml +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/third_party/sam2_backend/sam2/configs/sam2.1/sam2.1_hiera_t.yaml +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/third_party/sam2_backend/sam2/configs/sam2.1_training/sam2.1_hiera_b+_MOSE_finetune.yaml +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/third_party/sam2_backend/sam2/modeling/__init__.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/third_party/sam2_backend/sam2/modeling/backbones/__init__.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/third_party/sam2_backend/sam2/modeling/backbones/hieradet.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/third_party/sam2_backend/sam2/modeling/backbones/image_encoder.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/third_party/sam2_backend/sam2/modeling/backbones/utils.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/third_party/sam2_backend/sam2/modeling/memory_attention.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/third_party/sam2_backend/sam2/modeling/memory_encoder.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/third_party/sam2_backend/sam2/modeling/position_encoding.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/third_party/sam2_backend/sam2/modeling/sam/__init__.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/third_party/sam2_backend/sam2/modeling/sam/mask_decoder.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/third_party/sam2_backend/sam2/modeling/sam/prompt_encoder.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/third_party/sam2_backend/sam2/modeling/sam/transformer.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/third_party/sam2_backend/sam2/modeling/sam2_base.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/third_party/sam2_backend/sam2/modeling/sam2_utils.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/third_party/sam2_backend/sam2/sam2_hiera_b+.yaml +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/third_party/sam2_backend/sam2/sam2_hiera_l.yaml +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/third_party/sam2_backend/sam2/sam2_hiera_s.yaml +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/third_party/sam2_backend/sam2/sam2_hiera_t.yaml +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/third_party/sam2_backend/sam2/sam2_image_predictor.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/third_party/sam2_backend/sam2/sam2_video_predictor.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/third_party/sam2_backend/sam2/sam2_video_predictor_legacy.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/third_party/sam2_backend/sam2/utils/__init__.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/third_party/sam2_backend/sam2/utils/amg.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/third_party/sam2_backend/sam2/utils/misc.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/third_party/sam2_backend/sam2/utils/transforms.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/third_party/videoprism_backend/videoprism/__init__.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/third_party/videoprism_backend/videoprism/encoders.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/third_party/videoprism_backend/videoprism/layers.py +0 -0
- {singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/third_party/videoprism_backend/videoprism/models.py +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: singlebehaviorlab
|
|
3
|
-
Version: 2.3.
|
|
4
|
-
Summary:
|
|
3
|
+
Version: 2.3.3
|
|
4
|
+
Summary: Behavioral sequencing and phenotyping with lightweight task specific adaptation
|
|
5
5
|
Author: Almir Aljovic
|
|
6
6
|
Maintainer: Almir Aljovic
|
|
7
7
|
License: MIT License
|
|
@@ -59,7 +59,6 @@ Requires-Dist: einshape
|
|
|
59
59
|
Requires-Dist: huggingface-hub
|
|
60
60
|
Requires-Dist: sentencepiece
|
|
61
61
|
Requires-Dist: absl-py
|
|
62
|
-
Requires-Dist: tensorflow-cpu
|
|
63
62
|
Provides-Extra: test
|
|
64
63
|
Requires-Dist: pytest; extra == "test"
|
|
65
64
|
Requires-Dist: pytest-cov; extra == "test"
|
|
@@ -4,8 +4,8 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "singlebehaviorlab"
|
|
7
|
-
version = "2.3.
|
|
8
|
-
description = "
|
|
7
|
+
version = "2.3.3"
|
|
8
|
+
description = "Behavioral sequencing and phenotyping with lightweight task specific adaptation"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { file = "LICENSE" }
|
|
11
11
|
requires-python = ">=3.10"
|
|
@@ -43,7 +43,6 @@ dependencies = [
|
|
|
43
43
|
"huggingface-hub",
|
|
44
44
|
"sentencepiece",
|
|
45
45
|
"absl-py",
|
|
46
|
-
"tensorflow-cpu",
|
|
47
46
|
]
|
|
48
47
|
|
|
49
48
|
[project.urls]
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
"""Embedding-based timeline refinement.
|
|
2
|
+
|
|
3
|
+
Uses per-frame embeddings from the inference model to correct predictions
|
|
4
|
+
via semi-supervised label propagation on a nearest-neighbor graph, then
|
|
5
|
+
detects true behavior boundaries from embedding distance spikes.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import numpy as np
|
|
11
|
+
from typing import Optional
|
|
12
|
+
|
|
13
|
+
__all__ = ["refine_with_embeddings"]
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def _cosine_distance_adjacent(embeddings: np.ndarray) -> np.ndarray:
|
|
17
|
+
norms = np.maximum(np.linalg.norm(embeddings, axis=1, keepdims=True), 1e-8)
|
|
18
|
+
normed = embeddings / norms
|
|
19
|
+
return 1.0 - np.sum(normed[:-1] * normed[1:], axis=1)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _detect_boundaries(distances: np.ndarray, threshold_factor: float) -> list[int]:
|
|
23
|
+
if len(distances) == 0:
|
|
24
|
+
return []
|
|
25
|
+
median = float(np.median(distances))
|
|
26
|
+
mad = float(np.median(np.abs(distances - median)))
|
|
27
|
+
threshold = median + threshold_factor * max(mad, 1e-6)
|
|
28
|
+
boundaries = [0]
|
|
29
|
+
for i, d in enumerate(distances):
|
|
30
|
+
if d > threshold:
|
|
31
|
+
boundaries.append(i + 1)
|
|
32
|
+
return boundaries
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _majority_label(labels: np.ndarray, weights: Optional[np.ndarray] = None) -> int:
|
|
36
|
+
valid_mask = labels >= 0
|
|
37
|
+
valid = labels[valid_mask]
|
|
38
|
+
if len(valid) == 0:
|
|
39
|
+
return -1
|
|
40
|
+
if weights is not None:
|
|
41
|
+
w = weights[valid_mask]
|
|
42
|
+
counts: dict[int, float] = {}
|
|
43
|
+
for lbl, wt in zip(valid, w):
|
|
44
|
+
counts[int(lbl)] = counts.get(int(lbl), 0.0) + float(wt)
|
|
45
|
+
return max(counts, key=counts.get)
|
|
46
|
+
vals, cnts = np.unique(valid, return_counts=True)
|
|
47
|
+
return int(vals[np.argmax(cnts)])
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def _label_propagation_correction(
|
|
51
|
+
frame_labels: np.ndarray,
|
|
52
|
+
frame_embeddings: np.ndarray,
|
|
53
|
+
frame_confidences: np.ndarray,
|
|
54
|
+
confidence_threshold: float,
|
|
55
|
+
) -> np.ndarray:
|
|
56
|
+
from sklearn.semi_supervised import LabelSpreading
|
|
57
|
+
|
|
58
|
+
n_frames = len(frame_labels)
|
|
59
|
+
labels_for_propagation = frame_labels.copy()
|
|
60
|
+
|
|
61
|
+
for i in range(n_frames):
|
|
62
|
+
if frame_confidences[i] < confidence_threshold:
|
|
63
|
+
labels_for_propagation[i] = -1
|
|
64
|
+
|
|
65
|
+
n_labeled = np.sum(labels_for_propagation >= 0)
|
|
66
|
+
if n_labeled < 2 or n_labeled == n_frames:
|
|
67
|
+
return frame_labels.copy()
|
|
68
|
+
|
|
69
|
+
n_neighbors = min(7, n_frames - 1)
|
|
70
|
+
lp = LabelSpreading(kernel="knn", n_neighbors=n_neighbors, max_iter=30, alpha=0.2)
|
|
71
|
+
lp.fit(frame_embeddings, labels_for_propagation)
|
|
72
|
+
propagated = lp.transduction_
|
|
73
|
+
|
|
74
|
+
result = frame_labels.copy()
|
|
75
|
+
for i in range(n_frames):
|
|
76
|
+
if frame_confidences[i] < confidence_threshold and propagated[i] >= 0:
|
|
77
|
+
result[i] = int(propagated[i])
|
|
78
|
+
|
|
79
|
+
return result
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def refine_with_embeddings(
|
|
83
|
+
frame_labels: np.ndarray,
|
|
84
|
+
frame_embeddings: np.ndarray,
|
|
85
|
+
frame_confidences: Optional[np.ndarray] = None,
|
|
86
|
+
n_classes: int = 0,
|
|
87
|
+
boundary_sensitivity: float = 1.5,
|
|
88
|
+
min_segment_frames: int = 3,
|
|
89
|
+
confidence_threshold: float = 0.7,
|
|
90
|
+
) -> np.ndarray:
|
|
91
|
+
"""Refine per-frame predictions using label propagation and boundary detection.
|
|
92
|
+
|
|
93
|
+
High-confidence predictions seed a nearest-neighbor graph. Labels
|
|
94
|
+
propagate to uncertain frames through embedding similarity. Boundary
|
|
95
|
+
detection then snaps segment edges to real embedding transitions.
|
|
96
|
+
"""
|
|
97
|
+
n_frames = len(frame_labels)
|
|
98
|
+
if n_frames < 4 or frame_embeddings.shape[0] != n_frames:
|
|
99
|
+
return frame_labels.copy()
|
|
100
|
+
|
|
101
|
+
if frame_confidences is None:
|
|
102
|
+
frame_confidences = np.ones(n_frames, dtype=np.float32)
|
|
103
|
+
|
|
104
|
+
corrected = _label_propagation_correction(
|
|
105
|
+
frame_labels, frame_embeddings, frame_confidences, confidence_threshold,
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
distances = _cosine_distance_adjacent(frame_embeddings)
|
|
109
|
+
boundaries = _detect_boundaries(distances, boundary_sensitivity)
|
|
110
|
+
boundaries.append(n_frames)
|
|
111
|
+
|
|
112
|
+
refined = corrected.copy()
|
|
113
|
+
segments: list[tuple[int, int]] = []
|
|
114
|
+
for i in range(len(boundaries) - 1):
|
|
115
|
+
start, end = boundaries[i], boundaries[i + 1]
|
|
116
|
+
if end <= start:
|
|
117
|
+
continue
|
|
118
|
+
majority = _majority_label(corrected[start:end], frame_confidences[start:end])
|
|
119
|
+
refined[start:end] = majority
|
|
120
|
+
segments.append((start, end))
|
|
121
|
+
|
|
122
|
+
changed = True
|
|
123
|
+
while changed:
|
|
124
|
+
changed = False
|
|
125
|
+
new_segments = []
|
|
126
|
+
i = 0
|
|
127
|
+
while i < len(segments):
|
|
128
|
+
start, end = segments[i]
|
|
129
|
+
if (end - start) < min_segment_frames and len(segments) > 1:
|
|
130
|
+
mean_emb = frame_embeddings[start:end].mean(axis=0)
|
|
131
|
+
mean_emb /= max(np.linalg.norm(mean_emb), 1e-8)
|
|
132
|
+
best_sim, merge_with = -1.0, -1
|
|
133
|
+
for j in [i - 1, i + 1]:
|
|
134
|
+
if 0 <= j < len(segments):
|
|
135
|
+
ns, ne = segments[j]
|
|
136
|
+
ne_emb = frame_embeddings[ns:ne].mean(axis=0)
|
|
137
|
+
ne_emb /= max(np.linalg.norm(ne_emb), 1e-8)
|
|
138
|
+
sim = float(np.dot(mean_emb, ne_emb))
|
|
139
|
+
if sim > best_sim:
|
|
140
|
+
best_sim, merge_with = sim, j
|
|
141
|
+
if merge_with >= 0:
|
|
142
|
+
ms, me = segments[merge_with]
|
|
143
|
+
ms2, me2 = min(start, ms), max(end, me)
|
|
144
|
+
majority = _majority_label(corrected[ms2:me2], frame_confidences[ms2:me2])
|
|
145
|
+
refined[ms2:me2] = majority
|
|
146
|
+
if merge_with < i:
|
|
147
|
+
new_segments[-1] = (ms2, me2)
|
|
148
|
+
else:
|
|
149
|
+
new_segments.append((ms2, me2))
|
|
150
|
+
i += 1
|
|
151
|
+
changed = True
|
|
152
|
+
i += 1
|
|
153
|
+
continue
|
|
154
|
+
new_segments.append((start, end))
|
|
155
|
+
i += 1
|
|
156
|
+
segments = new_segments
|
|
157
|
+
|
|
158
|
+
return refined
|
{singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/gui/inference_widget.py
RENAMED
|
@@ -320,6 +320,27 @@ class InferenceWidget(QWidget):
|
|
|
320
320
|
self.timeline_theme_combo.currentIndexChanged.connect(self._on_theme_changed)
|
|
321
321
|
timeline_controls_layout.addWidget(self.timeline_theme_combo)
|
|
322
322
|
|
|
323
|
+
self.embedding_refine_check = QCheckBox("Embedding refinement")
|
|
324
|
+
self.embedding_refine_check.setToolTip(
|
|
325
|
+
"Use the model's internal frame embeddings to detect true behavior\n"
|
|
326
|
+
"boundaries and correct predictions via label propagation."
|
|
327
|
+
)
|
|
328
|
+
self.embedding_refine_check.stateChanged.connect(self._on_embedding_refine_changed)
|
|
329
|
+
timeline_controls_layout.addWidget(self.embedding_refine_check)
|
|
330
|
+
|
|
331
|
+
self.embedding_refine_threshold = QDoubleSpinBox()
|
|
332
|
+
self.embedding_refine_threshold.setRange(0.1, 0.99)
|
|
333
|
+
self.embedding_refine_threshold.setSingleStep(0.05)
|
|
334
|
+
self.embedding_refine_threshold.setValue(0.70)
|
|
335
|
+
self.embedding_refine_threshold.setToolTip(
|
|
336
|
+
"Confidence threshold for embedding refinement.\n"
|
|
337
|
+
"Frames above this are trusted as seed labels.\n"
|
|
338
|
+
"Frames below defer to their embedding neighbors.\n"
|
|
339
|
+
"Lower = more aggressive correction."
|
|
340
|
+
)
|
|
341
|
+
self.embedding_refine_threshold.valueChanged.connect(self._on_embedding_refine_changed)
|
|
342
|
+
timeline_controls_layout.addWidget(self.embedding_refine_threshold)
|
|
343
|
+
|
|
323
344
|
self._advanced_toggle = QPushButton("Advanced")
|
|
324
345
|
self._advanced_toggle.setCheckable(True)
|
|
325
346
|
self._advanced_toggle.setChecked(False)
|
|
@@ -2910,6 +2931,11 @@ class InferenceWidget(QWidget):
|
|
|
2910
2931
|
self._interactive_timeline.set_model(model, colors)
|
|
2911
2932
|
self._minimap.set_model(model, colors)
|
|
2912
2933
|
|
|
2934
|
+
def _on_embedding_refine_changed(self, *_args):
|
|
2935
|
+
if self.predictions and self.frame_aggregation_check.isChecked():
|
|
2936
|
+
self._build_timeline_segments()
|
|
2937
|
+
self._display_results()
|
|
2938
|
+
|
|
2913
2939
|
def _toggle_advanced_controls(self, show: bool):
|
|
2914
2940
|
for w in self._advanced_widgets:
|
|
2915
2941
|
w.setVisible(show)
|
|
@@ -3247,10 +3273,22 @@ class InferenceWidget(QWidget):
|
|
|
3247
3273
|
if float(fs[fi, ci]) < thr:
|
|
3248
3274
|
frame_labels[fi] = -1
|
|
3249
3275
|
|
|
3250
|
-
# Merge-gap and min-segment run ONCE as the final cleanup, after all
|
|
3251
|
-
# other preprocessing (smoothing + threshold) is done.
|
|
3252
3276
|
frame_labels = self._apply_gap_merge_and_min_seg(frame_labels, T)
|
|
3253
3277
|
|
|
3278
|
+
if self.embedding_refine_check.isChecked():
|
|
3279
|
+
frame_embs = None
|
|
3280
|
+
if hasattr(self, 'video_path') and self.video_path and self.video_path in self.results_cache:
|
|
3281
|
+
frame_embs = self.results_cache[self.video_path].get("aggregated_frame_embs")
|
|
3282
|
+
if isinstance(frame_embs, np.ndarray) and frame_embs.shape[0] >= T:
|
|
3283
|
+
from singlebehaviorlab.backend.embedding_refine import refine_with_embeddings
|
|
3284
|
+
frame_conf = np.max(fs, axis=1)
|
|
3285
|
+
frame_labels = refine_with_embeddings(
|
|
3286
|
+
frame_labels[:T], frame_embs[:T], frame_conf,
|
|
3287
|
+
n_classes=C,
|
|
3288
|
+
min_segment_frames=max(3, self._min_segment_frames),
|
|
3289
|
+
confidence_threshold=float(self.embedding_refine_threshold.value()),
|
|
3290
|
+
)
|
|
3291
|
+
|
|
3254
3292
|
segments = []
|
|
3255
3293
|
cur_cls = int(frame_labels[0])
|
|
3256
3294
|
cur_start = 0
|
{singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/gui/inference_worker.py
RENAMED
|
@@ -598,6 +598,7 @@ class InferenceWorker(QThread):
|
|
|
598
598
|
"orig_fps": video_orig_fps,
|
|
599
599
|
"frame_interval": video_frame_interval,
|
|
600
600
|
"aggregated_frame_probs": aggregated_frame_probs,
|
|
601
|
+
"aggregated_frame_embs": aggregated_frame_embs,
|
|
601
602
|
}
|
|
602
603
|
if sample_ranges:
|
|
603
604
|
res_entry["sample_ranges"] = sample_ranges
|
{singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/gui/registration_widget.py
RENAMED
|
@@ -326,7 +326,7 @@ class EmbeddingExtractionWorker(QThread):
|
|
|
326
326
|
error = pyqtSignal(str)
|
|
327
327
|
log_message = pyqtSignal(str)
|
|
328
328
|
|
|
329
|
-
def __init__(self, clip_paths: list, output_dir: str, experiment_name: str = None, model_name: str = 'videoprism_public_v1_base', clip_frame_ranges: dict = None, append_to_existing: bool = False, flip_invariant: bool = False
|
|
329
|
+
def __init__(self, clip_paths: list, output_dir: str, experiment_name: str = None, model_name: str = 'videoprism_public_v1_base', clip_frame_ranges: dict = None, append_to_existing: bool = False, flip_invariant: bool = False):
|
|
330
330
|
super().__init__()
|
|
331
331
|
self.clip_paths = clip_paths
|
|
332
332
|
self.clip_frame_ranges = clip_frame_ranges or {}
|
|
@@ -336,8 +336,6 @@ class EmbeddingExtractionWorker(QThread):
|
|
|
336
336
|
self.should_stop = False
|
|
337
337
|
self.append_to_existing = append_to_existing
|
|
338
338
|
self.flip_invariant = flip_invariant
|
|
339
|
-
self.align_orientation = align_orientation
|
|
340
|
-
self.mask_path = mask_path
|
|
341
339
|
|
|
342
340
|
def stop(self):
|
|
343
341
|
self.should_stop = True
|
|
@@ -1256,11 +1254,6 @@ class RegistrationWidget(QWidget):
|
|
|
1256
1254
|
experiment_name = self.config.get("experiment_name", None)
|
|
1257
1255
|
|
|
1258
1256
|
# Start extraction worker with frame ranges if available
|
|
1259
|
-
mask_path = None
|
|
1260
|
-
if self.align_orientation_check.isChecked() and self.video_mask_pairs:
|
|
1261
|
-
mask_path = self.video_mask_pairs[0][1] if len(self.video_mask_pairs) > 0 else None
|
|
1262
|
-
self.log_text.append(f"Align orientation: mask_path={mask_path}, pairs={len(self.video_mask_pairs)}, frame_ranges={len(self.clip_frame_ranges)}")
|
|
1263
|
-
|
|
1264
1257
|
self.embedding_worker = EmbeddingExtractionWorker(
|
|
1265
1258
|
clip_paths,
|
|
1266
1259
|
self.output_dir,
|
|
@@ -1269,8 +1262,6 @@ class RegistrationWidget(QWidget):
|
|
|
1269
1262
|
clip_frame_ranges=self.clip_frame_ranges if hasattr(self, 'clip_frame_ranges') else None,
|
|
1270
1263
|
append_to_existing=self.append_embeddings_check.isChecked(),
|
|
1271
1264
|
flip_invariant=self.flip_invariant_check.isChecked(),
|
|
1272
|
-
align_orientation=self.align_orientation_check.isChecked(),
|
|
1273
|
-
mask_path=mask_path,
|
|
1274
1265
|
)
|
|
1275
1266
|
self.embedding_worker.progress.connect(self._on_embedding_progress)
|
|
1276
1267
|
self.embedding_worker.finished.connect(self._on_embedding_finished)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: singlebehaviorlab
|
|
3
|
-
Version: 2.3.
|
|
4
|
-
Summary:
|
|
3
|
+
Version: 2.3.3
|
|
4
|
+
Summary: Behavioral sequencing and phenotyping with lightweight task specific adaptation
|
|
5
5
|
Author: Almir Aljovic
|
|
6
6
|
Maintainer: Almir Aljovic
|
|
7
7
|
License: MIT License
|
|
@@ -59,7 +59,6 @@ Requires-Dist: einshape
|
|
|
59
59
|
Requires-Dist: huggingface-hub
|
|
60
60
|
Requires-Dist: sentencepiece
|
|
61
61
|
Requires-Dist: absl-py
|
|
62
|
-
Requires-Dist: tensorflow-cpu
|
|
63
62
|
Provides-Extra: test
|
|
64
63
|
Requires-Dist: pytest; extra == "test"
|
|
65
64
|
Requires-Dist: pytest-cov; extra == "test"
|
|
@@ -18,6 +18,7 @@ singlebehaviorlab/backend/augmentations.py
|
|
|
18
18
|
singlebehaviorlab/backend/clustering.py
|
|
19
19
|
singlebehaviorlab/backend/contrastive.py
|
|
20
20
|
singlebehaviorlab/backend/data_store.py
|
|
21
|
+
singlebehaviorlab/backend/embedding_refine.py
|
|
21
22
|
singlebehaviorlab/backend/inference.py
|
|
22
23
|
singlebehaviorlab/backend/model.py
|
|
23
24
|
singlebehaviorlab/backend/registration.py
|
|
@@ -17,9 +17,6 @@
|
|
|
17
17
|
from collections.abc import Sequence
|
|
18
18
|
from typing import Protocol
|
|
19
19
|
|
|
20
|
-
import tensorflow as tf
|
|
21
|
-
from tensorflow.io import gfile
|
|
22
|
-
|
|
23
20
|
import sentencepiece
|
|
24
21
|
|
|
25
22
|
SentencePieceProcessor = sentencepiece.SentencePieceProcessor
|
|
@@ -44,7 +41,7 @@ class Tokenizer(Protocol):
|
|
|
44
41
|
|
|
45
42
|
def to_int_tf_op(
|
|
46
43
|
self, text: str | Sequence[str], *, bos: bool = False, eos: bool = False
|
|
47
|
-
)
|
|
44
|
+
):
|
|
48
45
|
"""Same as `to_int()`, but as TF ops to be used in data pipelines.
|
|
49
46
|
|
|
50
47
|
Args:
|
|
@@ -55,6 +52,7 @@ class Tokenizer(Protocol):
|
|
|
55
52
|
Returns:
|
|
56
53
|
A tf.Tensor of tokens.
|
|
57
54
|
"""
|
|
55
|
+
import tensorflow as tf
|
|
58
56
|
|
|
59
57
|
@property
|
|
60
58
|
def pad_token(self) -> int:
|
|
@@ -82,7 +80,7 @@ class SentencePieceTokenizer(Tokenizer):
|
|
|
82
80
|
Args:
|
|
83
81
|
model_path: A path to load the SentencePiece model.
|
|
84
82
|
"""
|
|
85
|
-
with
|
|
83
|
+
with open(model_path, "rb") as f:
|
|
86
84
|
model_bytes = f.read()
|
|
87
85
|
|
|
88
86
|
self._model = SentencePieceProcessor()
|
|
@@ -115,7 +113,7 @@ class SentencePieceTokenizer(Tokenizer):
|
|
|
115
113
|
|
|
116
114
|
def to_int_tf_op(
|
|
117
115
|
self, text: str | Sequence[str], *, bos: bool = False, eos: bool = False
|
|
118
|
-
)
|
|
116
|
+
):
|
|
119
117
|
"""Same as `to_int()`, but as TF ops to be used in data pipelines.
|
|
120
118
|
|
|
121
119
|
Args:
|
|
@@ -16,13 +16,10 @@
|
|
|
16
16
|
|
|
17
17
|
import collections
|
|
18
18
|
from collections.abc import Mapping, Sequence
|
|
19
|
-
import io
|
|
20
|
-
import os
|
|
21
19
|
import string
|
|
22
20
|
|
|
23
21
|
import jax
|
|
24
22
|
import numpy as np
|
|
25
|
-
from tensorflow.io import gfile
|
|
26
23
|
|
|
27
24
|
|
|
28
25
|
def traverse_with_names(tree, with_inner_nodes=False):
|
|
@@ -106,13 +103,7 @@ def recover_tree(keys, values):
|
|
|
106
103
|
def npload(fname):
|
|
107
104
|
"""Loads `fname` and returns an np.ndarray or dict thereof."""
|
|
108
105
|
# Load the data; use local paths directly if possible:
|
|
109
|
-
|
|
110
|
-
loaded = np.load(fname, allow_pickle=False)
|
|
111
|
-
else:
|
|
112
|
-
# For other (remote) paths go via gfile+BytesIO as np.load requires seeks.
|
|
113
|
-
with gfile.GFile(fname, "rb") as f:
|
|
114
|
-
data = f.read()
|
|
115
|
-
loaded = np.load(io.BytesIO(data), allow_pickle=False)
|
|
106
|
+
loaded = np.load(fname, allow_pickle=False)
|
|
116
107
|
|
|
117
108
|
# Support loading both single-array files (np.save) and zips (np.savez).
|
|
118
109
|
if isinstance(loaded, np.ndarray):
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/backend/augmentations.py
RENAMED
|
File without changes
|
|
File without changes
|
{singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/backend/contrastive.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/backend/registration.py
RENAMED
|
File without changes
|
{singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/backend/segmentation.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/backend/training_runner.py
RENAMED
|
File without changes
|
{singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/backend/uncertainty.py
RENAMED
|
File without changes
|
{singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/backend/video_processor.py
RENAMED
|
File without changes
|
{singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/backend/video_utils.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/data/config/config.yaml
RENAMED
|
File without changes
|
{singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/data/training_profiles.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/gui/analysis_widget.py
RENAMED
|
File without changes
|
{singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/gui/attention_export.py
RENAMED
|
File without changes
|
{singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/gui/clip_extraction_widget.py
RENAMED
|
File without changes
|
{singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/gui/clustering_widget.py
RENAMED
|
File without changes
|
{singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/gui/inference_popups.py
RENAMED
|
File without changes
|
{singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/gui/interactive_timeline.py
RENAMED
|
File without changes
|
{singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/gui/labeling_widget.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/gui/motion_tracking.py
RENAMED
|
File without changes
|
|
File without changes
|
{singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/gui/plot_integration.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/gui/tab_tutorial_dialog.py
RENAMED
|
File without changes
|
{singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/gui/timeline_themes.py
RENAMED
|
File without changes
|
{singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/gui/training_profiles.py
RENAMED
|
File without changes
|
{singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/gui/training_widget.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab/licenses/VideoPrism-LICENSE
RENAMED
|
File without changes
|
{singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab.egg-info/entry_points.txt
RENAMED
|
File without changes
|
{singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/singlebehaviorlab.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/third_party/sam2_backend/sam2/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/third_party/sam2_backend/sam2/benchmark.py
RENAMED
|
File without changes
|
{singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/third_party/sam2_backend/sam2/build_sam.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/third_party/sam2_backend/sam2/sam2_hiera_b+.yaml
RENAMED
|
File without changes
|
{singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/third_party/sam2_backend/sam2/sam2_hiera_l.yaml
RENAMED
|
File without changes
|
{singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/third_party/sam2_backend/sam2/sam2_hiera_s.yaml
RENAMED
|
File without changes
|
{singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/third_party/sam2_backend/sam2/sam2_hiera_t.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/third_party/sam2_backend/sam2/utils/__init__.py
RENAMED
|
File without changes
|
{singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/third_party/sam2_backend/sam2/utils/amg.py
RENAMED
|
File without changes
|
{singlebehaviorlab-2.3.2 → singlebehaviorlab-2.3.3}/third_party/sam2_backend/sam2/utils/misc.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|