Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitf5916f8

Browse files
committed
NF: Adds overlay option in OrthoSlicer3D
Beginning of functionality to allow overlays in OrthoSlicer3D
1 parentfcc5448 commitf5916f8

File tree

1 file changed

+109
-1
lines changed

1 file changed

+109
-1
lines changed

‎nibabel/viewers.py‎

Lines changed: 109 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@ def __init__(self, data, affine=None, axes=None, title=None):
6969
self._title=title
7070
self._closed=False
7171
self._cross=True
72+
self._overlay=None
73+
self._threshold=None
74+
self._alpha=1
7275

7376
data=np.asanyarray(data)
7477
ifdata.ndim<3:
@@ -286,6 +289,111 @@ def clim(self, clim):
286289
self._clim=tuple(clim)
287290
self.draw()
288291

292+
@property
293+
defoverlay(self):
294+
"""The current overlay """
295+
returnself._overlay
296+
297+
@property
298+
defthreshold(self):
299+
"""The current data display threshold """
300+
returnself._threshold
301+
302+
@threshold.setter
303+
defthreshold(self,threshold):
304+
# mask data array
305+
ifthresholdisnotNone:
306+
self._data=np.ma.masked_array(np.asarray(self._data),
307+
np.asarray(self._data)<=threshold)
308+
self._threshold=float(threshold)
309+
else:
310+
self._data=np.asarray(self._data)
311+
self._threshold=threshold
312+
313+
# update current volume data w/masked array and re-draw everything
314+
ifself._data.ndim>3:
315+
self._current_vol_data=self._data[...,self._data_idx[3]]
316+
else:
317+
self._current_vol_data=self._data
318+
self._set_position(None,None,None,notify=False)
319+
320+
@property
321+
defalpha(self):
322+
""" The current alpha (transparency) value """
323+
returnself._alpha
324+
325+
@alpha.setter
326+
defalpha(self,alpha):
327+
alpha=float(alpha)
328+
ifalpha>1oralpha<0:
329+
raiseValueError('alpha must be between 0 and 1')
330+
foriminself._ims:
331+
im.set_alpha(alpha)
332+
self._alpha=alpha
333+
self.draw()
334+
335+
defset_overlay(self,data,affine=None,threshold=None,cmap='viridis'):
336+
ifaffineisNone:
337+
try:# did we get an image?
338+
affine=data.affine
339+
data=data.dataobj
340+
exceptAttributeError:
341+
pass
342+
343+
# check that we have sufficient information to match the overlays
344+
ifaffineisNoneanddata.shape[:3]!=self._data.shape[:3]:
345+
raiseValueError('Provided `data` do not match shape of '
346+
'underlay and no `affine` matrix was '
347+
'provided. Please provide an `affine` matrix '
348+
'or resample first three dims of `data` to {}'
349+
.format(self._data.shape[:3]))
350+
351+
# we need to resample the provided data to the already-plotted data
352+
ifnotnp.allclose(affine,self._affine):
353+
from .processingimportresample_from_to
354+
from .nifti1importNifti1Image
355+
target_shape=self._data.shape[:3]+data.shape[3:]
356+
# we can't just use SpatialImage because we need an image type
357+
# where the spatial axes are _always_ first
358+
data=resample_from_to(Nifti1Image(data,affine),
359+
(target_shape,self._affine)).dataobj
360+
affine=self._affine
361+
362+
ifself._overlayisnotNone:
363+
# remove all images + cross hair lines
364+
fornn,iminenumerate(self._overlay._ims):
365+
im.remove()
366+
forlineinself._overlay._crosshairs[nn].values():
367+
line.remove()
368+
# remove the fourth axis, if it was created for the overlay
369+
if (self._overlay.n_volumes>1andlen(self._overlay._axes)>3
370+
andself.n_volumes==1):
371+
a=self._axes.pop(-1)
372+
a.remove()
373+
374+
# create an axis if we have a 4D overlay (vs a 3D underlay)
375+
axes=self._axes
376+
o_n_volumes=int(np.prod(data.shape[3:]))
377+
ifo_n_volumes>self.n_volumes:
378+
axes+= [axes[0].figure.add_subplot(224)]
379+
elifo_n_volumes<self.n_volumes:
380+
axes=axes[:-1]
381+
382+
# mask array for provided threshold
383+
self._overlay=self.__class__(data,affine=affine,axes=axes)
384+
self._overlay.threshold=threshold
385+
386+
# set transparency and new cmap
387+
self._overlay.cmap=cmap
388+
foriminself._overlay._ims:
389+
im.set_alpha(0.7)
390+
391+
# no double cross-hairs (they get confused when we have linked orthos)
392+
forcrossinself._overlay._crosshairs:
393+
cross['horiz'].set_visible(False)
394+
cross['vert'].set_visible(False)
395+
self._overlay._draw()
396+
289397
deflink_to(self,other):
290398
"""Link positional changes between two canvases
291399
@@ -413,7 +521,7 @@ def _set_position(self, x, y, z, notify=True):
413521
idx= [slice(None)]*len(self._axes)
414522
foriiinrange(3):
415523
idx[self._order[ii]]=self._data_idx[ii]
416-
vdata=self._data[tuple(idx)].ravel()
524+
vdata=np.asarray(self._data[tuple(idx)].ravel())
417525
vdata=np.concatenate((vdata, [vdata[-1]]))
418526
self._volume_ax_objs['patch'].set_x(self._data_idx[3]-0.5)
419527
self._volume_ax_objs['step'].set_ydata(vdata)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp