def transformPoints(points_source, transformDirectory, sink=None, invert=False): """Transform coordinates math:`x` via elastix estimated transformation to :math:`T(x)` Note the transformation is from the fixed image coorindates to the moving image coordiantes. Arguments: points_source (str or numpy.array): source of the points. Returns: array or str: array or file name of transformed points """ log.info('transforming points with ' + transformDirectory) log.info('invert: {}'.format(invert)) pts = io.readPoints(points_source).tolist() composite_trans = _compose_transforms(transformDirectory, invert=invert) trans_pts = [] for i in pts: trans_pts.append(composite_trans.apply_to_point(i)) res = np.array(trans_pts) if isinstance(sink, str): return io.writeData(sink, res) else: return res
def writePoints(filename, points, indices=True): """Write points as elastix/transformix point file. with format: <index, point> <number of points> point1 x point1 y [point1 z] point2 x point2 y [point2 z] Arguments: filename (str): file name of the elastix point file. points (array or str): source of the points. indices (bool): write as pixel indices or physical coordiantes Returns: str : file name of the elastix point file """ log.debug('writing points to text file for Elastix input') points = io.readPoints(points) with open(filename, 'w+') as pointfile: if indices: pointfile.write('index\n') else: pointfile.write('point\n') pointfile.write('{}\n'.format(points.shape[0])) np.savetxt(pointfile, points, delimiter=' ', newline='\n', fmt='%.5e') pointfile.close() return filename
def thresholdPoints(points, intensities, threshold=0, row=0): """Threshold points by intensities""" points, intensities = io.readPoints((points, intensities)) # set up params if not isinstance(row, tuple): row = (row, row) # filter min values if intensities.ndim > 1: i = intensities[:, row[0]] else: i = intensities iids = np.ones(i.shape, dtype='bool') if not threshold[0] is all: iids = np.logical_and(iids, i >= threshold[0]) # filter max values if intensities.ndim > 1: i = intensities[:, row[1]] if not threshold[1] is all: iids = np.logical_and(iids, i <= threshold[1]) pointsThresh = points[iids, ...] intensitiesThresh = intensities[iids, ...] return pointsThresh, intensitiesThresh
def readPointsGroup(filenames, **args): """Turn a list of filenames for points into a np stack""" #check if stack already: if isinstance(filenames, np.ndarray): return filenames #read the individual files group = [] for f in filenames: data = io.readPoints(f, **args) group.append(data) return group
def add_point_groups(self, points_sources): """ add point counts to each region with voxel info Points will be added to self.voxels as a list at each coordinate making up the region. Point density by group will added to self.points_density Arguments: points_sources (array, str, list): array, file, or list of files with point coordinates in [(x,y,z),...] """ timer = Timer() if not isinstance(points_sources, list): points_sources = [points_sources] start_group = len(self.tree_root.nPoints) n = len(points_sources) for region in PostOrderIter(self.tree_root): region.add_empty_voxel_groups(ngroups = n) self.backround.add_empty_voxel_groups(ngroups = n) for group, points in enumerate(points_sources): group_index = start_group + group coords = io.readPoints(points).astype(int) for i in coords: i = tuple(i) try: self.get_region_by_voxel(i).add_point(i, group_index) except: # if coord is out of the image it will be included in backgroud self.get_region_by_id(0).nPoints[group_index] += 1 if self.COLLAPSE: for region in PostOrderIter(self.tree_root): region.collapse_nPoints(index = slice(start_group, None)) # calculate densities self.calc_point_densities() timer.log_elapsed(prefix='Added points group')
def voxelize(points, dataSize=None, sink=None, method='Spherical', size=(5, 5, 5), weights=None): """Converts a list of points into an volumetric image array Arguments: points (array): point data array dataSize (tuple or str): size of final image in xyz. If str, will use the size of the passed image. sink (str, array or None): the location to write or return the resulting voxelization image, if None return array method (str or None): method for voxelization: 'Spherical', 'Rectangular' or 'Pixel' size (tuple): size parameter for the voxelization weights (array or None): weights for each point, None is uniform weights Returns: (array): volumetric data of smeared out points """ log.verbose('voxelizing points') points = io.readPoints(points) if dataSize is None: dataSize = tuple( int(math.ceil(points[:, i].max())) for i in range(points.shape[1])) elif isinstance(dataSize, str): dataSize = io.dataSize(dataSize) if method.lower() == 'spherical': if weights is None: data = vox.voxelizeSphere(points.astype('float'), dataSize[0], dataSize[1], dataSize[2], size[0], size[1], size[2]) else: data = vox.voxelizeSphereWithWeights(points.astype('float'), dataSize[0], dataSize[1], dataSize[2], size[0], size[1], size[2], weights) elif method.lower() == 'rectangular': if weights is None: data = vox.voxelizeRectangle(points.astype('float'), dataSize[0], dataSize[1], dataSize[2], size[0], size[1], size[2]) else: data = vox.voxelizeRectangleWithWeights(points.astype('float'), dataSize[0], dataSize[1], dataSize[2], size[0], size[1], size[2], weights) elif method.lower() == 'pixel': data = voxelizePixel(points, dataSize, weights) else: raise RuntimeError('voxelize: mode: %s not supported!' % method) if data.dtype == np.float64: log.warning( 'Converting dtype float64 to int32 for output. This may result in loss of info.' ) data = data.astype('int32') if sink: return io.writeData(sink, data, returnMemmap=True) else: return data
def overlay_points(pointSource, dataSource, output=None, overlay=True, x=all, y=all, z=all): """Overlay points on 3D data and return as color image Arguments: pointSource (str or array): point data to be overlayed on the image data dataSource (str or array): volumetric image data. if None just output points as an image overlay (bool): if False will not overlay and just output points as an image. x, y, z (all or tuple): sub-range specification Returns: (str or array): image overlayed with points See Also: :func:`overlayLabel` """ points = (io.readPoints(pointSource, x=x, y=y, z=z, shift=True)).astype(int) if overlay: X, Y, Z = io.dataSize(dataSource) datatype = io.readData(dataSource, x=x, y=y, z=0).dtype if io.isMappable(output): output = tif.tifffile.memmap(output, dtype=datatype, shape=(Z, 2, Y, X), imagej=True) # TZCYXS FIJI elif io.isFileExpression(output): output = [ tif.tifffile.memmap(output, dtype=datatype, shape=(2, Y, X), imagej=True) for z in range(Z) ] # sequence of memmap files elif output is None: output = numpy.zeros((Z, 2, Y, X), dtype=datatype) else: RuntimeError('output format not compatable with overlayPoints: ' + output) for z in range(Z): print(('Overlaying {}...'.format(z))) output[z][0][:] = io.readData(dataSource, x=x, y=y, z=z).squeeze().T z_points = points[points[:, -1] == z][:, :2] output[z][1][[*z_points[:, ::-1].T]] = 1 return output else: shape = io.dataSize(dataSource) cimage = vox.voxelize( points, shape, output=output, method='Pixel', weights=65535 ) # TODO: weight should depend on bit depth of dataSource return cimage
def resamplePoints(source, sink=None, dataSizeSource=None, dataSizeSink=None, orientation=None, resolutionSource=(4.0625, 4.0625, 3), resolutionSink=(25, 25, 25), **args): """Resample Points to map from original data to the coordinates of the resampled image The resampling of points here corresponds to he resampling of an image in :func:`resampleData` Arguments: pointSource (str or array): image to be resampled pointSink (str or None): destination of resampled image orientation (tuple): orientation specified by permuation and change in sign of (1,2,3) dataSizeSource (str, tuple or None): size of the data source dataSizeSink (tuple or None): target size of the resampled image resolutionSource (tuple): resolution of the source image (in length per pixel) resolutionSink (tuple): resolution of the resampled image (in length per pixel) Returns: (array or str): data or file name of resampled points Notes: * resolutions are assumed to be given for the axes of the intrinsic orientation of the data and reference as when viewed by matplotlib or ImageJ * orientation: permuation of 1,2,3 with potential sign, indicating which axes map onto the reference axes, a negative sign indicates reversal of that particular axes * only a minimal set of information to detremine the resampling parameter has to be given, e.g. dataSizeSource and dataSizeSink """ log.info('resampling points') # size of data source if isinstance(dataSizeSource, str): dataSizeSource = io.dataSize(dataSizeSource) if isinstance(dataSizeSink, str): dataSizeSink = io.dataSize(dataSizeSink) dataSizeSource, dataSizeSink, resolutionSource, resolutionSink = resampleDataSize( dataSizeSource=dataSizeSource, dataSizeSink=dataSizeSink, resolutionSource=resolutionSource, resolutionSink=resolutionSink, orientation=orientation) points = io.readPoints(source) dataSizeSinkI = orientDataSizeInverse(dataSizeSink, orientation) # scaling factors scale = [ float(dataSizeSource[i]) / float(dataSizeSinkI[i]) for i in range(3) ] repoints = points.copy() for i in range(3): repoints[:, i] = repoints[:, i] / scale[i] # permute for non trivial orientation if not orientation is None: per = orientationToPermuation(orientation) repoints = repoints[:, per] for i in range(3): if orientation[i] < 0: repoints[:, i] = dataSizeSink[i] - repoints[:, i] if sink: return io.writePoints(sink, repoints) else: return repoints
def transformPoints(source, sink=None, transformParameter=None, indices=True, resultDirectory=None, tmpFile=None): """Transform coordinates math:`x` via elastix estimated transformation to :math:`T(x)` Note the transformation is from the fixed image coorindates to the moving image coordiantes. Arguments: source (str): source of the points sink (str or None): sink for transformed points transformParameterFile (str or None): parameter file for the primary transformation, if None, the file is determined from the transformDirectory. transformDirectory (str or None): result directory of elastix alignment, if None the transformParameterFile has to be given. indices (bool): if True use points as pixel coordinates otherwise spatial coordinates. resultDirectory (str or None): elastic result directory tmpFile (str or None): file name for the elastix point file. Returns: array or str: array or file name of transformed points """ if tmpFile == None: tmpFile = os.path.join(tempfile.tempdir, 'elastix_input.txt') # write text file if isinstance(source, str): # check if we have elastix signature with open(source) as f: line = f.readline() f.close() if line[:5] == 'point' or line[:5] != 'index': txtfile = source else: points = io.readPoints(source) # points = points[:,[1,0,2]]; txtfile = tmpFile writePoints(txtfile, points) elif isinstance(source, np.ndarray): txtfile = tmpFile # points = source[:,[1,0,2]]; writePoints(txtfile, source) else: raise RuntimeError('transformPoints: source not string or array!') if resultDirectory == None: outdirname = os.path.join(tempfile.tempdir, 'elastix_output') else: outdirname = resultDirectory if not os.path.exists(outdirname): os.makedirs(outdirname) if os.path.isdir(transformParameter): transformparameterfile = getTransformParameterFiles( transformParameter)[-1] transformparameterdir = transformParameter elif os.path.isfile(transformParameter): transformparameterdir = os.path.split(transformParameter)[0] transformparameterfile = transformParameter else: raise RuntimeError('could not find parameters ' + transformParameter) # transform # make path in parameterfiles absolute setPathTransformParameterFiles(transformparameterdir) # run transformix cmd = config.tranformix_binary + ' -def ' + txtfile + ' -out ' + outdirname + ' -tp ' + transformparameterfile res = os.system(cmd) if res != 0: raise RuntimeError('failed executing ' + cmd) # read data / file if sink == []: return io.path.join(outdirname, 'outputpoints.txt') else: # read coordinates transpoints = parseElastixOutputPoints(os.path.join( outdirname, 'outputpoints.txt'), indices=indices) # correct x,y,z to y,x,z # transpoints = transpoints[:,[1,0,2]]; # cleanup for f in os.listdir(outdirname): os.remove(os.path.join(outdirname, f)) os.rmdir(outdirname) return io.writePoints(sink, transpoints)
from bq3d.alignment.ants import alignData #correction between channels: alignData(**CorrectionAlignmentParam) #alignment to the Atlas: alignData(**RegistrationAlignmentParam) ################ ## Transform Point Coordinates: ################ from bq3d import io from bq3d.alignment.resampling import resamplePoints from bq3d.alignment.ants import transformPoints from bq3d.analysis.voxelization import voxelize from bq3d.stack_processing.cell_detection import jsonify_points points = io.readPoints(sink) # Downsample to chromatic correction size points = resamplePoints(sink, **CorrectionResamplingPointsParam) vox = voxelize(points, CorrectionResamplingParamSignal['sink'], sink=os.path.join(BaseDirectory, 'cells_cd1.tif'), **voxelizeParameter) # Apply correction transform points = transformPoints(points, CorrectionAlignmentParam["resultDirectory"], invert=True) vox = voxelize(points, CorrectionResamplingParamSignal['sink'], sink=os.path.join(BaseDirectory, 'cells_corr.tif'), **voxelizeParameter) # Upsample back to original size