|
3 | 3 | import numpy
|
4 | 4 | from neuron import h, nrn
|
5 | 5 | from .rxdException import RxDException
|
| 6 | +from itertools import groupby |
6 | 7 |
|
7 | 8 | try:
|
8 | 9 | from neuron.rxd import geometry3d
|
@@ -151,6 +152,8 @@ def scale_by_constant(scale, f):
|
151 | 152 | inside = RxDGeometry()
|
152 | 153 | if has_geometry3d:
|
153 | 154 | inside.volumes3d = geometry3d.voxelize2
|
| 155 | + inside._scale_internal_volumes3d = 1 |
| 156 | + inside._scale_surface_volumes3d = 1 |
154 | 157 | # neighbor_area_fraction can be a constant or a function
|
155 | 158 | inside.neighbor_area_fraction = 1
|
156 | 159 | inside.volumes1d = _volumes1d
|
@@ -201,6 +204,8 @@ class DistributedBoundary(RxDGeometry):
|
201 | 204 |
|
202 | 205 | def __init__(self, area_per_vol, perim_per_area=0):
|
203 | 206 | self._area_per_vol = area_per_vol
|
| 207 | + self._scale_internal_volumes3d = area_per_vol |
| 208 | + self._scale_surface_volumes3d = area_per_vol |
204 | 209 | self._perim_per_area = 0
|
205 | 210 |
|
206 | 211 | self.surface_areas1d = _always_0
|
@@ -268,6 +273,9 @@ def __init__(
|
268 | 273 | self.is_volume = _always_true
|
269 | 274 | self.is_area = _always_false
|
270 | 275 | self._volume_fraction = volume_fraction
|
| 276 | + self._scale_internal_volumes3d = volume_fraction |
| 277 | + self._scale_surface_volumes3d = volume_fraction |
| 278 | + |
271 | 279 | self._surface_fraction = surface_fraction
|
272 | 280 | self._neighbor_areas_fraction = neighbor_areas_fraction
|
273 | 281 | # TODO: does the else case ever make sense?
|
@@ -585,6 +593,36 @@ def _get_geo(self, sec):
|
585 | 593 | )
|
586 | 594 | return geo
|
587 | 595 |
|
| 596 | + def volumes3d(self, source, dx=0.25): |
| 597 | + geos = {} |
| 598 | + for sec in source: |
| 599 | + geo = self._get_geo(sec) |
| 600 | + geos.setdefault(geo, []).append(sec) |
| 601 | + internal_voxels, surface_voxels, mesh_grid = geometry3d.voxelize2(source, dx) |
| 602 | + internal_key = lambda itm: itm[1][1].sec |
| 603 | + surface_key = lambda itm: itm[1][2].sec |
| 604 | + internal_by_sec = groupby(internal_voxels.items(), key=internal_key) |
| 605 | + surface_by_sec = groupby(surface_voxels.items(), key=surface_key) |
| 606 | + for geo, secs in geos.items(): |
| 607 | + # only scale if not multiplying by 1 |
| 608 | + if geo._scale_internal_volumes3d != 1: |
| 609 | + for sec, voxels in internal_by_sec: |
| 610 | + # only scale if sec is in this geometry |
| 611 | + if sec in secs: |
| 612 | + # scale the internal volume |
| 613 | + for key, _ in voxels: |
| 614 | + internal_voxels[key][0] *= geo._scale_internal_volumes3d |
| 615 | + # only scale if not multiplying by 1 |
| 616 | + if geo._scale_surface_volumes3d != 1: |
| 617 | + for sec, voxels in surface_by_sec: |
| 618 | + # only scale if sec is in this geometry |
| 619 | + if sec in secs: |
| 620 | + # scale the surface volume |
| 621 | + for key, _ in voxels: |
| 622 | + surface_voxels[key][0] *= geo._scale_surface_volumes3d |
| 623 | + |
| 624 | + return internal_voxels, surface_voxels, mesh_grid |
| 625 | + |
588 | 626 | def volumes1d(self, sec):
|
589 | 627 | return self._get_geo(sec).volumes1d(sec)
|
590 | 628 |
|
|
0 commit comments