canns 0.12.7__py3-none-any.whl → 0.13.1__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.
- canns/analyzer/data/__init__.py +3 -11
- canns/analyzer/data/asa/__init__.py +84 -0
- canns/analyzer/data/asa/cohospace.py +905 -0
- canns/analyzer/data/asa/config.py +246 -0
- canns/analyzer/data/asa/decode.py +445 -0
- canns/analyzer/data/asa/embedding.py +269 -0
- canns/analyzer/data/asa/filters.py +208 -0
- canns/analyzer/data/{cann1d.py → asa/fly_roi.py} +98 -45
- canns/analyzer/data/asa/fr.py +431 -0
- canns/analyzer/data/asa/path.py +389 -0
- canns/analyzer/data/asa/plotting.py +1287 -0
- canns/analyzer/data/asa/tda.py +901 -0
- canns/analyzer/visualization/core/backend.py +1 -1
- canns/analyzer/visualization/core/config.py +77 -0
- canns/analyzer/visualization/core/rendering.py +10 -6
- canns/analyzer/visualization/energy_plots.py +22 -8
- canns/analyzer/visualization/spatial_plots.py +31 -11
- canns/analyzer/visualization/theta_sweep_plots.py +15 -6
- canns/pipeline/__init__.py +4 -8
- canns/pipeline/asa/__init__.py +21 -0
- canns/pipeline/asa/__main__.py +11 -0
- canns/pipeline/asa/app.py +1000 -0
- canns/pipeline/asa/runner.py +1095 -0
- canns/pipeline/asa/screens.py +215 -0
- canns/pipeline/asa/state.py +248 -0
- canns/pipeline/asa/styles.tcss +221 -0
- canns/pipeline/asa/widgets.py +233 -0
- canns/pipeline/gallery/__init__.py +7 -0
- canns/task/open_loop_navigation.py +3 -1
- {canns-0.12.7.dist-info → canns-0.13.1.dist-info}/METADATA +6 -3
- {canns-0.12.7.dist-info → canns-0.13.1.dist-info}/RECORD +34 -17
- {canns-0.12.7.dist-info → canns-0.13.1.dist-info}/entry_points.txt +1 -0
- canns/analyzer/data/cann2d.py +0 -2565
- canns/pipeline/theta_sweep.py +0 -573
- {canns-0.12.7.dist-info → canns-0.13.1.dist-info}/WHEEL +0 -0
- {canns-0.12.7.dist-info → canns-0.13.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
"""Custom Textual widgets for ASA TUI.
|
|
2
|
+
|
|
3
|
+
This module provides reusable UI components for the ASA analysis interface.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import os
|
|
7
|
+
import subprocess
|
|
8
|
+
import sys
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
11
|
+
from rich.ansi import AnsiDecoder
|
|
12
|
+
from rich.text import Text
|
|
13
|
+
from textual.app import ComposeResult
|
|
14
|
+
from textual.containers import Horizontal, ScrollableContainer, Vertical
|
|
15
|
+
from textual.widgets import Button, Input, Label, Static
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class ImagePreview(Vertical):
|
|
19
|
+
"""Widget for previewing images in the terminal using climage."""
|
|
20
|
+
|
|
21
|
+
DEFAULT_CSS = """
|
|
22
|
+
ImagePreview {
|
|
23
|
+
height: auto;
|
|
24
|
+
min-height: 20;
|
|
25
|
+
border: solid $accent;
|
|
26
|
+
padding: 1;
|
|
27
|
+
}
|
|
28
|
+
#preview-content {
|
|
29
|
+
width: 100%;
|
|
30
|
+
height: auto;
|
|
31
|
+
}
|
|
32
|
+
#preview-scroll {
|
|
33
|
+
height: 1fr;
|
|
34
|
+
}
|
|
35
|
+
#preview-controls Button {
|
|
36
|
+
margin: 0 1 0 0;
|
|
37
|
+
}
|
|
38
|
+
#preview-arrows Button {
|
|
39
|
+
margin: 0 1 0 0;
|
|
40
|
+
}
|
|
41
|
+
#preview-controls, #preview-arrows {
|
|
42
|
+
height: auto;
|
|
43
|
+
}
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
def __init__(self, image_path: Path | None = None, **kwargs):
|
|
47
|
+
super().__init__(**kwargs)
|
|
48
|
+
self.image_path = image_path
|
|
49
|
+
self._zoom_step = 0
|
|
50
|
+
|
|
51
|
+
def compose(self) -> ComposeResult:
|
|
52
|
+
yield Label("Image Preview", id="preview-label")
|
|
53
|
+
yield Static("Path: (none)", id="preview-path")
|
|
54
|
+
yield Input(value="", id="preview-path-input")
|
|
55
|
+
with Horizontal(id="preview-controls"):
|
|
56
|
+
yield Button("Load", id="preview-load-btn")
|
|
57
|
+
yield Button("Open", id="preview-open-btn")
|
|
58
|
+
yield Button("Zoom +", id="preview-zoom-in-btn")
|
|
59
|
+
yield Button("Zoom -", id="preview-zoom-out-btn")
|
|
60
|
+
yield Button("Fit", id="preview-zoom-fit-btn")
|
|
61
|
+
with Horizontal(id="preview-arrows"):
|
|
62
|
+
yield Button("←", id="preview-pan-left-btn")
|
|
63
|
+
yield Button("→", id="preview-pan-right-btn")
|
|
64
|
+
yield Button("↑", id="preview-pan-up-btn")
|
|
65
|
+
yield Button("↓", id="preview-pan-down-btn")
|
|
66
|
+
with ScrollableContainer(id="preview-scroll"):
|
|
67
|
+
yield Static("No image loaded", id="preview-content")
|
|
68
|
+
|
|
69
|
+
def on_button_pressed(self, event: Button.Pressed) -> None:
|
|
70
|
+
if event.button.id == "preview-load-btn":
|
|
71
|
+
raw = self.query_one("#preview-path-input", Input).value.strip()
|
|
72
|
+
if not raw:
|
|
73
|
+
self.update_image(None)
|
|
74
|
+
return
|
|
75
|
+
path = self._resolve_path(raw)
|
|
76
|
+
self.update_image(path)
|
|
77
|
+
elif event.button.id == "preview-open-btn":
|
|
78
|
+
path = self.image_path
|
|
79
|
+
raw = self.query_one("#preview-path-input", Input).value.strip()
|
|
80
|
+
if raw:
|
|
81
|
+
path = self._resolve_path(raw)
|
|
82
|
+
if path is None or not path.exists():
|
|
83
|
+
content = self.query_one("#preview-content", Static)
|
|
84
|
+
content.update("No image to open")
|
|
85
|
+
return
|
|
86
|
+
try:
|
|
87
|
+
if sys.platform == "darwin":
|
|
88
|
+
subprocess.Popen(["open", str(path)])
|
|
89
|
+
elif sys.platform.startswith("win"):
|
|
90
|
+
os.startfile(str(path))
|
|
91
|
+
else:
|
|
92
|
+
subprocess.Popen(["xdg-open", str(path)])
|
|
93
|
+
except Exception as e:
|
|
94
|
+
content = self.query_one("#preview-content", Static)
|
|
95
|
+
content.update(f"Open failed: {e}")
|
|
96
|
+
elif event.button.id == "preview-zoom-in-btn":
|
|
97
|
+
self._zoom_step += 1
|
|
98
|
+
self.update_image(self.image_path)
|
|
99
|
+
elif event.button.id == "preview-zoom-out-btn":
|
|
100
|
+
self._zoom_step -= 1
|
|
101
|
+
self.update_image(self.image_path)
|
|
102
|
+
elif event.button.id == "preview-zoom-fit-btn":
|
|
103
|
+
self._zoom_step = 0
|
|
104
|
+
self.update_image(self.image_path)
|
|
105
|
+
elif event.button.id in {
|
|
106
|
+
"preview-pan-left-btn",
|
|
107
|
+
"preview-pan-right-btn",
|
|
108
|
+
"preview-pan-up-btn",
|
|
109
|
+
"preview-pan-down-btn",
|
|
110
|
+
}:
|
|
111
|
+
scroll = self.query_one("#preview-scroll", ScrollableContainer)
|
|
112
|
+
dx = 0
|
|
113
|
+
dy = 0
|
|
114
|
+
step = 5
|
|
115
|
+
if event.button.id == "preview-pan-left-btn":
|
|
116
|
+
dx = -step
|
|
117
|
+
elif event.button.id == "preview-pan-right-btn":
|
|
118
|
+
dx = step
|
|
119
|
+
elif event.button.id == "preview-pan-up-btn":
|
|
120
|
+
dy = -step
|
|
121
|
+
elif event.button.id == "preview-pan-down-btn":
|
|
122
|
+
dy = step
|
|
123
|
+
scroll.scroll_relative(x=dx, y=dy, animate=False)
|
|
124
|
+
|
|
125
|
+
def on_resize(self, event) -> None:
|
|
126
|
+
if self.image_path and self.image_path.exists():
|
|
127
|
+
self.update_image(self.image_path)
|
|
128
|
+
|
|
129
|
+
def update_image(self, path: Path | None):
|
|
130
|
+
"""Update the previewed image."""
|
|
131
|
+
self.image_path = path
|
|
132
|
+
content = self.query_one("#preview-content", Static)
|
|
133
|
+
path_label = self.query_one("#preview-path", Static)
|
|
134
|
+
path_input = self.query_one("#preview-path-input", Input)
|
|
135
|
+
|
|
136
|
+
if path is None or not path.exists():
|
|
137
|
+
content.update("No image loaded")
|
|
138
|
+
path_label.update("Path: (none)")
|
|
139
|
+
path_input.value = ""
|
|
140
|
+
return
|
|
141
|
+
path_label.update(f"Path: {path}")
|
|
142
|
+
path_input.value = str(path)
|
|
143
|
+
|
|
144
|
+
# Try to use climage for terminal preview
|
|
145
|
+
try:
|
|
146
|
+
import climage
|
|
147
|
+
|
|
148
|
+
scroll = self.query_one("#preview-scroll", ScrollableContainer)
|
|
149
|
+
base_width = max(20, scroll.size.width - 4)
|
|
150
|
+
base_height = max(8, scroll.size.height - 2)
|
|
151
|
+
scale = max(0.4, 1 + (self._zoom_step * 0.1))
|
|
152
|
+
width = max(20, int(base_width * scale))
|
|
153
|
+
height = max(8, int(base_height * scale))
|
|
154
|
+
try:
|
|
155
|
+
img_output = climage.convert(str(path), width=width, height=height, is_unicode=True)
|
|
156
|
+
except TypeError:
|
|
157
|
+
img_output = climage.convert(str(path), width=width, is_unicode=True)
|
|
158
|
+
decoder = AnsiDecoder()
|
|
159
|
+
chunks = list(decoder.decode(img_output))
|
|
160
|
+
content.update(Text("\n").join(chunks) if chunks else "")
|
|
161
|
+
except ImportError:
|
|
162
|
+
content.update(f"Image: {path.name}\n(Install climage for preview)")
|
|
163
|
+
except Exception as e:
|
|
164
|
+
content.update(f"Error loading image: {e}")
|
|
165
|
+
|
|
166
|
+
def _resolve_path(self, raw: str) -> Path:
|
|
167
|
+
path = Path(raw).expanduser()
|
|
168
|
+
if path.is_absolute():
|
|
169
|
+
return path
|
|
170
|
+
app = getattr(self, "app", None)
|
|
171
|
+
if app is not None:
|
|
172
|
+
state = getattr(app, "state", None)
|
|
173
|
+
if state is not None and hasattr(state, "workdir"):
|
|
174
|
+
return Path(state.workdir) / path
|
|
175
|
+
return Path.cwd() / path
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
class ParamGroup(Vertical):
|
|
179
|
+
"""Widget for grouping related parameters."""
|
|
180
|
+
|
|
181
|
+
DEFAULT_CSS = """
|
|
182
|
+
ParamGroup {
|
|
183
|
+
border: round $secondary;
|
|
184
|
+
padding: 1;
|
|
185
|
+
margin: 1 0;
|
|
186
|
+
height: auto;
|
|
187
|
+
width: 100%;
|
|
188
|
+
}
|
|
189
|
+
"""
|
|
190
|
+
|
|
191
|
+
def __init__(self, title: str, **kwargs):
|
|
192
|
+
super().__init__(**kwargs)
|
|
193
|
+
self.title = title
|
|
194
|
+
|
|
195
|
+
def compose(self) -> ComposeResult:
|
|
196
|
+
yield Label(self.title, classes="param-group-title")
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
class LogViewer(Vertical):
|
|
200
|
+
"""Widget for displaying log messages."""
|
|
201
|
+
|
|
202
|
+
DEFAULT_CSS = """
|
|
203
|
+
LogViewer {
|
|
204
|
+
height: 10;
|
|
205
|
+
border: solid $primary;
|
|
206
|
+
padding: 1;
|
|
207
|
+
overflow-y: scroll;
|
|
208
|
+
}
|
|
209
|
+
"""
|
|
210
|
+
|
|
211
|
+
def __init__(self, **kwargs):
|
|
212
|
+
super().__init__(**kwargs)
|
|
213
|
+
self.log_lines = []
|
|
214
|
+
|
|
215
|
+
def compose(self) -> ComposeResult:
|
|
216
|
+
yield Static("", id="log-content")
|
|
217
|
+
|
|
218
|
+
def add_log(self, message: str):
|
|
219
|
+
"""Add a log message."""
|
|
220
|
+
self.log_lines.append(message)
|
|
221
|
+
if len(self.log_lines) > 100:
|
|
222
|
+
self.log_lines = self.log_lines[-100:]
|
|
223
|
+
|
|
224
|
+
content = self.query_one("#log-content", Static)
|
|
225
|
+
content.update("\n".join(self.log_lines))
|
|
226
|
+
# Auto-scroll to latest entry
|
|
227
|
+
self.scroll_end(animate=False, immediate=True)
|
|
228
|
+
|
|
229
|
+
def clear(self):
|
|
230
|
+
"""Clear all log messages."""
|
|
231
|
+
self.log_lines = []
|
|
232
|
+
content = self.query_one("#log-content", Static)
|
|
233
|
+
content.update("")
|
|
@@ -692,7 +692,9 @@ class OpenLoopNavigationTask(BaseNavigationTask):
|
|
|
692
692
|
|
|
693
693
|
if not hasattr(self, "agent") or self.agent is None:
|
|
694
694
|
self.agent = Agent(
|
|
695
|
-
environment=self.env,
|
|
695
|
+
environment=self.env,
|
|
696
|
+
params=copy.deepcopy(self.agent_params),
|
|
697
|
+
rng_seed=self.rng_seed,
|
|
696
698
|
)
|
|
697
699
|
|
|
698
700
|
# Set initial position
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: canns
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.13.1
|
|
4
4
|
Summary: A Python Library for Continuous Attractor Neural Networks
|
|
5
5
|
Project-URL: Repository, https://github.com/routhleck/canns
|
|
6
6
|
Author-email: Sichao He <sichaohe@outlook.com>
|
|
@@ -18,6 +18,7 @@ Classifier: Typing :: Typed
|
|
|
18
18
|
Requires-Python: <4.0,>=3.11
|
|
19
19
|
Requires-Dist: brainpy[cpu]
|
|
20
20
|
Requires-Dist: canns-lib>=0.6.2
|
|
21
|
+
Requires-Dist: climage>=0.2.2
|
|
21
22
|
Requires-Dist: furo>=2025.7.19
|
|
22
23
|
Requires-Dist: imageio[ffmpeg]>=2.37.0
|
|
23
24
|
Requires-Dist: notebook>=7.4.4
|
|
@@ -25,6 +26,7 @@ Requires-Dist: numba>=0.56.0
|
|
|
25
26
|
Requires-Dist: numpy<2.3,>=1.24
|
|
26
27
|
Requires-Dist: scipy>=1.9.0
|
|
27
28
|
Requires-Dist: seaborn>=0.13.2
|
|
29
|
+
Requires-Dist: textual>=7.3.0
|
|
28
30
|
Requires-Dist: tqdm
|
|
29
31
|
Provides-Extra: cpu
|
|
30
32
|
Requires-Dist: brainpy[cpu]; extra == 'cpu'
|
|
@@ -65,7 +67,7 @@ CANNs is a Python library built on top of brainpy with performance‑critical mo
|
|
|
65
67
|
- **Task-first API** – `canns.task.tracking` and `canns.task.open_loop_navigation` generate smooth tracking inputs, population coding stimuli, or import experimental trajectories.
|
|
66
68
|
- **Rich analysis suite** – `canns.analyzer` covers energy landscapes, tuning curves, spike embeddings, UMAP/TDA helpers, and theta-sweep animations.
|
|
67
69
|
- **Unified training** – `canns.trainer.HebbianTrainer` implements generic Hebbian learning and prediction, layered on the abstract `Trainer` base.
|
|
68
|
-
- **
|
|
70
|
+
- **Pipeline workspace** – the ASA TUI (Attractor Structure Analyzer) provides an end-to-end analysis workflow (TDA → decode → CohoMap/CohoSpace/FR/FRM) for interactive runs.
|
|
69
71
|
- **Extensible foundations** – base classes (`BasicModel`, `Task`, `Trainer`, `Pipeline`) keep custom components consistent with the built-in ecosystem.
|
|
70
72
|
|
|
71
73
|
## Visual Gallery
|
|
@@ -115,6 +117,7 @@ pip install canns
|
|
|
115
117
|
# Optional accelerators (Linux only)
|
|
116
118
|
pip install canns[cuda12]
|
|
117
119
|
pip install canns[tpu]
|
|
120
|
+
|
|
118
121
|
```
|
|
119
122
|
|
|
120
123
|
## Quick Start
|
|
@@ -150,7 +153,7 @@ us, inputs = bm.for_loop(
|
|
|
150
153
|
)
|
|
151
154
|
```
|
|
152
155
|
|
|
153
|
-
For
|
|
156
|
+
For the ASA pipeline, run the TUI via `python -m canns.pipeline.asa` (or the `canns-tui` entrypoint) and point it at your ASA `.npz` inputs.
|
|
154
157
|
|
|
155
158
|
## Documentation & Notebooks
|
|
156
159
|
|
|
@@ -2,9 +2,18 @@ canns/__init__.py,sha256=ZK4buN-csoLKXaKtoDrOoZbNGCoLCNuF2XS96X8LbH8,1523
|
|
|
2
2
|
canns/_version.py,sha256=zIvJPOGBFvo4VV6f586rlO_bvhuFp1fsxjf6xhsqkJY,1547
|
|
3
3
|
canns/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
4
|
canns/analyzer/__init__.py,sha256=EQ02fYHkpMADp-ojpVCVtapuSPkl6j5WVfdPy0mOTs4,506
|
|
5
|
-
canns/analyzer/data/__init__.py,sha256=
|
|
6
|
-
canns/analyzer/data/
|
|
7
|
-
canns/analyzer/data/
|
|
5
|
+
canns/analyzer/data/__init__.py,sha256=5LJ8Q4SyDpi6CAzyW3lSpra3I0BgG20kmQMceONw7A4,158
|
|
6
|
+
canns/analyzer/data/asa/__init__.py,sha256=vfZCggZ_FvXwlYXLKErc_eltN6nOQiHWIivGYqpt8NM,1885
|
|
7
|
+
canns/analyzer/data/asa/cohospace.py,sha256=n6DfPWUH_k67KrPbNMt1EUdxMuRFFmXCaqh4gcuXngM,27847
|
|
8
|
+
canns/analyzer/data/asa/config.py,sha256=zVs-snLkD93hGc97GEX9CkcjTtUqORvMCs3khHhqd64,6288
|
|
9
|
+
canns/analyzer/data/asa/decode.py,sha256=NG8vVx2cPG7uSJDovnC2vzk0dsqU8oR4jaNPxxrvCc0,16501
|
|
10
|
+
canns/analyzer/data/asa/embedding.py,sha256=rT3hOHk6BzHF1X5YznIFxE_dDveklbT0fx9GtA2w3z0,9550
|
|
11
|
+
canns/analyzer/data/asa/filters.py,sha256=D-1mDVn4hBEAphKUgx1gQEUfgbghKcNQhZmr4xEExQA,7146
|
|
12
|
+
canns/analyzer/data/asa/fly_roi.py,sha256=_scBOd-4t9yv_1tHk7wbXJwPieU-L-QtFJY6fhHpxDI,38031
|
|
13
|
+
canns/analyzer/data/asa/fr.py,sha256=jt99H50e1RRAQgMIdkfK0rBbembZJEr9SMrxK-ZI_LA,13449
|
|
14
|
+
canns/analyzer/data/asa/path.py,sha256=p3r8EGcJi8NewNFutr3kdO-ekdU_5Icpy6nAoELzSq4,12233
|
|
15
|
+
canns/analyzer/data/asa/plotting.py,sha256=xuKRuq12pITK0BOC4Bj3ZfJs-07DA2OUHCpJmtJLOnw,40852
|
|
16
|
+
canns/analyzer/data/asa/tda.py,sha256=Hn110SBN4wKgHmcwPRkxHdbQ5DFW2xLdSv26J37_Zxc,30342
|
|
8
17
|
canns/analyzer/metrics/__init__.py,sha256=WaTCJE2WhqPtZXYTtMilF_f0LZUfz2h9a25HzwmCwP8,132
|
|
9
18
|
canns/analyzer/metrics/spatial_metrics.py,sha256=ZdS7tGH3lMgNlSYoHlH8IPsCw4XL0KtEnGALg_WHRX8,8965
|
|
10
19
|
canns/analyzer/metrics/systematic_ratemap.py,sha256=MzXfa6_fGgrxD5xEd4hfrZR_fyUmhXQCxnPE3hUonE8,14004
|
|
@@ -17,17 +26,17 @@ canns/analyzer/slow_points/finder.py,sha256=y-YKg-LI7lRM4JMghfcb5NGSYhIM2VPRA37Y
|
|
|
17
26
|
canns/analyzer/slow_points/fixed_points.py,sha256=Qp-iezwydWWUTchb2hGXJv0QKJqIm9gSG6hh0H9Eb6E,10099
|
|
18
27
|
canns/analyzer/slow_points/visualization.py,sha256=sRmmxs900OSB680MTp0PNIGLpS5i5AmJ58ek20vmrSE,10610
|
|
19
28
|
canns/analyzer/visualization/__init__.py,sha256=pNIokzS8y3ydzEMmVm1FNrOMRALDeuOHbcwZicPUm90,2131
|
|
20
|
-
canns/analyzer/visualization/energy_plots.py,sha256=
|
|
21
|
-
canns/analyzer/visualization/spatial_plots.py,sha256=
|
|
29
|
+
canns/analyzer/visualization/energy_plots.py,sha256=u0TOLzd7AWEfs-tRYZg1UBwsGYGPF_eWsMip1ZG9jPA,35671
|
|
30
|
+
canns/analyzer/visualization/spatial_plots.py,sha256=30m02xhYkZfEETCtvBSwLix9SEOPcLZTg0AGGFvPc2w,34605
|
|
22
31
|
canns/analyzer/visualization/spike_plots.py,sha256=wOm4gh_3obJy6gwo31maoaiZ7O8rsoYeFdhseoVmX78,12280
|
|
23
|
-
canns/analyzer/visualization/theta_sweep_plots.py,sha256=
|
|
32
|
+
canns/analyzer/visualization/theta_sweep_plots.py,sha256=2kiP7-IizqGm0q-ohQ4HhDZpm3sqs_lgn3GErHEZzbI,62262
|
|
24
33
|
canns/analyzer/visualization/tuning_plots.py,sha256=9JOeC4dlulVzpHQWDVy3dlJnxcBZiOPeapPdVFR-7Zk,5178
|
|
25
34
|
canns/analyzer/visualization/core/__init__.py,sha256=Vngm2A05cTu9ZVEYepTF7lVpuwQvMRjXs9XPLfZzedI,1928
|
|
26
35
|
canns/analyzer/visualization/core/animation.py,sha256=qfBYMd81_GwWEw4MHOu3GrVXJtHS9W1xxtmOx-J5ZyM,7664
|
|
27
|
-
canns/analyzer/visualization/core/backend.py,sha256=
|
|
28
|
-
canns/analyzer/visualization/core/config.py,sha256=
|
|
36
|
+
canns/analyzer/visualization/core/backend.py,sha256=Nbk-ARL_xeWlb3nl5SUPrFQNns2wq5BeHU3Q_tAbd_c,9539
|
|
37
|
+
canns/analyzer/visualization/core/config.py,sha256=9_n5hrvJXZgv32OlE_PuNh4JaPgw3dRAp_8LRzYnt_w,24131
|
|
29
38
|
canns/analyzer/visualization/core/jupyter_utils.py,sha256=JD56VeeWb7w9t5DJ8TpgnxRWkUK46ArbbPSTlFdIM10,6034
|
|
30
|
-
canns/analyzer/visualization/core/rendering.py,sha256=
|
|
39
|
+
canns/analyzer/visualization/core/rendering.py,sha256=YCbiXu8MOAqE9FVb_id5JKr5g9O64sCh-dOs0EK4gnU,18291
|
|
31
40
|
canns/analyzer/visualization/core/writers.py,sha256=HLsP953hgsv140ZX2XPzHfCUTqenjmjbLNrbknKam_s,15607
|
|
32
41
|
canns/data/__init__.py,sha256=BjQWgDYxh4jqtcKzcEZbdTech92AUzt_1KsDU1S88kM,864
|
|
33
42
|
canns/data/datasets.py,sha256=TRHxQGlMPoboiTPKhjTv1AMGbMnIt9T472Juyz4PYS0,13480
|
|
@@ -45,14 +54,22 @@ canns/models/brain_inspired/hopfield.py,sha256=KQmXWBvUTdQ17t9VG-8Sy_uJznEt4eunO
|
|
|
45
54
|
canns/models/brain_inspired/linear.py,sha256=oRjJnTqrheAADA5unYBu83RSm4UoUH-BK2Mt_liwDtw,6141
|
|
46
55
|
canns/models/brain_inspired/spiking.py,sha256=hr2w7c6Eobxwp2z6vkV9Yivpv1964-cno-XOfMSh3RU,5557
|
|
47
56
|
canns/models/hybrid/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
48
|
-
canns/pipeline/__init__.py,sha256=
|
|
57
|
+
canns/pipeline/__init__.py,sha256=OgFh5UXId99j_W4MkcpTaYD9qpQVXt-v9xN8cCY8sSc,371
|
|
49
58
|
canns/pipeline/_base.py,sha256=bYCmvXQ_0vGF-MEVpi0sUljrqmW6Ax8csQ5fcnX7nAE,1869
|
|
50
|
-
canns/pipeline/
|
|
59
|
+
canns/pipeline/asa/__init__.py,sha256=JR4T0onfmkKMOrUq-k0San1RTSb1om6cd27tWovBp0c,466
|
|
60
|
+
canns/pipeline/asa/__main__.py,sha256=_KgAeuGQ2-SXmuZhvZCkRx9luFf7VgKUCuszNlUswyA,197
|
|
61
|
+
canns/pipeline/asa/app.py,sha256=L5al6PrGoEzRNosZlHbn-VaTxXCoVyfKFn0f1e-0FUI,49906
|
|
62
|
+
canns/pipeline/asa/runner.py,sha256=PfHXlI-m3m-IYVFcFRhSODfPoRlCrloDOqEftvAfasg,42723
|
|
63
|
+
canns/pipeline/asa/screens.py,sha256=DbqidxmoKe4KzSLuxuriVv1PIVFn5Z-PfScVfjrIiEA,5954
|
|
64
|
+
canns/pipeline/asa/state.py,sha256=XukidfcFIOmm9ttT226FOTYR5hv2VAY8_DZt7V1Ml2g,6955
|
|
65
|
+
canns/pipeline/asa/styles.tcss,sha256=eaXI3rQeWdBYmWdLJMMiSO6acHtreLRVKKoIHb2-dBk,3349
|
|
66
|
+
canns/pipeline/asa/widgets.py,sha256=3vPGGQWP9V5FwuwqykCVp7dzAHdpcFkDqib0DtIw-lQ,8087
|
|
67
|
+
canns/pipeline/gallery/__init__.py,sha256=PPOvxmTRzEnj33jHlsFlaWuEfhrcNe39pMPQkTisjlo,187
|
|
51
68
|
canns/task/__init__.py,sha256=sfo8TBBVAqkx73Nu5lVv77UCwZjKqjt042ezW4Wv2Ec,350
|
|
52
69
|
canns/task/_base.py,sha256=rdRy4mr6x53z4aJv04UJcpqCyv78AxB1k1DhxnriLpg,4401
|
|
53
70
|
canns/task/closed_loop_navigation.py,sha256=QxxLdAg4Zd8763bS001jFqfts3A6_r6hpTTfrh1LdW8,10204
|
|
54
71
|
canns/task/navigation_base.py,sha256=s7mgXKhJyxIEUnSY8zXL3k9kH26MMQDv2xptzObu7Fc,40692
|
|
55
|
-
canns/task/open_loop_navigation.py,sha256=
|
|
72
|
+
canns/task/open_loop_navigation.py,sha256=jD77GVIGLaBVm0zKmOfghKk_Vj_9pjkjK8_a40907bU,45402
|
|
56
73
|
canns/task/tracking.py,sha256=KNJ7QkecRimxDa4lLC9JnzTvQGB-c0_lvU-InlmcLOY,31866
|
|
57
74
|
canns/trainer/__init__.py,sha256=ouHRuCuLuwFyrsOWbaotGxHIs5BdiYBtMhqE2k7HcKI,660
|
|
58
75
|
canns/trainer/_base.py,sha256=EQIXnvRvhCo0veTItGQumNeGuerHzsqipxyGZGIt2QI,1536
|
|
@@ -65,8 +82,8 @@ canns/trainer/utils.py,sha256=ZdoLiRqFLfKXsWi0KX3wGUp0OqFikwiou8dPf3xvFhE,2847
|
|
|
65
82
|
canns/typing/__init__.py,sha256=mXySdfmD8fA56WqZTb1Nj-ZovcejwLzNjuk6PRfTwmA,156
|
|
66
83
|
canns/utils/__init__.py,sha256=OMyZ5jqZAIUS2Jr0qcnvvrx6YM-BZ1EJy5uZYeA3HC0,366
|
|
67
84
|
canns/utils/benchmark.py,sha256=oJ7nvbvnQMh4_MZh7z160NPLp-197X0rEnmnLHYlev4,1361
|
|
68
|
-
canns-0.
|
|
69
|
-
canns-0.
|
|
70
|
-
canns-0.
|
|
71
|
-
canns-0.
|
|
72
|
-
canns-0.
|
|
85
|
+
canns-0.13.1.dist-info/METADATA,sha256=4HIOm94szk2GaS6A9Kbp9nZHXfoqVvNj_rOBdrExZWE,8827
|
|
86
|
+
canns-0.13.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
87
|
+
canns-0.13.1.dist-info/entry_points.txt,sha256=HDzYp0e9E1wfKYRkYtnUgVKK_u33_7eIn9exgm7t-wg,75
|
|
88
|
+
canns-0.13.1.dist-info/licenses/LICENSE,sha256=u6NJ1N-QSnf5yTwSk5UvFAdU2yKD0jxG0Xa91n1cPO4,11306
|
|
89
|
+
canns-0.13.1.dist-info/RECORD,,
|