def main():
    size = int("${size}")
    margin = int("${wsi_margin}")
    # Load sample
    slide = open_image("${sample}")
    mask = io.imread("${mask}")[:, :, 0]

    original_size = get_whole_image(slide, slide.level_count - 2).shape
    mask = resize(mask,
                  original_size[:2],
                  preserve_range=True,
                  anti_aliasing=True,
                  order=0)

    # Load segmentation_model
    opt = type('', (), {})()
    opt.meta = os.path.join("${model}", "meta.pkl")
    opt.backbone, opt.model = get_backbone_model(
        os.path.join("${model}", "final_score.csv"))
    opt.weights = os.path.join("${model}", "model_weights.h5")
    opt.mean, opt.std = load_meta(opt.meta)

    model = load_model_v2(opt.backbone, opt.model, opt.weights)

    # Divide and analyse
    list_positions = tile(slide, 0, mask, size, margin, slide.level_count - 2)
    raw, segmented_tiles = wsi_analysis(slide, model, size, list_positions,
                                        margin, opt)
    np.savez("segmented_tiles.npz",
             tiles=segmented_tiles,
             positions=list_positions,
             raw=raw)
Beispiel #2
0
def tile_image(wsi, xml, outfolder, level, size):
    """Downsize at level and save a WSI in the output folder 
    
    Parameters
    ----------
    wsi : str
        path to the WSI. May also be an openslide image.
    outfolder : str
        path where to stock the image
    level : int
        level to which downsample
    """
    name_wsi, ext = os.path.splitext(os.path.basename(wsi))
    slide = usi.open_image(wsi)
    mask_level = 3
    new_path = os.path.join(outfolder, name_wsi)
    #os.makedirs(new_path)
    mask_function = lambda x: get_polygon(path_xml=xml, label='t')
    param_tiles = usi.patch_sampling(slide=wsi,
                                     mask_level=mask_level,
                                     mask_function=mask_function,
                                     sampling_method='grid',
                                     analyse_level=level,
                                     patch_size=(size, size))
    return len(param_tiles)
def main():

    args = get_options()

    model = prep_model(args.weight)
    mask_level = open_image(args.slide).level_count - 2
    analyse_level = args.analyse_level

    info, encoded = encode_patient(args.slide, args.xml_file, analyse_level,
                                   mask_level, model)
    name_encoded = os.path.basename(args.slide).replace('.tiff', '.npy')
    name_mean = os.path.basename(args.slide).replace('.tiff', '_mean.npy')
    name_visu = os.path.basename(args.slide).replace('.tiff', '_visu.png')

    with open(
            os.path.basename(args.slide).replace('.tiff', "_info.txt"),
            "wb") as fp:  #Pickling
        pickle.dump(info, fp)
    np.save(name_encoded, encoded.astype('float32'))
    np.save(name_mean, encoded.mean(axis=(0)).astype('float32'))

    ## for tissue check:
    # matplotlib without
    import matplotlib as mpl
    mpl.use('Agg')
    import matplotlib.pyplot as plt
    PLOT_ARGS = {
        'color': 'red',
        'size': (12, 12),
        'with_show': False,
        'title': "n_tiles={}".format(len(info))
    }
    visualise_cut(args.slide,
                  info,
                  res_to_view=mask_level,
                  plot_args=PLOT_ARGS)
    plt.savefig(name_visu)
    return options


if __name__ == "__main__":
    options = get_options()
    out = options.out + "_tiles.txt"
    out_visu = options.out + "_visualisation.png"

    # because we are doing UNet! :-) this should disappear
    image = options.slide
    extension = image.split('.')[-1]
    overlap = options.marge + 92  ## because we do segmentation with UNet and we need padding
    slide_file_name = os.path.basename(options.slide).replace(
        ".{}".format(extension), "")

    mask_level = open_image(image).level_count - 2

    def load_gt(img):  ## dirty trick to keep it compatible
        lbl = make_label_with_otsu(options.xml_file, img)
        return lbl

    options_applying_mask = {
        'mask_level': mask_level,
        'mask_function': load_gt
    }

    ## Options regarding the sampling. Method, level, size, if overlapping or not.
    ## You can even use custom functions. Tolerance for the mask segmentation.
    ## allow overlapping is for when the patch doesn't fit in the image, do you want it?
    ## n_samples and with replacement are for the methods random_patch
    parser.add_option("--slide", dest="slide",type="string",
                    help="slide to get dimensions of wsi")
    (options, _) = parser.parse_args()
    
    return options


