Skip to content

Commit

Permalink
Merge pull request #197 from Dana-Farber-AIOS/release-1.0.2
Browse files Browse the repository at this point in the history
Release v1.0.2
  • Loading branch information
ryanccarelli authored Sep 22, 2021
2 parents 538de4b + 9fb216d commit 6755a6a
Show file tree
Hide file tree
Showing 13 changed files with 59 additions and 42 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ A toolkit for computational pathology and machine learning.

There are several ways to install `PathML`:

1. pip install (recommended for users)
1. pip install (**recommended for users**)
2. clone repo to local machine and install from source (recommended for developers/contributors)

Options (1) and (2) require that you first install all external dependencies:
Expand All @@ -32,7 +32,7 @@ Download Miniconda [here](https://docs.conda.io/en/latest/miniconda.html)

Create conda environment
````
conda create --name pathml python=3.8 numpy=1.18.5
conda create --name pathml python=3.8
conda activate pathml
````

Expand Down
1 change: 1 addition & 0 deletions docs/source/h5path.rst
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ Here we examine the **h5path** file format in detail:
root/ (Group)
├── fields/ (Group)
│ ├── name (Attribute, str)
│ ├── shape (Attribute, tuple)
│ ├── labels (Group)
│ │ ├── label1 (Attribute, [str, int, float, array])
│ │ ├── label2 (Attribute, [str, int, float, array])
Expand Down
25 changes: 11 additions & 14 deletions environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,17 @@ channels:
dependencies:
- pip==21.2.2
- python==3.8
- numpy>=1.16.4,<1.19.0
- scipy>=1.5.4
- scikit-image>=0.16.2
- numpy==1.19.5
- scipy==1.7.1
- scikit-image==0.18.3
- matplotlib==3.1.3
- python-spams>=2.6.1
- python-spams==2.6.1
- openjdk==8.0.152
- pytorch==1.9.0
- h5py==3.1.0
- dask==2021.7.1
- pydicom==2.1.2
- pytest>=6.2.2
- pytest==6.2.5
- pre-commit==2.13.0
- coverage==5.5
- pip:
Expand All @@ -27,12 +27,9 @@ dependencies:
- python-bioformats==4.0.0
- scanpy==1.7.2
- anndata==0.7.6
- deepcell>=0.9.0
- cellpose>=0.6.1
- tensorly==0.6.0
- ipython>=7.20.0
- sphinx>=3.4.3
- nbsphinx>=0.8.1
- nbsphinx-link>=1.3.0
- sphinx-rtd-theme>=0.5.1
- sphinx-autoapi>=1.8.3
- ipython==7.27.0
- sphinx==4.2.0
- nbsphinx==0.8.7
- nbsphinx-link==1.3.0
- sphinx-rtd-theme==1.0.0
- sphinx-autoapi==1.8.4
3 changes: 2 additions & 1 deletion pathml/core/h5managers.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ def __init__(self, h5path=None, slidedata=None):
# create group
fieldsgroup = self.h5.create_group("fields")
fieldsgroup.attrs["name"] = slidedata.name
fieldsgroup.attrs["shape"] = slidedata.slide.get_image_shape()
labelsgroup = self.h5["fields"].create_group("labels")
if slidedata.labels:
for key, label in slidedata.labels.items():
Expand Down Expand Up @@ -638,6 +639,6 @@ def check_valid_h5path_format(h5path):
"""
assert set(h5path.keys()) == {"fields", "array", "masks", "counts", "tiles"}
assert set(h5path["fields"].keys()) == {"labels", "slide_type"}
assert set(h5path["fields"].attrs.keys()) == {"name"}
assert set(h5path["fields"].attrs.keys()) == {"name", "shape"}
# slide_type attributes are not enforced
return True
6 changes: 5 additions & 1 deletion pathml/core/slide_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ def __init__(
[
isinstance(val, (str, np.ndarray))
or np.issubdtype(type(val), np.number)
or np.issubdtype(type(val), np.bool_)
for val in labels.values()
]
), (
Expand Down Expand Up @@ -336,7 +337,10 @@ def shape(self):
Returns:
Tuple[int, int]: Shape of image (H, W)
"""
return self.slide.get_image_shape()
if self.backend == "h5path":
return tuple(self.h5manager.h5["fields"].attrs["shape"])
else:
return self.slide.get_image_shape()

@staticmethod
def _create_tile_dataset(slidedata):
Expand Down
1 change: 1 addition & 0 deletions pathml/core/tile.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ def __init__(
[
isinstance(val, (str, np.ndarray))
or np.issubdtype(type(val), np.number)
or np.issubdtype(type(val), np.bool_)
for val in labels.values()
]
), (
Expand Down
38 changes: 18 additions & 20 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

setuptools.setup(
name="pathml",
version="1.0.1",
version="1.0.2",
author="Jacob Rosenthal, Ryan Carelli et al.",
author_email="[email protected]",
description="Tools for computational pathology",
Expand All @@ -17,26 +17,24 @@
"Source Code": "https://github.com/Dana-Farber-AIOS/pathml",
},
install_requires=[
"pip==21.2.2",
"numpy>=1.16.4,<1.19.0",
"pandas==1.1.5",
"scipy==1.5.4",
"pip",
"numpy>=1.16.4",
"pandas",
"scipy",
"scikit-image",
"statsmodels==0.12.2",
"matplotlib==3.1.3",
"openslide-python==1.1.2",
"pydicom==2.1.2",
"h5py==3.1.0",
"spams==2.6.2.5",
"scikit-learn==0.24.2",
"dask[distributed]==2021.7.1",
"anndata==0.7.6",
"scanpy==1.7.2",
"pre-commit==2.13.0",
"torch==1.9.0",
"opencv-contrib-python==4.5.3.56",
"tensorly==0.6.0",
"python-bioformats==4.0.0",
"statsmodels",
"matplotlib",
"openslide-python",
"pydicom",
"h5py",
"spams",
"scikit-learn",
"dask[distributed]",
"anndata>=0.7.6",
"scanpy",
"torch",
"opencv-contrib-python",
"python-bioformats",
],
classifiers=[
"License :: OSI Approved :: GNU General Public License v2 (GPLv2)",
Expand Down
2 changes: 2 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ def create_HE_tile():
"test_array_label": np.array([2, 3, 4]),
"test_int_label": 3,
"test_float_label": 3.0,
"test_bool_label": True,
}
tile = Tile(image=im_np_rgb, coords=(1, 3), masks=masks, labels=labs)
return tile
Expand Down Expand Up @@ -83,6 +84,7 @@ def tileVectra():
"test_array_label": np.array([2, 3, 4]),
"test_int_label": 3,
"test_float_label": 3.0,
"test_bool_label": True,
}

tile = Tile(
Expand Down
5 changes: 5 additions & 0 deletions tests/core_tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import anndata
import numpy as np

# define fixtures here, and use them throughout the other tests in core_tests/
import pytest
from pathml.core import SlideData, SlideDataset, Tile, VectraSlide, types
Expand All @@ -17,6 +18,7 @@ def example_slide_data():
"test_array_label": np.array([2, 3, 4]),
"test_int_label": 3,
"test_float_label": 3.0,
"test_bool_label": True,
}
wsi = SlideData(
"tests/testdata/small_HE.svs", name=f"test", labels=labs, backend="openslide"
Expand All @@ -31,6 +33,7 @@ def example_slide_data_with_tiles(tile):
"test_array_label": np.array([2, 3, 4]),
"test_int_label": 3,
"test_float_label": 3.0,
"test_bool_label": True,
}
adata = anndata.AnnData()
wsi = SlideData(
Expand All @@ -52,6 +55,7 @@ def slide_dataset(example_slide_data_with_tiles):
"test_array_label": np.array([2, 3, 4]),
"test_int_label": 3,
"test_float_label": 3.0,
"test_bool_label": True,
}
slide_list = [
SlideData(
Expand All @@ -74,6 +78,7 @@ def slide_dataset_with_tiles(tile, example_slide_data_with_tiles):
"test_array_label": np.array([2, 3, 4]),
"test_int_label": 3,
"test_float_label": 3.0,
"test_bool_label": True,
}
slide_list = [
SlideData(
Expand Down
2 changes: 2 additions & 0 deletions tests/core_tests/test_slide_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,9 @@ def test_read_write_heslide(tmp_path, example_slide_data_with_tiles):
path = tmp_path / "testhe.h5"
slidedata.write(path)
readslidedata = SlideData(path)
repr(readslidedata)
assert readslidedata.name == slidedata.name
assert readslidedata.shape == slidedata.shape
np.testing.assert_equal(readslidedata.labels, slidedata.labels)
if slidedata.masks is None:
assert readslidedata.masks is None
Expand Down
1 change: 1 addition & 0 deletions tests/integration_tests/test_pipeline_running.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ def test_pipeline_bioformats_tiff(tmp_path, dist, tile_size):
@pytest.mark.parametrize("dist", [False, True])
@pytest.mark.parametrize("tile_size", [1000, (1920, 1440)])
def test_pipeline_bioformats_vectra(tmp_path, dist, tile_size):
SegmentMIF = pytest.importorskip("pathml.preprocessing.transforms.SegmentMIF")
slide = VectraSlide("tests/testdata/small_vectra.qptiff")
pipeline = Pipeline(
[
Expand Down
4 changes: 2 additions & 2 deletions tests/preprocessing_tests/test_pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
import numpy as np
import pandas as pd
import copy
import pytest

from pathml.preprocessing import Pipeline

from pathml.preprocessing import (
MedianBlur,
GaussianBlur,
Expand All @@ -22,7 +22,6 @@
StainNormalizationHE,
NucleusDetectionHE,
TissueDetectionHE,
SegmentMIF,
QuantifyMIF,
CollapseRunsVectra,
)
Expand Down Expand Up @@ -75,6 +74,7 @@ def test_pipeline_mif(tileVectra):
"""
Run MIF pipeline
"""
SegmentMIF = pytest.importorskip("pathml.preprocessing.transforms.SegmentMIF")
orig_tile = copy.copy(tileVectra)
pipe = Pipeline(
[
Expand Down
9 changes: 7 additions & 2 deletions tests/preprocessing_tests/test_transforms.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
LabelArtifactTileHE,
LabelWhiteSpaceHE,
QuantifyMIF,
SegmentMIF,
CollapseRunsVectra,
CollapseRunsCODEX,
)
Expand Down Expand Up @@ -130,6 +129,7 @@ def test_binary_label_transforms(tileHE, transform):


def test_segment_mif(tileVectra):
SegmentMIF = pytest.importorskip("pathml.preprocessing.transforms.SegmentMIF")
vectra_collapse = CollapseRunsVectra()
vectra_collapse.apply(tileVectra)
t = SegmentMIF(nuclear_channel=0, cytoplasm_channel=1)
Expand All @@ -141,6 +141,7 @@ def test_segment_mif(tileVectra):


def test_quantify_mif(tileVectra):
SegmentMIF = pytest.importorskip("pathml.preprocessing.transforms.SegmentMIF")
t = QuantifyMIF("cell_segmentation")
with pytest.raises(AssertionError):
t.apply(tileVectra)
Expand Down Expand Up @@ -178,10 +179,14 @@ def test_collapse_runs_vectra(tileVectra):
LabelArtifactTileHE(),
LabelWhiteSpaceHE(),
QuantifyMIF(segmentation_mask="test"),
SegmentMIF(nuclear_channel=0, cytoplasm_channel=1),
CollapseRunsVectra(),
CollapseRunsCODEX(z=0),
],
)
def test_repr(transform):
repr(transform)


def test_segmentMIF_repr():
SegmentMIF = pytest.importorskip("pathml.preprocessing.transforms.SegmentMIF")
repr(SegmentMIF(nuclear_channel=0, cytoplasm_channel=1))

0 comments on commit 6755a6a

Please sign in to comment.