|
25 | 25 |
|
26 | 26 | from bluepyopt.ephys.base import BaseEPhys |
27 | 27 | from bluepyopt.ephys.serializer import DictMixin |
| 28 | +import numpy as np |
28 | 29 |
|
29 | 30 |
|
30 | 31 | class Location(BaseEPhys): |
@@ -354,7 +355,7 @@ def __init__( |
354 | 355 | name, |
355 | 356 | soma_distance=soma_distance, |
356 | 357 | seclist_name=sec_name, |
357 | | - comment='' |
| 358 | + comment=comment, |
358 | 359 | ) |
359 | 360 | self.sec_index = sec_index |
360 | 361 |
|
@@ -392,6 +393,74 @@ def instantiate(self, sim=None, icell=None): |
392 | 393 | return self.find_icomp(sim, branches) |
393 | 394 |
|
394 | 395 |
|
| 396 | +class NrnTrunkSomaDistanceCompLocation(NrnSecSomaDistanceCompLocation): |
| 397 | + """Location at a distance from soma along a main direction. |
| 398 | +
|
| 399 | + We search for the section that is the furthest away from some along |
| 400 | + a direction, and pick a location at a given distance from soma along |
| 401 | + the path to that section. |
| 402 | +
|
| 403 | + If direction == 'radial', the largest radial direction is used. |
| 404 | +
|
| 405 | + This is most useful to follow the trunk of an apical dendrite |
| 406 | + without knowing the apical point, but only that apical trunk goes along y. |
| 407 | + """ |
| 408 | + |
| 409 | + def __init__( |
| 410 | + self, |
| 411 | + name, |
| 412 | + soma_distance=None, |
| 413 | + sec_index=None, |
| 414 | + sec_name=None, |
| 415 | + direction=None, |
| 416 | + comment="" |
| 417 | + ): |
| 418 | + """Constructor |
| 419 | +
|
| 420 | + Args: |
| 421 | + name (str): name of this object |
| 422 | + soma_distance (float): distance from soma to this compartment |
| 423 | + sec_index (int): index of the section to consider |
| 424 | + sec_name (str): name of Neuron sections (ex: 'apic') |
| 425 | + direction (list of 3 elements): 3d vector representing direction, |
| 426 | + if None, default is [0, 1, 0] |
| 427 | + """ |
| 428 | + super(NrnTrunkSomaDistanceCompLocation, self).__init__( |
| 429 | + name, |
| 430 | + soma_distance=soma_distance, |
| 431 | + sec_index=sec_index, |
| 432 | + sec_name=sec_name, |
| 433 | + comment=comment |
| 434 | + ) |
| 435 | + |
| 436 | + if direction is None: |
| 437 | + direction = [0.0, 1.0, 0.0] |
| 438 | + self.direction = direction |
| 439 | + |
| 440 | + def set_sec_index(self, icell=None): |
| 441 | + """Search for the point furthest away along given direction.""" |
| 442 | + points = np.array( |
| 443 | + [ |
| 444 | + [ |
| 445 | + section.x3d(section.n3d() - 1), |
| 446 | + section.y3d(section.n3d() - 1), |
| 447 | + section.z3d(section.n3d() - 1), |
| 448 | + ] |
| 449 | + for section in getattr(icell, self.seclist_name) |
| 450 | + ] |
| 451 | + ) |
| 452 | + if self.direction == 'radial': |
| 453 | + self.sec_index = int(np.argmax(np.linalg.norm(points, axis=1))) |
| 454 | + else: |
| 455 | + self.sec_index = int(np.argmax(points.dot(self.direction))) |
| 456 | + |
| 457 | + def instantiate(self, sim=None, icell=None): |
| 458 | + """ """ |
| 459 | + if self.sec_index is None: |
| 460 | + self.set_sec_index(icell=icell) |
| 461 | + return super().instantiate(sim=sim, icell=icell) |
| 462 | + |
| 463 | + |
395 | 464 | class EPhysLocInstantiateException(Exception): |
396 | 465 |
|
397 | 466 | """All exception generated by location instantiation""" |
|
0 commit comments