if __name__ == "__main__":
    options = get_options()
    margin = options.marge

    basename = os.path.basename(options.slide).split('.')[0]


    # output wsi
    size_x, size_y = open_image(options.slide).dimensions
    img = pyvips.Image.black(size_x, size_y)

    # files to iterate over
    files = join(options.input, "*.tif")

    for f in tqdm(glob(files)):

        tile = pyvips.Image.new_from_file(f, 
                                    access=pyvips.Access.SEQUENTIAL)
        _, _x, _y, _size_x, level = f.split('/')[-1].split('.')[0].split('_')
        _size_y = _size_x

        _size_x, _size_y = int(_size_x) - 2 * margin, int(_size_y) - 2 * margin
        sub_tile = tile.extract_area(margin, margin, _size_x, _size_y)
        img = img.insert(sub_tile, int(_x) + margin, int(_y) + margin)
def from_cell_to_heatmap(slide,
                         trans,
                         cell_table,
                         filter_out="LBP",
                         level=7,
                         n_comp=2):
    """
    
    Parameters
    ----------
    slide : wsi object,
        openslide object from which we extract.
    trans : function,
        infers the new coordinates of a given point. It is or:
            - the sequential application of PCA+UMAP
            - application of UMAP.
    cell_table : pandas dataframe,
        patient table, where each line corresponds to a nucleus.
    filter_out: str,
        String pattern to filter out columns from the feature table, in 'glob' form. 
        If pattern in the feature name, exclude feature.
    level : int,
        level of the resulting heatmap.
    n_comp : int,
        number of components after UMAP projection.
    Returns
    -------
    Returns a heatmap with the projected components of a given slide
    at a given resolution.
    """
    slide = open_image(slide)
    f1, f2 = normalise_csv(cell_table)
    feat = f1.columns
    feat = [el for el in feat if filter_out not in el]
    f1 = f1[feat]
    f1 = drop_na_axis(f1)
    standard_embedding = trans(f1)
    x = standard_embedding[:, 0]
    y = standard_embedding[:, 1]

    if level < slide.level_count:
        # if the pyramid scheme has a the png at the correct resolution
        shape_slide_level = get_whole_image(slide, level=level,
                                            numpy=True).shape
        within_slide_levels = True
    else:
        # if the pyramid scheme doesn't have the png at the correct resolution
        within_slide_levels = False
        high_pyramid_level = slide.level_count - 1
        power = level - high_pyramid_level
        shape_slide_level = get_whole_image(slide,
                                            level=high_pyramid_level,
                                            numpy=True).shape
        shape_slide_level = tuple((int(shape_slide_level[0] / (2**power)),
                                   int(shape_slide_level[1] / (2**power)), 3))
    xshape, yshape = shape_slide_level[0:2]
    f2["coord_l"] = f2.apply(lambda row: f(slide, row, shape_slide_level),
                             axis=1)
    heatmap = np.zeros(shape=(xshape, yshape, 3))

    f1 = f1.reset_index(drop=True)
    f2 = f2.reset_index(drop=True)
    for coord_l, group in tqdm(f2.groupby("coord_l")):
        y_l, x_l = [int(el) for el in coord_l]
        heatmap[x_l, y_l, 0] = np.mean(x[group.index])
        heatmap[x_l, y_l, 1] = np.mean(y[group.index])
        if n_comp == 2:
            count = group.shape[0]
            heatmap[x_l, y_l, 2] = count
        else:
            z = standard_embedding[:, 2]
            heatmap[x_l, y_l, 2] = np.mean(z[group.index])
    return heatmap