Example #1
0
    def __init__(self, path, image=None):
        """Open ROI (.roi) or list of ROIs (.zip) using ijroi modules
        INPUT: Path to ROI file
        image: Defines the path to an image associated with the ROIs. Optional. Can be added later"""
        from read_roi import read_roi_file, read_roi_zip
        import pims

        # Import ROI list
        if path.split('.')[-1] == "zip":
            self.rois = read_roi_zip(path)  # imports a labeled dict
        elif path.split('.')[-1] == "roi":
            self.rois = read_roi_file(path)  # import single ROI
        else:  # no file extension provided
            try:
                self.rois = read_roi_zip(path +
                                         '.zip')  # imports a labeled dict
                print('importing list of rois')
            except FileNotFoundError:  # .roi file, not .zip file
                self.rois = read_roi_file(path + '.roi')  # import single ROI
                print("Opening single ROI...")

        self.keys = list(
            self.rois.keys())  # get list of ROI names for referencing in Dict

        self.attach_image(image)  # attach image if specified

        return
Example #2
0
def plot_clusters_in_roi(roi_path,
                         pixel_size,
                         cluster_list,
                         noise=None,
                         save=False,
                         filename=None,
                         show_plot=True,
                         new_figure=True,
                         cluster_marker_size=4):

    filename, ext = os.path.splitext(roi_path)
    print(ext)
    if 'zip' in ext:
        rois = read_roi_zip(roi_path)
    else:
        rois = read_roi_file(roi_path)

    for roi_id, roi in rois.items():
        for k, v in roi.items():
            if not isinstance(v, str):
                roi[k] = float(v) * pixel_size

        plot_optics_clusters(cluster_list,
                             noise=noise,
                             save=False,
                             filename=None,
                             show_plot=True,
                             new_figure=True,
                             cluster_marker_size=4,
                             roi=roi)
Example #3
0
def get_rect_coordinates_from_roi(fname):
    """
		This function returns the coordinates from a rectangular region of interest
		defined in a .roi file generated by ImageJ / Fiji.

		N.B.: indexing starts from 0.
		Incremet rowmax and col_max  + 1 to crop an image, for example:
		crop = img[rowmin:(rowmax+1),  colmin:(colmax+1)]

		Parameters
		----------
		fname : str
			String defining the path or the name of the Image ROI file.

		Returns
		-------
		rowmin : int
			The minimum row coordinate.

		rowmax : int
			The maximum row coordinate.

		colmin : int
			The minimum column coordinate.

		colmax : int
			The maximum column coordinate.

	"""

    # file name check
    if (type(fname) is not str):
        logs.error('File name must be a string.')
        raise TypeError('File name must be a string.')
    else:
        if not (fname.endswith('.roi')):
            logs.warning('File extension shold be .roi')

    # read roi file
    roi = read_roi_file(fname)

    # convert keys to list
    l = list(roi.keys())

    # extract coordinates and length
    height = roi[l[0]]['height']
    width = roi[l[0]]['width']
    top = roi[l[0]]['top']
    left = roi[l[0]]['left']

    rowmin = int(top)
    rowmax = int(top + height - 1)
    colmin = int(left)
    colmax = int(left + width - 1)

    # log infos
    logs.info('ROI file succesfully read: %s', fname)

    return rowmin, rowmax, colmin, colmax
Example #4
0
def get_roi(name):
    listing = s3_client.list_objects(Bucket=BUCKET, Prefix=image_path(name))
    result = []
    for file in listing["Contents"]:
        if (file["Key"].endswith('.roi')):
            print(file["Key"])
            tmp_file = '/tmp/roi_file_tmp.roi'
            with open(tmp_file, 'wb') as f:
                s3_client.download_fileobj(BUCKET, file["Key"], f)
            rois = read_roi_file(tmp_file)
            result.append(rois)
    return jsonify(result)
Example #5
0
def read_roi_and_get_mask(roi_paths, mask_names, root_data_folder, mask_folder,
                          im_type, image_name, shape):
    #Create Black image to put the masks on:
    mask_img = np.zeros(shape, np.uint8)

    for i, (roi_path, mask_name) in enumerate(zip(roi_paths, mask_names)):
        #Get the roi
        roi = read_roi_file(roi_path)[mask_name]
        #Create the mask
        mask_img = obtain_mask(mask_img, roi)
        #Define the path to be written to
        mask_path = root_data_folder + "/" + mask_folder + "/" + image_name + "_" + im_type + ".jpg"
    return mask_path, mask_img
Example #6
0
    def _load_profiles_from_imagej(self, fn, constant_slice=None, gui=True):
        """
        Read line profiles from Fiji/ImageJ.

        Parameters
        ----------
            fn : str
                Filename containing line profiles.
            constant_slice : int
                Set slice to a constant value. Useful if ImageJ 
                output is inconsistent.
            gui: bool
                flag to update names / send signals to update the gui profile list.
        """
        import zipfile
        try:
            import read_roi
        except (ImportError):
            raise ImportError(
                'Please install the read_roi package (https://pypi.org/project/read-roi/).'
            )

        try:
            imagej_rois = read_roi.read_roi_zip(fn)
        except (zipfile.BadZipFile):
            imagej_rois = read_roi.read_roi_file(fn)

        for key in imagej_rois.keys():
            roi = imagej_rois[key]
            # Check for a slice val
            if constant_slice is None:
                try:
                    slice_val = roi['position'] - 1
                except KeyError:
                    slice_val = 0
            else:
                slice_val = constant_slice
            # x, y transposed in Fiji/ImageJ
            # Position is 1-indexed in Fiji/ImageJ
            self.add_line_profile(rois.LineProfile(roi['y1'],
                                                   roi['x1'],
                                                   roi['y2'],
                                                   roi['x2'],
                                                   slice=slice_val,
                                                   width=roi['width'],
                                                   identifier=roi['name'],
                                                   image_name=self.image_name),
                                  update=False)
        if gui:
            self.update_names(relabel=True)
            self._on_list_changed()
Example #7
0
def batch_stats(folder, conditions, use_roi=False):

    for filename in os.listdir(folder):
        if filename.endswith('xlsx'):
            stats_path = os.path.join(folder, filename)
            basename = os.path.splitext(filename)[0]

            if use_roi:
                roi_zip_path = os.path.join(folder, basename + '_roiset.zip')
                roi_file_path = os.path.join(folder, basename + '_roiset.roi')
                if os.path.exists(roi_zip_path):
                    rois = read_roi_zip(roi_zip_path)
                elif os.path.exists(roi_file_path):
                    rois = read_roi_file(roi_file_path)
                else:
                    raise ValueError(("No ImageJ roi file exists -"
                                      "you should put the file in the same"
                                      "directory as the data"))

                stats = []
                for roi in rois.keys():
                    stats.append(import_cluster_stats(stats_path),
                                 sheetname=roi)
                stats_df = pd.concat(stats)
            else:
                stats_df = import_cluster_stats(stats_path)

            fnames = [f for f in listdir(folder) if isfile(join(folder, f))]
            outpath = os.path.join(folder, 'cluster_statistics_test.xlsx')
            for condition in conditions:
                condition_fnames = [
                    fname for fname in fnames if condition in fname
                ]
                cluster_stats = []
                for cf in condition_fnames:
                    cluster_stats.append(stats[cf])

                cddf = pd.DataFrame(condition_fnames)
                cddf.columns = ['filename']
                csdf = pd.concat(cluster_stats, axis=0)
                data = pd.concat([cddf, csdf.reset_index(drop=True)], axis=1)
                statistics.write_stats(stats_path, data, condition)
