From 5e072e7abcfa35ec83318b11991f457a47caefdc Mon Sep 17 00:00:00 2001 From: Chris Frick Date: Wed, 25 Sep 2024 15:55:09 -0700 Subject: [PATCH] update plots --- .../draw_nucleus_contours_on_watershed.py | 110 ++++++++++++++++++ .../analyses/density/watershed_validate.py | 37 ++++-- .../twoD_zMIP_area/pseudo_cell_helper.py | 4 +- 3 files changed, 138 insertions(+), 13 deletions(-) create mode 100644 nuc_morph_analysis/analyses/density/draw_nucleus_contours_on_watershed.py diff --git a/nuc_morph_analysis/analyses/density/draw_nucleus_contours_on_watershed.py b/nuc_morph_analysis/analyses/density/draw_nucleus_contours_on_watershed.py new file mode 100644 index 00000000..5ae2f7ed --- /dev/null +++ b/nuc_morph_analysis/analyses/density/draw_nucleus_contours_on_watershed.py @@ -0,0 +1,110 @@ +#%% +from nuc_morph_analysis.lib.preprocessing.twoD_zMIP_area import watershed_workflow, pseudo_cell_helper, pseudo_cell_testing_helper +from pathlib import Path +import pandas as pd +from nuc_morph_analysis.lib.preprocessing import global_dataset_filtering +from nuc_morph_analysis.lib.preprocessing import filter_data + +import numpy as np +import matplotlib.pyplot as plt +import matplotlib.cm as cm +from nuc_morph_analysis.analyses.dataset_images_for_figures.figure_helper import return_glasbey_on_dark +from skimage.measure import find_contours +from nuc_morph_analysis.lib.visualization.plotting_tools import colorize_image +from nuc_morph_analysis.analyses.density.watershed_validate import get_contours_from_pair_of_2d_seg_image, draw_contours_on_image + + +def run_validation_and_plot(TIMEPOINT=48,colony='medium',RESOLUTION_LEVEL=1,plot_everything=False, testing=False): + """ + run an image through the watershed based pseudo cell segmentation and examine the outputs + optionally, run a test image through the same pipeline + + Parameters + ---------- + TIMEPOINT : int, optional + The timepoint to analyze, by default 48 + colony : str, optional + The colony to analyze, by default 'medium' + RESOLUTION_LEVEL : int, optional + The resolution level to analyze, by default 1 + plot_everything : bool, optional + Whether to plot a large set of extra images colored by features and with contours, by default True + testing : bool, optional + Whether to run a test image through the pipeline, by default False + + Returns + ------- + pd.DataFrame + The dataframe containing the pseudo cell segmentation results + if plot_everything is False + if plot_everything is True, returns the full dataframe (after merging with the tracking dataset) + + """ + + # perform watershed based pseudo cell segmentation + if testing: # on test data + labeled_nucleus_image = pseudo_cell_testing_helper.make_nucleus_image_array() + df_2d, img_dict = pseudo_cell_helper.get_pseudo_cell_boundaries(labeled_nucleus_image, return_img_dict=True) + colony = 'test' + else: # or on real data + df_2d, img_dict = watershed_workflow.get_image_and_run(colony, TIMEPOINT, RESOLUTION_LEVEL, return_img_dict=True) + + # now display all of the intermediates of the + # watershed based pseudo cell segmentation + # 'cyto_distance':(cyto_distance, "Distance Transform restricted\nto Cytoplasmic Segmentation"), + # 'nucleus_edge_img':(nucleus_edge_img, "Nucleus Edge"), + cmapstr = 'viridis' + nuc_mip = img_dict['mip_of_labeled_image'][0] + cell_mip = img_dict['pseudo_cells_img'][0] + + nuc_edge = img_dict['nucleus_edge_img'][0] + cytp_dist = img_dict['cyto_distance'][0] + for full_crop, sizes in [('crop',(500,200,500,500)),('full',(0,0,nuc_edge.shape[1],nuc_edge.shape[0]))]: + x1,y1,w,h = sizes + crop_exp = np.index_exp[y1:y1+h,x1:x1+w] + + + + cimg = cytp_dist + + # define the colormap for the image + cmap = cm.get_cmap(cmapstr) + + fig, axlist = plt.subplots(1, 1, figsize=(6, 4)) + + vmin,vmax = (None,None) + mappable = axlist.imshow(cimg, interpolation='nearest',cmap=cmap, + vmin=vmin,vmax=vmax, + ) + cbar = plt.colorbar(mappable,ax=axlist,label='cyto_distance') + + # create the contours + contour_list = get_contours_from_pair_of_2d_seg_image(nuc_mip,cell_mip) + # remove cell contours + contour_list2 = [] + for contour in contour_list: + contour_item = list(contour) + contour_item[2] = [] # empty list + contour_list2.append(contour_item) + + draw_contours_on_image(axlist,contour_list2,new_color=np.asarray((200,0,200))) + # remove the axis + plt.axis('off') + plt.xlim([x1,x1+w]) + plt.ylim([y1,y1+h]) + titlestr = f"edges of nuclei overlaid on cytoplasmic distance transform\n{colony}_{TIMEPOINT}_{full_crop}_res{RESOLUTION_LEVEL}" + plt.title(f'{titlestr}') + + # now save the figure + savedir = Path(__file__).parent / 'figures' / 'validating nucleus edge' + savedir.mkdir(exist_ok=True,parents=True) + savename = f'{colony}_{TIMEPOINT}_{full_crop}_res{RESOLUTION_LEVEL}.png' + savepath = savedir / savename + plt.savefig(savepath, + dpi=300, + bbox_inches='tight') + +if __name__ == '__main__': + # set the details + dft_test = run_validation_and_plot(testing=True) + dft0 = run_validation_and_plot(plot_everything=True) \ No newline at end of file diff --git a/nuc_morph_analysis/analyses/density/watershed_validate.py b/nuc_morph_analysis/analyses/density/watershed_validate.py index 65379d32..dd3d5ae4 100644 --- a/nuc_morph_analysis/analyses/density/watershed_validate.py +++ b/nuc_morph_analysis/analyses/density/watershed_validate.py @@ -12,10 +12,14 @@ from skimage.measure import find_contours from nuc_morph_analysis.lib.visualization.plotting_tools import colorize_image -def get_contours_from_pair_of_2d_seg_image(nuc_mip,cell_mip): +def get_contours_from_pair_of_2d_seg_image(nuc_mip,cell_mip,dft=None): contour_list = [] # (label, nucleus_contour, cell_contour, color) rgb_array0_255, _, _ = return_glasbey_on_dark() for label_img in range(0,nuc_mip.max()+1): + if dft is not None: + #ask if the label_img is in the dataframe + if label_img not in dft['label_img'].values: + continue color = np.float64(rgb_array0_255[label_img % len(rgb_array0_255)]) # get the nucleus boundary @@ -32,9 +36,11 @@ def get_contours_from_pair_of_2d_seg_image(nuc_mip,cell_mip): return contour_list -def draw_contours_on_image(axlist,contour_list): +def draw_contours_on_image(axlist,contour_list,new_color=None): # draw contours for label, nuc_contours, cell_contours, color in contour_list: + if new_color is not None: + color = new_color for contour in nuc_contours: axlist.plot(contour[:, 1], contour[:, 0], linewidth=1, color=color/255) for contour in cell_contours: @@ -55,6 +61,10 @@ def plot_colorized_image_with_contours(img_dict,dft,feature,cmapstr,colony='test if feature == 'zeros': cimg = np.zeros_like(nuc_mip) else: + if categorical: + if dft[feature].dtype == 'bool': + dft = dft.copy() + dft[feature] = dft[feature]+1 cimg = colorize_image(nuc_mip, dft, feature=feature) # define the colormap for the image @@ -77,8 +87,8 @@ def plot_colorized_image_with_contours(img_dict,dft,feature,cmapstr,colony='test if draw_contours: # create the contours - contour_list = get_contours_from_pair_of_2d_seg_image(nuc_mip,cell_mip) - draw_contours_on_image(axlist,contour_list) + contour_list = get_contours_from_pair_of_2d_seg_image(nuc_mip,cell_mip,dft) + draw_contours_on_image(axlist,contour_list,new_color=np.asarray((200,0,200))) # remove the axis plt.axis('off') plt.xlim([x1,x1+w]) @@ -126,19 +136,21 @@ def run_validation_and_plot(TIMEPOINT=48,colony='medium',RESOLUTION_LEVEL=1,plot if testing: # on test data labeled_nucleus_image = pseudo_cell_testing_helper.make_nucleus_image_array() df_2d, img_dict = pseudo_cell_helper.get_pseudo_cell_boundaries(labeled_nucleus_image, return_img_dict=True) + colony = 'test' else: # or on real data df_2d, img_dict = watershed_workflow.get_image_and_run(colony, TIMEPOINT, RESOLUTION_LEVEL, return_img_dict=True) - # now display all of the intermediates of the # watershed based pseudo cell segmentation mip = img_dict['mip_of_labeled_image'][0] for full_crop, sizes in [('crop',(500,200,500,500)),('full',(0,0,mip.shape[1],mip.shape[0]))]: x1,y1,w,h = sizes crop_exp = np.index_exp[y1:y1+h,x1:x1+w] - nrows = 1 - ncols = len(img_dict) + nrows = 2 + ncols = np.ceil(len(img_dict)//2).astype(int) + assert ncols>1 fig,axr = plt.subplots(nrows,ncols,figsize=(ncols*4,nrows*4)) + axx = np.asarray([axr]).flatten() for i,key in enumerate(img_dict.keys()): ax = axx[i] @@ -190,12 +202,14 @@ def run_validation_and_plot(TIMEPOINT=48,colony='medium',RESOLUTION_LEVEL=1,plot plot_colorized_image_with_contours(img_dict,dft,'colony_depth','tab10',colony,TIMEPOINT,RESOLUTION_LEVEL,categorical=True,draw_contours=False) plot_colorized_image_with_contours(img_dict,dft,'colony_depth','tab10',colony,TIMEPOINT,RESOLUTION_LEVEL,categorical=True,draw_contours=True) + plot_colorized_image_with_contours(img_dict,dft,'has_mitotic_neighbor_dilated','tab10',colony,TIMEPOINT,RESOLUTION_LEVEL,categorical=True,draw_contours=False) + plot_colorized_image_with_contours(img_dict,dft,'has_mitotic_neighbor_dilated','tab10',colony,TIMEPOINT,RESOLUTION_LEVEL,categorical=True,draw_contours=True) plot_colorized_image_with_contours(img_dict,dft,'2d_area_nuc_cell_ratio','viridis',colony,TIMEPOINT,RESOLUTION_LEVEL,categorical=False,draw_contours=False) plot_colorized_image_with_contours(img_dict,dft,'2d_area_nuc_cell_ratio','viridis',colony,TIMEPOINT,RESOLUTION_LEVEL,categorical=False,draw_contours=True) plot_colorized_image_with_contours(img_dict,dft,'2d_area_pseudo_cell','viridis',colony,TIMEPOINT,RESOLUTION_LEVEL,categorical=False,draw_contours=False) plot_colorized_image_with_contours(img_dict,dft,'2d_area_pseudo_cell','viridis',colony,TIMEPOINT,RESOLUTION_LEVEL,categorical=False,draw_contours=True) - plot_colorized_image_with_contours(img_dict,dft,'2d_area_cyto','viridis',colony,TIMEPOINT,RESOLUTION_LEVEL,categorical=False,draw_contours=False) - plot_colorized_image_with_contours(img_dict,dft,'2d_area_cyto','viridis',colony,TIMEPOINT,RESOLUTION_LEVEL,categorical=False,draw_contours=True) + plot_colorized_image_with_contours(img_dict,dft,'2d_intensity_min_edge','viridis',colony,TIMEPOINT,RESOLUTION_LEVEL,categorical=False,draw_contours=False) + plot_colorized_image_with_contours(img_dict,dft,'2d_intensity_min_edge','viridis',colony,TIMEPOINT,RESOLUTION_LEVEL,categorical=False,draw_contours=True) plot_colorized_image_with_contours(img_dict,dft,'density','viridis',colony,TIMEPOINT,RESOLUTION_LEVEL,categorical=False,draw_contours=False) plot_colorized_image_with_contours(img_dict,dft,'density','viridis',colony,TIMEPOINT,RESOLUTION_LEVEL,categorical=False,draw_contours=True) plot_colorized_image_with_contours(img_dict,dft,'zeros','viridis',colony,TIMEPOINT,RESOLUTION_LEVEL,categorical=False,draw_contours=True) @@ -205,5 +219,6 @@ def run_validation_and_plot(TIMEPOINT=48,colony='medium',RESOLUTION_LEVEL=1,plot if __name__ == '__main__': # set the details - dft_test = run_validation_and_plot(testing=True) - dft0 = run_validation_and_plot(plot_everything=False) \ No newline at end of file + # dft_test = run_validation_and_plot(testing=True) + # dft0 = run_validation_and_plot(plot_everything=True) + dft0 = run_validation_and_plot(247,colony='small',RESOLUTION_LEVEL=1,plot_everything=True) \ No newline at end of file diff --git a/nuc_morph_analysis/lib/preprocessing/twoD_zMIP_area/pseudo_cell_helper.py b/nuc_morph_analysis/lib/preprocessing/twoD_zMIP_area/pseudo_cell_helper.py index 7702c913..5eb88a81 100644 --- a/nuc_morph_analysis/lib/preprocessing/twoD_zMIP_area/pseudo_cell_helper.py +++ b/nuc_morph_analysis/lib/preprocessing/twoD_zMIP_area/pseudo_cell_helper.py @@ -148,8 +148,8 @@ def get_pseudo_cell_boundaries_from_labeled_nucleus_image(labeled_nucleus_image, 'distance':(distance, "Distance Transform"), 'watershed_img':(watershed_img, "Watershed of Distance Transform"), 'pseudo_cells_img':(pseudo_cells_img, "Pseudo Cell Segmentation"), - 'cell_shed_bin': (cell_shed>0, "Binary Watershed of Distance Transform with Watershed Line"), - 'cyto_distance':(cyto_distance, "Distance Transform restricted to Cytoplasmic Segmentation"), + 'cell_shed_bin': (cell_shed>0, "Binary Watershed of Distance\nTransform with Watershed Line"), + 'cyto_distance':(cyto_distance, "Distance Transform restricted\nto Cytoplasmic Segmentation"), 'nucleus_edge_img':(nucleus_edge_img, "Nucleus Edge"), }