def _test(): """Tests""" import ClearMap.Settings as settings import ClearMap.IO.IO as io import ClearMap.Visualization.Plot3d as p3d; import ClearMap.Alignment.Resampling as res from importlib import reload reload(res) r = res.resample_shape(source_shape=(100,200,300), sink_shape=(50,50,30)); print('resampled source_shape=%r, sink_shape=%r, source_resolution=%r, sink_resolution=%r' % r) r = res.resample_shape(source_shape=(100,200,300), source_resolution=(2,2,2), sink_resolution=(10,2,1)) print('resampled source_shape=%r, sink_shape=%r, source_resolution=%r, sink_resolution=%r' % r) source = io.join(settings.test_data_path, 'Resampling/test.tif') sink = io.join(settings.test_data_path, "Resampling/resampled.npy") source = io.join(settings.test_data_path, 'Tif/sequence/sequence<Z,4>.tif') sink = io.join(settings.test_data_path, "Resampling/resampled_sequence.tif") source_shape, sink_shape, source_res, sink_res = res.resample_shape(source_shape=io.shape(source), source_resolution=(1.,1.,1.), sink_resolution=(1.6,1.6,2)) axes_order = res._axes_order(None, source_shape, sink_shape); print(axes_order) resampled = res.resample(source, sink, source_resolution=(1.,1.,1.), sink_resolution = (1.6,1.6,2), orientation=None, processes=None); p3d.plot(resampled) p3d.plot(source) inverse = res.resample_inverse(resampled, sink=None, resample_source=source, source_resolution=(1,1,1), sink_resolution = (10,10,2), orientation=None, processes='serial') p3d.plot([source, inverse]) resampled = res.resample(source, sink, source_resolution=(1,1,1), sink_resolution = (10,10,2), orientation=(2,-1,3), processes=None); p3d.plot(resampled) inverse = res.resample_inverse(resampled, sink=None, resample_source=source, source_resolution=(1,1,1), sink_resolution = (10,10,2), orientation=(2,-1,3), processes=None) p3d.plot([source, inverse]) resampled = res.resample(source, sink=None, source_resolution=(1.6,1.6,2), sink_shape=(10,20,30), orientation=None, processes=None) p3d.plot(resampled) # ponints points = res.np.array([[0,0,0], [1,1,1], [1,2,3]], dtype=float); resampled_points = res.resample_points(points, resample_source=source , resample_sink=sink, orientation=None) print(resampled_points) inverse_points = res.resample_points_inverse(resampled_points, resample_source=source , resample_sink=sink, orientation=None) print(inverse_points) print(res.np.allclose(points, inverse_points))
def graph_to_skeleton(graph, sink = None, dtype = bool): """Create a binary skeleton from a graph.""" if not graph.has_edge_geometry(): coordinates = graph.vertex_coordinates(); else: coordinates = graph.edge_geometry('coordinates'); coordinates = np.vstack(coordinates); if sink is None: shape = graph.shape; if shape is None: shape = tuple(np.max(coordinates, axis = 0)); sink = np.zeros(shape, dtype=dtype); shape = io.shape(sink); coordinates = list(coordinates.T); sink[coordinates] = True; return sink;
def detect_cells( source, sink=None, cell_detection_parameter=default_cell_detection_parameter, processing_parameter=default_cell_detection_processing_parameter): """Cell detection pipeline. Arguments --------- source : source specification The source of the stitched raw data. sink : sink specification or None The sink to write the result to. If None, an array is returned. cell_detection_parameter : dict Parameter for the binarization. See below for details. processing_parameter : dict Parameter for the parallel processing. See :func:`ClearMap.ParallelProcessing.BlockProcesing.process` for description of all the parameter. verbose : bool If True, print progress output. Returns ------- sink : Source The result of the cell detection. Notes ----- Effectively this function performs the following steps: * illumination correction via :func:`~ClearMap.ImageProcessing.IlluminationCorrection.correct_illumination` * background removal * difference of Gaussians (DoG) filter * maxima detection via :func:`~ClearMap.Analysis.Measurements.MaximaDetection.find_extended_maxima` * cell shape detection via :func:`~ClearMap.Analysis.Measurements.ShapeDetection.detect_shape` * cell intensity and size measurements via: :func:`~ClearMap.ImageProcessing.Measurements.ShapeDetection.find_intensity`, :func:`~ClearMap.ImageProcessing.Measurements.ShapeDetection.find_size`. The parameters for each step are passed as sub-dictionaries to the cell_detection_parameter dictionary. * If None is passed for one of the steps this step is skipped. * Each step also has an additional parameter 'save' that enables saving of the result of that step to a file to inspect the pipeline. Illumination correction ----------------------- illumination_correction : dict or None Illumination correction step parameter. flatfield : array or str The flat field estimate for the image planes. background : array or None A background level to assume for the flatfield correction. scaling : float, 'max', 'mean' or None Optional scaling after the flat field correction. save : str or None Save the result of this step to the specified file if not None. See also :func:`ClearMap.ImageProcessing.IlluminationCorrection.correct_illumination` Background removal ------------------ background_correction : dict or None Background removal step parameter. shape : tuple The shape of the structure lement to estimate the background. This should be larger than the typical cell size. form : str The form of the structur element (e.g. 'Disk') save : str or None Save the result of this step to the specified file if not None. Equalization ------------ equalization : dict or None Equalization step parameter. See also :func:`ClearMap.ImageProcessing.LocalStatistics.local_percentile` precentile : tuple The lower and upper percentiles used to estimate the equalization. The lower percentile is used for normalization, the upper to limit the maximal boost to a maximal intensity above this percentile. max_value : float The maximal intensity value in the equalized image. selem : tuple The structural element size to estimate the percentiles. Should be larger than the larger vessels. spacing : tuple The spacing used to move the structural elements. Larger spacings speed up processing but become locally less precise. interpolate : int The order of the interpoltation used in constructing the full background estimate in case a non-trivial spacing is used. save : str or None Save the result of this step to the specified file if not None. DoG Filter ---------- dog_filter : dict or None Difference of Gaussian filter step parameter. shape : tuple The shape of the filter. This should be near the typical cell size. sigma : tuple or None The std of the inner Gaussian. If None, detemined automatically from shape. sigma2 : tuple or None The std of the outer Gaussian. If None, detemined automatically from shape. save : str or None Save the result of this step to the specified file if not None. Maxima detection ---------------- maxima_detection : dict or None Extended maxima detection step parameter. h_max : float or None The 'height'for the extended maxima. If None, simple local maxima detection isused. shape : tuple The shape of the structural element for extended maxima detection. This should be near the typical cell size. threshold : float or None Only maxima above this threshold are detected. If None, all maxima are detected. valid : bool If True, only detect cell centers in the valid range of the blocks with overlap. save : str or None Save the result of this step to the specified file if not None. Shape detection --------------- shape_detection : dict or None Shape detection step parameter. threshold : float Cell shape is expanded from maxima if pixles are above this threshold and not closer to another maxima. save : str or None Save the result of this step to the specified file if not None. Intensity detection ------------------- intensity_detection : dict or None Intensity detection step parameter. method : {'max'|'min','mean'|'sum'} The method to use to measure the intensity of a cell. shape : tuple or None If no cell shapes are detected a disk of this shape is used to measure the cell intensity. save : str or None Save the result of this step to the specified file if not None. References ---------- [1] Renier, Adams, Kirst, Wu et al., "Mapping of Brain Activity by Automated Volume Analysis of Immediate Early Genes.", Cell 165, 1789 (2016) [1] Kirst et al., "Mapping the Fine-Scale Organization and Plasticity of the Brain Vasculature", Cell 180, 780 (2020) """ #initialize sink shape = io.shape(source) order = io.order(source) for key in cell_detection_parameter.keys(): par = cell_detection_parameter[key] if isinstance(par, dict): filename = par.get('save', None) if filename: ap.initialize_sink(filename, shape=shape, order=order, dtype='float') cell_detection_parameter.update( verbose=processing_parameter.get('verbose', False)) results, blocks = bp.process(detect_cells_block, source, sink=None, function_type='block', return_result=True, return_blocks=True, parameter=cell_detection_parameter, **processing_parameter) #merge results results = np.vstack([np.hstack(r) for r in results]) #create column headers header = ['x', 'y', 'z'] dtypes = [int, int, int] if cell_detection_parameter['shape_detection'] is not None: header += ['size'] dtypes += [int] measures = cell_detection_parameter['intensity_detection']['measure'] header += measures dtypes += [float] * len(measures) dt = { 'names': header, 'formats': dtypes } cells = np.zeros(len(results), dtype=dt) for i, h in enumerate(header): cells[h] = results[:, i] #save results return io.write(sink, cells)
def average(source, sink=None, shape=None, dtype=None, weights=None, indices=None, kernel=None, return_counts=False, processes=None, verbose=False): """Averages a list of points into an volumetric image array. Arguments --------- source : str, array or Source Source of point of nxd coordinates. sink : str, array or None The sink for the devolved image, if None return array. shape : tuple, str or None Shape of the final devolved data. If None, determine from points. If str, determine shape from the source at the specified location. dtype : dtype or None Optional data type of the sink. weights : array or None Weight array of length n for each point. If None, use uniform weights. method : str Method for voxelization: 'sphere', 'rectangle' or 'pixel'. indices : array The relative indices to the center to devolve over as nxd array. kernel : array Optional kernel weights for each index in indices. processes : int or None Number of processes to use. verbose : bool If True, print progress info. Returns ------- sink : str, array Volumetric data of devolved point data. """ processes, timer = ap.initialize_processing(processes=processes, verbose=verbose, function='devolve') #points, points_buffer = ap.initialize_source(points); points_buffer = io.read(source) if points_buffer.ndim == 1: points_buffer = points_buffer[:, None] if sink is None and shape is None: if points_buffer.ndim > 1: shape = tuple( int(math.ceil(points_buffer[:, d].max())) for d in range(points_buffer.shape[1])) else: shape = (int(math.ceil(points_buffer[:].max())), ) elif isinstance(shape, str): shape = io.shape(shape) if sink is None and dtype is None: if weights is not None: dtype = io.dtype(weights) elif kernel is not None: kernel = np.asarray(kernel) dtype = kernel.dtype else: dtype = int sink, sink_buffer, sink_shape, sink_strides = ap.initialize_sink( sink=sink, shape=shape, dtype=dtype, return_shape=True, return_strides=True, as_1d=True) #TODO: initialize properly counts = np.zeros(sink_shape, dtype=int, order=sink.order) counts_buffer = counts.reshape(-1, order='A') #print(counts.shape, counts_buffer.shape) if indices is None: return sink indices = np.asarray(indices, dtype=int) if indices.ndim == 1: indices = indices[:, None] if kernel is not None: kernel = np.asarray(kernel, dtype=float) #print(kernel); #print(weights) #return; code.average(points_buffer, weights, indices, sink_buffer, sink_shape, sink_strides, counts_buffer, processes) # if weights is None: # if kernel is None: # code.devolve_uniform(points_buffer, indices, sink_buffer, sink_shape, sink_strides, processes); # else: # code.devolve_uniform_kernel(points_buffer, indices, kernel, sink_buffer, sink_shape, sink_strides, processes); # else: # if kernel is None: # code.devolve_weights(points_buffer, weights, indices, sink_buffer, sink_shape, sink_strides, processes); # else: # code.devolve_weights_kernel(points_buffer, weights, indices, kernel, sink_buffer, sink_shape, sink_strides, processes); #TODO: move to code good = counts_buffer > 0 sink_buffer[good] /= counts_buffer[good] ap.finalize_processing(verbose=verbose, function='devolve', timer=timer) if return_counts: return sink, counts else: return sink
def resample_points_inverse(source, sink = None, resample_source = None, resample_sink = None, orientation = None, source_shape = None, sink_shape = None, source_resolution = None, sink_resolution = None, **args): """Resample points from original coordiantes to resampled ones. Arguments --------- source : str or array Points to be resampled inversely. sink : str or None Sink for the inversly resmapled points. resample_source : str, array or None Optional source as in :func:`resample`. resample_sink: str, array or None Optional sink used in :func:`resample`. orientation : tuple Orientation as specified in :func:`resample`. source_shape : tuple or None Optional value of source_shape as in :func:`resample`. source_resolution : tuple or None Optional value of source_resolution as in :func:`resample`. sink_resolution : tuple or None Optional value of sink_resolution as in :func:`resample`. Returns ------- resmapled : array or str Sink for the inversly resampled point coordinates. Notes ----- * The resampling of points here corresponds to the inverse resampling of an image in :func:`resample`, i.e. to func:`resample_inverse` * The arguments should be passed exactly as in :func:`resample` except source and sink that point to the point sources. Use resample_source and resmaple_sink to pass the source and sink values used in :func:`resample`. """ #orientation orientation = format_orientation(orientation); #original source info if source_shape is None: if source_resolution is None and resample_source is None: raise ValueError('Either source_shape, source_resolution or resample_source must to be given!') if resample_source is not None: source_shape = io.shape(resample_source); #original sink info if sink_shape is None and sink_resolution is None: if resample_sink is None: sink_shape = io.shape(source); else: sink_shape = io.shape(resample_sink); source_shape, sink_shape, source_resolution, sink_resolution = \ resample_shape(source_shape=source_shape, sink_shape=sink_shape, source_resolution=source_resolution, sink_resolution=sink_resolution, orientation=orientation); sink_shape_in_source_orientation = orient_shape(sink_shape, orientation, inverse=True); resample_factor = [float(t)/float(s) for s,t in zip(source_shape, sink_shape_in_source_orientation)]; points = io.read(source); # reorient points if orientation is not None: #reverse axes reslice = False; slicing = [slice(None)] * len(source_shape); for d,o in enumerate(orientation): if o < 0: slicing[d] = slice(None, None, -1); reslice = True; if reslice: points = points[slicing]; #permute per = orientation_to_permuation(orientation); points = points.transpose(per); points = points[:] / resample_factor; return io.write(sink, points);
def resample_inverse(source, sink = None, resample_source = None, resample_sink = None, orientation = None, source_shape = None, source_resolution = None, sink_shape = None, sink_resolution = None, axes_order = None, method = 'memmap', interpolation = 'linear', processes = None, verbose = True, **args): """Resample data inversely to :func:`resample` routine. Arguments --------- source : str, array Source to be inversly resampled (e.g. sink in :func:`resample`). sink : str or None Sink to write the inversly resampled image to. resample_source : str, array or None Optional source in :func:`resample`. resmaple_sink: str, array or None Optional sink used in :func:`resample`. orientation : tuple Orientation as specified as in :func:`resample`. source_shape : tuple or None Optional value of source_shape as in :func:`resample`. source_resolution : tuple or None Optional value of source_resolution as in :func:`resample`. sink_resolution : tuple or None Optional value of sink_resolution as in :func:`resample`. processing_directory : str or None Optional directory in which to perform resmapling in parallel. If None, a temporary directry will be created. axis_order : list of tuples of int or None The axes pairs along which to resample the data as in :func:`resample`. method : 'shared' or 'memmap' Method to handle intermediate resampling results. If 'shared' use shared memory, otherwise use a memory map on disk. interpolation : str Method to use for interpolating to the resmapled image. processes int or None Number of processes to use for parallel resampling. verbose : bool If True, print progress information. Returns ------- resampled : array or str Data or file name of inversly resampled image. Notes ----- * All arguments, except source and sink should be passed as :func:`resample` to invert the resmapling. """ source = io.as_source(source); ndim = source.ndim; dtype = source.dtype; #orientation orientation = format_orientation(orientation); orientation_inverse = inverse_orientation(orientation); #original source info if source_shape is None: if source_resolution is None and resample_source is None: raise ValueError('Either source_shape, source_resolution or resample_source must to be given!') if resample_source is not None: source_shape = io.shape(resample_source); #original sink info if sink_shape is None and sink_resolution is None: if resample_sink is None: sink_shape = io.shape(source); else: sink_shape = io.shape(resample_sink); source_shape, sink_shape, source_resolution, sink_resolution = \ resample_shape(source_shape=source_shape, sink_shape=sink_shape, source_resolution=source_resolution, sink_resolution=sink_resolution, orientation=orientation); sink_shape_in_source_orientation = orient_shape(sink_shape, orientation, inverse=True); axes_order, shape_order = _axes_order(axes_order, source, source_shape, sink_shape_in_source_orientation); interpolation = _interpolation_to_cv2(interpolation); if processes is None or not processes == 'serial': processes = io.mp.cpu_count(); #reversed orientation if not orientation is None: #reverse axes slicing = [slice(None)] * ndim; reslice = False; for d,o in enumerate(orientation): if o < 0: slicing[d] = slice(None, None, -1); reslice = True; if reslice: source = source[slicing]; #re-orient per = orientation_to_permuation(orientation_inverse); source = io.read(source); source = source.transpose(per); source = io.sma.as_shared(source); #reverse resampling steps axes_order = axes_order[::-1]; shape_order = shape_order[:-1]; shape_order = shape_order[::-1]; shape_order = shape_order + [source_shape] #print(axes_order, shape_order) #reverse resampling n_steps = len(axes_order); last_source = source; delete_files = []; #print(last_source) for step, axes, shape in zip(range(n_steps), axes_order, shape_order): if step == n_steps-1: resampled = io.initialize(source=sink, shape=shape, dtype=dtype, memory='shared', as_source=True); else: if method == 'shared': resampled = io.sma.create(shape, dtype=dtype, order='C', as_source=True); else: location = tempfile.mktemp() + '.npy'; resampled = io.mmp.create(location, shape=shape, dtype=dtype, order='C', as_source=True); delete_files.append(location); #indices for non-resampled axes indices = tuple([range(s) for d,s in enumerate(shape) if d not in axes]); indices = [i for i in itertools.product(*indices)]; n_indices = len(indices); #resample step last_source_virtual = last_source.as_virtual(); resampled_virtual = resampled.as_virtual(); _resample = ft.partial(_resample_2d, source=last_source_virtual, sink=resampled_virtual, axes=axes, shape=shape, interpolation=interpolation, n_indices=n_indices, verbose=verbose) if processes == 'serial': for index in indices: _resample(index=index); else: with concurrent.futures.ProcessPoolExecutor(processes) as executor: executor.map(_resample, indices); last_source = resampled; for f in delete_files: io.delete_file(f); sink = resampled.as_real(); return sink;
def resample_shape(source_shape, sink_shape = None, source_resolution = None, sink_resolution = None, orientation = None): """Calculate scaling factors and data shapes for resampling. Arguments --------- source_shape : tuple The shape the source. sink_shape : tuple or None The shape of the resmapled sink. source_resolution : tuple or None The resolution of the source. sink_resolution : tuple or None The resolution of the sink. orientation : tuple or str The re-orientation specification. Returns ------- source_shape : tuple The shape of the source. sink_shape : tuple The shape of the sink. source_resolution : tuple or None The resolution of the source. sink_resolution : tuple or None The resolution of the sink. See Also -------- `Orientation`_ """ orientation = format_orientation(orientation); #determine shapes if not specified if sink_shape is None and source_shape is None: raise RuntimeError('Source or sink shape must be defined!'); if sink_shape is None and sink_resolution is None: raise RuntimeError('Sink shape or resolution must be defined!'); if sink_resolution is None and not isinstance(sink_shape, tuple): sink_shape = io.shape(sink_shape); if source_shape is not None: ndim = len(source_shape); else: ndim = len(sink_shape); if sink_shape is None: if source_resolution is None: source_resolution = (1.0,) * ndim; if sink_resolution is None: sink_resolution = (1.0,) * ndim; #orient resolution of source to resolution of sink to get sink shape source_resolutionO = orient_resolution(source_resolution, orientation); source_shapeO = orient_shape(source_shape, orientation); sink_shape = tuple([int(np.ceil(source_shapeO[i] * float(source_resolutionO[i])/float(sink_resolution[i]))) for i in range(ndim)]); if source_shape is None: if source_resolution is None: source_resolution = (1,) * ndim; if sink_resolution is None: sink_resolution = (1,) * ndim; #orient resolution of source to resolution of sink to get sink shape source_resolutionO = orient_resolution(source_resolution, orientation); source_shape = tuple([int(np.ceil(sink_shape[i] * float(sink_resolution[i])/float(source_resolutionO[i]))) for i in range(ndim)]); source_shape = orient_shape(source_shape, orientation, inverse=True); #calculate effecive resolutions if source_resolution is None: if sink_resolution is None: source_resolution = (1,1,1); else: source_shapeO = orient_shape(source_shape, orientation); source_resolution = tuple(float(sink_shape[i]) / float(source_shapeO[i]) * sink_resolution[i] for i in range(ndim)); source_resolution = orient_resolution(source_resolution, orientation, inverse=True); source_shapeO = orient_shape(source_shape, orientation); source_resolutionO = orient_resolution(source_resolution, orientation); sink_resolution = tuple(float(source_shapeO[i]) / float(sink_shape[i]) * source_resolutionO[i] for i in range(ndim)); return source_shape, sink_shape, source_resolution, sink_resolution
def binarize(source, sink = None, binarization_parameter = default_binarization_parameter, processing_parameter = default_binarization_processing_parameter): """Multi-path binarization of iDISCO+ cleared vasculature data. Arguments --------- source : source specification The source of the stitched raw data. sink : sink specification or None The sink to write the result to. If None, an array is returned. binarization_parameter : dict Parameter for the binarization. See below for details. processing_parameter : dict Parameter for the parallel processing. See :func:`ClearMap.ParallelProcessing.BlockProcesing.process` for description of all the parameter. verbose : bool If True, print progress output. Returns ------- sink : Source The result of the binarization. Notes ----- * The binarization pipeline is composed of several steps. The parameters for each step are passed as sub-dictionaries to the binarization_parameter dictionary. * If None is passed for one of the steps this step is skipped. * Each step also has an additional parameter 'save' that enables saving of the result of that step to a file to inspect the pipeline. General parameter ----------------- binary_status : str or None File name to save the information about which part of the multi-path binarization contributed to the final result. max_bin : int Number of intensity levels to use for the data after preprocessing. Higher values will increase the intensity resolution but slow down processing. For the vasculature a typical value is 2**12. Clipping -------- clip : dict or None Clipping and mask generation step parameter. clip_range : tuple The range to clip the raw data as (lowest, highest) Voxels above lowest define the foregournd mask used in the following steps. For the vasculature a typical value is (400,60000). save : str or None Save the result of this step to the specified file if not None. See also :mod:`ClearMap.ImageProcessing.Clipping.Clipping` Lightsheet correction --------------------- lightsheet : dict or None Lightsheet correction step parameter. percentile : float Percentile in [0,1] used to estimate the lightshieet artifact. For the vasculature a typical value is 0.25. lightsheet : dict Parameter for the ligthsheet artifact percentile estimation. See :func:`ClearMap.ImageProcessing.LightsheetCorrection.correct_lightsheet` for list of all parameters. The crucial parameter is selem : tuple The structural element shape used to estimate the stripe artifact. It should match the typical lenght, width, and depth of the artifact in the data. For the vasculature a typical value is (150,1,1). background : dict Parameter for the background estimation in the light sheet correction. See :func:`ClearMap.ImageProcessing.LightsheetCorrection.correct_lightsheet` for list of all parameters. The crucial parameters are selem : tuple The structural element shape used to estimate the background. It should be bigger than the largest vessels, For the vasculature a typical value is (200,200,1). spacing : tuple The spacing to use to estimate the background. Larger spacings speed up processing but become less local estimates. For the vasculature a typical value is (25,25,1) step : tuple This parameter enables to subsample from the entire array defined by the structural element using larger than single voxel steps. For the vasculature a typical value is (2,2,1). interpolate : int The order of the interpoltation used in constructing the full background estimate in case a non-trivial spacing is used. For the vasculature a typical value is 1. lightsheet_vs_background : float The background is multiplied by this weight before comparing to the lightsheet artifact estimate. For the vasculature a typical value is 2. save : str or None Save the result of this step to the specified file if not None. Median filter ------------- median : dict or None Median correction step parameter. See :func:`ClearMap.ImageProcessing.Filter.Rank.median` for all parameter. The important parameters are selem : tuple The structural element size for the median filter. For the vascualture a typical value is (3,3,3). save : str or None Save the result of this step to the specified file if not None. Pseudo Deconvolution -------------------- deconvolve : dict The deconvolution step parameter. sigma : float The std of a Gaussina filter applied to the high intensity pixel image. The number should reflect the scale of the halo effect seen around high intensity structures. For the vasculature a typical value is 10. save : str or None Save the result of this step to the specified file if not None. threshold : float Voxels above this threshold will be added to the binarization result in the multi-path biniarization. For the vasculature a typical value is 750. Adaptive Thresholding --------------------- adaptive : dict or None Adaptive thresholding step parameter. A local ISODATA threshold is estimated. See also :mod:`ClearMap.ImageProcessing.LocalStatistics`. selem : tuple The structural element size to estimate the percentiles. Should be larger than the larger vessels. For the vasculature a typical value is (200,200,5). spacing : tuple The spacing used to move the structural elements. Larger spacings speed up processing but become locally less precise. For the vasculature a typical value is (50,50,5) interpolate : int The order of the interpoltation used in constructing the full background estimate in case a non-trivial spacing is used. For the vasculature a typical value is 1. save : str or None Save the result of this step to the specified file if not None. Equalization ------------ equalize : dict or None Equalization step parameter. See also :func:`ClearMap.ImageProcessing.LocalStatistics.local_percentile` precentile : tuple The lower and upper percentiles used to estimate the equalization. The lower percentile is used for normalization, the upper to limit the maximal boost to a maximal intensity above this percentile. For the vasculature a typical value is (0.4, 0.975). max_value : float The maximal intensity value in the equalized image. For the vasculature a typical value is 1.5. selem : tuple The structural element size to estimate the percentiles. Should be larger than the larger vessels. For the vasculature a typical value is (200,200,5). spacing : tuple The spacing used to move the structural elements. Larger spacings speed up processing but become locally less precise. For the vasculature a typical value is (50,50,5) interpolate : int The order of the interpoltation used in constructing the full background estimate in case a non-trivial spacing is used. For the vasculature a typical value is 1. save : str or None Save the result of this step to the specified file if not None. threshold : float Voxels above this threshold will be added to the binarization result in the multi-path biniarization. For the vasculature a typical value is 1.1. Tube filter ----------- vesselize : dict The tube filter step parameter. background : dict or None Parameters to correct for local background. See :func:`ClearMap.ImageProcessing.Filter.Rank.percentile`. If None, no background correction is done before the tube filter. selem : tuple The structural element specification to estimate the percentiles. Should be larger than the largest vessels intended to be boosted by the tube filter. For the vasculature a typical value is ('disk', (30,30,1)) . percentile : float Percentile in [0,1] used to estimate the background. For the vasculature a typical value is 0.5. tubness : dict Parameters used for the tube filter. See :func:`ClearMap.ImageProcessing.Differentiation.Hessian.lambda123`. sigma : float The scale of the vessels to boos in the filter. For the vasculature a typical value is 1.0. save : str or None Save the result of this step to the specified file if not None. threshold : float Voxels above this threshold will be added to the binarization result in the multi-path biniarization. For the vasculature a typical value is 120. Binary filling -------------- fill : dict or None If not None, apply a binary filling the binarized result. For the vasculature this step is set to None and done globally in the postprocessing step. Binary smoothing ---------------- smooth : dict or None The smoothing parameter passed to :func:`ClearMap.ImageProcessing.Binary.Smoothing.smooth_by_configuration`. For the vasculature this step is set to None and done globally in the postprocessing step. References ---------- [1] C. Kirst et al., "Mapping the Fine-Scale Organization and Plasticity of the Brain Vasculature", Cell 180, 780 (2020) """ #initialize sink shape = io.shape(source); order = io.order(source); sink, sink_buffer = ap.initialize_sink(sink=sink, shape=shape, order=order, dtype=bool); #, memory='shared'); #initialize addition output sinks binary_status = binarization_parameter.get('binary_status', None); if binary_status: ap.initialize_sink(binary_status, source=sink, shape=shape, order=order, dtype='uint16'); for key in binarization_parameter.keys(): par = binarization_parameter[key]; if isinstance(par, dict): filename = par.get('save', None); if filename: ap.initialize_sink(filename, shape=shape, order=order, dtype='float'); binarization_parameter.update(verbose=processing_parameter.get('verbose', False)); bp.process(binarize_block, source, sink, function_type='block', parameter=binarization_parameter, **processing_parameter) return sink;
size_intensity = np.hstack( [raw_source[c][:, None] for c in ['size', 'background']]) coordinates_raw = np.hstack([raw_source[c][:, None] for c in 'xyz']) # Swap axes to go from horizontal to sagittal orientation coordinates_raw_swapped_axes = np.zeros_like(coordinates_raw) coordinates_raw_swapped_axes[:, 0] = coordinates_raw[:, 2] coordinates_raw_swapped_axes[:, 1] = coordinates_raw[:, 1] coordinates_raw_swapped_axes[:, 2] = coordinates_raw[:, 0] # Transform cell coordinates from raw 642-space to downsampled 642-space coordinates_resampled = res.resample_points( coordinates_raw_swapped_axes, sink=None, orientation=None, source_shape=io.shape(ws.filename('stitched'))[::-1], sink_shape=io.shape(ch642_downsized_file)) # Transform cell coordinates from 642-space to 488-space coordinates_aligned_to_488 = elx.transform_points( coordinates_resampled, sink=None, transform_directory=os.path.join(elastix_inverse_dir, '488_to_642'), temp_file='/tmp/elastix_input_pipeline.bin', result_directory='/tmp/elastix_output_pipeline') # Change permissions back since transformix alters permissions when it is run os.chmod( os.path.join(elastix_inverse_dir, '488_to_642', 'TransformParameters.0.txt'), 0o777) os.chmod(
def test_completed_cumulatives_in_spheres(points1, intensities1, points2, intensities2, shape=ano.default_annotation_file, radius=100, method='AndresonDarling'): """Performs completed cumulative distribution tests for each pixel using points in a ball centered at that cooridnates, returns 4 arrays p value, statistic value, number in each group""" #TODO: sinple implementation -> slow -> speed up if not isinstance(shape, tuple): shape = io.shape(shape) if len(shape) != 3: raise RuntimeError('Shape expected to be 3d, found %r' % (shape, )) # distances^2 to origin x1 = points1[:, 0] y1 = points1[:, 1] z1 = points1[:, 2] i1 = intensities1 d1 = x1 * x1 + y1 * y1 + z1 * z1 x2 = points2[:, 0] y2 = points2[:, 1] z2 = points2[:, 2] i2 = intensities2 d2 = x2 * x2 + y2 * y2 + z2 * z2 r2 = radius * radius # TODO: inhomogenous in 3d ! p = np.zeros(dataSize) s = np.zeros(dataSize) n1 = np.zeros(dataSize, dtype='int') n2 = np.zeros(dataSize, dtype='int') for x in range(dataSize[0]): #print x for y in range(dataSize[1]): #print y for z in range(dataSize[2]): #print z d11 = d1 - 2 * (x * x1 + y * y1 + z * z1) + (x * x + y * y + z * z) d22 = d2 - 2 * (x * x2 + y * y2 + z * z2) + (x * x + y * y + z * z) ii1 = d11 < r2 ii2 = d22 < r2 n1[x, y, z] = ii1.sum() n2[x, y, z] = ii2.sum() if n1[x, y, z] > 0 and n2[x, y, z] > 0: (pp, ss) = self.testCompletedCumulatives( (i1[ii1], i2[ii2]), method=method) else: pp = 0 ss = 0 p[x, y, z] = pp s[x, y, z] = ss return (p, s, n1, n2)