Exemplo n.º 1
0
    def __init__(self, data, transformer=None):
        try:
            self.data = data
            self.id = data['id']
            # If space is not explicitly set, assume the coordinates are already in
            # the target space.
            self.space = data[
                'space'] if 'space' in data else transformer.target
        except Exception as e:
            logger.error("Missing ID and/or space fields. "
                         "Please check database file, caught: %s" % str(e))
            exit()

        # Loop through rows and set coordinates
        peaks = np.zeros((len(data['peaks']), 3), dtype=int)
        for i, f in enumerate(data['peaks']):
            peaks[i, ] = [float(j) for j in f[0:3]]

        # Convert between stereotactic spaces
        if transformer is not None and self.space != transformer.target:
            peaks = transformer.apply(self.space, peaks)

        # Convert from XYZ coordinates to matrix indices, saving both
        self.xyz = peaks
        self.peaks = transformations.xyz_to_mat(peaks)
Exemplo n.º 2
0
    def get_ids_by_peaks(self,
                         peaks,
                         r=10,
                         threshold=0.0,
                         get_image_data=False):
        """ A wrapper for get_ids_by_mask. Takes a set of xyz coordinates and generates
        a new Nifti1Image to use as a mask.

        Args:
          peaks: Either an n x 3 numpy array, or a list of lists (e.g., [[-10, 22, 14]])
            specifying the world (x/y/z) coordinates of the target location(s).
          r: Radius in millimeters of the sphere to grow around each location.
          threshold: Optional float indicating the proportion of voxels that must be
            active in order for a Mappable to be considered active.
          get_image_data: If true, returns the image data for all activated Mappables in
            a voxel x Mappable numpy array. Otherwise, returns just the IDs of Mappables.

        Returns:
          Either a list of ids (if get_image_data = False) or a numpy array of image data.

        """
        peaks = np.array(peaks)  # Make sure we have a numpy array
        peaks = transformations.xyz_to_mat(peaks)
        img = imageutils.map_peaks_to_image(peaks,
                                            r,
                                            vox_dims=self.masker.vox_dims,
                                            dims=self.masker.dims,
                                            header=self.masker.get_header())
        return self.get_ids_by_mask(img,
                                    threshold,
                                    get_image_data=get_image_data)
Exemplo n.º 3
0
    def get_ids_by_peaks(self, peaks, r=10, threshold=0.0,
                         get_image_data=False):
        """ A wrapper for get_ids_by_mask. Takes a set of xyz coordinates and
        generates a new Nifti1Image to use as a mask.

        Args:
            peaks (ndarray, list): Either an n x 3 numpy array, or a list of 
                lists (e.g., [[-10, 22, 14]]) specifying the world (x/y/z)
                coordinates of the target location(s).
            r (int): Radius in millimeters of the sphere to grow around each
                location.
          threshold (float): Optional float indicating the proportion of voxels
            that must be active in order for a Mappable to be considered
            active.
            get_image_data (bool): When True, returns a voxel x mappable matrix
            of image data rather than the Mappable instances themselves.

        Returns:
            Either a list of ids (if get_image_data = False) or a numpy array
            of image data.

        """
        peaks = np.array(peaks)  # Make sure we have a numpy array
        peaks = transformations.xyz_to_mat(peaks)
        img = imageutils.map_peaks_to_image(
            peaks, r, vox_dims=self.masker.vox_dims,
            dims=self.masker.dims, header=self.masker.get_header())
        return self.get_ids_by_mask(img, threshold,
                                    get_image_data=get_image_data)
Exemplo n.º 4
0
    def _load_activations(self, filename):
        """ Load activation data from a text file.

        Args:
            filename (str): a string pointing to the location of the txt file
                to read from.
        """
        logger.info("Loading activation data from %s..." % filename)

        activations = pd.read_csv(filename, sep='\t')
        activations.columns = [col.lower()
                               for col in list(activations.columns)]

        # Make sure all mandatory columns exist
        mc = ['x', 'y', 'z', 'id', 'space']
        if (set(mc) - set(list(activations.columns))):
            logger.error(
                "At least one of mandatory columns (x, y, z, id, and space) "
                "is missing from input file.")
            return

        # Transform to target space where needed
        spaces = activations['space'].unique()
        xyz = activations[['x', 'y', 'z']].values
        for s in spaces:
            if s != self.transformer.target:
                inds = activations['space'] == s
                xyz[inds] = self.transformer.apply(s, xyz[inds])
        activations[['x', 'y', 'z']] = xyz

        # xyz --> ijk
        ijk = pd.DataFrame(
            transformations.xyz_to_mat(xyz), columns=['i', 'j', 'k'])
        activations = pd.concat([activations, ijk], axis=1)
        return activations
Exemplo n.º 5
0
def peaks_to_vector(coordinates, mask=
                    '/scratch/02863/mparikh/data/MNI152_T1_2mm_brain.nii.gz', 
                    radius=10):
    """
    Takes in a list of valid peak coordinates and 
    returns a vector of the corresponding image
    Parameters
    ----------
    coordinates : list of lists
        list of x/y/z coordinates
    mask : mask object in nifti fomat
        used to vectorize the image
    radius : int, optional
        the radius of sphere to expand around the peaks in mm.
        defaults to 10mm.

    Returns
    -------
    dense_img : nifti image
        1D Numpy array of in-mask voxels
    """
    # transform the coordinates to matrix space
    #print(coordinates)
    new_coordinates = nbt.xyz_to_mat(np.array(coordinates))
    # now  get the denser image, expanding via spheres
    dense_img  = nbi.map_peaks_to_image(new_coordinates, r=radius)
    # Create a mask object for the image
    niftiMask = nbm.Mask(mask)
    # mask the image formed
    return niftiMask.mask(dense_img)
Exemplo n.º 6
0
    def _load_activations(self, filename):
        """ Load activation data from a text file.

        Args:
            filename (str): a string pointing to the location of the txt file
                to read from.
        """
        logger.info("Loading activation data from %s..." % filename)

        activations = pd.read_csv(filename, sep='\t')
        activations.columns = [col.lower()
                               for col in list(activations.columns)]

        # Make sure all mandatory columns exist
        mc = ['x', 'y', 'z', 'id', 'space']
        if (set(mc) - set(list(activations.columns))):
            logger.error(
                "At least one of mandatory columns (x, y, z, id, and space) "
                "is missing from input file.")
            return

        # Transform to target space where needed
        spaces = activations['space'].unique()
        xyz = activations[['x', 'y', 'z']].values
        for s in spaces:
            if s != self.transformer.target:
                inds = activations['space'] == s
                xyz[inds] = self.transformer.apply(s, xyz[inds])
        activations[['x', 'y', 'z']] = xyz

        # xyz --> ijk
        ijk = pd.DataFrame(
            transformations.xyz_to_mat(xyz), columns=['i', 'j', 'k'])
        activations = pd.concat([activations, ijk], axis=1)
        return activations
Exemplo n.º 7
0
    def __init__(self, data, transformer=None):
        try:
            self.data = data
            self.id = data['id']
            # If space is not explicitly set, assume the coordinates are already in
            # the target space.
            self.space = data[
                'space'] if 'space' in data else transformer.target
        except Exception as e:
            logger.error("Missing ID and/or space fields. "
                         "Please check database file, caught: %s" % str(e))
            exit()

        # Loop through rows and set coordinates
        peaks = np.zeros((len(data['peaks']), 3), dtype=int)
        for i, f in enumerate(data['peaks']):
            peaks[i,] = [float(j) for j in f[0:3]]

        # Convert between stereotactic spaces
        if transformer is not None and self.space != transformer.target:
            peaks = transformer.apply(self.space, peaks)

        # Convert from XYZ coordinates to matrix indices, saving both
        self.xyz = peaks
        self.peaks = transformations.xyz_to_mat(peaks)
Exemplo n.º 8
0
    def __init__(self, data, transformer=None):
        try:
            self.data = data.copy().reset_index()
            self.id = data['id'].values[0]
            # If space is not explicitly set, assume the coordinates are already in
            # the target space.
            self.space = data['space'].values[0] if 'space' in data.columns else transformer.target
        except Exception as e:
            logger.error("Missing ID and/or space fields. "
                         "Please check database file, caught: %s" % str(e))
            exit()

        peaks = data[['x','y','z']].values

        # Convert between stereotactic spaces
        if transformer is not None and self.space != transformer.target:
            peaks = transformer.apply(self.space, peaks)

        # Convert from XYZ coordinates to matrix indices, saving both
        self.xyz = peaks
        self.peaks = transformations.xyz_to_mat(peaks)
