Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using DeepFeatureExtractor for slides which require manual specification of power and resolution #879

Closed
GeorgeBatch opened this issue Nov 4, 2024 · 1 comment

Comments

@GeorgeBatch
Copy link
Contributor

GeorgeBatch commented Nov 4, 2024

  • TIA Toolbox version: develop branch
  • Python version: 3.11
  • Operating System: Linux

Description

I use some public data withtif files that do not have mpp and power recorded. However, the group that released this data provided the mpp and power values for each slide separately. I know I can provide them manually when reading the wsi with WSIReader.open():

dataset_2_sample_slide = {
        "dhmc_20x": {
            "path": "data/DHMC/DHMC_0001.tif",
            "mpp": 0.503,
            "power": 20,
        },
        "dhmc_40x": {
            "path": "data/DHMC/DHMC_0006.tif",
            "mpp": 0.252,
            "power": 40,
        },
}

for dataset, slide_args in dataset_2_sample_slide.items():
    slide_path = slide_args["path"]
    mpp = slide_args.get("mpp", None)
    power = slide_args.get("power", None)

    print(f"{dataset}: {slide_path}")
    
    wsi = WSIReader.open(slide_path, mpp=mpp, power=power)
    print(reader)
    
    info_dict = reader.info.as_dict()
    pprint(info_dict)  # noqa: T203
    
    wsi_thumbnail = wsi.slide_thumbnail(resolution=1.25, units="power")
    wsi_thumbnail_path = os.path.join(f"{slide_name}_thumbnail.jpg")
    imwrite(wsi_thumbnail_path, wsi_thumbnail)
    
    mask = wsi.tissue_mask(resolution=1.25, units="power")
    mask_thumbnail = mask.slide_thumbnail(resolution=1.25, units="power",)
    mask_thumbnail_path = os.path.join(f"{slide_name}_mask.png")
    imwrite(mask_thumbnail_path, np.uint8(mask_thumbnail * 255))

So I can use this to get thumbnails and masks.

How do I provide this information directly to the feature extractor?

Here is the code I found in https://github.com/TissueImageAnalytics/tiatoolbox/blob/develop/examples/full-pipelines/slide-graph.ipynb

def extract_deep_features(
    wsi_paths: list[str],
    msk_paths: list[str],
    save_dir: str,
    preproc_func: Callable | None = None,
) -> list:
    """Helper function to extract deep features."""
    ioconfig = IOSegmentorConfig(
        input_resolutions=[
            {"units": "mpp", "resolution": 0.25},
        ],
        output_resolutions=[
            {"units": "mpp", "resolution": 0.25},
        ],
        patch_input_shape=[512, 512],
        patch_output_shape=[512, 512],
        stride_shape=[512, 512],
        save_resolution={"units": "mpp", "resolution": 8.0},
    )
    model = CNNBackbone("resnet50")
    extractor = DeepFeatureExtractor(batch_size=16, model=model, num_loader_workers=4)
    # Injecting customized preprocessing functions,
    # check the document or sample code below for API.
    extractor.model.preproc_func = preproc_func

    rmdir(save_dir)
    output_map_list = extractor.predict(
        wsi_paths,
        msk_paths,
        mode="wsi",
        ioconfig=ioconfig,
        on_gpu=ON_GPU,
        crash_on_exception=True,
        save_dir=save_dir,
    )

    # Rename output files
    for input_path, output_path in output_map_list:
        input_name = Path(input_path).stem

        output_parent_dir = Path(output_path).parent

        src_path = Path(f"{output_path}.position.npy")
        new_path = Path(f"{output_parent_dir}/{input_name}.position.npy")
        src_path.rename(new_path)

        src_path = Path(f"{output_path}.features.0.npy")
        new_path = Path(f"{output_parent_dir}/{input_name}.features.npy")
        src_path.rename(new_path)

    return output_map_list

This code assumes that giving slide path is enough and the reader behind DeepFeatureExtractor will handle everything automatically. Is it possible to use the wsi that I got through wsi = WSIReader.open(slide_path, mpp=mpp, power=power) inside extractor.predict()?

@shaneahmed
Copy link
Member

The new engine design supports WSIReader input. #578

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants