Skip to content

Commit 04a2135

Browse files
committed
more WIP
1 parent 7e60631 commit 04a2135

File tree

2 files changed

+136
-11
lines changed

2 files changed

+136
-11
lines changed

needles2/needles_viewer.py

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
from iblviewer.atlas_controller import AtlasController
2+
import vedo
3+
from iblviewer.atlas_model import AtlasModel, AtlasUIModel, CameraModel
4+
from iblviewer.slicer_model import SlicerModel
5+
6+
from iblviewer.atlas_view import AtlasView
7+
from iblviewer.volume_view import VolumeView
8+
from iblviewer.slicer_view import SlicerView
9+
import iblviewer.utils as utils
10+
11+
from ipyvtk_simple.viewer import ViewInteractiveWidget
12+
13+
14+
class NeedlesViewer(AtlasController):
15+
def __init__(self):
16+
super(NeedlesViewer, self).__init__()
17+
18+
def initialize(self, plot, resolution=25, mapping='Allen', num_windows=1, render=False):
19+
vedo.settings.allowInteraction = False
20+
self.plot = plot
21+
self.plot_window_id = 0
22+
self.model = AtlasModel()
23+
self.model.initialize(resolution)
24+
self.model.load_allen_volume(mapping)
25+
self.model.initialize_slicers()
26+
27+
self.view = AtlasView(self.plot, self.model)
28+
self.view.initialize()
29+
self.view.volume = VolumeView(self.plot, self.model.volume, self.model)
30+
31+
#pn = SlicerModel.NAME_XYZ_POSITIVE
32+
nn = SlicerModel.NAME_XYZ_NEGATIVE
33+
34+
#pxs_model = self.model.find_model(pn[0], self.model.slicers)
35+
#self.px_slicer = SlicerView(self.plot, self.view.volume, pxs_model, self.model)
36+
#pys_model = self.model.find_model(pn[1], self.model.slicers)
37+
#self.py_slicer = SlicerView(self.plot, self.view.volume, pys_model, self.model)
38+
#pzs_model = self.model.find_model(pn[2], self.model.slicers)
39+
#self.pz_slicer = SlicerView(self.plot, self.view.volume, pzs_model, self.model)
40+
41+
nxs_model = self.model.find_model(nn[0], self.model.slicers)
42+
self.nx_slicer = SlicerView(self.plot, self.view.volume, nxs_model, self.model)
43+
nys_model = self.model.find_model(nn[1], self.model.slicers)
44+
self.ny_slicer = SlicerView(self.plot, self.view.volume, nys_model, self.model)
45+
nzs_model = self.model.find_model(nn[2], self.model.slicers)
46+
self.nz_slicer = SlicerView(self.plot, self.view.volume, nzs_model, self.model)
47+
48+
self.slicers = [self.nx_slicer, self.ny_slicer, self.nz_slicer]
49+
50+
vedo.settings.defaultFont = self.model.ui.font
51+
self.initialize_embed_ui(slicer_target=self.view.volume)
52+
53+
self.plot.show(interactive=False)
54+
self.handle_transfer_function_update()
55+
# By default, the atlas volume is our target
56+
self.model.camera.target = self.view.volume.actor
57+
# We start with a sagittal view
58+
self.set_left_view()
59+
60+
self.render()
61+
62+
def initialize_embed_ui(self, slicer_target=None):
63+
s_kw = self.model.ui.slider_config
64+
d = self.view.volume.model.dimensions
65+
if d is None:
66+
return
67+
68+
#self.add_slider('px', self.update_px_slicer, 0, int(d[0]), 0, pos=(0.05, 0.065, 0.12),
69+
# title='+X', **s_kw)
70+
#self.add_slider('py', self.update_py_slicer, 0, int(d[1]), 0, pos=(0.2, 0.065, 0.12),
71+
# title='+Y', **s_kw)
72+
#self.add_slider('pz', self.update_pz_slicer, 0, int(d[2]), 0, pos=(0.35, 0.065, 0.12),
73+
# title='+Z', **s_kw)
74+
75+

needles2/run_needles2.py

Lines changed: 61 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@
1010
from ibllib.atlas import AllenAtlas, regions
1111
import qt
1212