Exemplo n.º 9
0
    def __init__(self, data, transformer=None):
        try:
            self.data = data.copy().reset_index()
            self.id = data['id'].values[0]
            # If space is not explicitly set, assume the coordinates are already in
            # the target space.
            self.space = data['space'].values[
                0] if 'space' in data.columns else transformer.target
        except Exception as e:
            logger.error("Missing ID and/or space fields. "
                         "Please check database file, caught: %s" % str(e))
            exit()

        peaks = data[['x', 'y', 'z']].values

        # Convert between stereotactic spaces
        if transformer is not None and self.space != transformer.target:
            peaks = transformer.apply(self.space, peaks)

        # Convert from XYZ coordinates to matrix indices, saving both
        self.xyz = peaks
        self.peaks = transformations.xyz_to_mat(peaks)
Exemplo n.º 10
0
def is_valid(coordinates, mask='/scratch/02863/mparikh/data/2mm_brain_mask.npy'):
    """
    Validates that the given x/y/z tuple is valid
    for the given mask

    Parameters
    ----------
    coordinates : list/tuple
        x, y, z coordinates to be validated
    mask : mask object in nifti format

    Returns
    -------
    bool : whether it is a valid coordinate or not
    """
    try:
        mat = np.load(mask)
        idx = nbt.xyz_to_mat(np.asarray([coordinates]))
        idx_t = tuple(idx.reshape(1, -1)[0])
        return mat[idx_t] == 1
    except IndexError as e:
        return False
Exemplo n.º 11
0
    def get_ids_by_peaks(self, peaks, r=10, threshold=0.0, get_image_data=False):
        """ A wrapper for get_ids_by_mask. Takes a set of xyz coordinates and generates
        a new Nifti1Image to use as a mask.

        Args:
          peaks: Either an n x 3 numpy array, or a list of lists (e.g., [[-10, 22, 14]])
            specifying the world (x/y/z) coordinates of the target location(s).
          r: Radius in millimeters of the sphere to grow around each location.
          threshold: Optional float indicating the proportion of voxels that must be
            active in order for a Mappable to be considered active.
          get_image_data: If true, returns the image data for all activated Mappables in
            a voxel x Mappable numpy array. Otherwise, returns just the IDs of Mappables.

        Returns:
          Either a list of ids (if get_image_data = False) or a numpy array of image data.

        """
        peaks = np.array(peaks)  # Make sure we have a numpy array
        peaks = transformations.xyz_to_mat(peaks)
        img = imageutils.map_peaks_to_image(
            peaks, r, vox_dims=self.volume.vox_dims,
            dims=self.volume.dims, header=self.volume.get_header())
        return self.get_ids_by_mask(img, threshold, get_image_data=get_image_data)
