Skip to content

Commit

Permalink
Merge pull request #334 from Dana-Farber-AIOS/merge-master
Browse files Browse the repository at this point in the history
Merge main branch into dev
  • Loading branch information
jacob-rosenthal committed Oct 26, 2022
2 parents 3e13d2b + 0662001 commit d95ff9b
Show file tree
Hide file tree
Showing 55 changed files with 331 additions and 261 deletions.
4 changes: 4 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[flake8]
max-line-length = 88
extend-ignore = E203 E501
per-file-ignores = __init__.py:F401
17 changes: 17 additions & 0 deletions .github/workflows/precommit-hooks.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
name: pre-commit-hooks

on: [pull_request]

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Python 3.8
uses: actions/setup-python@v1
with:
python-version: 3.8
- name: Linting
run: |
pip install pre-commit
pre-commit run --all-files
22 changes: 16 additions & 6 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,22 @@ repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.0.1
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files

- repo: https://github.com/psf/black
rev: 21.6b0 # Replace by any tag/version: https://github.com/psf/black/tags
rev: 22.8.0
hooks:
- id: black
language_version: python3 # Should be a command that runs python3.6+

- repo: https://github.com/timothycrosley/isort
rev: 5.10.1
hooks:
- id: isort

- repo: https://github.com/pycqa/flake8
rev: 5.0.4
hooks:
- id: flake8
64 changes: 64 additions & 0 deletions CITATION.cff
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
cff-version: 1.2.0
message: "Citation for this repository"
authors:
- family-names: Rosenthal
given-names: Jacob
- family-names: Carelli
given-names: Ryan
- family-names: Mohammed
given-names: Omar
- family-names: Brundage
given-names: David
- family-names: Halbert
given-names: Ella
- family-names: Nyman
given-names: Jackson
- family-names: Hari
given-names: Surya
- family-names: Van Allen
given-names: Eliezer
- family-names: Marchionni
given-names: Luigi
- family-names: Umeton
given-names: Renato
- family-names: Loda
given-names: Massimo
title: "Building Tools for Machine Learning and Artificial Intelligence in Cancer Research: Best Practices and a Case Study with the PathML Toolkit for Computational Pathology"
date-released: 2022-02-03
doi: 10.1158/1541-7786.MCR-21-0665
url: https://github.com/Dana-Farber-AIOS/pathml
preferred-citation:
type: article
authors:
- family-names: Rosenthal
given-names: Jacob
- family-names: Carelli
given-names: Ryan
- family-names: Mohammed
given-names: Omar
- family-names: Brundage
given-names: David
- family-names: Halbert
given-names: Ella
- family-names: Nyman
given-names: Jackson
- family-names: Hari
given-names: Surya
- family-names: Van Allen
given-names: Eliezer
- family-names: Marchionni
given-names: Luigi
- family-names: Umeton
given-names: Renato
- family-names: Loda
given-names: Massimo
doi: 10.1158/1541-7786.MCR-21-0665
journal: "Molecular Cancer Research"
publisher: American Academy of Cancer Research
month: 2
year: 2022
issue: 2
volume: 20
start: 202
title: "Building Tools for Machine Learning and Artificial Intelligence in Cancer Research: Best Practices and a Case Study with the PathML Toolkit for Computational Pathology"
url: https://doi.org/10.1158/1541-7786.MCR-21-0665
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ pip install -e .

First, download or build the PathML Docker container:

![pathml-docker-installation](https://user-images.githubusercontent.com/25375373/191053363-477497a1-9804-48f3-91f9-767dc7f859ed.gif)

- Option A: download PathML container from Docker Hub
````
docker pull pathml/pathml:latest
Expand Down
2 changes: 1 addition & 1 deletion pathml/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
License: GNU GPL 2.0
"""

from .core import *
from . import datasets as ds
from . import ml
from . import preprocessing as pp
from ._logging import PathMLLogger
from ._version import __version__
from .core import * # noqa: F403
3 changes: 2 additions & 1 deletion pathml/_logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
License: GNU GPL 2.0
"""

from loguru import logger
import functools
import sys

from loguru import logger


class PathMLLogger:
"""
Expand Down
2 changes: 1 addition & 1 deletion pathml/_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
License: GNU GPL 2.0
"""

__version__ = "2.0.4"
__version__ = "2.1.0"
10 changes: 5 additions & 5 deletions pathml/core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@
"""

from .masks import Masks
from .slide_backends import OpenSlideBackend, BioFormatsBackend, DICOMBackend
from .slide_backends import BioFormatsBackend, DICOMBackend, OpenSlideBackend
from .slide_data import (
SlideData,
CODEXSlide,
HESlide,
IHCSlide,
MultiparametricSlide,
SlideData,
VectraSlide,
CODEXSlide,
IHCSlide,
)
from .slide_dataset import SlideDataset
from .slide_types import SlideType, types
from .tile import Tile
from .tiles import Tiles
from .slide_types import SlideType, types
31 changes: 15 additions & 16 deletions pathml/core/h5managers.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@
License: GNU GPL 2.0
"""

import itertools
import os
import tempfile
from collections import OrderedDict

import anndata
from loguru import logger
import h5py
import numpy as np
from loguru import logger

import pathml.core
import pathml.core.masks
import pathml.core.tile
Expand All @@ -35,10 +34,10 @@ def __init__(self, h5path=None, slidedata=None):
if h5path:
assert (
not slidedata
), f"if creating h5pathmanager from h5path, slidedata should not be required"
), "if creating h5pathmanager from h5path, slidedata should not be required"
assert check_valid_h5path_format(
h5path
), f"h5path must conform to .h5path standard, see documentation"
), "h5path must conform to .h5path standard, see documentation"
# copy h5path into self.h5
for ds in h5path.keys():
if ds in ["fields", "masks", "tiles"]:
Expand All @@ -52,19 +51,19 @@ def __init__(self, h5path=None, slidedata=None):
)