def voronoi(locs_path,
            roi_path=None,
            pixel_size=16.0,
            density_factor=2,
            min_size=5,
            show_plot=True,
            verbose=True):

    if locs_path.endswith('csv'):  # Thunderstorm
        locs_df = pd.read_csv(locs_path)

        if roi_path:
            if roi_path.endswith('zip'):
                rois = read_roi_zip(roi_path)
            elif roi_path.endswith('roi'):
                rois = read_roi_file(roi_path)
            else:
                raise ValueError(
                    ("No ImageJ roi file exists -"
                     "you should put the file in the same directory"
                     "as the data and make sure it has the same base"
                     "filename as the localisations."))
        else:
            # use all the localisations but mimic the rois dict data structure
            dx = locs_df['x [nm]'].max() - locs_df['x [nm]'].min()
            dy = locs_df['y [nm]'].max() - locs_df['y [nm]'].min()
            rois = {'image': {'locs': locs_df, 'width': dx, 'height': dy}}

        for roi_id, roi in rois.items():
            vor = build_voronoi(rois[roi_id]['locs'],
                                show_plot=False,
                                verbose=verbose)
            clusters = voronoi_clustering(vor, density_factor, min_size)
            if show_plot:
                plot_voronoi_diagram(clusters['voronoi'],
                                     locs_df=clusters['locs'])

        return clusters
    else:
        raise ValueError(
            "This can only handle data from Thunderstorm at present")
Example #9
0
def get_locs_in_rois(ijroi_path, roi_scale, locs):

    if ijroi_path.endswith('zip'):
        rois = read_roi_zip(ijroi_path)
    elif ijroi_path.endswith('roi'):
        rois = read_roi_file(ijroi_path)
    else:
        raise ValueError("No ImageJ roi file exists")

    for _, roi in rois.items():
        for k, v in roi.items():
            if not isinstance(v, str):
                roi[k] = float(v) * roi_scale

        roi['locs'] = locs[(locs['x'] > roi['left'])
                           & (locs['x'] < roi['left'] + roi['width']) &
                           (locs['y'] > roi['top']) &
                           (locs['y'] <
                            roi['top'] + roi['height'])].reset_index(drop=True)

    return rois
def voronoi_segmentation(locs_path,
                         roi_path=None,
                         segment_rois=False,
                         pixel_size=16.0,
                         monte_carlo=True,
                         object_density_factor=2,
                         object_min_samples=3,
                         cluster_density_factor=20,
                         cluster_min_samples=3,
                         num_rois=5,
                         roi_size=7000.0,
                         show_plot=False):
    """
    This uses a Monte Carlo simulation to predict which
    localisations are no better than a random distribution.
    This is used to do a first pass segmentation of 'objects'
    after which 'clusters' are located in those in those objects
    based on local density and a minimum number of objects.
    """
    # read in the complete localisations
    if locs_path.endswith('csv'):  # Thunderstorm
        locs = pd.read_csv(locs_path)
    else:
        raise ValueError(
            "This can only handle data from Thunderstorm at present")

    if roi_path:
        if roi_path.endswith('zip'):
            input_rois = read_roi_zip(roi_path)
        elif roi_path.endswith('roi'):
            input_rois = read_roi_file(roi_path)
        else:
            raise ValueError(("No ImageJ roi file exists -"
                              "you should put the file in the same directory"
                              "as the data and make sure it has the same base"
                              "filename as the localisations."))
        # add the localisations to the rois dict
        rois = roi_coords(locs, input_rois, pixel_size)
    else:
        # generate a random set of rois
        rois = random_rois(locs, num_rois, roi_size)

    if monte_carlo:
        intersection = 0.0
        for roi_id, roi in rois.items():
            print("Monte Carlo simulation in ROI {0}".format(roi_id))
            # pass the locs DataFrame and roi dict to voronoi_montecarlo
            rmc = voronoi_montecarlo(roi, show_plot=show_plot)
            intersection += rmc['intersection']

        # always use the average intersection
        intersection /= float(len(rois))
        thresh = 1.0 / intersection

    # density factor for each roi (whether random roi or IJ roi)
    density_factor = {}
    for roi_id, roi in rois.items():
        if monte_carlo:
            density_factor[roi_id] = thresh / density(roi['locs'])
        else:
            density_factor[roi_id] = object_density_factor

    if not segment_rois:
        # use all the localisations but mimic the rois dict data structure
        rois = {'image': {'locs': locs}}
        # and reset the density_factor for the whole image
        density_factor = {}
        if monte_carlo:
            density_factor['image'] = thresh / density(rois['image']['locs'])
        else:
            density_factor['image'] = object_density_factor

    print("density_factor: {}".format(density_factor))

    # now loop over the rois data structure
    for roi_id, roi in rois.items():
        # build the voronoi diagram
        roi_locs = roi['locs']
        roi_locs['object_id'] = -1
        roi_locs['cluster_id'] = -1
        vor = build_voronoi(roi_locs)

        if monte_carlo:
            print("intersection: {0}".format(intersection))
            print("density threshold: {0}".format(thresh))

        print("density_factor: {}".format(density_factor[roi_id]))

        objs = voronoi_clustering(vor,
                                  density_factor[roi_id],
                                  object_min_samples,
                                  cluster_column='object_id')

        # write the objects to the original localisations data structure
        obj_locs = objs['locs']
        roi_locs.loc[roi_locs.object_id.isin(obj_locs.object_id),
                     ['object_id']] = (
                         obj_locs[obj_locs['object_id'] > -1]['object_id'])

        # retain only the objects that are 'clustered'
        filtered = obj_locs[obj_locs['object_id'] != -1]

        # prepare the data structure for re-clustering
        data = {'voronoi': vor['voronoi'], 'locs': filtered}

        # set parameters and find clusters in objects
        n_locs = len(roi_locs.index)
        clusters = voronoi_clustering(data,
                                      cluster_density_factor,
                                      cluster_min_samples,
                                      cluster_column='cluster_id',
                                      num_locs=n_locs)

        # write the clusters to the original localisations data structure
        clust_locs = clusters['locs']
        roi_locs.loc[roi_locs.cluster_id.isin(clust_locs.cluster_id),
                     ['cluster_id']] = (clust_locs[
                         clust_locs['cluster_id'] > -1]['cluster_id'])

        if show_plot:
            cfig = plot_voronoi_diagram(clusters['voronoi'],
                                        locs_df=clusters['locs'],
                                        cluster_column='cluster_id')
            plot_cluster_polygons(objs['locs'],
                                  figure=cfig,
                                  cluster_column='object_id')
            plt.show()

        # fill nan values before returning
        roi_locs[['object_id',
                  'cluster_id']] = roi_locs[['object_id',
                                             'cluster_id']].fillna(value=-1)
        roi['locs'] = roi_locs
    return rois
Example #11
0
from read_roi import read_roi_file
import numpy as np
from PIL import Image, ImageDraw
from matplotlib import pyplot as plt

width = 84
height = 128

ROIFilename = '15_ADC'

# read roi file
roi_object = read_roi_file(ROIFilename + '.roi')
roi_temp = roi_object[ROIFilename]

# make polygon
polygon = []
for x, y in zip(roi_temp['x'], roi_temp['y']):
    polygon.append(x)
    polygon.append(y)

# make mask
img = Image.new('L', (width, height), 0)
ImageDraw.Draw(img).polygon(polygon, outline=1, fill=1)
mask = np.array(img)