Exemplo n.º 12
0
    def get_studies(self, features=None, expression=None, mask=None,
                    peaks=None, frequency_threshold=0.001,
                    activation_threshold=0.0, func=np.sum, return_type='ids',
                    r=6
                    ):
        """ Get IDs or data for studies that meet specific criteria.

        If multiple criteria are passed, the set intersection is returned. For
        example, passing expression='emotion' and mask='my_mask.nii.gz' would
        return only those studies that are associated with emotion AND report
        activation within the voxels indicated in the passed image.

        Args:
            ids (list): A list of IDs of studies to retrieve.
            features (list or str): The name of a feature, or a list of
                features, to use for selecting studies.
            expression (str): A string expression to pass to the PEG for study
                retrieval.
            mask: the mask image (see Masker documentation for valid data
                types).
            peaks (ndarray or list): Either an n x 3 numpy array, or a list of
                lists (e.g., [[-10, 22, 14]]) specifying the world (x/y/z)
                coordinates of the target location(s).
            frequency_threshold (float): For feature-based or expression-based
                selection, the threshold for selecting studies--i.e., the
                cut-off for a study to be included. Must be a float in range
                [0, 1].
            activation_threshold (int or float): For mask-based or peak-based
                selection, threshold for a study to be included based on
                amount of activation displayed. If an integer, represents the
                absolute number of voxels that must be active within the mask
                (or generated ROIs) in order for a study to be selected. If a
                float, it represents the proportion of voxels that must be
                active.
            func (Callable): The function to use when aggregating over the list
                of features. See documentation in FeatureTable.get_ids() for a
                full explanation. Only used for feature- or expression-based
                selection.
            return_type (str): A string specifying what data to return. Valid
                options are:
                'ids': returns a list of IDs of selected studies.
                'images': returns a voxel x mappable matrix of data for all
                selected studies.
                'weights': returns a dict where the keys are study IDs and the
                values are the computed weights. Only valid when performing
                feature-based selection.
            r (int): For peak-based selection, the radius in millimeters of the
                sphere to grow around each peak.

        Returns:
            When return_type is 'ids' (default), returns a list of IDs of the
            selected studies. When return_type is 'data', returns a 2D numpy
            array, with voxels in rows and studies in columns. When return_type
            is 'weights' (valid only for expression-based selection), returns
            a dict, where the keys are study IDs, and the values are the
            computed weights.

        Examples
        --------
        Select all studies tagged with the feature 'emotion':

            >>> ids = dataset.get_studies(features='emotion')

        Select all studies that activate at least 20% of voxels in an amygdala
        mask, and retrieve activation data rather than IDs:

            >>> data = dataset.get_studies(mask='amygdala_mask.nii.gz',
                threshold=0.2, return_type='images')

        Select studies that activate at least 5% of all voxels within 12 mm of
        three specific foci:

            >>> ids = dataset.get_studies(peaks=[[12, -20, 30], [-26, 22, 22],
                                                [0, 36, -20]], r=12)

        """
        results = []

        # Feature-based selection
        if features is not None:
            # Need to handle weights as a special case, because we can't
            # retrieve the weights later using just the IDs.
            if return_type == 'weights':
                if expression is not None or mask is not None or \
                        peaks is not None:
                    raise ValueError(
                        "return_type cannot be 'weights' when feature-based "
                        "search is used in conjunction with other search "
                        "modes.")
                return self.feature_table.get_ids(
                    features, frequency_threshold, func, get_weights=True)
            else:
                results.append(self.feature_table.get_ids(
                    features, frequency_threshold, func))

        # Logical expression-based selection
        if expression is not None:
            _ids = self.feature_table.get_ids_by_expression(
                expression, frequency_threshold, func)
            results.append(list(_ids))

        # Mask-based selection
        if mask is not None:
            mask = self.masker.mask(mask, in_global_mask=True).astype(bool)
            num_vox = np.sum(mask)
            prop_mask_active = self.image_table.data.T.dot(mask).astype(float)
            if isinstance(activation_threshold, float):
                prop_mask_active /= num_vox
            indices = np.where(prop_mask_active > activation_threshold)[0]
            results.append([self.image_table.ids[ind] for ind in indices])

        # Peak-based selection
        if peaks is not None:
            peaks = np.array(peaks)  # Make sure we have a numpy array
            peaks = transformations.xyz_to_mat(peaks)
            m = self.masker
            img = imageutils.map_peaks_to_image(
                peaks, r, vox_dims=m.vox_dims, dims=m.dims,
                header=m.get_header())
            results.append(self.get_studies(
                mask=img, activation_threshold=activation_threshold))

        # Get intersection of all sets
        ids = list(reduce(lambda x, y: set(x) & set(y), results))

        if return_type == 'ids':
            return ids
        elif return_type == 'data':
            return self.get_image_data(ids)
