/ concept-collection / dandiset_000986
Sign in
concept-collection / dandiset_000986
dandiset_000986 / scripts / create_figure.py
198 lines · 5.7 KBBlameHistoryRaw
1import sys
2import pynwb
3import h5py
4import remfile
5import numpy as np
6import figpack.views as fp
7import figpack_spike_sorting.views as fpss
8from figpack.utils import read_script
9from dandi.dandiapi import DandiAPIClient
11asset_path = None
12if len(sys.argv) > 1:
13 asset_path = sys.argv[1]
15output_file = None
16if len(sys.argv) > 2:
17 output_file = sys.argv[2]
19if 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 )
24if output_file is not None:
25 print(f"Output file specified: {output_file}")
27# Initialize Dandi client and load NWB file
28print("Connecting to DANDI API...")
29client = DandiAPIClient()
30dandiset = client.get_dandiset("000986", "draft")
31nwb_file_url = dandiset.get_asset_by_path(asset_path).download_url
33print("Loading NWB file...")
34# Open the remote file with disk cache
35disk_cache = remfile.DiskCache("./cache")
36remote_file = remfile.File(nwb_file_url, disk_cache=disk_cache)
37h5_file = h5py.File(remote_file)
38nwb_io = pynwb.NWBHDF5IO(file=h5_file)
39nwb = nwb_io.read()
40print("NWB file loaded successfully")
42# Extract pupil diameter data
43print("\nExtracting pupil diameter data...")
44pupil = (
45 nwb.processing["behavior"]
46 .data_interfaces["PupilTracking"]
47 .time_series["pupil_diameter"]
49pupil_data = pupil.data[:]
50pupil_timestamps = pupil.timestamps[:]
51print(f"Pupil data: {len(pupil_data)} samples")
53# Create pupil diameter time series graph
54print("Creating pupil diameter graph...")
55pupil_graph = fp.TimeseriesGraph(hide_nav_toolbar=True)
56pupil_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,
65# Extract running speed data
66print("\nExtracting running speed data...")
67running_speed = nwb.processing["behavior"].data_interfaces["running_speed"]
68running_speed_data = running_speed.data[:]
69running_speed_timestamps = running_speed.timestamps[:]
70print(f"Running speed data: {len(running_speed_data)} samples")
72# Create running speed time series graph
73print("Creating running speed graph...")
74running_speed_graph = fp.TimeseriesGraph(hide_nav_toolbar=True)
75running_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,
85# Extract interval data
86print("\nExtracting interval data...")
87spontaneous_blocks = nwb.intervals["spontaneous_blocks"]
88spontaneous_start = spontaneous_blocks["start_time"][:]
89spontaneous_stop = spontaneous_blocks["stop_time"][:]
90print(f"Spontaneous blocks: {len(spontaneous_start)} intervals")
92trials = nwb.intervals["trials"]
93trials_start = trials["start_time"][:]
94trials_stop = trials["stop_time"][:]
95print(f"Trials: {len(trials_start)} intervals")
97# Create trials interval graph
98print("Creating trials interval graph...")
99trials_graph = fp.TimeseriesGraph(hide_nav_toolbar=True)
100trials_graph.add_interval_series(
101 name="trials",
102 t_start=trials_start,
103 t_end=trials_stop,
104 color="lightblue",
105 # alpha=0.5
108# Create spontaneous blocks interval graph
109print("Creating spontaneous blocks interval graph...")
110spontaneous_graph = fp.TimeseriesGraph(hide_nav_toolbar=True)
111print(spontaneous_start)
112print(spontaneous_stop)
113spontaneous_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,
121# Create raster plot of neural units
122print("\nExtracting neural units data...")
123units = nwb.units
124num_units = len(units.id)
125print(f"Number of units: {num_units}")
127print("Creating raster plot...")
128raster_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)
135raster_start_time = 0
136raster_end_time = np.max(units.spike_times_index[num_units - 1]) + 10
138raster_plot = fpss.RasterPlot(
139 start_time_sec=raster_start_time,
140 end_time_sec=raster_end_time,
141 plots=raster_plot_items,
144# Create combined visualization
145print("\nCreating combined visualization...")
146combined_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,
183# Display combined view
184print("Displaying combined view...")
185this_script = read_script(__file__, _this_script_contains_no_sensitive_info=True)
186url = 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,
194if 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)
moveopenescclose