# display
plt.imshow(mask, cmap='gray')
plt.show()
Example #12
0
def calc_nuclear_enrichment(FQ_file, binsHist):

    ## Get folder
    drive, path_and_file = os.path.splitdrive(FQ_file)
    path_results, file_results = os.path.split(path_and_file)

    # *************************************************************************
    # Load nuclear outline

    # Generate binary masks for a selected data-set
    binaryGen = maskGenerator.BinaryMaskGenerator(erose_size=5,
                                                  obj_size_rem=500,
                                                  save_indiv=True,
                                                  progress_callback=None)

    ## Import annotations for nuclei
    path_annot = os.path.join(drive, path_results, 'zstack_segmentation')
    folderImporter = annotationImporter.FolderImporter(
        channels={'nuclei': 'C4-'},
        data_category={'roi': ''},
        annot_ext='__RoiSet.zip',
        progress_callback=None)
    annotDict = folderImporter.load(path_annot)
    print('average roi size:', annotDict['roi_size'])

    # The generate function uses as an input the sub-dictionary for one data-category and one channel
    annotatFiles = annotDict['roi']['nuclei']
    mask_dict_nuclei = binaryGen.generate(annotatFiles)

    keys_delete = []
    for k, v in annotatFiles.items():

        # Make sure that key in present in mask, otherwise delete
        if k in mask_dict_nuclei:
            v.update(mask_dict_nuclei[k])

        else:
            keys_delete.append(k)

    # *************************************************************************
    #  Load embryo outline
    file_embryo = os.path.join(drive, path_results, 'embryo_contour.roi')

    # Conver dictionary & get size of ROIS
    roi_import = read_roi_file(file_embryo)
    roi_dict = {}
    roi_dict['embryo'] = {}
    roi_dict['embryo']['type'] = roi_import['embryo_contour']['type']
    roi_dict['embryo']['pos'] = np.column_stack(
        (roi_import['embryo_contour']['y'], roi_import['embryo_contour']['x']))

    # Assemble structure to call mask generator
    image_size = annotatFiles.values().__iter__().__next__()['image'].shape
    image_fake = np.zeros(image_size, dtype=np.uint8)

    annotat_files_embryo = {}
    annotat_files_embryo['embryo_contour'] = {}
    annotat_files_embryo['embryo_contour']['roi'] = roi_dict
    annotat_files_embryo['embryo_contour']['image'] = image_fake

    mask_dict_embryo = binaryGen.generate(annotat_files_embryo)
    mask_embryo = mask_dict_embryo['embryo_contour']['mask_fill']

    # *************************************************************************
    #  Load and analyze FQ results

    fq_dict = FQtoolbox.read_FQ_matlab(file_load)
    spots_all = FQtoolbox.get_rna(fq_dict)

    # Z position in pixel
    Zrna = np.divide(spots_all[:, [2]],
                     fq_dict['settings']['microscope']['pix_z']).astype(int)

    # Other parameters for calculation
    dist_membr_RNA = np.array([])
    dist_membr_pix = np.array([])
    idx = 0

    # Loop over all z-slices
    print(' == Loop over slices')

    for idx_file, (k_annot, v_annot) in enumerate(annotatFiles.items()):

        print(f'Slice: {k_annot}')

        # Get Z coordinate
        m = re.search('.*_Z([0-9]*)\.tif', k_annot)
        Zmask = int(m.group(1))

        # Check if outside of specified z range
        if Zrange is not None:
            if (Zmask < Zrange[0]) or (Zmask > Zrange[1]):
                print(f'Z-slice outside of specified range: {Zmask}')
                continue

        # Get z-range for loop
        Zloop = np.logical_and(Zrna <= Zmask + dZ,
                               Zrna >= Zmask - dZ).flatten()
        Zloop = (Zrna == Zmask).flatten()
        spots_loop = spots_all[Zloop, :]
        spots_loop_XY = np.divide(
            spots_loop[:, [0, 1]],
            fq_dict['settings']['microscope']['pix_xy']).astype(int)

        # Distance transform
        dist_nuc_outside = ndimage.distance_transform_edt(
            ~v_annot['mask_fill'])
        dist_nuc_inside = ndimage.distance_transform_edt(
            v_annot['mask_fill'])  # Negate mask
        dist_nuc = dist_nuc_outside - dist_nuc_inside

        # Indices have to be inversed to access array
        dist_nuc_RNA_loop = dist_nuc[spots_loop_XY[:, 0], spots_loop_XY[:, 1]]

        # Get distance from membrane for all pixel in the cell
        dist_membr_pix_loop = dist_nuc[mask_embryo.astype(bool)]

        # Save values
        if idx == 0:
            dist_membr_RNA = np.copy(dist_nuc_RNA_loop)
            dist_membr_pix = np.copy(dist_membr_pix_loop)
        else:
            dist_membr_RNA = np.append(dist_membr_RNA,
                                       dist_nuc_RNA_loop,
                                       axis=0)
            dist_membr_pix = np.append(dist_membr_pix,
                                       dist_membr_pix_loop,
                                       axis=0)
        idx += 1

    # *************************************************************************
    #  Load and analyze FQ results
    xTicks = binsHist[:-1]
    width = 0.9 * np.diff(binsHist)
    width_full = np.diff(binsHist)
    center = (binsHist[:-1] + binsHist[1:]) / 2

    histRNA_all, bins = np.histogram(dist_membr_RNA, binsHist, density=False)
    histPIX_all, bins = np.histogram(dist_membr_pix, binsHist, density=False)
    histRNA_norm = np.divide(histRNA_all, histPIX_all)
    counts_total = np.nansum(np.multiply(histRNA_norm, width_full))
    histRNA_norm = np.divide(histRNA_norm, counts_total)

    fig1, ax = plt.subplots(3, 1)
    ax[0].bar(center, histRNA_all, align='center', width=width)
    ax[0].set_xlabel('Dist to nuc')
    ax[0].set_ylabel('# RNAs')
    ax[0].set_xticks(xTicks)
    ax[0].set_xticklabels(xTicks.astype(int))

    ax[1].bar(center, histPIX_all, align='center', width=width)
    ax[1].set_xlabel('Dist to nuc')
    ax[1].set_ylabel('# pixels')
    ax[1].set_xticks(xTicks)
    ax[1].set_xticklabels(xTicks.astype(int))

    ax[2].bar(center, histRNA_norm, align='center', width=width)
    ax[2].set_xlabel('Distance to nuc')
    ax[2].set_ylabel('RNA counts [a.u.]')
    ax[2].set_xticks(xTicks)
    ax[2].set_xticklabels(xTicks.astype(int))

    ax[0].title.set_text('RNAs')
    ax[1].title.set_text('All pixel')
    ax[2].title.set_text('RNA renormalized with pixels')

    plt.tight_layout()
Example #13
0
keys_delete = []
for k, v in annotatFiles.items():

    # Make sure that key in present in mask, otherwise delete
    if k in maskDict:
        v.update(maskDict[k])

    else:
        keys_delete.append(k)

#%% Determine embryo outline
from read_roi import read_roi_file
file_embryo = os.path.join(drive, path_results, 'embryo_contour.roi')

# Conver dictionary & get size of ROIS
roi_import = read_roi_file(file_embryo)
roi_dict = {}
roi_dict['embryo'] = {}
roi_dict['embryo']['type'] = roi_import['embryo_contour']['type']
roi_dict['embryo']['pos'] = np.column_stack(
    (roi_import['embryo_contour']['y'], roi_import['embryo_contour']['x']))

