def main(): parser = _build_arg_parser() args = parser.parse_args() assert_inputs_exist(parser, [args.tractogram]) assert_outputs_exist(parser, args, [], [args.save]) tracts_format = detect_format(args.tractogram) if tracts_format is not TrkFile: raise ValueError("Invalid input streamline file format " + "(must be trk): {0}".format(args.tractogram_filename)) # Load files and data. TRKs can have 'same' as reference tractogram = load_tractogram(args.tractogram, 'same') # Streamlines are saved in RASMM but seeds are saved in VOX # This might produce weird behavior with non-iso tractogram.to_vox() streamlines = tractogram.streamlines if 'seeds' not in tractogram.data_per_streamline: parser.error('Tractogram does not contain seeds') seeds = tractogram.data_per_streamline['seeds'] # Make display objects streamlines_actor = actor.line(streamlines) points = actor.dots(seeds, color=(1., 1., 1.)) # Add display objects to canvas s = window.Scene() s.add(streamlines_actor) s.add(points) # Show and record if needed if args.save is not None: window.record(s, out_path=args.save, size=(1000, 1000)) window.show(s)
def main(): parser = _build_args_parser() args = parser.parse_args() assert_inputs_exist(parser, [args.tractogram]) assert_outputs_exist(parser, args, [], [args.save]) tracts_format = detect_format(args.tractogram) if tracts_format is not TrkFile: raise ValueError("Invalid input streamline file format " + "(must be trk): {0}".format(args.tractogram_filename)) # Load files and data trk = TrkFile.load(args.tractogram) tractogram = trk.tractogram streamlines = tractogram.streamlines if 'seeds' not in tractogram.data_per_streamline: parser.error('Tractogram does not contain seeds') seeds = tractogram.data_per_streamline['seeds'] # Make display objects streamlines_actor = actor.line(streamlines) points = actor.dots(seeds, color=(1., 1., 1.)) # Add display objects to canvas r = window.Renderer() r.add(streamlines_actor) r.add(points) # Show and record if needed if args.save is not None: window.record(r, out_path=args.save, size=(1000, 1000)) window.show(r)
def save_tractogram(fname, streamlines, affine, vox_size=None, shape=None, header=None, reduce_memory_usage=False, tractogram_file=None): """ Saves tractogram files (*.trk or *.tck or *.dpy) Parameters ---------- fname : str output trk filename streamlines : list of 2D arrays, generator or ArraySequence Each 2D array represents a sequence of 3D points (points, 3). affine : array_like (4, 4) The mapping from voxel coordinates to streamline points. vox_size : array_like (3,), optional The sizes of the voxels in the reference image (default: None) shape : array, shape (dim,), optional The shape of the reference image (default: None) header : dict, optional Metadata associated to the tractogram file(*.trk). (default: None) reduce_memory_usage : {False, True}, optional If True, save streamlines in a lazy manner i.e. they will not be kept in memory. Otherwise, keep all streamlines in memory until saving. tractogram_file : class TractogramFile, optional Define tractogram class type (TrkFile vs TckFile) Default is None which means auto detect format """ if 'dpy' in os.path.splitext(fname)[1].lower(): dpw = Dpy(fname, 'w') dpw.write_tracks(Streamlines(streamlines)) dpw.close() return tractogram_file = tractogram_file or detect_format(fname) if tractogram_file is None: raise ValueError("Unknown format for 'fname': {}".format(fname)) if vox_size is not None and shape is not None: if not isinstance(header, dict): header = {} header[Field.VOXEL_TO_RASMM] = affine.copy() header[Field.VOXEL_SIZES] = vox_size header[Field.DIMENSIONS] = shape header[Field.VOXEL_ORDER] = "".join(aff2axcodes(affine)) if reduce_memory_usage and not callable(streamlines): sg = lambda: (s for s in streamlines) else: sg = streamlines tractogram_loader = LazyTractogram if reduce_memory_usage else Tractogram tractogram = tractogram_loader(sg) tractogram.affine_to_rasmm = affine track_file = tractogram_file(tractogram, header=header) nib.streamlines.save(track_file, fname)
def create_tractogram_header(tractogram_type, affine, dimensions, voxel_sizes, voxel_order): """ Write a standard trk/tck header from spatial attribute """ if isinstance(tractogram_type, str): tractogram_type = detect_format(tractogram_type) new_header = tractogram_type.create_empty_header() new_header[nib.streamlines.Field.VOXEL_SIZES] = tuple(voxel_sizes) new_header[nib.streamlines.Field.DIMENSIONS] = tuple(dimensions) new_header[nib.streamlines.Field.VOXEL_TO_RASMM] = affine new_header[nib.streamlines.Field.VOXEL_ORDER] = voxel_order return new_header
def main(): parser = _build_arg_parser() args = parser.parse_args() assert_inputs_exist(parser, [args.tractogram_filename]) assert_outputs_exist(parser, args, [args.seed_density_filename]) tracts_format = detect_format(args.tractogram_filename) if tracts_format is TckFile: raise ValueError("Invalid input streamline file format " + "(must be trk): {0}".format(args.tractogram_filename)) max_ = np.iinfo(np.int16).max if args.binary is not None and (args.binary <= 0 or args.binary > max_): parser.error( 'The value of --binary ({}) ' 'must be greater than 0 and smaller or equal to {}'.format( args.binary, max_)) # Load tractogram and load seeds tracts_file = load(args.tractogram_filename, args.lazy_load) if 'seeds' in tracts_file.tractogram.data_per_streamline: seeds = tracts_file.tractogram.data_per_streamline['seeds'] else: parser.error('Tractogram does not contain seeds') # Transform seeds if they're all in memory if not args.lazy_load: seeds = apply_affine(np.linalg.inv(tracts_file.affine), seeds) # Create seed density map shape = tracts_file.header[Field.DIMENSIONS] seed_density = np.zeros(shape, dtype=np.int32) for seed in seeds: # If seeds are lazily loaded, we have to transform them # as they get loaded if args.lazy_load: seed = apply_affine(np.linalg.inv(tracts_file.affine), seed) # Set value at mask, either binary or increment seed_voxel = np.round(seed).astype(np.int) if args.binary is not None: seed_density[tuple(seed_voxel)] = args.binary else: seed_density[tuple(seed_voxel)] += 1 # Save seed density map dm_img = Nifti1Image(seed_density.astype(np.int32), tracts_file.affine) dm_img.to_filename(args.seed_density_filename)
def main(): parser = _build_arg_parser() args = parser.parse_args() assert_inputs_exist(parser, [args.tractogram_filename]) assert_outputs_exist(parser, args, [args.seed_density_filename]) tracts_format = detect_format(args.tractogram_filename) if tracts_format is not TrkFile: raise ValueError("Invalid input streamline file format " + "(must be trk): {0}".format(args.tractogram_filename)) max_ = np.iinfo(np.int16).max if args.binary is not None and (args.binary <= 0 or args.binary > max_): parser.error( 'The value of --binary ({}) ' 'must be greater than 0 and smaller or equal to {}'.format( args.binary, max_)) # Load files and data. TRKs can have 'same' as reference # Can handle streamlines outside of bbox sft = load_tractogram(args.tractogram_filename, 'same', bbox_valid_check=False) # Streamlines are saved in RASMM but seeds are saved in VOX # This might produce weird behavior with non-iso sft.to_vox() sft.to_corner() if 'seeds' in sft.data_per_streamline: seeds = sft.data_per_streamline['seeds'] else: parser.error('Tractogram does not contain seeds') # Create seed density map _, shape, _, _ = sft.space_attributes seed_density = np.zeros(shape, dtype=np.int32) for seed in seeds: # Set value at mask, either binary or increment seed_voxel = np.round(seed).astype(int) if args.binary is not None: seed_density[tuple(seed_voxel)] = args.binary else: seed_density[tuple(seed_voxel)] += 1 # Save seed density map dm_img = Nifti1Image(seed_density.astype(np.int32), sft.affine) dm_img.to_filename(args.seed_density_filename)
def save_tractogram(sft, filename, bbox_valid_check=True): """ Save the stateful tractogram in any format (trk, tck, vtk, fib, dpy) Parameters ---------- sft : StatefulTractogram The stateful tractogram to save filename : string Filename with valid extension bbox_valid_check : bool Verification for negative voxel coordinates or values above the volume dimensions. Default is True, to enforce valid file. Returns ------- output : bool True if the saving operation was successful """ _, extension = os.path.splitext(filename) if extension not in ['.trk', '.tck', '.vtk', '.fib', '.dpy']: raise TypeError('Output filename is not one of the supported format') if bbox_valid_check and not sft.is_bbox_in_vox_valid(): raise ValueError('Bounding box is not valid in voxel space, cannot ' + 'load a valid file if some coordinates are ' + 'invalid. Please use the function ' + 'remove_invalid_streamlines to discard invalid ' + 'streamlines or set bbox_valid_check to False') old_space = deepcopy(sft.space) old_shift = deepcopy(sft.shifted_origin) sft.to_rasmm() sft.to_center() timer = time.time() if extension in ['.trk', '.tck']: tractogram_type = detect_format(filename) header = create_tractogram_header(tractogram_type, *sft.space_attributes) new_tractogram = Tractogram(sft.streamlines, affine_to_rasmm=np.eye(4)) if extension == '.trk': new_tractogram.data_per_point = sft.data_per_point new_tractogram.data_per_streamline = sft.data_per_streamline fileobj = tractogram_type(new_tractogram, header=header) nib.streamlines.save(fileobj, filename) elif extension in ['.vtk', '.fib']: save_vtk_streamlines(sft.streamlines, filename, binary=True) elif extension in ['.dpy']: dpy_obj = Dpy(filename, mode='w') dpy_obj.write_tracks(sft.streamlines) dpy_obj.close() logging.debug('Save %s with %s streamlines in %s seconds', filename, len(sft), round(time.time() - timer, 3)) if old_space == Space.VOX: sft.to_vox() elif old_space == Space.VOXMM: sft.to_voxmm() if old_shift: sft.to_corner() return True
def save_tractogram(sft, filename, bbox_valid_check=True): """ Save the stateful tractogram in any format (trk, tck, vtk, fib, dpy) Parameters ---------- sft : StatefulTractogram The stateful tractogram to save filename : string Filename with valid extension Returns ------- output : bool Did the saving work properly """ _, extension = os.path.splitext(filename) if extension not in ['.trk', '.tck', '.vtk', '.fib', '.dpy']: TypeError('Output filename is not one of the supported format') if bbox_valid_check and not sft.is_bbox_in_vox_valid(): raise ValueError('Bounding box is not valid in voxel space, cannot ' + 'save a valid file if some coordinates are invalid') old_space = deepcopy(sft.space) old_shift = deepcopy(sft.shifted_origin) sft.to_rasmm() sft.to_center() timer = time.time() if extension in ['.trk', '.tck']: tractogram_type = detect_format(filename) header = create_tractogram_header(tractogram_type, *sft.space_attribute) new_tractogram = Tractogram(sft.streamlines, affine_to_rasmm=np.eye(4)) if extension == '.trk': new_tractogram.data_per_point = sft.data_per_point new_tractogram.data_per_streamline = sft.data_per_streamline fileobj = tractogram_type(new_tractogram, header=header) nib.streamlines.save(fileobj, filename) elif extension in ['.vtk', '.fib']: save_vtk_streamlines(sft.streamlines, filename, binary=True) elif extension in ['.dpy']: dpy_obj = Dpy(filename, mode='w') dpy_obj.write_tracks(sft.streamlines) dpy_obj.close() logging.debug('Save %s with %s streamlines in %s seconds', filename, len(sft), round(time.time() - timer, 3)) if old_space == Space.VOX: sft.to_vox() elif old_space == Space.VOXMM: sft.to_voxmm() if old_shift: sft.to_corner() return True