def test_FiberGroup_unique_coords(): """ Test class method Fiber.unique_coords """ for x in range(1000): x1 = np.random.randn() x2 = np.random.randn() y1 = np.random.randn() y2 = np.random.randn() z1 = np.random.randn() z2 = np.random.randn() # So the next line isn't too long: npta = npt.assert_almost_equal # Should work if both fibers have non-unique coords npta(mtf.FiberGroup([ mtf.Fiber([[x1, x1, x2], [y1, y1, y2], [z1, z1, z2]]), mtf.Fiber([[x1, x1, x2], [y1, y1, y2], [z1, z1, z2]]) ]).unique_coords, np.array([[x1, x2], [y1, y2], [z1, z2]]), decimal=4) # And also for extracting across fibers with unique coords npta(mtf.FiberGroup( [mtf.Fiber([[x1], [y1], [z1]]), mtf.Fiber([[x2], [y2], [z2]])]).unique_coords, np.array([[x1, x2], [y1, y2], [z1, z2]]), decimal=4) # And also for extracting across shared coords npta(mtf.FiberGroup([ mtf.Fiber([[x1], [y1], [z1]]), mtf.Fiber([[x2, x1], [y2, y1], [z2, z1]]) ]).unique_coords, np.array([[x1, x2], [y1, y2], [z1, z2]]), decimal=4)
def test_FiberGroup_xform(): """ Test affine transformation method of FiberGroup """ # This affine rotates vectors 90 degrees around the x axis: pi_2 = np.pi / 2 affine1 = np.matrix([[1, 0, 0, 0], [0, np.cos(pi_2), -np.sin(pi_2), 0], [0, np.sin(pi_2), np.cos(pi_2), 0], [0, 0, 0, 1]]) y = [0, 0, 1] x = [0, 1, 0] f1 = mtf.Fiber(x, affine=affine1) f2 = mtf.Fiber(y, affine=affine1) fg1 = mtf.FiberGroup([f1, f2]) fg1.xform() # The first fiber's coordinates should be like the second one originally: npt.assert_almost_equal(fg1.fibers[0].coords, y) f3 = mtf.Fiber(x) f4 = mtf.Fiber(y) fg2 = mtf.FiberGroup([f3, f4], affine=affine1) fg2.xform() # Same should be true when the affine is associated with the FiberGroup: npt.assert_almost_equal(fg2.fibers[0].coords, y) # And the transformtation should have mutated the original object: npt.assert_almost_equal(f3.coords, y) f5 = mtf.Fiber(x) f6 = mtf.Fiber(y) fg3 = mtf.FiberGroup([f5, f6]) fg3.xform(affine1) # Same should be true when the affine is provided as input: npt.assert_almost_equal(fg3.fibers[0].coords, y) # And the transformtation should have mutated the original object: npt.assert_almost_equal(f5.coords, y) # This also attaches the inverse of this affine to the original object, so # that you can always find your way back: npt.assert_almost_equal(f5.affine, affine1.getI()) f7 = mtf.Fiber(x) f8 = mtf.Fiber(y) fg4 = mtf.FiberGroup([f7, f8]) fg4.xform() npt.assert_equal(fg4.affine, None) # The affine should 'stick': fg4.xform(np.eye(4)) npt.assert_equal(fg4.affine, np.eye(4)) # Even to the fibers: npt.assert_equal(f8.affine, np.eye(4))
def fg_from_trk(trk_file, affine=None): """ Read data from a trackvis .trk file and create a FiberGroup object according to the information in it. """ # Generate right away, since we're going to do it anyway: read_trk = tv.read(trk_file, as_generator=False) fibers_trk = read_trk[0] # Per default read from the affine from the file header: if affine is not None: aff = affine else: hdr = read_trk[1] aff = tv.aff_from_hdr(hdr) # If the header contains a bogus affine, we revert to np.eye(4), so we # don't get into trouble later: try: np.matrix(aff).getI() except np.linalg.LinAlgError: e_s = "trk file contains bogus header, reverting to np.eye(4)" warnings.warn(e_s) aff = np.eye(4) fibers = [] for f in fibers_trk: fibers.append(ozf.Fiber(np.array(f[0]).T, affine=aff)) return ozf.FiberGroup(fibers, affine=aff)
def test_pdb_from_fg(): """ Test writing a fiber-group to file """ coords1 = np.arange(900).reshape(3, 300) coords2 = np.arange(900).reshape(3, 300) + 100 fiber_stats = dict(foo=1, bar=2) node_stats = dict(ecc=np.arange(300)) fg = mtf.FiberGroup([ mtf.Fiber(coords1, fiber_stats=fiber_stats, node_stats=node_stats), mtf.Fiber(coords2, fiber_stats=fiber_stats, node_stats=node_stats) ]) temp_dir = tempfile.gettempdir() mio.pdb_from_fg(fg, os.path.join(temp_dir, 'fg.pdb')) # Test that the properties are preserved upon reloading: fg2 = mio.fg_from_pdb(os.path.join(temp_dir, 'fg.pdb')) npt.assert_equal(fg2[0].coords, fg[0].coords) npt.assert_equal(fg2[1].coords, fg[1].coords) npt.assert_equal(fg2[0].node_stats, fg[0].node_stats) npt.assert_equal(fg2[1].node_stats, fg[1].node_stats) npt.assert_equal(fg2.fiber_stats, fg.fiber_stats)
def test_FiberGroup(): """ Testing intialization of FiberGroup class. """ arr2d = np.array([[1, 2], [3, 4], [5, 6]]) arr1d = np.array([5, 6, 7]) f1 = mtf.Fiber(arr2d, fiber_stats=dict(a=1, b=2)) f2 = mtf.Fiber(arr1d, fiber_stats=dict(a=1)) fg1 = mtf.FiberGroup([f1, f2]) npt.assert_equal(fg1.n_fibers, 2) # We have to sort, because it could also come out as ['b', 'a']: npt.assert_equal(np.sort(fg1.fiber_stats.keys()), ['a', 'b']) # The number of nodes is just the sum of nodes/fiber: npt.assert_equal(fg1.n_nodes, f1.n_nodes + f2.n_nodes)
def fg_from_pdb(file_name, verbose=True): """ Read the definition of a fiber-group from a .pdb file Parameters ---------- file_name: str Full path to the .pdb file Returns ------- A FiberGroup object Note ---- This only reads Version 3 PDB. For the full file-format spec, see the osmosis.io module top-level docstring """ # Read the file as binary info: f_obj = file(file_name, 'r') f_read = f_obj.read() f_obj.close() # This is an updatable index into this read: idx = 0 # First part is an int encoding the offset to the fiber part: offset, idx = _unpacker(f_read, idx, 1) # Next bit are doubles, encoding the xform (4 by 4 = 16 of them): xform, idx = _unpacker(f_read, idx, 16, 'double') xform = np.reshape(xform, (4, 4)) # Next is an int encoding the number of stats: numstats, idx = _unpacker(f_read, idx, 1) # The stats header is a dict with lists holding the stat per stats_header = dict( luminance_encoding=[], # int => bool computed_per_point=[], # int => bool viewable=[], # int => bool agg_name=[], # char array => string local_name=[], # char array => string uid=[] # int ) # Read the stats header: counter = 0 while counter < numstats: counter += 1 for k in ["luminance_encoding", "computed_per_point", "viewable"]: this, idx = _unpacker(f_read, idx, 1) stats_header[k].append(np.bool(this)) for k in ["agg_name", "local_name"]: this, idx = _unpacker(f_read, idx, 255, 'char') stats_header[k].append(_word_maker(this)) # Must have integer reads be word aligned (?): idx += 2 this, idx = _unpacker(f_read, idx, 1) stats_header["uid"].append(this) # We skip the whole bit with the algorithms and go straight to the version # number, which is one int length before the fibers: idx = offset - 4 version, idx = _unpacker(f_read, idx, 1) if int(version) < 2: raise ValueError("Can only read PDB version 2 or version 3 files") elif verbose: print("Loading a PDB version %s file from: %s" % (int(version), file_name)) if int(version) == 2: idx = offset # How many fibers? numpaths, idx = _unpacker(f_read, idx, 1) if int(version) == 2: pts = [] if verbose: prog_bar = ProgressBar(numpaths[0]) f_name = inspect.stack()[0][3] f_stats = [] n_stats = [] for p_idx in range(numpaths): f_stats_dict = {} n_stats_dict = {} # Keep track of where you are right now ppos = idx path_offset, idx = _unpacker(f_read, idx, 1) n_nodes, idx = _unpacker(f_read, idx, 1) # As far as I can tell the following two don't matter much: algo_type, idx = _unpacker(f_read, idx, 1) seed_pt_idx, idx = _unpacker(f_read, idx, 1) # Read out the per-path stats: for stat_idx in range(numstats): per_fiber_stat, idx = _unpacker(f_read, idx, 1, 'double') f_stats_dict[stats_header["local_name"][stat_idx]] = \ per_fiber_stat f_stats.append(f_stats_dict) # Skip forward to where the paths themselves are: idx = ppos # Read the nodes: pathways, idx = _unpacker(f_read, idx, n_nodes * 3, 'double') pts.append(np.reshape(pathways, (n_nodes, 3)).T) for stat_idx in range(numstats): if stats_header["computed_per_point"][stat_idx]: name = stats_header["local_name"][stat_idx] n_stats_dict[name], idx = _unpacker( f_read, idx, n_nodes, 'double') n_stats.append(n_stats_dict) fibers = [] # Initialize all the fibers: for p_idx in range(numpaths): this_fstats_dict = f_stats[p_idx] f_stat_k = this_fstats_dict.keys() f_stat_v = [this_fstats_dict[k] for k in f_stat_k] this_nstats_dict = n_stats[p_idx] n_stats_k = this_nstats_dict.keys() n_stats_v = [this_nstats_dict[k] for k in n_stats_k] fibers.append( ozf.Fiber(pts[p_idx], xform, fiber_stats=dict(zip(f_stat_k, f_stat_v)), node_stats=dict(zip(n_stats_k, n_stats_v)))) elif int(version) == 3: # The next few bytes encode the number of points in each fiber: pts_per_fiber, idx = _unpacker(f_read, idx, numpaths) total_pts = np.sum(pts_per_fiber) # Next we have the xyz coords of the nodes in all fibers: fiber_pts, idx = _unpacker(f_read, idx, total_pts * 3, 'double') # We extract the information on a fiber-by-fiber basis pts_read = 0 pts = [] if verbose: prog_bar = ProgressBar(numpaths[0]) f_name = inspect.stack()[0][3] for p_idx in range(numpaths): n_nodes = pts_per_fiber[p_idx] pts.append( np.reshape(fiber_pts[pts_read * 3:(pts_read + n_nodes) * 3], (n_nodes, 3)).T) pts_read += n_nodes if verbose: prog_bar.animate(p_idx, f_name=f_name) f_stats_dict = {} for stat_idx in range(numstats): per_fiber_stat, idx = _unpacker(f_read, idx, numpaths, 'double') # This is a fiber-stat only if it's not computed per point: if not stats_header["computed_per_point"][stat_idx]: f_stats_dict[stats_header["local_name"][stat_idx]] =\ per_fiber_stat per_point_stat = [] n_stats_dict = {} for stat_idx in range(numstats): pts_read = 0 # If it is computer per point, it's a node-stat: if stats_header["computed_per_point"][stat_idx]: name = stats_header["local_name"][stat_idx] n_stats_dict[name] = [] per_point_stat, idx = _unpacker(f_read, idx, total_pts, 'double') for p_idx in range(numpaths): n_stats_dict[name].append( per_point_stat[pts_read:pts_read + pts_per_fiber[p_idx]]) pts_read += pts_per_fiber[p_idx] else: per_point_stat.append([]) fibers = [] # Initialize all the fibers: for p_idx in range(numpaths): f_stat_k = f_stats_dict.keys() f_stat_v = [f_stats_dict[k][p_idx] for k in f_stat_k] n_stats_k = n_stats_dict.keys() n_stats_v = [n_stats_dict[k][p_idx] for k in n_stats_k] fibers.append( ozf.Fiber(pts[p_idx], xform, fiber_stats=dict(zip(f_stat_k, f_stat_v)), node_stats=dict(zip(n_stats_k, n_stats_v)))) if verbose: print("Done reading from file") name = os.path.split(file_name)[-1].split('.')[0] return ozf.FiberGroup(fibers, name=name, affine=xform)