# Assemble structure to call mask generator
image_size = annotatFiles.values().__iter__().__next__()['image'].shape
image_fake = np.zeros(image_size, dtype=np.uint8)

annotat_files_embryo = {}
annotat_files_embryo['embryo_contour'] = {}
annotat_files_embryo['embryo_contour']['roi'] = roi_dict
annotat_files_embryo['embryo_contour']['image'] = image_fake
Example #14
0
        nTotFiles) + ") " + ch1_filenames[nFile]
    print(sWork)
    # ADD WAITBAR

    # read tiff file
    filenameG = filebase + ".tif"

    I_G = plt.imread(filenameG)

    szG = I_G.shape

    imwidth = I_G.shape[1]
    imheight = I_G.shape[0]

    #read Kymo_ROI
    sROI = read_roi_file(filebase + ".roi")
    if sROI[ch1_filenames[nFile]]["type"] == "line":
        xcoord = list()
        ycoord = list()
        xcoord = int(sROI[ch1_filenames[nFile]]['x1']), (int(
            sROI[ch1_filenames[nFile]]['x2']))
        ycoord = int(sROI[ch1_filenames[nFile]]['y1']), (int(
            sROI[ch1_filenames[nFile]]['y2']))
        sROI[ch1_filenames[nFile]]["x"] = xcoord
        sROI[ch1_filenames[nFile]]["y"] = ycoord
        del sROI[ch1_filenames[nFile]]['x1']
        del sROI[ch1_filenames[nFile]]['x2']
        del sROI[ch1_filenames[nFile]]['y1']
        del sROI[ch1_filenames[nFile]]['y2']

    nPoints = len(sROI[ch1_filenames[nFile]]['x'])
Example #15
0
def get_line_profile(image,
                     start=(),
                     end=(),
                     froi='',
                     ShowPlot=True,
                     PlotTitle='Profile',
                     linewidth=1,
                     order=1,
                     mode='constant',
                     cval=0.0):
    """
	This function returns the intensity profile of an image measured along a line defined by the points:

			start = (x_start, y_start)  [i.e. (col_start row_start)]
			end   = (x_end, y_en)       [i.e. (col_end row_end)]

	or an ImageJ .roi file containing the line selection. A plot representing the intensity profile can be shown.

    Parameters
    ----------
    image : ndarray
        The image grayscale (2D array) or a stack of images (3d array) with shape (slices, rows, columns).
        Ffor a 3D array the first axis represents the image index.

    start : 2-tuple of numeric scalar (float or int) (x y) [i.e. (col row)]
        The start point of the scan line.

    end : 2-tuple of numeric scalar (float or int) (x y) [i.e. (col row)]
        The end point of the scan line. The destination point is *included*
        in the profile, in constrast to standard numpy indexing.

    froi : string
        Path of the imagej file containing the line selection.

    ShowPlot : bool
        If True a canvas is created representing the Plot Profile.

    linewidth : int, optional
        Width of the scan, perpendicular to the line

    order : int in {0, 1, 2, 3, 4, 5}, optional
        The order of the spline interpolation to compute image values at
        non-integer coordinates. 0 means nearest-neighbor interpolation.

    mode : {'constant', 'nearest', 'reflect', 'mirror', 'wrap'}, optional
        How to compute any values falling outside of the image.

    cval : float, optional
        If `mode` is 'constant', what constant value to use outside the image.

    Returns
    -------
    return_value : array
        The intensity profile along the scan line. The length of the profile
        is the ceil of the computed length of the scan line.
	"""

    if (froi and (start or end)):
        raise ValueError(
            'Please indicate an ImageJ .roi file or two tuples of coordinates.'
        )

    if (froi):
        # read roi file
        roi = read_roi_file(froi)

        # convert keys to list
        l = list(roi.keys())

        # extract type
        tp = roi[l[0]]['type']

        if (tp == 'line'):
            start = np.floor([roi[l[0]]['x1'], roi[l[0]]['y1']])
            end = np.floor([roi[l[0]]['x2'], roi[l[0]]['y2']])
        else:
            raise ValueError(
                "File specified does not contain a line selection.")

    start = start[::-1]
    end = end[::-1]

    if (image.ndim == 3):
        image = image.swapaxes(0, 2).swapaxes(0, 1)

    y = profile_line(image, start, end, linewidth, order, mode, cval)

    if (ShowPlot):
        plt.figure(PlotTitle)
        plt.plot(y, '-')
        plt.show(block=False)

    if (image.ndim == 3):
        y = y.swapaxes(0, 1)

    return y