Exemplo n.º 13
0
    def get_studies(self, features=None, expression=None, mask=None,
                    peaks=None, frequency_threshold=0.001,
                    activation_threshold=0.0, func=np.sum, return_type='ids',
                    r=6
                    ):
        """ Get IDs or data for studies that meet specific criteria.

        If multiple criteria are passed, the set intersection is returned. For
        example, passing expression='emotion' and mask='my_mask.nii.gz' would
        return only those studies that are associated with emotion AND report
        activation within the voxels indicated in the passed image.

        Args:
            ids (list): A list of IDs of studies to retrieve.
            features (list or str): The name of a feature, or a list of
                features, to use for selecting studies.
            expression (str): A string expression to pass to the PEG for study
                retrieval.
            mask: the mask image (see Masker documentation for valid data
                types).
            peaks (ndarray or list): Either an n x 3 numpy array, or a list of
                lists (e.g., [[-10, 22, 14]]) specifying the world (x/y/z)
                coordinates of the target location(s).
            frequency_threshold (float): For feature-based or expression-based
                selection, the threshold for selecting studies--i.e., the
                cut-off for a study to be included. Must be a float in range
                [0, 1].
            activation_threshold (int or float): For mask-based or peak-based
                selection, threshold for a study to be included based on
                amount of activation displayed. If an integer, represents the
                absolute number of voxels that must be active within the mask
                (or generated ROIs) in order for a study to be selected. If a
                float, it represents the proportion of voxels that must be
                active.
            func (Callable): The function to use when aggregating over the list
                of features. See documentation in FeatureTable.get_ids() for a
                full explanation. Only used for feature- or expression-based
                selection.
            return_type (str): A string specifying what data to return. Valid
                options are:
                'ids': returns a list of IDs of selected studies.
                'images': returns a voxel x mappable matrix of data for all
                selected studies.
                'weights': returns a dict where the keys are study IDs and the
                values are the computed weights. Only valid when performing
                feature-based selection.
            r (int): For peak-based selection, the radius in millimeters of the
                sphere to grow around each peak.

        Returns:
            When return_type is 'ids' (default), returns a list of IDs of the
            selected studies. When return_type is 'data', returns a 2D numpy
            array, with voxels in rows and studies in columns. When return_type
            is 'weights' (valid only for expression-based selection), returns
            a dict, where the keys are study IDs, and the values are the
            computed weights.

        Examples
        --------
        Select all studies tagged with the feature 'emotion':

            >>> ids = dataset.get_studies(features='emotion')

        Select all studies that activate at least 20% of voxels in an amygdala
        mask, and retrieve activation data rather than IDs:

            >>> data = dataset.get_studies(mask='amygdala_mask.nii.gz',
                threshold=0.2, return_type='images')

        Select studies that activate at least 5% of all voxels within 12 mm of
        three specific foci:

            >>> ids = dataset.get_studies(peaks=[[12, -20, 30], [-26, 22, 22],
                                                [0, 36, -20]], r=12)

        """
        results = []

        # Feature-based selection
        if features is not None:
            # Need to handle weights as a special case, because we can't
            # retrieve the weights later using just the IDs.
            if return_type == 'weights':
                if expression is not None or mask is not None or \
                        peaks is not None:
                    raise ValueError(
                        "return_type cannot be 'weights' when feature-based "
                        "search is used in conjunction with other search "
                        "modes.")
                return self.feature_table.get_ids(
                    features, frequency_threshold, func, get_weights=True)
            else:
                results.append(self.feature_table.get_ids(
                    features, frequency_threshold, func))

        # Logical expression-based selection
        if expression is not None:
            _ids = self.feature_table.get_ids_by_expression(
                expression, frequency_threshold, func)
            results.append(list(_ids))

        # Mask-based selection
        if mask is not None:
            mask = self.masker.mask(mask, in_global_mask=True).astype(bool)
            num_vox = np.sum(mask)
            prop_mask_active = self.image_table.data.T.dot(mask).astype(float)
            if isinstance(activation_threshold, float):
                prop_mask_active /= num_vox
            indices = np.where(prop_mask_active > activation_threshold)[0]
            results.append([self.image_table.ids[ind] for ind in indices])

        # Peak-based selection
        if peaks is not None:
            peaks = np.array(peaks)  # Make sure we have a numpy array
            peaks = transformations.xyz_to_mat(peaks)
            m = self.masker
            img = imageutils.map_peaks_to_image(
                peaks, r, vox_dims=m.vox_dims, dims=m.dims,
                header=m.get_header())
            results.append(self.get_studies(
                mask=img, activation_threshold=activation_threshold))

        # Get intersection of all sets
        ids = list(reduce(lambda x, y: set(x) & set(y), results))

        if return_type == 'ids':
            return ids
        elif return_type == 'data':
            return self.get_image_data(ids)