Esempio n. 1
0
    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&copyAnnotations=%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
Esempio n. 3
0
    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)
Esempio n. 5
0
    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])
Esempio n. 6
0
    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())
Esempio n. 9
0
    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())