def calc_nuclear_enrichment(FQ_file,
                            binsHist,
                            channels={'nuclei': ''},
                            show_plots=False,
                            Zrange=None,
                            dZ=2,
                            plot_callback=None,
                            progress_callback=None,
                            log_callback=None):
    """
    Enrichment at the nuclear MEMBRANE
    Function uses annotations generated in FIJI and creates mask based
    on the specified parameters.
    """

    # Get input args. Has to be FIRST call!
    input_args = locals()

    # Get folder
    drive, path_and_file = os.path.splitdrive(FQ_file)
    path_results, file_results = os.path.split(path_and_file)
    file_base, ext = os.path.splitext(file_results)

    path_save = os.path.join(
        drive, path_results, file_base, 'NucEnvelopDist_{}'.format(
            time.strftime("%y%m%d-%H%M", time.localtime())))
    if not os.path.isdir(path_save):
        os.makedirs(path_save)

    # *************************************************************************
    # Load nuclear outline
    utils.log_message(f'Reading segmentation masks of nuclei',
                      callback_fun=log_callback)

    # Generate binary masks for a selected data-set
    binaryGen = maskGenerator.BinaryMaskGenerator(
        erose_size=5,
        obj_size_rem=500,
        save_indiv=True,
        progress_callback=progress_callback)

    # Import annotations for nuclei
    path_annot = os.path.join(drive, path_results, 'zstack_segmentation')
    folderImporter = annotationImporter.FolderImporter(
        channels=channels,
        data_category={'roi': ''},
        annot_ext='__RoiSet.zip',
        progress_callback=progress_callback)
    annotDict = folderImporter.load(path_annot)

    # The generate function uses as an input the sub-dictionary for one data-category and one channel
    annotatFiles = annotDict['roi']['nuclei']
    mask_dict_nuclei = binaryGen.generate(annotatFiles)

    keys_delete = []
    for k, v in annotatFiles.items():

        # Make sure that key in present in mask, otherwise delete
        if k in mask_dict_nuclei:
            v.update(mask_dict_nuclei[k])

        else:
            keys_delete.append(k)

    # *************************************************************************
    #  Load embryo outline
    file_embryo = os.path.join(drive, path_results, 'embryo_contour.roi')

    # Convert dictionary & get size of ROIS
    roi_import = read_roi_file(file_embryo)
    roi_dict = {}
    roi_dict['embryo'] = {}
    roi_dict['embryo']['type'] = roi_import['embryo_contour']['type']
    roi_dict['embryo']['pos'] = np.column_stack(
        (roi_import['embryo_contour']['y'], roi_import['embryo_contour']['x']))

    # Assemble structure to call mask generator
    image_size = annotatFiles.values().__iter__().__next__()['image'].shape
    image_fake = np.zeros(image_size, dtype=np.uint8)

    annotat_files_embryo = {}
    annotat_files_embryo['embryo_contour'] = {}
    annotat_files_embryo['embryo_contour']['roi'] = roi_dict
    annotat_files_embryo['embryo_contour']['image'] = image_fake

    mask_dict_embryo = binaryGen.generate(annotat_files_embryo)
    mask_embryo = mask_dict_embryo['embryo_contour']['mask_fill']

    # *************************************************************************
    #  Load and analyze FQ results

    fq_dict = FQtoolbox.read_FQ_matlab(FQ_file)
    spots_all = FQtoolbox.get_rna(fq_dict)

    # Z position in pixel
    Zrna = np.divide(spots_all[:, [2]],
                     fq_dict['settings']['microscope']['pix_z']).astype(int)

    # Other parameters for calculation
    dist_membr_RNA = np.array([])
    dist_membr_pix = np.array([])
    idx = 0

    # Loop over all z-slices
    utils.log_message(f'Loop over z-slices', callback_fun=log_callback)

    N_annot = len(annotatFiles)
    for idx_file, (k_annot, v_annot) in enumerate(annotatFiles.items()):

        # Indicate progress via callback
        if progress_callback:
            perc = int(100 * (idx_file + 1) / (N_annot))
            progress_callback({
                "task": "analyze_slices",
                "text": f"{perc}%, {k_annot}",
                "progress": perc
            })
        else:
            print(f'Slice: {k_annot}')

        # Get Z coordinate
        m = re.search('.*_Z([0-9]*)\.tif', k_annot)
        Zmask = int(m.group(1))

        # Check if outside of specified z range
        if Zrange is not None:
            if not (Zrange[0] == 0 and Zrange[1] == 0):
                if (Zmask < Zrange[0]) or (Zmask > Zrange[1]):
                    print(f'Z-slice outside of specified range: {Zmask}')
                    continue

        # Get z-range for loop
        if dZ == 0:
            Zloop = np.logical_and(Zrna <= Zmask + dZ,
                                   Zrna >= Zmask - dZ).flatten()
        else:
            Zloop = (Zrna == Zmask).flatten()

        spots_loop = spots_all[Zloop, :]
        spots_loop_XY = np.divide(
            spots_loop[:, [0, 1]],
            fq_dict['settings']['microscope']['pix_xy']).astype(int)

        # Distance transform
        dist_nuc_outside = ndimage.distance_transform_edt(
            ~v_annot['mask_fill'])
        dist_nuc_inside = ndimage.distance_transform_edt(
            v_annot['mask_fill'])  # Negate mask
        dist_nuc = dist_nuc_outside - dist_nuc_inside

        # Indices have to be inverted to access array
        dist_nuc_RNA_loop = dist_nuc[spots_loop_XY[:, 0], spots_loop_XY[:, 1]]

        # Get distance from membrane for all pixel in the cell
        dist_membr_pix_loop = dist_nuc[mask_embryo.astype(bool)]

        # Save values
        if idx == 0:
            dist_membr_RNA = np.copy(dist_nuc_RNA_loop)
            dist_membr_pix = np.copy(dist_membr_pix_loop)
        else:
            dist_membr_RNA = np.append(dist_membr_RNA,
                                       dist_nuc_RNA_loop,
                                       axis=0)
            dist_membr_pix = np.append(dist_membr_pix,
                                       dist_membr_pix_loop,
                                       axis=0)
        idx += 1

    # *************************************************************************
    #  Load and analyze FQ results
    utils.log_message(f'Analyzing smFISH data', callback_fun=log_callback)

    x_ticks = binsHist[:-1]
    width = 0.9 * np.diff(binsHist)
    width_full = np.diff(binsHist)
    center = (binsHist[:-1] + binsHist[1:]) / 2

    #histRNA_all, bins = np.histogram(dist_membr_RNA,binsHist ,density=False)
    #histPIX_all, bins = np.histogram(dist_membr_pix,binsHist ,density=False)
    #histRNA_norm = np.divide(histRNA_all,histPIX_all)
    #counts_total = np.nansum(np.multiply(histRNA_norm,width_full))
    #histRNA_norm = np.divide(histRNA_norm,counts_total)

    # Distance of all pixel from distance map
    hist_pix_all, bins = np.histogram(dist_membr_pix, binsHist, density=False)
    hist_pix_all_norm = hist_pix_all / hist_pix_all.sum()

    # Distance of all RNAs
    hist_rna_all, bins = np.histogram(dist_membr_RNA, binsHist, density=False)
    hist_rna_all_norm = hist_rna_all / hist_rna_all.sum()

    # Re-normalize RNA distances
    hist_rna_all_norm_pix = np.divide(hist_rna_all_norm, hist_pix_all_norm)
    hist_rna_all_norm_pix = np.nan_to_num(hist_rna_all_norm_pix)

    # Save file with histogram
    histo_dist = {
        'center': center,
        'width': width_full,
        'bins': binsHist,
        'x_ticks': x_ticks,
        'hist_pix_all': hist_pix_all,
        'hist_pix_all_norm': hist_pix_all_norm,
        'hist_rna_all': hist_rna_all,
        'hist_rna_all_norm': hist_rna_all_norm,
        'hist_rna_all_norm_pix': hist_rna_all_norm_pix
    }

    # Save entire analysis results as json
    input_args.pop('show_plot', None)
    input_args.pop('plot_callback', None)
    input_args.pop('progress_callback', None)
    input_args.pop('log_callback', None)

    analysis_results = {
        'args': input_args,
        'histogram': histo_dist,
    }

    name_json = os.path.join(path_save, 'DataAnalysis.json')

    with open(name_json, 'w') as fp:
        json.dump(analysis_results,
                  fp,
                  sort_keys=True,
                  indent=4,
                  cls=utils.NumpyEncoder)

    # Save histogram of pooled data as csv
    name_csv = os.path.join(path_save, '_HistogramDistances.csv')
    histo_dist.pop('bins', None)
    csv_header = ';'.join(histo_dist.keys())
    hist_values = np.array(list(histo_dist.values())).transpose()
    np.savetxt(name_csv,
               hist_values,
               delimiter=";",
               fmt='%f',
               header=csv_header,
               comments='')

    # *************************************************************************
    # Plot results
    # Don't show plots when they are saved
    if not show_plots:
        plt.ioff()

    fig1, ax = plt.subplots(3, 1)
    ax[0].bar(center, hist_rna_all, align='center', width=width)
    ax[0].set_xlabel('Dist to nuc')
    ax[0].set_ylabel('# RNAs')
    ax[0].set_xticks(x_ticks)
    ax[0].set_xticklabels(x_ticks.astype(int))

    ax[1].bar(center, hist_pix_all, align='center', width=width)
    ax[1].set_xlabel('Dist to nuc')
    ax[1].set_ylabel('# pixels')
    ax[1].set_xticks(x_ticks)
    ax[1].set_xticklabels(x_ticks.astype(int))

    ax[2].bar(center, hist_rna_all_norm_pix, align='center', width=width)
    ax[2].set_xlabel('Distance to nuc')
    ax[2].set_ylabel('RNA counts [a.u.]')
    ax[2].set_xticks(x_ticks)
    ax[2].set_xticklabels(x_ticks.astype(int))

    ax[0].title.set_text('RNAs')
    ax[1].title.set_text('All pixel in images')
    ax[2].title.set_text('RNAs renormalized with pixels')

    plt.tight_layout()

    # Save and close if display not required
    name_save = os.path.join(path_save, '_DistanceEnrichmentSummary.png')
    plt.savefig(name_save, dpi=300)

    if not show_plots:
        plt.close()

    if plot_callback:
        plot_callback(name_save)

    if progress_callback:
        with open(name_save, 'rb') as f:
            data = f.read()
            result = base64.b64encode(data).decode('ascii')
            img_url = 'data:image/png;base64,' + result
            progress_callback({"task": "show_results", "src": img_url})