13+
from PyQt5 import Qt
14+
import vedo
15+
from vtk.qt.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor
16+
from oneibl.one import ONE
17+
#one = ONE()
18+
from ibllib.pipes.histology import coverage
19+
from needles2.needles_viewer import NeedlesViewer
1320

1421
class MainWindow(QtWidgets.QMainWindow):
1522

@@ -38,6 +45,19 @@ def __init__(self):
3845

3946
self.atlas = AllenAtlas(25)
4047
main_layout = QtWidgets.QGridLayout()
48+
self.frame = Qt.QFrame()
49+
self.vl = Qt.QVBoxLayout()
50+
self.vtkWidget = QVTKRenderWindowInteractor(self.frame)
51+
self.vl.addWidget(self.vtkWidget)
52+
self.plt = vedo.Plotter(qtWidget=self.vtkWidget, N=1)
53+
self.la = NeedlesViewer()
54+
self.la.initialize(self.plt)
55+
print(self.la)
56+
self.la2 = NeedlesViewer()
57+
self.la2.initialize(self.plt)
58+
self.frame.setLayout(self.vl)
59+
60+
4161
self.coronal = SliceView(self, self.atlas, waxis=0, haxis=2, daxis=1)
4262
self.sagittal = SliceView(self, self.atlas, waxis=1, haxis=2, daxis=0)
4363
self.top = TopView(self, self.atlas)
@@ -61,6 +81,12 @@ def __init__(self):
6181
images = ['Image', 'Annotation']
6282
self.add_menu_bar(self.img_menu, self.img_group, images, callback=self.change_image)
6383

84+
# Add menu bar for coverage
85+
self.coverage_menu = menu_bar.addMenu('Coverage')
86+
self.coverage_group = QtGui.QActionGroup(self.coverage_menu)
87+
self.coverage_group.setExclusive(True)
88+
self.add_menu_bar(self.img_menu, self.img_group, ['Coverage'], callback=self.change_image)
89+
6490
self.region_list = QtGui.QStandardItemModel()
6591
self.region_combobox = QtWidgets.QComboBox()
6692
# Add line edit and completer to be able to search for subject
@@ -70,23 +96,24 @@ def __init__(self):
7096
self.region_combobox.setCompleter(region_completer)
7197
self.region_combobox.setModel(self.region_list)
7298
self.region_combobox.completer().setModel(self.region_list)
73-
data = self.atlas.regions.name[self.atlas._get_mapping(mapping=self.get_mapping())]
74-
self.populate_lists(data, self.region_list, self.region_combobox)
75-
7699
self.region_combobox.activated.connect(self.on_region_selected)
100+
self.change_mapping()
101+
77102

103+
offset = self.atlas.bc.lim(0)[0]
104+
self.la.update_slicer(self.la.nx_slicer, self.top.line_sagittal.value()*1e6 + offset*1e6)
78105

79106
main_layout.addWidget(self.region_combobox)
80107
main_layout.addWidget(self.top)
81108
main_layout.addWidget(self.coronal)
82109
main_layout.addWidget(self.sagittal)
110+
main_layout.addWidget(self.frame)
83111
main_widget.setLayout(main_layout)
84112

85113
# initialise
86114
self.set_slice(self.coronal)
87115
self.set_slice(self.sagittal)
88-
# menu bar for mapping
89-
# menu bar for image type
116+
90117

