Skip to content

Commit 33735ba

Browse files
committed
atlas: probabilistic brain regions lookup
1 parent f1ca006 commit 33735ba

File tree

2 files changed

+29
-3
lines changed

2 files changed

+29
-3
lines changed

ibllib/atlas/atlas.py

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -300,16 +300,34 @@ def _lookup(self, xyz):
300300
"""
301301
return self._lookup_inds(self.bc.xyz2i(xyz))
302302

303-
def get_labels(self, xyz, mapping='Allen'):
303+
def get_labels(self, xyz, mapping='Allen', radius_um=None):
304304
"""
305305
Performs a 3D lookup from real world coordinates to the volume labels
306306
and return the regions ids according to the mapping
307307
:param xyz: [n, 3] array of coordinates
308308
:param mapping: brain region mapping (defaults to original Allen mapping)
309+
:param radius_um: if not null, returns a regions ids array and an array of proportion
310+
of regions in a sphere of size radius around the coordinates.
309311
:return: n array of region ids
310312
"""
311-
regions_indices = self._get_mapping(mapping=mapping)[self.label.flat[self._lookup(xyz)]]
312-
return self.regions.id[regions_indices]
313+
if radius_um:
314+
nrx = int(np.ceil(radius_um / abs(self.bc.dx) / 1e6))
315+
nry = int(np.ceil(radius_um / abs(self.bc.dy) / 1e6))
316+
nrz = int(np.ceil(radius_um / abs(self.bc.dz) / 1e6))
317+
nr = [nrx, nry, nrz]
318+
iii = self.bc.xyz2i(xyz)
319+
# computing the cube radius and indices is more complicated as volume indices are not
320+
# necessariy in ml, ap, dv order so the indices order is dynamic
321+
rcube = np.meshgrid(*tuple((np.arange(
322+
-nr[i], nr[i] + 1) * self.bc.dxyz[i]) ** 2 for i in self.xyz2dims))
323+
rcube = np.sqrt(rcube[0] + rcube[1], rcube[2]) * 1e6
324+
icube = tuple(slice(-nr[i] + iii[i], nr[i] + iii[i] + 1) for i in self.xyz2dims)
325+
cube = self.regions.mappings[mapping][self.label[icube]]
326+
ilabs, counts = np.unique(cube[rcube <= radius_um], return_counts=True)
327+
return self.regions.id[ilabs], counts / np.sum(counts)
328+
else:
329+
regions_indices = self._get_mapping(mapping=mapping)[self.label.flat[self._lookup(xyz)]]
330+
return self.regions.id[regions_indices]
313331

314332
def _get_mapping(self, mapping='Allen'):
315333
"""

ibllib/tests/test_atlas.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,14 @@ def test_lookups(self):
347347
assert self.ba.get_labels([0, 0, self.ba.bc.i2z(103)], mapping='Cosmos') == 997
348348
assert self.ba.get_labels([0, 0, 0], mapping='Cosmos') == 0
349349

350+
def test_lookups_probabilistic(self):
351+
xyz = np.array([0, -.0058, -.0038])
352+
aid = self.ba.get_labels(xyz, mapping='Beryl')
353+
aids, proportions = self.ba.get_labels(xyz, mapping='Beryl', radius_um=250)
354+
self.assertEqual(aid, 0)
355+
assert (np.all(aids == np.array([0])))
356+
assert (np.isclose(proportions, np.array([1.])))
357+
350358
def test_slice(self):
351359
ba = self.ba
352360
nx, ny, nz = ba.bc.nxyz

0 commit comments

Comments
 (0)