def test_pull_label(): def _img_to_labels(img, voxel, low=None, up=255): img_T1 = sitk.GetImageFromArray(np.squeeze(img), isVector=False) img_T1_255 = sitk.Cast(sitk.RescaleIntensity(img_T1), sitk.sitkUInt8) seed = (int(voxel[2]), int(voxel[1]), int(voxel[0])) seg = sitk.Image(img_T1.GetSize(), sitk.sitkUInt8) seg.CopyInformation(img_T1) seg[seed] = 1 seg = sitk.BinaryDilate(seg, 1) seg_con = sitk.ConnectedThreshold(img_T1_255, seedList=[seed], lower=int(np.round(low)), upper=up) vectorRadius = (1, 1, 1) kernel = sitk.sitkBall seg_clean = sitk.BinaryMorphologicalClosing(seg_con, vectorRadius, kernel) labels = sitk.GetArrayFromImage(seg_clean) return labels url = "s3://mouse-light-viz/precomputed_volumes/brain1_lowres" ngl = NeuroglancerSession(url, mip=1, url_segments=url + "_segments") # ngl_seg = NeuroglancerSession(url, mip=1, url_segments=url + "_segments") img, bounds, voxel = ngl.pull_chunk(2, 300) label = _img_to_labels(img, voxel, low=11) # ngl_seg.push(label, bounds) # label2 = ngl_seg.pull_bounds_seg(bounds) # assert np.all(np.squeeze(np.array(label) == np.squeeze(np.array(label2)))) assert True
def test_set_url_segments(vars_local): """Tests setting a segmentation url .""" _, url, url_segments, mip, seg_id, v_id = vars_local sess = NeuroglancerSession(url=url, mip=mip) sess.set_url_segments(url_segments) assert sess.url_segments == url_segments assert len(sess.cv_segments.scales) > 0
def test_session_bad_urls(vars_local): """Tests that initializing a NeuroglancerSession object by passing bad urls isn't valid.""" _, url, url_segments, mip, seg_id, v_id = vars_local url_bad = url + "0" # bad url url_segments_bad = url_segments + "0" # bad url with pytest.raises(InfoUnavailableError): sess = NeuroglancerSession(url_bad) with pytest.raises(InfoUnavailableError): sess = NeuroglancerSession(url, url_segments=url_segments_bad)
def test_tubes_from_paths(): """Tests that, given valid paths, valid tubes are created.""" sess = NeuroglancerSession(url, 0, url_seg) img, bbox, verts = sess.pull_voxel(2, 300, radius=5) # A valid bbox with data. G_paths = sess.get_segments(2, bbox) bbox = bbox.to_list() paths = G_paths[1] # valid paths size = np.subtract(bbox[3:], bbox[:3]) tubes = tube_seg.tubes_from_paths(size, paths) assert (tubes != 0).any()
def test_draw_tube_spheres(): """ Test if the function maps all the points within the radius of a segment line (defined by 2 given points) to 1, otherwise 0 The output array should have the same size of input image and binary values Distance between a point and the segment line: <= radius (if the point has value 1) > radius (if the point has value 0) """ ngl_session = NeuroglancerSession(url=url, url_segments=url_seg) img, _, _ = ngl_session.pull_vertex_list(2, [4], expand=True) shape = img.shape vertex0 = [ np.random.randint(shape[0] / 2), np.random.randint(shape[1]), np.random.randint(shape[2]), ] vertex1 = [ np.random.randint(shape[0] / 2, shape[0]), np.random.randint(shape[1]), np.random.randint(shape[2]), ] radius = np.random.randint(1, 4) labels = tube_seg.draw_tube_from_spheres(img, vertex0, vertex1, radius) line = draw.line_nd(vertex0, vertex1, endpoint=True) coords = np.where(labels < 1) d_bg = max(shape) for pt in np.array(coords).T: distance_min = min(np.sum((np.array(line).T - pt)**2, axis=1)) d_bg = min(distance_min, d_bg) coords = np.where(labels > 0) d_tube = 0 for pt in np.array(coords).T: distance_min = min(np.sum((np.array(line).T - pt)**2, axis=1)) d_tube = max(distance_min, d_tube) """ Verify: I. the size of output array II. if the output is binary-valued III. minimum distance between 0-valued points and the segment line is greater than radius IV. maximum distance between 1-valued points and the segment line is less than or equal to radius """ assert labels.shape == shape assert np.unique(labels).all() in [0, 1] assert d_bg > radius**2 assert d_tube <= radius**2
def test_session_incomplete_urls(vars_local): """Tests that initializing a NeuroglancerSession on data without segmentation or annotation channels is valid and raises a warning.""" input, url, url_seg, mip, _, _ = vars_local path = (Path(__file__).parents[3] / "data" / "test_upload" / "serial").as_uri() # does not have segments or annotation with pytest.warns(UserWarning): sess = NeuroglancerSession(path)
def test_tubes_seg(): """ Test if the function maps all the points within the radius of polyline (defined by given vertices) to 1, otherwise 0 The output array should have the same size of input image and binary values Distance between a point and the polyline: <= radius (if the point has value 1) > radius (if the point has value 0) """ ngl_session = NeuroglancerSession(url=url, url_segments=url_seg) img, _, _ = ngl_session.pull_vertex_list(2, [4], expand=True) shape = img.shape vertices = np.random.randint(min(shape), size=(4, 3)) radius = np.random.randint(1, 4) labels = tube_seg.tubes_seg(img, vertices, radius) point = np.empty((3, 0), dtype=int) for i in range(3): lines = draw.line_nd(vertices[i], vertices[i + 1], endpoint=True) point = np.concatenate((point, np.array(lines)), axis=1) coords = np.where(labels < 1) d_bg = max(shape) for pt in np.array(coords).T: distance_min = min(np.sum((point.T - pt)**2, axis=1)) d_bg = min(distance_min, d_bg) coords = np.where(labels > 0) d_tube = 0 for pt in np.array(coords).T: distance_min = min(np.sum((point.T - pt)**2, axis=1)) d_tube = max(distance_min, d_tube) """ Verify: I. the size of output array II. if the output is binary-valued III. minimum distance between 0-valued points and the polyline is greater than radius IV. maximum distance between 1-valued points and the polyline is less than or equal to radius """ assert labels.shape == shape assert np.unique(labels).all() in [0, 1] assert d_bg > radius**2 assert d_tube <= radius**2
def test_tubes_from_paths_bad_inputs(): """Tests that the tubes_from_paths method raises errors when given bad inputs.""" sess = NeuroglancerSession(url, 0, url_seg) img, bbox, verts = sess.pull_voxel(2, 300, radius=5) # A valid bbox with data. G_paths = sess.get_segments(2, bbox) G = G_paths[0] paths = G_paths[1] # valid paths bbox = bbox.to_list() size = np.subtract(bbox[3:], bbox[:3]) with pytest.raises(TypeError): tube_seg.tubes_from_paths("asdf", paths) with pytest.raises(ValueError): tube_seg.tubes_from_paths((-1, -1, -1), paths) with pytest.raises(TypeError): tube_seg.tubes_from_paths(size, "asdf") with pytest.raises(TypeError): tube_seg.tubes_from_paths(size, [[0, 0, "asdf"]]) with pytest.raises(TypeError): tube_seg.tubes_from_paths(size, paths, radius="asdf") with pytest.raises(ValueError): tube_seg.tubes_from_paths(size, paths, radius=-1)
def test_draw_sphere(): """ Test if the function maps all the points located within the given radius of the given center to 1, otherwise 0 The output array should have the same size of input image and binary values Distance between a point and the given center: <= radius (if the point has value 1) > radius (if the point has value 0) """ ngl_session = NeuroglancerSession(url=url, url_segments=url_seg) img, _, _ = ngl_session.pull_vertex_list(2, [4], expand=True) shape = img.shape center = [ np.random.randint(shape[0]), np.random.randint(shape[1]), np.random.randint(shape[2]), ] radius = np.random.randint(1, 4) sphere = tube_seg.draw_sphere(shape, center, radius) coords = np.where(sphere < 1) d_bg = min(np.sum((np.array(coords).T - center)**2, axis=1)) coords = np.where(sphere > 0) d_s = max(np.sum((np.array(coords).T - center)**2, axis=1)) """ Verify: I. the size of output array II. if the output is binary-valued III. minimum distance between 0-valued points and the center is greater than radius IV. maximum distance between 1-valued points and the center is less than or equal to radius """ assert sphere.shape == shape assert np.unique(sphere).all() in [0, 1] assert d_bg > radius**2 assert d_s <= radius**2
def test_NeuroglancerSession_bad_inputs(vars_local): """Tests that errors are raised when bad inputs are given to initializing session.NeuroglancerSession.""" _, url, url_seg, mip, seg_id, v_id = vars_local with pytest.raises(TypeError): NeuroglancerSession(url=0) with pytest.raises(NotImplementedError): NeuroglancerSession(url="asdf") with pytest.raises(TypeError): NeuroglancerSession(url=url, mip=1.5) with pytest.raises(ValueError): NeuroglancerSession(url=url, mip=-1) with pytest.raises(ValueError): NeuroglancerSession(url=url, mip=100) with pytest.raises(TypeError): NeuroglancerSession(url, url_segments=0) with pytest.raises(NotImplementedError): NeuroglancerSession(url, url_segments="asdf")
def test_pull_v_list(): url = "s3://mouse-light-viz/precomputed_volumes/brain1" ngl = NeuroglancerSession(url, mip=4, url_segments=url + "_segments") img, bounds, voxel = ngl.pull_vertex_list(2, np.arange(10)) assert True
def fit( self, seg_ids, num_verts=None, file_path=None, batch_size=10000, start_seg=None, start_vert=0, include_neighborhood=False, n_jobs=1, ): """ Pulls image and background. Parameters ---------- seg_ids : list of ints A list of segment indices. num_verts : int, optional (default=None) If not none, only runs on a set number of vertices. file_path : str If not none, then the extracted data will be written directly into a feather binary file. The file_path specifies the prefix of the file. batch_size : int Size of each batch of data to be loaded/written. Is only used when file_path is not none. start_seg : int Specifies which segment in the seg_ids list to start at. start_vert : int Specifies which vertex of the first seg_id to start at include_neighborhood : boolean If extracting linear features, specifies if the general neighborhood should be extracted as well. n_jobs : int Number of cores to use. -1 to use all available cores. Returns ------- df : ndarray A dataframe of data. """ voxel_dict = {} counter = 0 batch_id = 0 ngl = NeuroglancerSession(self.url, segment_url=self.segment_url) # if self.segment_url is None: # ngl_skel = NeuroglancerSession(self.url) # else: # ngl_skel = NeuroglancerSession(self.url, self.segment_url) if start_seg is not None: seg_ids = seg_ids[seg_ids.index(start_seg):] if file_path is None: return self._serial_processing(seg_ids, ngl, num_verts, start_vert, include_neighborhood) else: if n_jobs == 1: self._serial_processing( seg_ids, ngl, num_verts, start_vert, include_neighborhood, True, batch_size, file_path, ) else: start_vertices = [0] * len(seg_ids) start_vertices[0] = start_vert par = Parallel(n_jobs=n_jobs) par( delayed(self._parallel_processing)( seg_id, ngl, ngl_skel, num_verts, start_vertices[i], include_neighborhood, batch_size, file_path, ) for i, seg_id in enumerate(seg_ids))
def fit( self, seg_ids: List[int], num_verts: Optional[int] = None, file_path: Optional[str] = None, batch_size: int = 10000, start_seg: Optional[int] = None, start_vert: int = 0, include_neighborhood: bool = False, n_jobs: int = 1, ) -> np.ndarray: """Pulls image and background. Arguments: seg_ids: A list of segment indices. num_verts: If not None, only runs on a set number of vertices. Defaults to None. file_path: If not None, then the extracted data will be written directly into a feather binary file. The file_path specifies the prefix of the file. Defaults to None. batch_size: Size of each batch of data to be loaded/written. Only used when file_path is not none. Default 10000. start_seg: Specifies which segment in the seg_ids list to start at. Default 0. start_vert: Specifies which vertex of the first seg_id to start at. Default 0. include_neighborhood: If extracting linear features, specifies if the general neighborhood should be extracted as well. Defaults to False. n_jobs: Number of cores to use. -1 to use all available cores. Defaults to 1. Returns: df: A dataframe of data containing [segment, vertex, label, f_1, f_2, ..., f_d] columns. """ check_iterable_type(seg_ids, (int, np.integer)) if num_verts is not None: check_type(num_verts, (int, np.integer)) if file_path is not None: check_type(file_path, str) check_type(batch_size, (int, np.integer)) if batch_size < 1: raise ValueError( f"Batch size {batch_size} should not be negative.") if start_seg is not None: check_type(start_seg, (int, np.integer)) if start_seg < 0: raise ValueError( f"Starting segment {start_seg} should not be negative.") check_type(start_vert, (int, np.integer)) if start_vert < 0: raise ValueError( f"Starting vertex {start_vert} should not be negative.") check_type(include_neighborhood, bool) check_type(n_jobs, (int, np.integer)) if n_jobs < 1: raise ValueError(f"Number of jobs {n_jobs} should be positive.") voxel_dict = {} counter = 0 batch_id = 0 ngl = NeuroglancerSession(self.url, url_segments=self.segment_url) # ngl.cv.progress = False ngl.cv_segments.progress = False # if self.segment_url is None: # ngl_skel = NeuroglancerSession(self.url) # else: # ngl_skel = NeuroglancerSession(self.url, self.segment_url) if start_seg is not None: seg_ids = seg_ids[seg_ids.index(start_seg):] if file_path is None: return self._serial_processing(seg_ids, ngl, num_verts, start_vert, include_neighborhood) else: if n_jobs == 1: self._serial_processing( seg_ids, ngl, num_verts, start_vert, include_neighborhood, True, batch_size, file_path, ) else: start_vertices = [0] * len(seg_ids) start_vertices[0] = start_vert par = Parallel(n_jobs=n_jobs) par( delayed(self._parallel_processing)( seg_id, ngl, ngl_skel, num_verts, start_vertices[i], include_neighborhood, batch_size, file_path, ) for i, seg_id in enumerate(seg_ids))
def session(vars_local): # using local vars _, url, url_seg, mip, seg_id, v_id = vars_local sess = NeuroglancerSession(url=url, mip=mip, url_segments=url_seg) return sess, seg_id, v_id
df_voxel_s3 = swc.swc_to_voxel(df_s3, spacing=spacing, origin=np.array([0, 0, 0])) # convert from dataframe to directed graph G = swc.df_to_graph(df_voxel=df_voxel) G_s3 = swc.df_to_graph(df_voxel=df_voxel_s3) # convert directed graph into list of paths paths = swc.graph_to_paths(G) paths_s3 = swc.graph_to_paths(G_s3) # create a subset of the dataframe url = "s3://mouse-light-viz/precomputed_volumes/brain1_lowres" mip = 1 ngl = NeuroglancerSession(url, mip=mip, url_segments=url + "_segments") buffer = [10, 10, 10] subneuron_df = df_s3[0:5] vertex_list = subneuron_df["sample"].array img, bounds, vox_in_img_list = ngl.pull_vertex_list(2, vertex_list, buffer=buffer, expand=True) df_s3_subset = swc.generate_df_subset(df_s3[0:5], vox_in_img_list) def test_read_s3_dataframe(): """test if output is correct type (pd.DataFrame)""" try: assert isinstance(df_s3, pd.DataFrame) except:
def test_pull(): url = "s3://mouse-light-viz/precomputed_volumes/brain1" ngl = NeuroglancerSession(url, mip=4, url_segments=url + "_segments") img, bounds, voxel = ngl.pull_voxel(2, 300) img2 = ngl.pull_bounds_img(bounds) assert np.all(np.squeeze(np.array(img)) == np.squeeze(np.array(img2)))
def test_session_no_urls(vars_local): """Tests that initializing a NeuroglancerSession object without passing urls is valid.""" _, url, url_seg, mip, _, _ = vars_local NeuroglancerSession(url) NeuroglancerSession(url, url_segments=url_seg)