91118
def populate_lists(self, data, list_name, combobox):
92119
"""
@@ -104,7 +131,7 @@ def populate_lists(self, data, list_name, combobox):
104131
item.setEditable(False)
105132
list_name.appendRow(item)
106133

107-
# This makes sure the drop down menu is wide enough to showw full length of string
134+
# This makes sure the drop down menu is wide enough to show full length of string
108135
min_width = combobox.fontMetrics().width(max(data, key=len))
109136
min_width += combobox.view().autoScrollMargin()
110137
min_width += combobox.style().pixelMetric(QtGui.QStyle.PM_ScrollBarExtent)
@@ -114,7 +141,8 @@ def populate_lists(self, data, list_name, combobox):
114141
combobox.setCurrentIndex(0)
115142

116143
def change_mapping(self):
117-
data = self.atlas.regions.name[self.atlas._get_mapping(mapping=self.get_mapping())]
144+
data = np.unique(self.atlas.regions.name[self.atlas._get_mapping(
145+
mapping=self.get_mapping())])
118146
self.populate_lists(data, self.region_list, self.region_combobox)
119147
self._refresh()
120148

@@ -128,6 +156,14 @@ def change_image(self):
128156
self.img_group.checkedAction().text())
129157
self._refresh()
130158

159+
def add_coverage(self):
160+
traj = one.alyx.rest('trajectories', 'list', provenance='Ephys aligned histology track')
161+
self.coverage = coverage(traj, self.atlas)
162+
self.coronal.ctrl.add_volume_layer(self.coronal.fig_slice, self.coverage)
163+
self.sagittal.ctrl.add_volume_layer(self.sagittal.fig_slice, self.coverage)
164+
self._refresh()
165+
166+
131167
def add_menu_bar(self, menu, group, items, callback=None, default=None):
132168
if not default:
133169
default = items[0]
@@ -176,9 +212,13 @@ def _refresh(self):
176212

177213
def _refresh_coronal(self):
178214
self.set_slice(self.coronal, self.top.line_coronal.value())
215+
offset = self.atlas.bc.lim(1)[1]
216+
self.la.update_slicer(self.la.ny_slicer, (self.top.line_coronal.value()*1e6 + offset*16))
179217

180218
def _refresh_sagittal(self):
181219
self.set_slice(self.sagittal, self.top.line_sagittal.value())
220+
offset = self.atlas.bc.lim(0)[0]
221+
self.la.update_slicer(self.la.nx_slicer, self.top.line_sagittal.value()*1e6 + offset*1e6)
182222

183223
def _refresh_locked_region(self, region):
184224
region_values = np.zeros_like(self.atlas.regions.id)
@@ -197,6 +237,7 @@ def _refresh_locked_region(self, region):
197237
self._refresh()
198238
self.set_selected_region(region)
199239
# need to set the drop down to the selected region
240+
self.la.reveal_regions(region_idx)
200241

201242
def _reset_region(self, name):
202243
region_values = np.zeros_like(self.atlas.regions.id)
@@ -282,13 +323,13 @@ def __init__(self, qmain: MainWindow, atlas: AllenAtlas, waxis, haxis, daxis):
282323
label_layout.addWidget(self.label_ix)
283324
label_layout.addWidget(self.label_iy)
284325
label_layout.addWidget(self.label_v)
285-
label_layout.addWidget(self.label_region)
326+
#label_layout.addWidget(self.label_region)
286327
label_layout.addWidget(self.label_acronym)
287328
label_group.setLayout(label_layout)
288329

289330

290-
main_layout.addWidget(self.fig_slice)
291-
main_layout.addWidget(label_group)
331+
main_layout.addWidget(self.fig_slice, 0, 0)
332+
main_layout.addWidget(label_group, 0, 1)
292333
self.setLayout(main_layout)
293334

294335
# init the image display
@@ -332,7 +373,7 @@ def mouseMoveEvent(self, scenepos):
332373
self.label_acronym.setText("")
333374
self.qmain._reset_region('non_locked')
334375
else:
335-
self.label_region.setText(region['name'][0])
376+
#self.label_region.setText(region['name'][0])
336377
self.label_acronym.setText(region['acronym'][0])
337378

338379
if region['acronym'][0] != 'void':
@@ -414,6 +455,15 @@ def add_mask_layer(self, fig, name='locked', cmap='Blues'):
414455
'volume': 'value', 'region_values': np.zeros_like(self.atlas.regions.id),
415456
'mode': 'clip'})
416457

458+
def add_volume_layer(self, fig, volume, name='coverage', cmap='viridis'):
459+
colormap = matplotlib.cm.get_cmap(cmap)
460+
colormap._init()
461+
# The last one is [0, 0, 0, 0] so remove this
462+
lut = (colormap._lut * 255).view(np.ndarray)[:-1]
463+
lut = np.insert(lut, 0, [0, 0, 0, 0], axis=0)
464+
self.add_image_layer(fig, name=name, pg_kwargs={'lut': lut, 'opacity': 0.8}, slice_kwargs={
465+
'volume': 'volume', 'region_values': volume, 'mode': 'clip'})
466+
417467
def change_base_layer(self, fig, image='Image'):
418468
base_layer = self.get_image_layer(name='base')
419469
if image == 'Image':

0 commit comments

Comments
 (0)