def test_polygon_merger(self): """Test Polygon_merger.run().""" # init and run polygon merger on masks grid pm = Polygon_merger(maskpaths=maskpaths, GTCodes_df=GTCodes_df, discard_nonenclosed_background=True, verbose=1) contours_df = pm.run() # make sure it is what we expect self.assertTupleEqual(contours_df.shape, (17, 13)) self.assertSetEqual( set(contours_df.loc[:, 'group']), { 'roi', 'mostly_tumor', 'mostly_stroma', 'mostly_lymphocytic_infiltrate' }) # deleting existing annotations in target slide (if any) delete_annotations_in_slide(gc, SAMPLE_SLIDE_ID) # get list of annotation documents annotation_docs = get_annotation_documents_from_contours( contours_df.copy(), separate_docs_by_group=True, docnamePrefix='test', verbose=False, monitorPrefix=SAMPLE_SLIDE_ID + ": annotation docs") # post annotations to slide -- make sure it posts without errors for annotation_doc in annotation_docs: resp = gc.post("/annotation?itemId=" + SAMPLE_SLIDE_ID, json=annotation_doc) self.assertTrue('annotation' in resp.keys())
def cellularity_detection_workflow(gc, cdo, slide_id, monitorPrefix='', destination_folder_id=None, keep_existing_annotations=False): """Run cellularity detection for single slide. The cellularity detection algorithm can either be Cellularity_detector_superpixels or Cellularity_detector_thresholding. Arguments ----------- gc : object girder client object cdo : object Cellularity_detector object instance. Can either be Cellularity_detector_superpixels() or Cellularity_detector_thresholding(). The thresholding-based workflow seems to be more robust, despite being simpler. slide_id : str girder id of slide on which workflow is done monitorPrefix : str this will set the cds monitorPrefix attribute destination_folder_id : str or None if not None, copy slide to this girder folder and post results there instead of original slide. keep_existing_annotations : bool keep existing annotations in slide when posting results? """ cdo.monitorPrefix = monitorPrefix # copy slide to target folder, otherwise work in-place if destination_folder_id is not None: cdo._print1("%s: copying slide to destination folder" % monitorPrefix) resp = gc.post( "/item/%s/copy?folderId=%s©Annotations=%s" % (slide_id, destination_folder_id, keep_existing_annotations)) slide_id = resp['_id'] elif not keep_existing_annotations: cdo._print1("%s: deleting existing annotations" % monitorPrefix) delete_annotations_in_slide(gc, slide_id) # run cds for this slide cdo.slide_id = slide_id cdo.run() return slide_id
def test_polygon_merger_tiled_masks(self, girderClient): # noqa """Test Polygon_merger.run().""" # read GTCodes dataframe gtcodePath = getTestFilePath('sample_GTcodes.csv') GTCodes_df = read_csv(gtcodePath) GTCodes_df.index = GTCodes_df.loc[:, 'group'] # This is where masks for adjacent rois are saved mask_loadpath = getTestFilePath( os.path.join('annotations_and_masks', 'polygon_merger_roi_masks')) maskpaths = [ os.path.join(mask_loadpath, j) for j in os.listdir(mask_loadpath) if j.endswith('.png') ] # init and run polygon merger on masks grid pm = Polygon_merger(maskpaths=maskpaths, GTCodes_df=GTCodes_df, discard_nonenclosed_background=True, verbose=1) contours_df = pm.run() # make sure it is what we expect assert contours_df.shape == (13, 13) assert set(contours_df.loc[:, 'group']) == { 'roi', 'mostly_tumor', 'mostly_stroma', 'mostly_lymphocytic_infiltrate' } # deleting existing annotations in target slide (if any) sampleSlideItem = girderClient.resourceLookup( '/user/admin/Public/TCGA-A2-A0YE-01Z-00-DX1.8A2E3094-5755-42BC-969D-7F0A2ECA0F39.svs' ) # noqa sampleSlideId = str(sampleSlideItem['_id']) delete_annotations_in_slide(girderClient, sampleSlideId) # get list of annotation documents annotation_docs = get_annotation_documents_from_contours( contours_df.copy(), separate_docs_by_group=True, docnamePrefix='test', verbose=False, monitorPrefix=sampleSlideId + ": annotation docs") # post annotations to slide -- make sure it posts without errors for annotation_doc in annotation_docs: resp = girderClient.post("/annotation?itemId=" + sampleSlideId, json=annotation_doc) assert 'annotation' in resp.keys()
def test_get_tissue_boundary_annotation_documents(self): """Test get_tissue_boundary_annotation_documents().""" labeled = imread(os.path.join(savepath, 'tissue_binmask.png')) annotation_docs = get_tissue_boundary_annotation_documents( gc, slide_id=SAMPLE_SLIDE_ID, labeled=labeled) self.assertTrue('elements' in annotation_docs[0].keys()) self.assertEqual(len(annotation_docs[0]['elements']), 9) # deleting existing annotations in target slide (if any) delete_annotations_in_slide(gc, SAMPLE_SLIDE_ID) # post annotations to slide for doc in annotation_docs: _ = gc.post("/annotation?itemId=" + SAMPLE_SLIDE_ID, json=doc)
def test_get_tissue_boundary_annotation_documents(self): """Test get_tissue_boundary_annotation_documents().""" annotation_docs = get_tissue_boundary_annotation_documents( cfg.gc, slide_id=cfg.iteminfo['_id'], labeled=cfg.labeled) assert 'elements' in annotation_docs[0].keys() assert len(annotation_docs[0]['elements']) == 9 # test delete existing annotations in slide delete_annotations_in_slide(cfg.gc, cfg.iteminfo['_id']) # check that it posts without issues resps = [ cfg.gc.post("/annotation?itemId=" + cfg.iteminfo['_id'], json=doc) for doc in annotation_docs ] assert all(['annotation' in resp for resp in resps])
def test_Cellularity_detector_superpixels(self): """Test Cellularity_detector_superpixels().""" # deleting existing annotations in target slide (if any) delete_annotations_in_slide(gc, SAMPLE_SLIDE_ID) # run cellularity detector cds = Cellularity_detector_superpixels( gc, slide_id=SAMPLE_SLIDE_ID, MAG=3.0, compactness=0.1, spixel_size_baseMag=256 * 256, max_cellularity=40, visualize_spixels=True, visualize_contiguous=True, get_tissue_mask_kwargs={ 'deconvolve_first': False, 'n_thresholding_steps': 2, 'sigma': 1.5, 'min_size': 500, }, verbose=2, monitorPrefix='test', logging_savepath=logging_savepath) # cds.set_color_normalization_values( # mu=cnorm_thumbnail['mu'], # sigma=cnorm_thumbnail['sigma'], what='thumbnail') cds.set_color_normalization_values(mu=cnorm_main['mu'], sigma=cnorm_main['sigma'], what='main') tissue_pieces = cds.run() # check self.assertEqual(len(tissue_pieces), 2) self.assertTrue( all([ j in tissue_pieces[0].__dict__.keys() for j in ('tissue_mask', 'ymin', 'xmin', 'ymax', 'xmax', 'spixel_mask', 'fdata', 'cluster_props') ])) self.assertEqual(len(tissue_pieces[0].cluster_props), 5) # cleanup shutil.rmtree(logging_savepath)
def test_get_annotation_documents_from_contours(self, girderClient): # noqa """Test get_contours_from_bin_mask().""" self._setup() sampleSlideItem = girderClient.resourceLookup( '/user/admin/Public/TCGA-A2-A0YE-01Z-00-DX1.8A2E3094-5755-42BC-969D-7F0A2ECA0F39.svs' ) # noqa sampleSlideId = str(sampleSlideItem['_id']) # get list of annotation documents annprops = { 'X_OFFSET': self.X_OFFSET, 'Y_OFFSET': self.Y_OFFSET, 'opacity': 0.2, 'lineWidth': 4.0, } annotation_docs = get_annotation_documents_from_contours( self.CONTOURS_DF.copy(), separate_docs_by_group=True, annots_per_doc=10, docnamePrefix='test', annprops=annprops, verbose=False, monitorPrefix=self.MASKNAME[:12] + ": annotation docs") # make sure its what we expect assert len(annotation_docs) == 8 assert {j['name'] for j in annotation_docs} == { 'test_blood_vessel-0', 'test_exclude-0', 'test_mostly_lymphocytic_infiltrate-0', 'test_mostly_stroma-0', 'test_mostly_tumor-0', 'test_mostly_tumor-1', 'test_normal_acinus_or_duct-0', 'test_roi-0' } # deleting existing annotations in target slide (if any) delete_annotations_in_slide(girderClient, sampleSlideId) # post annotations to slide -- make sure it posts without errors resp = girderClient.post("/annotation?itemId=" + sampleSlideId, json=annotation_docs[0]) assert 'annotation' in resp.keys()
def test_polygon_merger_v2(self): """Test Polygon_merger_v2.run().""" # init & run polygon merger pm = Polygon_merger_v2(contours_df, verbose=1) pm.unique_groups.remove("roi") pm.run() # make sure it is what we expect self.assertTupleEqual(pm.new_contours.shape, (16, 13)) self.assertSetEqual( set(pm.new_contours.loc[:, 'group']), {'mostly_tumor', 'mostly_stroma', 'mostly_lymphocytic_infiltrate'}) # add colors (aesthetic) for group in pm.unique_groups: cs = contours_df.loc[contours_df.loc[:, "group"] == group, "color"] pm.new_contours.loc[pm.new_contours.loc[:, "group"] == group, "color"] = cs.iloc[0] # get rid of nonenclosed stroma (aesthetic) pm.new_contours = _discard_nonenclosed_background_group( pm.new_contours, background_group="mostly_stroma") # deleting existing annotations in target slide (if any) delete_annotations_in_slide(gc, POST_SLIDE_ID) # get list of annotation documents annotation_docs = get_annotation_documents_from_contours( pm.new_contours.copy(), separate_docs_by_group=True, docnamePrefix='test', verbose=False, monitorPrefix=POST_SLIDE_ID + ": annotation docs") # post annotations to slide -- make sure it posts without errors for annotation_doc in annotation_docs: resp = gc.post("/annotation?itemId=" + POST_SLIDE_ID, json=annotation_doc) self.assertTrue('annotation' in resp.keys())
def test_get_annotation_documents_from_contours(self): """Test get_contours_from_bin_mask().""" # get list of annotation documents annprops = { 'X_OFFSET': X_OFFSET, 'Y_OFFSET': Y_OFFSET, 'opacity': 0.2, 'lineWidth': 4.0, } annotation_docs = get_annotation_documents_from_contours( CONTOURS_DF.copy(), separate_docs_by_group=True, annots_per_doc=10, docnamePrefix='test', annprops=annprops, verbose=False, monitorPrefix=MASKNAME[:12] + ": annotation docs") # make sure its what we expect self.assertTrue(len(annotation_docs) == 8) self.assertSetEqual( {j['name'] for j in annotation_docs}, { 'test_blood_vessel-0', 'test_exclude-0', 'test_mostly_lymphocytic_infiltrate-0', 'test_mostly_stroma-0', 'test_mostly_tumor-0', 'test_mostly_tumor-1', 'test_normal_acinus_or_duct-0', 'test_roi-0' }) # deleting existing annotations in target slide (if any) delete_annotations_in_slide(gc, SAMPLE_SLIDE_ID) # post annotations to slide -- make sure it posts without errors resp = gc.post("/annotation?itemId=" + SAMPLE_SLIDE_ID, json=annotation_docs[0]) self.assertTrue('annotation' in resp.keys())