Example #17
0
def test_roi_data(name, true_data):
    fname = load_data(name)
    data = read_roi.read_roi_file(fname)
    TestCase().assertDictEqual(data, true_data)
def main():
    root_path = '/media/julien/Not_today/hne_not_today/data/crcns_data/chen_2013/'

    # identifier = "20120416_cell1_001"
    identifier = "20120416_cell1_002"
    # identifier = "20120417_cell3_001"
    # identifier = "20120417_cell3_003"
    # identifier = "20120515_cell1_003"
    # identifier = "20120417_cell4_001"
    # identifier = "20120627_cell3_001"
    # identifier = "20120515_cell1_004"
    # identifier = "20120417_cell4_002"
    # identifier = "20120417_cell3_002"
    # identifier = "20120627_cell3_002"
    # identifier = "20120417_cell1_002"
    # identifier = "20120417_cell4_003"
    # identifier = "20120417_cell5_002"
    # identifier = "20120515_cell1_003"
    # identifier = "20120515_cell1_005"
    # identifier = "20120515_cell1_006"
    # identifier = "20120627_cell4_002"
    # identifier = "20120627_cell4_004"
    # identifier = "20120627_cell4_005"

    # 20120417_cell4_001
    two_files_version = False
    # data_path = os.path.join(root_path, "for_test", identifier)
    data_path = os.path.join(root_path, identifier)

    downsampling_factor = 6

    # test = hdf5storage.loadmat(os.path.join(data_path, 'cell1_002.mat'))
    # print(f"test {test}")

    if two_files_version:
        frame_times_file = os.path.join(data_path,
                                        f"{identifier}_frame_times.mat")
        spike_times_file = os.path.join(data_path,
                                        f"{identifier}_spike_times.mat")
        frame_times = hdf5storage.loadmat(frame_times_file)['t_frame']
        spike_times = hdf5storage.loadmat(spike_times_file)['spike_time']
    else:
        info = hdf5storage.loadmat(
            os.path.join(data_path, f'info_{identifier}.mat'))
        frame_times = info['t_frame']
        spike_times = info['spike_time']
    frame_times = np.ndarray.flatten(frame_times)
    print(f"n frames {len(frame_times)}")

    zip_file = os.path.join(data_path, f"{identifier}_25_25.zip")
    roi_file = os.path.join(data_path, f"{identifier}_25_25.roi")
    zip_data = None
    if os.path.isfile(zip_file):
        zip_data = read_roi_zip(zip_file)
    else:
        roi = read_roi_file(roi_file)

    # test = hdf5storage.loadmat(os.path.join(data_path, 'p12_17_11_10_a000_CellDetect.mat'))
    # print(f"test {test}")

    # print(f"n frames {spike_times}")
    # print(f"n spikes {len(spike_times)}")
    # print(f"frames {frame_times.shape}")
    # print(f"spikes {spike_times}")

    # print(f"roi {roi}")

    # all_contours = []
    if zip_data is not None:
        coords_caiman_style = np.empty((len(zip_data), ), dtype=np.object)
        # for i in range(len(self.map_coords)):
        #     coords_caiman_style[i] = self.map_coords[i]
        for roi_index, roi in enumerate(zip_data.values()):
            n_points = len(roi['x'])
            contours = np.zeros((2, n_points), dtype="int16")
            contours[0] = roi['x']
            contours[1] = roi['y']
            coords_caiman_style[roi_index] = contours
            # all_contours.append(contours)
            # print(f"all_contours {all_contours}")
    else:
        coords_caiman_style = np.empty((1, ), dtype=np.object)
        roi = roi[list(roi.keys())[0]]
        n_points = len(roi['x'])
        contours = np.zeros((2, n_points), dtype="int16")
        contours[0] = roi['x']
        contours[1] = roi['y']
        coords_caiman_style[0] = contours

    n_times = len(frame_times)
    if downsampling_factor > 1:
        if n_times % downsampling_factor != 0:
            raise Exception(
                f"Number of frames {n_times} not divisible by {downsampling_factor}"
            )
        n_times = n_times // downsampling_factor

    spikes_num = np.zeros((len(coords_caiman_style), n_times), dtype="int8")
    for index_spike, spike_time in enumerate(spike_times):
        frame = find_nearest(array=frame_times, value=spike_time)
        frame = int(frame / downsampling_factor)
        if frame == n_times:
            frame -= 1
        spikes_num[0, frame] = 1

    np.save(os.path.join(data_path, f"{identifier}_contours.npy"),
            coords_caiman_style)
    # sio.savemat(os.path.join(data_path, f"{identifier}_contours.mat"), {"AllContours": coords_caiman_style})
    if downsampling_factor > 1:
        np.save(
            os.path.join(
                data_path,
                f"{identifier}_spikes_{int(60/downsampling_factor)}_hz.npy"),
            spikes_num)
    else:
        np.save(os.path.join(data_path, f"{identifier}_spikes.npy"),
                spikes_num)
diname = sorted(glob.glob(dipath))

# roi to mask
for fl in range(len(rfolname)):

    rpath = "../data/roi/" + rfolname[fl] + "/*"
    rfname = glob.glob(rpath)

    roiname = os.listdir("../data/roi/" + rfolname[fl])
    locset = []
    for rf in range(len(rfname)):

        rname, ext = os.path.splitext(roiname[rf])
        rfile = rfname[rf]

        roi = read_roi_file(rfile)

        x = roi[rname]['x']
        y = roi[rname]['y']

        pn = len(x)
        loc = np.ndarray((pn, 2), dtype=np.int32)

        for lo in range(len(x)):

            loc[lo] = (x[lo], y[lo])

        locset.append(loc)

        for fw in range(len(locset)):
Example #20
0
def read_roi(path):
    return read_roi_file(path)