else:
assert slidedata, f"must pass slidedata object to create h5path"
assert slidedata, "must pass slidedata object to create h5path"
# initialize h5path file hierarchy
# fields
fieldsgroup = self.h5.create_group("fields")
# name, shape, labels
fieldsgroup.attrs["name"] = slidedata.name
fieldsgroup.attrs["shape"] = slidedata.slide.get_image_shape()
labelsgroup = self.h5["fields"].create_group("labels")
self.h5["fields"].create_group("labels")
if slidedata.labels:
for key, label in slidedata.labels.items():
self.h5["fields/labels"].attrs[key] = label
# slidetype
slidetypegroup = self.h5["fields"].create_group("slide_type")
self.h5["fields"].create_group("slide_type")
if slidedata.slide_type:
for key, val in slidedata.slide_type.asdict().items():
self.h5["fields/slide_type"].attrs[key] = val
Expand All @@ -75,9 +74,9 @@ def __init__(self, h5path=None, slidedata=None):
# initialize stride with 0
tilesgroup.attrs["tile_stride"] = b"(0, 0)"
# masks
masksgroup = self.h5.create_group("masks")
self.h5.create_group("masks")
# counts
countsgroup = self.h5.create_group("counts")
self.h5.create_group("counts")

slide_type_dict = {
key: val for key, val in self.h5["fields/slide_type"].attrs.items()
Expand Down Expand Up @@ -150,7 +149,7 @@ def add_tile(self, tile):
if tile.masks:
# create a group to hold tile-level masks
if "masks" not in self.h5["tiles"][str(tile.coords)].keys():
masksgroup = self.h5["tiles"][str(tile.coords)].create_group("masks")
self.h5["tiles"][str(tile.coords)].create_group("masks")

# add tile-level masks
for key, mask in tile.masks.items():
Expand All @@ -168,7 +167,7 @@ def add_tile(self, tile):
self.h5["tiles"][str(tile.coords)].attrs["name"] = (
str(tile.name) if tile.name else 0
)
tilelabelsgroup = self.h5["tiles"][str(tile.coords)].create_group("labels")
self.h5["tiles"][str(tile.coords)].create_group("labels")
if tile.labels:
for key, val in tile.labels.items():
self.h5["tiles"][str(tile.coords)]["labels"].attrs[key] = val
Expand Down Expand Up @@ -198,7 +197,7 @@ def get_tile(self, item):
Tile(pathml.core.tile.Tile)
"""
if isinstance(item, bool):
raise KeyError(f"invalid key, pass str or tuple")
raise KeyError("invalid key, pass str or tuple")
if isinstance(item, (str, tuple)):
item = str(item)
if item not in self.h5["tiles"].keys():
Expand Down Expand Up @@ -246,7 +245,7 @@ def remove_tile(self, key):
Remove tile from self.h5 by key.
"""
if not isinstance(key, (str, tuple)):
raise KeyError(f"key must be str or tuple, check valid keys in repr")
raise KeyError("key must be str or tuple, check valid keys in repr")
if str(key) not in self.h5["tiles"].keys():
raise KeyError(f"key {key} is not in Tiles")
del self.h5["tiles"][str(key)]
Expand All @@ -270,7 +269,7 @@ def add_mask(self, key, mask):
raise ValueError(
f"key {key} already exists in 'masks'. Cannot add. Must update to modify existing mask."
)
newmask = self.h5["masks"].create_dataset(key, data=mask)
self.h5["masks"].create_dataset(key, data=mask)

def update_mask(self, key, mask):
"""
Expand Down Expand Up @@ -340,7 +339,7 @@ def remove_mask(self, key):
f"masks keys must be of type(str) but key was passed of type {type(key)}"
)
if key not in self.h5["masks"].keys():
raise KeyError(f"key is not in Masks")
raise KeyError("key is not in Masks")
del self.h5["masks"][key]

def get_slidetype(self):
Expand Down
9 changes: 3 additions & 6 deletions pathml/core/masks.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,10 @@
License: GNU GPL 2.0
"""

import numpy as np
import os
from pathlib import Path
from collections import OrderedDict
import h5py
import reprlib
from loguru import logger
from collections import OrderedDict

import numpy as np

import pathml.core.h5managers

Expand Down
Loading

0 comments on commit d95ff9b

Please sign in to comment.