Example #1
0
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
Example #2
0
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
Example #7
0
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
Example #9
0
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)
Example #10
0
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