Example #21
0
def read_mri_data(root_path, if_normalized=True):
    '''read five types of images from the parent folder, if_normalized points to the T1 SAG images'''
    ims_T1s = []
    ims_T1 = []
    ims_T2s = []
    ims_T2 = []
    ims_T2st = []
    pos = []
    axis_ens_T1 = []
    axis_ens_T2 = []
    axis_ens_T2star = []

    for root, dirnames, filenames in os.walk(root_path):
        for filename in filenames:
            if root.find('T1_TSE_SAG') is not -1:
                f = os.path.join(root, filename)
                nb_chosen = int(len(filenames) / 2) + 1
                if f.endswith(str(nb_chosen) + '.dcm'):
                    ds = pydicom.dcmread(f)  # dcm format
                    im_T1s = ds.pixel_array  # array 这里train data是(512,512) dtype = int16
                    if if_normalized:
                        im_T1s = (im_T1s - im_T1s.mean()) / im_T1s.std()
                    ims_T1s.append(im_T1s)
                    pos.append(os.path.abspath(os.path.dirname(root)))
                    break

            if root.find('T1_Images') is not -1:
                f = os.path.join(root, filename)
                nb_chosen = int(len(filenames) / 2)
                if f.endswith(str(nb_chosen) + '.dcm'):
                    ds = pydicom.dcmread(f)  # dcm format
                    im_T1 = ds.pixel_array  # array 这里train data是(512,512) dtype = int16
                    if if_normalized:
                        im_T1 = (im_T1 - im_T1.mean()) / im_T1.std()
                    ims_T1.append(im_T1)
                    break
                if f.endswith('.roi'):
                    ds = read_roi_file(f)
                    for i, key in enumerate(ds.keys()):
                        xs = ds[key]['x']
                        ys = ds[key]['y']
                        break
                    axis_T1 = np.array([xs, ys]).T
                    axis_ens_T1.append(axis_T1)

            if root.find('T2_TSE_SAG') is not -1:
                f = os.path.join(root, filename)
                nb_chosen = int(len(filenames) / 2) + 1
                if f.endswith(str(nb_chosen) + '.dcm'):
                    ds = pydicom.dcmread(f)  # dcm format
                    im_T2s = ds.pixel_array  # array 这里train data是(512,512) dtype = int16
                    if if_normalized:
                        im_T2s = (im_T2s - im_T2s.mean()) / im_T2s.std()
                    ims_T2s.append(im_T2s)
                    break

            if root.find('T2_Images') is not -1:
                f = os.path.join(root, filename)
                nb_chosen = int(len(filenames) / 2) + 1
                if f.endswith(str(nb_chosen) + '.dcm'):
                    ds = pydicom.dcmread(f)  # dcm format
                    im_T2 = ds.pixel_array  # array 这里train data是(512,512) dtype = int16
                    if if_normalized:
                        im_T2 = (im_T2 - im_T2.mean()) / im_T2.std()
                    ims_T2.append(im_T2)
                    break
                if f.endswith('.roi'):
                    ds = read_roi_file(f)
                    for i, key in enumerate(ds.keys()):
                        xs = ds[key]['x']
                        ys = ds[key]['y']
                        break
                    axis_T2 = np.array([xs, ys]).T
                    axis_ens_T2.append(axis_T2)

            if root.find('T2Star_Images') is not -1:
                f = os.path.join(root, filename)
                nb_chosen = int(len(filenames) / 2) + 1
                if f.endswith(str(nb_chosen) + '.dcm'):
                    ds = pydicom.dcmread(f)  # dcm format
                    im_T2st = ds.pixel_array  # array 这里train data是(512,512) dtype = int16
                    if if_normalized:
                        im_T2st = (im_T2st - im_T2st.mean()) / im_T2st.std()
                    ims_T2st.append(im_T2st)
                    break
                if f.endswith('.roi'):
                    ds = read_roi_file(f)
                    for i, key in enumerate(ds.keys()):
                        xs = ds[key]['x']
                        ys = ds[key]['y']
                        break
                    axis_T2star = np.array([xs, ys]).T
                    axis_ens_T2star.append(axis_T2star)

    return np.array(ims_T1s), np.array(ims_T1), np.array(ims_T2s), np.array(
        ims_T2), np.array(ims_T2st), pos, np.array(axis_ens_T1), np.array(
            axis_ens_T2), np.array(axis_ens_T2star)
Example #22
0
def _parse_roi_file_py3(roi_source):
    """Parses an individual ImageJ ROI

    This implementation utilises the read_roi package, which is more robust
    but only supports Python 3+ and not Python 2.7.

    Parameters
    ----------
    roi_source : str or file object
        Path to file, or file object containing a single ImageJ ROI

    Returns
    -------
    dict
        Returns a parsed ROI object, a dictionary with either a `'polygons'`
        or a `'mask'` field.

    Raises
    ------
    IOError
        If there is an error reading the roi file object.
    ValueError
        If unable to parse ROI.
    """

    # Use read_roi package to load up the roi as a dictionary
    roi = read_roi.read_roi_file(roi_source)
    # This is a dictionary with a single entry, whose key is the label
    # of the roi. We need to get out its contents, which is another dictionary.
    keys = list(roi.keys())
    if len(keys) == 1:
        roi = roi[keys[0]]

    # Convert the roi dictionary into either polygon or a mask
    if 'x' in roi and 'y' in roi and 'n' in roi:
        # ROI types "freehand", "freeline", "multipoint", "point", "polygon",
        # "polyline", and "trace" are loaded and returned as a set of polygon
        # co-ordinates.
        coords = np.empty((roi['n'], 3), dtype=np.float)
        coords[:, 0] = roi['x']
        coords[:, 1] = roi['y']
        coords[:, 2] = roi.get('z', 0)
        if np.all(coords[:, 0] < 0) or np.all(coords[:, 1] < 0):
            raise ValueError("ROI is entirely offscreen.")
        return {'polygons': coords}

    if 'width' in roi and 'height' in roi and 'left' in roi and 'top' in roi:
        width = roi['width']
        height = roi['height']
        left = roi['left']
        top = roi['top']
        right = left + width
        bottom = top + height
        if right < 0 or bottom < 0:
            raise ValueError("ROI is entirely offscreen.")

    z = roi.get('z', 0)

    if roi['type'] == 'rectangle':
        # Rectangle is converted into polygon co-ordinates
        coords = [[left, top, z], [right, top, z], [right, bottom, z],
                  [left, bottom, z]]
        coords = np.array(coords).astype('float')
        return {'polygons': coords}

    elif roi['type'] == 'oval':
        # Oval
        mask = np.zeros((z + 1, right, bottom), dtype=bool)

        # We subtract 0.5 because ImageJ's co-ordinate system has indices at
        # the pixel boundaries, and we are using indices at the pixel centers.
        x_mid = left + width / 2. - 0.5
        y_mid = top + height / 2. - 0.5

        # Ensure we only make a mask of things which are inside the image
        left = max(0, left)
        top = max(0, top)

        # Work out whether each pixel is inside the oval. We only need to check
        # pixels within the extent of the oval.
        xx = np.arange(left, right)
        yy = np.arange(top, bottom)
        xx = ((xx - x_mid) / (width / 2.)) ** 2
        yy = ((yy - y_mid) / (height / 2.)) ** 2
        dd = np.expand_dims(xx, 1) + np.expand_dims(yy, 0)
        mask[z, left:, top:] = dd <= 1
        return {'mask': mask}

    elif roi['type'] == 'ellipse' or (
        roi['type'] == 'freehand' and 'aspect_ratio' in roi and 'ex1' in roi
    ):
        # Ellipse
        # Co-ordinates of points at either end of major axis
        x1 = roi['ex1']
        y1 = roi['ey1']
        x2 = roi['ex2']
        y2 = roi['ey2']
        if (x1 < 0 and x2 < 0) or (y1 < 0 and y2 < 0):
            raise ValueError("ROI is entirely offscreen.")

        # Radius of major and minor axes
        r_radius = np.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2) / 2.
        c_radius = r_radius * roi['aspect_ratio']
        # Centre coordinates
        # We subtract 0.5 because ImageJ's co-ordinate system has indices at
        # the pixel boundaries, and we are using indices at the pixel centers.
        x_mid = (x1 + x2) / 2. - 0.5
        y_mid = (y1 + y2) / 2. - 0.5
        orientation = np.arctan2(y2 - y1, x2 - x1)

        # We need to make a mask which is a bit bigger than this, because
        # we don't know how big the ellipse will end up being. In the most
        # extreme case, it is a circle aligned along a cartesian axis.
        right = 1 + int(np.ceil(max(x1, x2) + r_radius))
        bottom = 1 + int(np.ceil(max(y1, y2) + r_radius))
        mask = np.zeros((z + 1, right, bottom), dtype=bool)

        # Generate the ellipse
        xx, yy = ellipse(
            x_mid,
            y_mid,
            r_radius,
            c_radius,
            mask.shape[1:],
            rotation=orientation,
        )
        if len(xx) == 0 or len(yy) == 0:
            raise ValueError("Ellipse ROI is empty.")

        # Trim mask down to only the points needed
        mask = mask[:, :max(xx) + 1, :max(yy) + 1]
        # Convert sparse ellipse representation to mask
        mask[z, xx, yy] = True
        return {'mask': mask}

    else:
        raise ValueError(
            'ROI type {} not supported'.format(roi['type'])
        )
