Skip to content

Commit 64c47bd

Browse files
committed
feat(python): add edit_states tool as example
1 parent ef74412 commit 64c47bd

File tree

1 file changed

+139
-0
lines changed

1 file changed

+139
-0
lines changed
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
import argparse
2+
import json
3+
import pathlib
4+
import webbrowser
5+
6+
import neuroglancer
7+
import neuroglancer.cli
8+
9+
10+
class Tool:
11+
def __init__(
12+
self,
13+
viewer: neuroglancer.Viewer,
14+
paths: list[pathlib.Path],
15+
num_to_prefetch: int,
16+
) -> None:
17+
self.viewer = viewer
18+
self.paths = paths
19+
self.num_to_prefetch = num_to_prefetch
20+
21+
key_bindings = [
22+
["bracketleft", "prev-index"],
23+
["bracketright", "next-index"],
24+
["home", "first-index"],
25+
["end", "last-index"],
26+
["control+keys", "save"],
27+
]
28+
self.viewer.actions.add("prev-index", self._prev_index)
29+
self.viewer.actions.add("next-index", self._next_index)
30+
self.viewer.actions.add("first-index", self._first_index)
31+
self.viewer.actions.add("last-index", self._last_index)
32+
self.viewer.actions.add("save", self.save)
33+
34+
with self.viewer.config_state.txn() as s:
35+
for key, command in key_bindings:
36+
s.input_event_bindings.viewer[key] = command
37+
s.input_event_bindings.data_view[key] = command
38+
s.status_messages["help"] = "KEYS: " + " | ".join(
39+
f"{key}={command}" for key, command in key_bindings
40+
)
41+
42+
self.index = -1
43+
self.set_index(0)
44+
45+
def set_index(self, index: int) -> None:
46+
if index == self.index:
47+
return
48+
if index < 0:
49+
index += len(self.paths)
50+
elif index >= len(self.paths):
51+
index -= len(self.paths)
52+
if index < 0 or index >= len(self.paths):
53+
return
54+
self.save()
55+
self.index = index
56+
self.load()
57+
58+
def _get_state(self, index: int) -> neuroglancer.ViewerState:
59+
content = self.paths[index].read_text(encoding="utf-8")
60+
try:
61+
state = neuroglancer.ViewerState(json.loads(content))
62+
except json.JSONDecodeError:
63+
state = neuroglancer.parse_url(content.strip())
64+
return state
65+
66+
def save(self) -> None:
67+
if self.index == -1:
68+
return
69+
state = self.viewer.state
70+
path = self.paths[self.index]
71+
existing_content = path.read_text(encoding="utf-8")
72+
try:
73+
json.loads(existing_content)
74+
path.write_text(neuroglancer.to_json_dump(state))
75+
except json.JSONDecodeError:
76+
path.write_text(neuroglancer.to_url(state))
77+
78+
def load(self) -> None:
79+
self.viewer.set_state(self._get_state(self.index))
80+
81+
prefetch_states = []
82+
for i in range(self.num_to_prefetch):
83+
prefetch_index = self.index + i + 1
84+
if prefetch_index >= len(self.paths):
85+
break
86+
prefetch_states.append(self._get_state(prefetch_index))
87+
88+
with self.viewer.config_state.txn() as s:
89+
s.prefetch = [
90+
neuroglancer.PrefetchState(state=prefetch_state, priority=-i)
91+
for i, prefetch_state in enumerate(prefetch_states)
92+
]
93+
94+
with self.viewer.config_state.txn() as s:
95+
s.status_messages["status"] = "[State %d/%d] %s" % (
96+
self.index,
97+
len(self.paths),
98+
self.paths[self.index],
99+
)
100+
101+
def _first_index(self, s):
102+
self.set_index(0)
103+
104+
def _last_index(self, s):
105+
self.set_index(-1)
106+
107+
def _next_index(self, s):
108+
self.set_index(self.index + 1)
109+
110+
def _prev_index(self, s):
111+
self.set_index(self.index - 1)
112+
113+
114+
if __name__ == "__main__":
115+
ap = argparse.ArgumentParser()
116+
neuroglancer.cli.add_server_arguments(ap)
117+
ap.add_argument(
118+
"path",
119+
nargs="*",
120+
type=pathlib.Path,
121+
help="Path to file containing URL or JSON state.",
122+
)
123+
ap.add_argument(
124+
"--prefetch", type=int, default=10, help="Number of states to prefetch"
125+
)
126+
ap.add_argument("--browser", action="store_true", help="Open in browser.")
127+
128+
args = ap.parse_args()
129+
neuroglancer.cli.handle_server_arguments(args)
130+
viewer = neuroglancer.Viewer()
131+
132+
tool = Tool(
133+
viewer=viewer,
134+
paths=args.path,
135+
num_to_prefetch=args.prefetch,
136+
)
137+
print(tool.viewer)
138+
if args.browser:
139+
webbrowser.open(str(tool.viewer))

0 commit comments

Comments
 (0)