Skip to content

Commit 848aa72

Browse files
anna-grimanna-grim
andauthored
Feat s3 img reader (#286)
* refactor: anistropy not hardcoded * refactor: anisotropy not built-in --------- Co-authored-by: anna-grim <anna.grim@alleninstitute.org>
1 parent 93a0b49 commit 848aa72

File tree

4 files changed

+48
-71
lines changed

4 files changed

+48
-71
lines changed

src/deep_neurographs/generate_proposals.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
@author: Anna Grim
55
@email: anna.grim@alleninstitute.org
66
7-
Module used to generate edge proposals.
7+
Module used to generate edge proposals for a fragments graph.
88
99
"""
1010

src/deep_neurographs/utils/graph_util.py

Lines changed: 31 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,20 @@
55
@email: anna.grim@alleninstitute.org
66
77
8-
Routines for loading fragments and building a fragments_graph.
8+
Overview
9+
--------
10+
Code that reads and preprocesses neuron fragments stored as swc files, then
11+
constructs a custom graph object called a "FragmentsGraph".
912
13+
Graph Construction Algorithm:
14+
1. Read Neuron Fragments
15+
to do...
16+
17+
2. Preprocess Fragments and Extract Irreducibles
18+
to do...
19+
20+
3. Build FragmentsGraph
21+
to do...
1022
1123
Terminology
1224
------------
@@ -31,12 +43,7 @@
3143
from tqdm import tqdm
3244

3345
from deep_neurographs import geometry
34-
from deep_neurographs.utils import img_util, swc_util, util
35-
36-
MIN_SIZE = 30
37-
NODE_SPACING = 1
38-
SMOOTH_BOOL = True
39-
PRUNE_DEPTH = 20
46+
from deep_neurographs.utils import swc_util, util
4047

4148

4249
class GraphLoader:
@@ -48,36 +55,35 @@ class GraphLoader:
4855
def __init__(
4956
self,
5057
anisotropy=[1.0, 1.0, 1.0],
51-
min_size=MIN_SIZE,
52-
node_spacing=NODE_SPACING,
58+
min_size=30,
59+
node_spacing=1,
5360
progress_bar=False,
54-
prune_depth=PRUNE_DEPTH,
55-
smooth_bool=SMOOTH_BOOL,
61+
prune_depth=20,
62+
smooth_bool=True,
5663
):
5764
"""
5865
Builds a FragmentsGraph by reading swc files stored either on the
5966
cloud or local machine, then extracting the irreducible components.
6067
6168
Parameters
6269
----------
63-
anisotropy : list[float], optional
64-
Scaling factors applied to xyz coordinates to account for the
65-
anisotropy of microscope. The default is [1.0, 1.0, 1.0].
70+
anisotropy : List[float], optional
71+
Image to physical coordinates scaling factors to account for the
72+
anisotropy of the microscope. The default is [1.0, 1.0, 1.0].
6673
min_size : float, optional
6774
Minimum path length of swc files which are stored as connected
68-
components in the FragmentsGraph. The default is 30ums.
75+
components in the FragmentsGraph. The default is 30.0 (microns).
6976
node_spacing : int, optional
70-
Spacing (in microns) between nodes. The default is the global
71-
variable "NODE_SPACING".
77+
Spacing (in microns) between nodes. The default is 1.
7278
progress_bar : bool, optional
7379
Indication of whether to print out a progress bar while building
7480
graph. The default is True.
7581
prune_depth : int, optional
7682
Branches less than "prune_depth" microns are pruned if "prune" is
77-
True. The default is the global variable "PRUNE_DEPTH".
83+
True. The default is 20.0 (microns).
7884
smooth_bool : bool, optional
7985
Indication of whether to smooth branches from swc files. The
80-
default is the global variable "SMOOTH".
86+
default is True.
8187
8288
Returns
8389
-------
@@ -90,12 +96,9 @@ def __init__(
9096
self.progress_bar = progress_bar
9197
self.prune_depth = prune_depth
9298
self.smooth_bool = smooth_bool
93-
9499
self.reader = swc_util.Reader(anisotropy, min_size)
95100

96-
def run(
97-
self, fragments_pointer, img_patch_origin=None, img_patch_shape=None
98-
):
101+
def run(self, fragments_pointer):
99102
"""
100103
Builds a FragmentsGraph by reading swc files stored either on the
101104
cloud or local machine, then extracting the irreducible components.
@@ -105,12 +108,6 @@ def run(
105108
fragments_pointer : dict, list, str
106109
Pointer to swc files used to build an instance of FragmentsGraph,
107110
see "swc_util.Reader" for further documentation.
108-
img_patch_origin : list[int], optional
109-
An xyz coordinate which is the upper, left, front corner of the
110-
image patch that contains the swc files. The default is None.
111-
img_patch_shape : list[int], optional
112-
Shape of the image patch which contains the swc files. The default
113-
is None.
114111
115112
Returns
116113
-------
@@ -120,12 +117,13 @@ def run(
120117
"""
121118
from deep_neurographs.fragments_graph import FragmentsGraph
122119

123-
# Load fragments and extract irreducibles
124-
self.img_bbox = img_util.init_bbox(img_patch_origin, img_patch_shape)
120+
# Step 1: Read Neuron Fragments
125121
swc_dicts = self.reader.load(fragments_pointer)
122+
123+
# Step: Preprocess Fragments and Extract Irreducibles
126124
irreducibles = self.schedule_processes(swc_dicts)
127125

128-
# Build FragmentsGraph
126+
# Step 3: Build FragmentsGraph
129127
fragments_graph = FragmentsGraph(node_spacing=self.node_spacing)
130128
while len(irreducibles):
131129
irreducible_set = irreducibles.pop()
@@ -186,15 +184,14 @@ def get_irreducibles(self, swc_dict):
186184
187185
Returns
188186
-------
189-
list
187+
List[dict]
190188
List of dictionaries such that each is the set of irreducibles in
191189
a connected component of the graph corresponding to "swc_dict".
192190
193191
"""
194192
# Build dense graph
195193
swc_dict["idx"] = dict(zip(swc_dict["id"], range(len(swc_dict["id"]))))
196194
graph, _ = swc_util.to_graph(swc_dict, set_attrs=True)
197-
self.clip_branches(graph, swc_dict["swc_id"])
198195
self.prune_branches(graph)
199196

200197
# Extract irreducibles
@@ -210,28 +207,6 @@ def get_irreducibles(self, swc_dict):
210207
irreducibles.append(result)
211208
return irreducibles
212209

213-
def clip_branches(self, graph, swc_id):
214-
"""
215-
Deletes all nodes from "graph" that are not contained in "img_bbox".
216-
217-
Parameters
218-
----------
219-
graph : networkx.Graph
220-
Graph to be searched
221-
222-
Returns
223-
-------
224-
None
225-
226-
"""
227-
if self.img_bbox:
228-
delete_nodes = set()
229-
for i in graph.nodes:
230-
xyz = img_util.to_voxels(graph.nodes[i]["xyz"], self.to_anisotropy)
231-
if not util.is_contained(self.img_bbox, xyz):
232-
delete_nodes.add(i)
233-
graph.remove_nodes_from(delete_nodes)
234-
235210
def prune_branches(self, graph):
236211
"""
237212
Prunes all short branches from "graph". A short branch is a path
@@ -316,7 +291,6 @@ def get_component_irreducibles(self, graph, swc_dict):
316291
# Visit j
317292
attrs = upd_edge_attrs(swc_dict, attrs, j)
318293
if j in leafs or j in branchings:
319-
# Check whether to smooth
320294
attrs["length"] = branch_length
321295
attrs = to_numpy(attrs)
322296
if self.smooth_bool:

src/deep_neurographs/utils/img_util.py

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
@author: Anna Grim
55
@email: anna.grim@alleninstitute.org
66
7-
Helper routines for working with images.
7+
8+
Helper routines for processing images.
89
910
"""
1011

@@ -313,29 +314,29 @@ def to_physical(voxel, anisotropy, shift=[0, 0, 0]):
313314
return tuple([voxel[i] * anisotropy[i] - shift[i] for i in range(3)])
314315

315316

316-
def to_voxels(xyz, anisotropy, downsample_factor=0):
317+
def to_voxels(xyz, anisotropy, multiscale=0):
317318
"""
318319
Converts coordinates from world to voxel.
319320
320321
Parameters
321322
----------
322323
xyz : ArrayLike
323-
xyz coordinate to be converted to voxels.
324+
Physical coordiante to be converted to a voxel coordinate.
324325
anisotropy : ArrayLike
325326
Image to physical coordinates scaling factors to account for the
326327
anisotropy of the microscope.
327-
downsample_factor : int, optional
328-
Downsampling factor that accounts for which level in the image pyramid
329-
the voxel coordinates must index into. The default is 0.
328+
multiscale : int, optional
329+
Level in the image pyramid that the voxel coordinate must index into.
330+
The default is 0.
330331
331332
Returns
332333
-------
333334
numpy.ndarray
334-
Coordinates converted to voxels.
335+
Voxel coordinate of the input.
335336
336337
"""
337-
downsample_factor = 1.0 / 2 ** downsample_factor
338-
voxel = downsample_factor * (xyz / np.array(anisotropy))
338+
scaling_factor = 1.0 / 2 ** multiscale
339+
voxel = scaling_factor * xyz / np.array(anisotropy)
339340
return np.round(voxel).astype(int)
340341

341342

@@ -348,9 +349,10 @@ def init_bbox(origin, shape):
348349
Parameters
349350
----------
350351
origin : tuple[int]
351-
Origin of bounding box which is assumed to be top, front, left corner.
352-
shape : tuple[int]
353-
Shape of bounding box.
352+
Voxel coordinate of the origin of the bounding box, which is assumed
353+
to be top-front-left corner.
354+
shape : Tuple[int]
355+
Shape of the bounding box.
354356
355357
Returns
356358
-------

src/deep_neurographs/utils/util.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
@author: Anna Grim
55
@email: anna.grim@alleninstitute.org
66
7-
General helper routines for various tasks.
7+
8+
Miscellaneous helper routines.
89
910
"""
1011

0 commit comments

Comments
 (0)