concept-collection / dandiset_000986
initial
Jeremy Magland <jmagland@flatironinstitute.org> committed commit b5658769192d Browse files
6 changed files+226−0
.gitignoreadded+3−0View file
@@ -0,0 +1,3 @@
1+cache/
2+.snakemake/
3+.vscode/
\ No newline at end of file
README.mdadded+7−0View file
@@ -0,0 +1,7 @@
1+# [Dandiset 000986](https://dandiarchive.org/dandiset/000986)
2+
3+This is a test
4+
5+<iframe src="https://figures.figpack.org/figures/default/d0be3702700b8893f0432754/index.html" width="100%" height="800px"></iframe>
6+
7+Will that iframe get rendered on github pages?
\ No newline at end of file
Snakefileadded+16−0View file
@@ -0,0 +1,16 @@
1+rule all:
2+ input:
3+ "figures/ses-1.url",
4+ "figures/ses-2.url",
5+
6+rule create_figure1:
7+ output:
8+ "figures/ses-1.url"
9+ shell:
10+ "python scripts/create_figure.py sub-LA11/sub-LA11_ses-1_behavior.nwb {output}"
11+
12+rule create_figure2:
13+ output:
14+ "figures/ses-2.url"
15+ shell:
16+ "python scripts/create_figure.py sub-LA11/sub-LA11_ses-2_behavior.nwb {output}"
figures/ses-1.urladded+1−0View file
@@ -0,0 +1 @@
1+https://figures.figpack.org/figures/default/d0be3702700b8893f0432754/index.html
\ No newline at end of file
figures/ses-2.urladded+1−0View file
@@ -0,0 +1 @@
1+https://figures.figpack.org/figures/default/bc864e107350c71743dd4eaf/index.html
\ No newline at end of file
scripts/create_figure.pyadded+198−0View file
@@ -0,0 +1,198 @@
1+import sys
2+import pynwb
3+import h5py
4+import remfile
5+import numpy as np
6+import figpack.views as fp
7+import figpack_spike_sorting.views as fpss
8+from figpack.utils import read_script
9+from dandi.dandiapi import DandiAPIClient
10+
11+asset_path = None
12+if len(sys.argv) > 1:
13+ asset_path = sys.argv[1]
14+
15+output_file = None
16+if len(sys.argv) > 2:
17+ output_file = sys.argv[2]
18+
19+if asset_path is None:
20+ raise ValueError(
21+ "Please provide the asset path as the first argument. For example: sub-LA11/sub-LA11_ses-2_behavior.nwb"
22+ )
23+
24+if output_file is not None:
25+ print(f"Output file specified: {output_file}")
26+
27+# Initialize Dandi client and load NWB file
28+print("Connecting to DANDI API...")
29+client = DandiAPIClient()
30+dandiset = client.get_dandiset("000986", "draft")
31+nwb_file_url = dandiset.get_asset_by_path(asset_path).download_url
32+
33+print("Loading NWB file...")
34+# Open the remote file with disk cache
35+disk_cache = remfile.DiskCache("./cache")
36+remote_file = remfile.File(nwb_file_url, disk_cache=disk_cache)
37+h5_file = h5py.File(remote_file)
38+nwb_io = pynwb.NWBHDF5IO(file=h5_file)
39+nwb = nwb_io.read()
40+print("NWB file loaded successfully")
41+
42+# Extract pupil diameter data
43+print("\nExtracting pupil diameter data...")
44+pupil = (
45+ nwb.processing["behavior"]
46+ .data_interfaces["PupilTracking"]
47+ .time_series["pupil_diameter"]
48+)
49+pupil_data = pupil.data[:]
50+pupil_timestamps = pupil.timestamps[:]
51+print(f"Pupil data: {len(pupil_data)} samples")
52+
53+# Create pupil diameter time series graph
54+print("Creating pupil diameter graph...")
55+pupil_graph = fp.TimeseriesGraph(hide_nav_toolbar=True)
56+pupil_graph.add_uniform_series(
57+ name="pupil",
58+ start_time_sec=pupil_timestamps[0],
59+ sampling_frequency_hz=1 / (pupil_timestamps[1] - pupil_timestamps[0]),
60+ data=pupil_data,
61+ timestamps_for_inserting_nans=pupil_timestamps,
62+)
63+
64+
65+# Extract running speed data
66+print("\nExtracting running speed data...")
67+running_speed = nwb.processing["behavior"].data_interfaces["running_speed"]
68+running_speed_data = running_speed.data[:]
69+running_speed_timestamps = running_speed.timestamps[:]
70+print(f"Running speed data: {len(running_speed_data)} samples")
71+
72+# Create running speed time series graph
73+print("Creating running speed graph...")
74+running_speed_graph = fp.TimeseriesGraph(hide_nav_toolbar=True)
75+running_speed_graph.add_uniform_series(
76+ name="running_speed",
77+ start_time_sec=running_speed_timestamps[0],
78+ sampling_frequency_hz=1
79+ / (running_speed_timestamps[1] - running_speed_timestamps[0]),
80+ data=running_speed_data,
81+ timestamps_for_inserting_nans=running_speed_timestamps,
82+)
83+
84+
85+# Extract interval data
86+print("\nExtracting interval data...")
87+spontaneous_blocks = nwb.intervals["spontaneous_blocks"]
88+spontaneous_start = spontaneous_blocks["start_time"][:]
89+spontaneous_stop = spontaneous_blocks["stop_time"][:]
90+print(f"Spontaneous blocks: {len(spontaneous_start)} intervals")
91+
92+trials = nwb.intervals["trials"]
93+trials_start = trials["start_time"][:]
94+trials_stop = trials["stop_time"][:]
95+print(f"Trials: {len(trials_start)} intervals")
96+
97+# Create trials interval graph
98+print("Creating trials interval graph...")
99+trials_graph = fp.TimeseriesGraph(hide_nav_toolbar=True)
100+trials_graph.add_interval_series(
101+ name="trials",
102+ t_start=trials_start,
103+ t_end=trials_stop,
104+ color="lightblue",
105+ # alpha=0.5
106+)
107+
108+# Create spontaneous blocks interval graph
109+print("Creating spontaneous blocks interval graph...")
110+spontaneous_graph = fp.TimeseriesGraph(hide_nav_toolbar=True)
111+print(spontaneous_start)
112+print(spontaneous_stop)
113+spontaneous_graph.add_interval_series(
114+ name="spontaneous_blocks",
115+ t_start=spontaneous_start,
116+ t_end=spontaneous_stop,
117+ color="lightcoral",
118+ alpha=0.5,
119+)
120+
121+# Create raster plot of neural units
122+print("\nExtracting neural units data...")
123+units = nwb.units
124+num_units = len(units.id)
125+print(f"Number of units: {num_units}")
126+
127+print("Creating raster plot...")
128+raster_plot_items = [
129+ fpss.RasterPlotItem(
130+ unit_id=str(units.id[i]), spike_times_sec=units.spike_times_index[i]
131+ )
132+ for i in range(num_units)
133+]
134+
135+raster_start_time = 0
136+raster_end_time = np.max(units.spike_times_index[num_units - 1]) + 10
137+
138+raster_plot = fpss.RasterPlot(
139+ start_time_sec=raster_start_time,
140+ end_time_sec=raster_end_time,
141+ plots=raster_plot_items,
142+)
143+
144+# Create combined visualization
145+print("\nCreating combined visualization...")
146+combined_view = fp.Box(
147+ direction="vertical",
148+ items=[
149+ fp.LayoutItem(
150+ view=trials_graph, title="Trials", stretch=1, max_size=80, collapsible=True
151+ ),
152+ fp.LayoutItem(
153+ view=spontaneous_graph,
154+ title="Spontaneous Blocks",
155+ stretch=1,
156+ max_size=80,
157+ collapsible=True,
158+ ),
159+ fp.LayoutItem(
160+ view=pupil_graph,
161+ title="Pupil Diameter",
162+ min_size=100,
163+ stretch=1,
164+ collapsible=True,
165+ ),
166+ fp.LayoutItem(
167+ view=running_speed_graph,
168+ title="Running Speed",
169+ min_size=100,
170+ stretch=1,
171+ collapsible=True,
172+ ),
173+ fp.LayoutItem(
174+ view=raster_plot,
175+ title="Spike Raster Plot",
176+ min_size=100,
177+ stretch=2,
178+ collapsible=True,
179+ ),
180+ ],
181+ show_titles=True,
182+)
183+# Display combined view
184+print("Displaying combined view...")
185+this_script = read_script(__file__, _this_script_contains_no_sensitive_info=True)
186+url = combined_view.show(
187+ title=f'DANDI:000986/{asset_path}',
188+ description="Test description",
189+ script=this_script,
190+ wait_for_input=False if output_file is not None else True,
191+ upload=True if output_file is not None else False,
192+)
193+
194+if output_file is not None:
195+ print(f"Figure URL: {url}")
196+ print(f"Writing figure URL to {output_file}...")
197+ with open(output_file, "w") as f:
198+ f.write(url)