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

Added Documentations #48

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,11 @@ instance/
.scrapy

# Sphinx documentation
docs/build/
docs/_build/
docs/html/
docs/_autosummary/
docs/src/

# PyBuilder
target/
Expand Down Expand Up @@ -131,3 +135,6 @@ dmypy.json

# Pyre type checker
.pyre/

# macOS
*.DS_Store
20 changes: 20 additions & 0 deletions docs/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Minimal makefile for Sphinx documentation
#

# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
SOURCEDIR = .
BUILDDIR = build

# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

.PHONY: help Makefile

# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
30 changes: 30 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
## Documentations

### Build

First install requirements for building docs:
```
python -m pip install -r docs/requirements.txt
```

Docs can then be built running the commands:

```
cd docs/
sphinx-apidoc -f -o src/ ../torchstain
make html
```

### Usage

To access the documentations, open the generated HTML in your browser, e.g., with firefox on Linux run this:
```
firefox build/html/index.html
```

Alternatively, on macOS you can open the HTML in chrome by:
```
open -a "Google Chrome" build/html/index.html
```

When documentations are pushed to production, they will be available at [torchstain.readthedocs.io/](https://torchstain.readthedocs.io/).
82 changes: 82 additions & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
"""Configuration file for the Sphinx documentation builder."""

import inspect
import os
import subprocess
import sys

import torchstain


sys.path.insert(0, os.path.abspath('..'))


# Project information
url = "https://github.com/EIDOSLAB/torchstain"

# General configuration
master_doc = 'index'

# Sphinx extension modules
extensions = [
'sphinx.ext.napoleon',
'sphinx.ext.autodoc',
'sphinx.ext.intersphinx',
'sphinx.ext.linkcode',
]

# Generate autosummary
autosummary_generate = True

# Add any paths that contain templates here, relative to this directory.
templates_path = ['templates']

# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files
exclude_patterns = ['templates']

# numpy style docs with Napoleon
napoleon_google_docstring = False
napoleon_use_param = False
napoleon_use_ivar = True

# Draw graphs in the SVG format instead of the default PNG format
graphviz_output_format = 'svg'

# sphinx.ext.linkcode: Try to link to source code on GitHub
REVISION_CMD = ['git', 'rev-parse', '--short', 'HEAD']
try:
_git_revision = subprocess.check_output(REVISION_CMD).strip()
except (subprocess.CalledProcessError, OSError):
_git_revision = 'master'
else:
_git_revision = _git_revision.decode('utf-8')


def linkcode_resolve(domain, info):
if domain != 'py':
return None
module = info.get('module', None)
fullname = info.get('fullname', None)
if not module or not fullname:
return None
obj = sys.modules.get(module, None)
if obj is None:
return None

for part in fullname.split('.'):
obj = getattr(obj, part)
if isinstance(obj, property):
obj = obj.fget
if hasattr(obj, '__wrapped__'):
obj = obj.__wrapped__

file = inspect.getsourcefile(obj)
package_dir = os.path.dirname(torchstain.__file__)
if file is None or os.path.commonpath([file, package_dir]) != package_dir:
return None
file = os.path.relpath(file, start=package_dir)
source, line_start = inspect.getsourcelines(obj)
line_end = line_start + len(source) - 1
filename = f'src/torchstain/{file}#L{line_start}-L{line_end}'
return f'{url}/blob/{_git_revision}/{filename}'
61 changes: 61 additions & 0 deletions docs/examples/stain_normalization.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
Stain Normalization
===================

The torchstain package supports three different backends: PyTorch,
TensorFlow, and NumPy. Below is a simple example of how to get started.
In this example we use PyTorch.

To run example, be sure to have installed the necessary dependencies:

``pip install torchstain[torch] torchvision opencv-python``

A simple usage example can be seen below:

.. code-block:: python

import torch
from torchvision import transforms
import torchstain
import cv2

target = cv2.cvtColor(cv2.imread("./data/target.png"), cv2.COLOR_BGR2RGB)
to_transform = cv2.cvtColor(cv2.imread("./data/source.png"), cv2.COLOR_BGR2RGB)

T = transforms.Compose([
transforms.ToTensor(),
transforms.Lambda(lambda x: x*255)
])

normalizer = torchstain.normalizers.MacenkoNormalizer(backend='torch')
normalizer.fit(T(target))

t_to_transform = T(to_transform)
norm, H, E = normalizer.normalize(I=t_to_transform, stains=True)


The generated result can be seen below:

.. image:: ../../data/result.png
:alt: Stain normalized result


Different Backends
------------------

To use TensorFlow or NumPy backend, simply change the *backend*
argument to the *MacenkoNormalizer*. Also note that different for
different backends and normalization techniques, different
preprocessing may be required.

For TensorFlow instead perform:

.. code-block:: python

import tensorflow as tf
import numpy as np

T = lambda x: tf.convert_to_tensor(np.moveaxis(x, -1, 0).astype("float32"))
t_to_transform = T(to_transform)

Whereas for NumPy *no* preprocessing is required, given that the image
is already channel-last and uint8 dtype.
61 changes: 61 additions & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
:github_url: https://github.com/EIDOSLAB/torchstain/tree/main/docs

TorchStain
-------------------

TorchStain is a modular Python package for GPU-accelerated stain normalization
and augmentation for histopathological image analysis. It supports PyTorch,
TensorFlow, and NumPy backends.

Installation
------------

The latest release of TorchStain can be installed from
`PyPI <https://pypi.org/project/torchstain/>`_ by:

``pip install torchstain``

To install a specific backend use either torchstain[torch] or torchstain[tf].
The numpy backend is included by default in both.

You may also install directly from GitHub, using the following command:

``pip install git+https://github.com/EIDOSLAB/torchstain``

.. toctree::
:glob:
:caption: Examples
:maxdepth: 2

examples/*

.. toctree::
:caption: API Documentation
:maxdepth: 10

src/modules

The Team
--------

The development of TorchStain is led by researchers at `EIDOSLAB <https://eidos.di.unito.it/>`_
and `SINTEF MIA <https://www.sintef.no/en/expertise/sintef-technology-and-society/medical-technology/>`_.
We are also very grateful to the open source community for contributing ideas, bug fixes, and issues.

Support
-------

If you are having issues, please let us know by filing an issue on our
`issue tracker <https://github.com/EIDOSLAB/torchstain/issues>`_.


License
-------

TorchStain is licensed under the `MIT License <https://github.com/EIDOSLAB/torchstain/blob/main/LICENSE>`_.


Indices and Tables
==================

* :ref:`genindex`
5 changes: 5 additions & 0 deletions docs/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
sphinx==5.3.0
sphinx-rtd-theme
torchstain
tensorflow
torch
32 changes: 32 additions & 0 deletions docs/templates/class.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{{ fullname | escape | underline}}

.. currentmodule:: {{ module }}

.. autoclass:: {{ objname }}
:members: <-- add at least this line
:show-inheritance: <-- plus I want to show inheritance...
:inherited-members: <-- ...and inherited members too

{% block methods %}
.. automethod:: __init__

{% if methods %}
.. rubric:: {{ _('Methods') }}

.. autosummary::
{% for item in methods %}
~{{ name }}.{{ item }}
{%- endfor %}
{% endif %}
{% endblock %}

{% block attributes %}
{% if attributes %}
.. rubric:: {{ _('Attributes') }}

.. autosummary::
{% for item in attributes %}
~{{ name }}.{{ item }}
{%- endfor %}
{% endif %}
{% endblock %}
66 changes: 66 additions & 0 deletions docs/templates/module.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
{{ fullname | escape | underline}}

.. automodule:: {{ fullname }}

{% block attributes %}
{% if attributes %}
.. rubric:: Module Attributes

.. autosummary::
:toctree: <-- add this line
{% for item in attributes %}
{{ item }}
{%- endfor %}
{% endif %}
{% endblock %}

{% block functions %}
{% if functions %}
.. rubric:: {{ _('Functions') }}

.. autosummary::
:toctree: <-- add this line
{% for item in functions %}
{{ item }}
{%- endfor %}
{% endif %}
{% endblock %}

{% block classes %}
{% if classes %}
.. rubric:: {{ _('Classes') }}

.. autosummary::
:toctree: <-- add this line
:template: class.rst <-- add this line
{% for item in classes %}
{{ item }}
{%- endfor %}
{% endif %}
{% endblock %}

{% block exceptions %}
{% if exceptions %}
.. rubric:: {{ _('Exceptions') }}

.. autosummary::
:toctree: <-- add this line
{% for item in exceptions %}
{{ item }}
{%- endfor %}
{% endif %}
{% endblock %}

{% block modules %}
{% if modules %}
.. rubric:: Modules

.. autosummary::
:toctree:
:template: class.rst <-- add this line
:recursive:
{% for item in modules %}
{{ item }}
{%- endfor %}
{% endif %}
{% endblock %}
Loading