def run_voronoi(parameters, verbose=True, use_roi=False, pixel_size=16.0):

    # parameters
    density_factor = parameters['density_factor']
    min_samples = parameters['min_samples']
    input_dir = parameters['input_dir']
    output_dir = parameters['output_dir']

    for filename in os.listdir(input_dir):

        if filename.endswith('csv'):
            print("voronoi clustering for file {0}".format(filename))
            filepath = os.path.join(input_dir, filename)
            basename = os.path.splitext(filename)[0]
            output_path = os.path.join(output_dir, basename+'_voronoi.xlsx')

            locs = pd.read_csv(filepath)

            if use_roi:
                roi_zip_path = os.path.join(input_dir,
                                            basename + '_roiset.zip')
                roi_file_path = os.path.join(input_dir,
                                             basename + '_roiset.roi')
                if os.path.exists(roi_zip_path):
                    rois = read_roi_zip(roi_zip_path)
                elif os.path.exists(roi_file_path):
                    rois = read_roi_file(roi_file_path)
                else:
                    raise ValueError(("No ImageJ roi file exists -"
                                      "you should put the file in the same"
                                      "directory as the data"))

                coords = {}
                for roi_id, roi in rois.items():
                    for k, v in roi.items():
                        if not isinstance(v, str):
                            roi[k] = float(v) * pixel_size

                    coords[roi_id] = (locs[
                        (locs['x [nm]'] > roi['left']) &
                        (locs['x [nm]'] < roi['left'] + roi['width']) &
                        (locs['y [nm]'] > roi['top']) &
                        (locs['y [nm]'] < roi['top'] + roi['height'])]
                    ).reset_index(drop=True)
            else:
                coords = dict([('image', locs)])

            for roi_id in coords.keys():
                df = coords[roi_id]

                if len(df.index) == 0:
                    print("no coords in roi")
                    continue

                voronoi_df = voronoi(df,
                                     density_factor,
                                     min_samples,
                                     show_plot=verbose,
                                     verbose=verbose)

                cluster_locs_df = voronoi_df[voronoi_df['lk'] != -1]
                labels = cluster_locs_df['lk'].unique()
                cluster_stats = {}
                cluster_stats['area'] = []
                cluster_stats['occupancy'] = []
                for m in labels:
                    cluster = cluster_locs_df[cluster_locs_df.lk == m]
                    cluster_stats['area'].append(cluster['area'].sum())
                    cluster_stats['occupancy'].append(len(cluster.index))

                cluster_stats_df = pd.DataFrame(cluster_stats)
                if any(labels):
                    writer = pd.ExcelWriter(output_path, engine='openpyxl')
                    if os.path.exists(output_path):
                        book = load_workbook(output_path)
                        writer.book = book
                        writer.sheets = dict(
                            (ws.title, ws) for ws in book.worksheets
                        )

                    cluster_locs_df.to_excel(
                        writer,
                        sheet_name='{0} localisations'.format(roi_id),
                        index=False
                    )
                    cluster_stats_df.to_excel(
                        writer,
                        sheet_name='{0} voronoi stats'.format(roi_id),
                        index=False
                    )
                    writer.save()
                else:
                    print("No clusters found in {0}".format(filename))
                    continue
                cur_sequence = roi_filename_split2[len(roi_filename_split2) -
                                                   2]

                if (cur_patient == patient) and (cur_sequence
                                                 == find_sequence):
                    flag = 1
                    break

        # ADC, DWI both exist
        if flag == 1:
            continue

        print(patient, fid, sequence, find_sequence, slice)

        # read roi file
        roi_object = read_roi_file(os.path.join(ROIPath, roi_file))
        roi_temp = roi_object[roi_filename]

        # find image dimension and path
        CSV_images_object.seek(0)
        CSV_images_reader = csv.DictReader(CSV_images_object)
        for row in CSV_images_reader:
            if row['ProxID'].split('-')[1] == patient:
                if ((len(roi_filename_split) == 4) and
                    (row['fid'] == str(fid))) or (len(roi_filename_split)
                                                  == 3):
                    if row['DCMSerDescr'] == find_sequence or \
                            ((find_sequence == ImageSequence_ROI[3]) and (row['DCMSerDescr'] == ImageSequence[3])):
                        image_dimension = row['Dim'].split('x')
                        image_path = row['DCMSerUID']
def run_optics(parameters, verbose=True, use_roi=False, pixel_size=16.0):

    # parameters
    eps = parameters['eps']
    eps_extract = parameters['eps_extract']
    min_samples = parameters['min_samples']
    input_dir = parameters['input_dir']
    output_dir = parameters['output_dir']
    data_source = parameters['data_source']

    for filename in os.listdir(input_dir):

        if 'nstorm' in data_source:
            ext = 'txt'
        elif 'thunderstorm' in data_source:
            ext = 'csv'

        file_ext = os.path.splitext(filename)[1]
        if ext in file_ext:
            print("optics clustering for file {0}".format(filename))
            filepath = os.path.join(input_dir, filename)
            basename = os.path.splitext(filename)[0]
            output_path = os.path.join(output_dir, basename+'_optics.xlsx')

            data = Localisations(filepath, source=data_source)
            points = data.points
            xy = points.as_matrix(columns=['x', 'y'])

            if use_roi:
                roi_zip_path = os.path.join(input_dir,
                                            basename + '_roiset.zip')
                roi_file_path = os.path.join(input_dir,
                                             basename + '_roiset.roi')

                if os.path.exists(roi_zip_path):
                    rois = read_roi_zip(roi_zip_path)
                elif os.path.exists(roi_file_path):
                    rois = read_roi_file(roi_file_path)
                else:
                    raise ValueError(("No ImageJ roi file exists -"
                                      "you should put the file in the same"
                                      "directory as the data"))

                coords = {}
                for roi_id, roi in rois.items():
                    for k, v in roi.items():
                        if not isinstance(v, str):
                            roi[k] = float(v) * pixel_size

                    coords[roi_id] = xy[(xy[:, 0] > roi['left']) &
                                        (xy[:, 0] < roi['left'] + roi['width']) &
                                        (xy[:, 1] > roi['top']) &
                                        (xy[:, 1] < roi['top'] + roi['height'])]
            else:
                coords = dict([('image', xy)])

            (optics_clusters, noise) = (
                optics_clustering(coords,
                                  eps=eps,
                                  eps_extract=eps_extract,
                                  min_samples=min_samples)
                )

            if verbose:
                if optics_clusters:
                    for roi_id in optics_clusters.keys():
                        plot_filename = os.path.join(
                            output_dir,
                            basename + '_{0}_clusters.png'.format(roi_id)
                        )
                        if noise:
                            noise_in_roi = noise[roi_id]
                        else:
                            noise_in_roi = None
                        plot_optics_clusters(optics_clusters[roi_id],
                                             noise=noise_in_roi,
                                             save=True,
                                             filename=plot_filename)

            for roi in optics_clusters.keys():

                oc = optics_clusters[roi]
                if oc.n_clusters > 0:
                    oc.save(output_path, sheetname=roi)
                else:
                    print("No clusters found in {0}".format(filename))
                    continue