├── docs
├── .nojekyll
├── _build
│ ├── html
│ │ ├── .nojekyll
│ │ ├── _static
│ │ │ ├── custom.css
│ │ │ ├── up.png
│ │ │ ├── down.png
│ │ │ ├── file.png
│ │ │ ├── plus.png
│ │ │ ├── comment.png
│ │ │ ├── minus.png
│ │ │ ├── ajax-loader.gif
│ │ │ ├── down-pressed.png
│ │ │ ├── up-pressed.png
│ │ │ ├── comment-bright.png
│ │ │ ├── comment-close.png
│ │ │ ├── pygments.css
│ │ │ ├── better.css
│ │ │ ├── better_basic.css
│ │ │ ├── doctools.js
│ │ │ ├── underscore.js
│ │ │ ├── documentation_options.js
│ │ │ ├── basic.css
│ │ │ ├── alabaster.css
│ │ │ └── searchtools.js
│ │ ├── objects.inv
│ │ ├── _images
│ │ │ ├── region.png
│ │ │ ├── thumb.png
│ │ │ ├── tissue.png
│ │ │ ├── color_bars.png
│ │ │ ├── random_patch.png
│ │ │ └── random_tumor_patch.png
│ │ ├── _sources
│ │ │ ├── show.rst.txt
│ │ │ ├── slide.rst.txt
│ │ │ ├── slide2.rst.txt
│ │ │ ├── beyondwsipre.rst.txt
│ │ │ ├── api.rst.txt
│ │ │ ├── wsiprein5minutes.rst.txt
│ │ │ ├── index.rst.txt
│ │ │ └── quick_intro.rst.txt
│ │ ├── .buildinfo
│ │ ├── _modules
│ │ │ └── index.html
│ │ ├── search.html
│ │ ├── py-modindex.html
│ │ ├── beyondwsipre.html
│ │ ├── wsiprein5minutes.html
│ │ ├── searchindex.js
│ │ ├── genindex.html
│ │ ├── index.html
│ │ ├── show.html
│ │ └── quick_intro.html
│ └── doctrees
│ │ ├── api.doctree
│ │ ├── show.doctree
│ │ ├── index.doctree
│ │ ├── slide.doctree
│ │ ├── slide2.doctree
│ │ ├── beyondwsipre.doctree
│ │ ├── environment.pickle
│ │ ├── quick_intro.doctree
│ │ └── wsiprein5minutes.doctree
├── show.rst
├── slide.rst
├── beyondwsipre.rst
├── index.html
├── Makefile
├── make.bat
├── index.rst
├── quick_intro.rst
└── conf.py
├── img
├── thumb.png
├── region.png
├── tissue.png
├── color_bars.png
├── random_patch.png
└── random_tumor_patch.png
├── wsipre
├── __init__.py
├── tissue.py
├── annotation.py
└── show.py
├── README.md
├── setup.py
├── LICENSE
├── .gitignore
└── environment.yml
/docs/.nojekyll:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/_build/html/.nojekyll:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/_build/html/_static/custom.css:
--------------------------------------------------------------------------------
1 | /* This file intentionally left blank. */
2 |
--------------------------------------------------------------------------------
/img/thumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvalesilva/wsipre/HEAD/img/thumb.png
--------------------------------------------------------------------------------
/img/region.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvalesilva/wsipre/HEAD/img/region.png
--------------------------------------------------------------------------------
/img/tissue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvalesilva/wsipre/HEAD/img/tissue.png
--------------------------------------------------------------------------------
/img/color_bars.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvalesilva/wsipre/HEAD/img/color_bars.png
--------------------------------------------------------------------------------
/img/random_patch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvalesilva/wsipre/HEAD/img/random_patch.png
--------------------------------------------------------------------------------
/docs/show.rst:
--------------------------------------------------------------------------------
1 | Figure
2 | ======
3 | .. module:: show
4 |
5 | .. autoclass:: Figure
6 | :members:
7 |
--------------------------------------------------------------------------------
/img/random_tumor_patch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvalesilva/wsipre/HEAD/img/random_tumor_patch.png
--------------------------------------------------------------------------------
/docs/_build/html/objects.inv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvalesilva/wsipre/HEAD/docs/_build/html/objects.inv
--------------------------------------------------------------------------------
/docs/_build/html/_static/up.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvalesilva/wsipre/HEAD/docs/_build/html/_static/up.png
--------------------------------------------------------------------------------
/docs/_build/doctrees/api.doctree:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvalesilva/wsipre/HEAD/docs/_build/doctrees/api.doctree
--------------------------------------------------------------------------------
/docs/_build/doctrees/show.doctree:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvalesilva/wsipre/HEAD/docs/_build/doctrees/show.doctree
--------------------------------------------------------------------------------
/docs/_build/html/_static/down.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvalesilva/wsipre/HEAD/docs/_build/html/_static/down.png
--------------------------------------------------------------------------------
/docs/_build/html/_static/file.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvalesilva/wsipre/HEAD/docs/_build/html/_static/file.png
--------------------------------------------------------------------------------
/docs/_build/html/_static/plus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvalesilva/wsipre/HEAD/docs/_build/html/_static/plus.png
--------------------------------------------------------------------------------
/docs/_build/doctrees/index.doctree:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvalesilva/wsipre/HEAD/docs/_build/doctrees/index.doctree
--------------------------------------------------------------------------------
/docs/_build/doctrees/slide.doctree:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvalesilva/wsipre/HEAD/docs/_build/doctrees/slide.doctree
--------------------------------------------------------------------------------
/docs/_build/doctrees/slide2.doctree:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvalesilva/wsipre/HEAD/docs/_build/doctrees/slide2.doctree
--------------------------------------------------------------------------------
/docs/_build/html/_images/region.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvalesilva/wsipre/HEAD/docs/_build/html/_images/region.png
--------------------------------------------------------------------------------
/docs/_build/html/_images/thumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvalesilva/wsipre/HEAD/docs/_build/html/_images/thumb.png
--------------------------------------------------------------------------------
/docs/_build/html/_images/tissue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvalesilva/wsipre/HEAD/docs/_build/html/_images/tissue.png
--------------------------------------------------------------------------------
/docs/_build/html/_static/comment.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvalesilva/wsipre/HEAD/docs/_build/html/_static/comment.png
--------------------------------------------------------------------------------
/docs/_build/html/_static/minus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvalesilva/wsipre/HEAD/docs/_build/html/_static/minus.png
--------------------------------------------------------------------------------
/docs/_build/html/_sources/show.rst.txt:
--------------------------------------------------------------------------------
1 | Figure
2 | ======
3 | .. module:: show
4 |
5 | .. autoclass:: Figure
6 | :members:
7 |
--------------------------------------------------------------------------------
/docs/slide.rst:
--------------------------------------------------------------------------------
1 | Slide
2 | =====
3 | .. module:: slide
4 |
5 | .. autoclass:: Slide
6 | :members:
7 | :inherited-members:
8 |
--------------------------------------------------------------------------------
/docs/_build/doctrees/beyondwsipre.doctree:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvalesilva/wsipre/HEAD/docs/_build/doctrees/beyondwsipre.doctree
--------------------------------------------------------------------------------
/docs/_build/doctrees/environment.pickle:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvalesilva/wsipre/HEAD/docs/_build/doctrees/environment.pickle
--------------------------------------------------------------------------------
/docs/_build/doctrees/quick_intro.doctree:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvalesilva/wsipre/HEAD/docs/_build/doctrees/quick_intro.doctree
--------------------------------------------------------------------------------
/docs/_build/html/_images/color_bars.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvalesilva/wsipre/HEAD/docs/_build/html/_images/color_bars.png
--------------------------------------------------------------------------------
/docs/_build/html/_images/random_patch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvalesilva/wsipre/HEAD/docs/_build/html/_images/random_patch.png
--------------------------------------------------------------------------------
/docs/_build/html/_static/ajax-loader.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvalesilva/wsipre/HEAD/docs/_build/html/_static/ajax-loader.gif
--------------------------------------------------------------------------------
/docs/_build/html/_static/down-pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvalesilva/wsipre/HEAD/docs/_build/html/_static/down-pressed.png
--------------------------------------------------------------------------------
/docs/_build/html/_static/up-pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvalesilva/wsipre/HEAD/docs/_build/html/_static/up-pressed.png
--------------------------------------------------------------------------------
/docs/_build/html/_static/comment-bright.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvalesilva/wsipre/HEAD/docs/_build/html/_static/comment-bright.png
--------------------------------------------------------------------------------
/docs/_build/html/_static/comment-close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvalesilva/wsipre/HEAD/docs/_build/html/_static/comment-close.png
--------------------------------------------------------------------------------
/docs/_build/doctrees/wsiprein5minutes.doctree:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvalesilva/wsipre/HEAD/docs/_build/doctrees/wsiprein5minutes.doctree
--------------------------------------------------------------------------------
/docs/beyondwsipre.rst:
--------------------------------------------------------------------------------
1 |
2 | **Coming soon...**
3 |
4 | Beyond wsipre
5 | =============
6 |
7 | Ways to use and extend **wsipre**'s output.
8 |
9 |
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/docs/_build/html/_images/random_tumor_patch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvalesilva/wsipre/HEAD/docs/_build/html/_images/random_tumor_patch.png
--------------------------------------------------------------------------------
/docs/_build/html/_sources/slide.rst.txt:
--------------------------------------------------------------------------------
1 | Slide
2 | =====
3 | .. module:: slide
4 |
5 | .. autoclass:: Slide
6 | :members:
7 | :inherited-members:
8 |
--------------------------------------------------------------------------------
/docs/_build/html/_sources/slide2.rst.txt:
--------------------------------------------------------------------------------
1 | Slide
2 | =====
3 | .. module:: slide
4 |
5 | .. autoclass:: OpenSlide
6 | :members:
7 | :inherited-members:
8 |
--------------------------------------------------------------------------------
/wsipre/__init__.py:
--------------------------------------------------------------------------------
1 | name = 'wsipre'
2 |
3 | # For relative imports to work
4 | import os, sys; sys.path.append(os.path.dirname(os.path.realpath(__file__)))
5 |
--------------------------------------------------------------------------------
/docs/_build/html/_sources/beyondwsipre.rst.txt:
--------------------------------------------------------------------------------
1 |
2 | **Coming soon...**
3 |
4 | Beyond wsipre
5 | =============
6 |
7 | Ways to use and extend **wsipre**'s output.
8 |
9 |
--------------------------------------------------------------------------------
/docs/_build/html/.buildinfo:
--------------------------------------------------------------------------------
1 | # Sphinx build info version 1
2 | # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
3 | config: e2d3e3cef9ab0211698d0b8975c331a1
4 | tags: 645f666f9bcd5a90fca523b33c5a78b7
5 |
--------------------------------------------------------------------------------
/docs/_build/html/_sources/api.rst.txt:
--------------------------------------------------------------------------------
1 | .. _api:
2 |
3 | API
4 | ===
5 |
6 | .. module:: slide
7 |
8 | This part of the documentation covers all the interfaces of **wsipre**.
9 |
10 | A Title
11 | ------------------
12 |
13 | .. autoclass:: OpenSlide
14 | :members:
15 | :inherited-members:
16 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # wsipre
2 |
3 | **W**hole-**S**lide **I**mage **PRE**processing
4 |
5 | **wsipre** is a small Python package to handle whole-slide images (WSI; also
6 | known as virtual slides) with region-level annotations.
7 |
8 | **wsipre** can be installed from PyPI as shown below. For more detail check out
9 | the [docs](https://luisvalesilva.com/wsipre/_build/html/index.html).
10 |
11 | ```console
12 | pip install wsipre
13 | ```
14 |
15 |
16 | ## License
17 |
18 | This project is licensed under the terms of the MIT license. See [LICENSE](LICENSE) file for details.
19 |
--------------------------------------------------------------------------------
/docs/Makefile:
--------------------------------------------------------------------------------
1 | # Minimal makefile for Sphinx documentation
2 | #
3 |
4 | # You can set these variables from the command line.
5 | SPHINXOPTS =
6 | SPHINXBUILD = sphinx-build
7 | SPHINXPROJ = wsipre
8 | SOURCEDIR = .
9 | BUILDDIR = _build
10 |
11 | # Put it first so that "make" without argument is like "make help".
12 | help:
13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
14 |
15 | .PHONY: help Makefile
16 |
17 | # Catch-all target: route all unknown targets to Sphinx using the new
18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
19 | %: Makefile
20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
--------------------------------------------------------------------------------
/docs/_build/html/_sources/wsiprein5minutes.rst.txt:
--------------------------------------------------------------------------------
1 | wsipre in 5 minutes
2 | ===================
3 |
4 | **wsipre** (**W**\ hole-**S**\ lide **I**\ mage **PRE**\ processing)
5 | is a wrapper of the excellent `OpenSlide Python`_ package, which
6 | allows reading whole-slide images (WSI), also known as virtual slides.
7 | **wsipre** conserves OpenSlide Python's API and extends it to handle WSI
8 | annotations and to perform some slide processing tasks. The driving objective
9 | is the preprocessing of WSIs, with or without annotations, for Machine Learning
10 | (ML), particularly Deep Learning (DL), applications.
11 |
12 | .. _OpenSlide Python: https://openslide.org/api/python/
13 |
14 |
15 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | import setuptools
2 |
3 | with open("README.md", "r") as fh:
4 | long_description = fh.read()
5 |
6 | setuptools.setup(
7 | name="wsipre",
8 | version="0.1.2",
9 | author="Luis A. Vale Silva",
10 | author_email="luisvalesilva@gmail.com",
11 | description="Whole-slide image preprocessing",
12 | long_description=long_description,
13 | long_description_content_type="text/markdown",
14 | license="BSD",
15 | keywords="whole-slide image virtual slide OpenSlide machine learning deep learning",
16 | url="https://github.com/luisvalesilva/wsipre",
17 | packages=setuptools.find_packages(),
18 | classifiers=[
19 | "Programming Language :: Python :: 3",
20 | "License :: OSI Approved :: MIT License",
21 | "Operating System :: OS Independent",
22 | ],
23 | )
24 |
--------------------------------------------------------------------------------
/docs/make.bat:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 |
3 | pushd %~dp0
4 |
5 | REM Command file for Sphinx documentation
6 |
7 | if "%SPHINXBUILD%" == "" (
8 | set SPHINXBUILD=sphinx-build
9 | )
10 | set SOURCEDIR=.
11 | set BUILDDIR=_build
12 | set SPHINXPROJ=wsipre
13 |
14 | if "%1" == "" goto help
15 |
16 | %SPHINXBUILD% >NUL 2>NUL
17 | if errorlevel 9009 (
18 | echo.
19 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
20 | echo.installed, then set the SPHINXBUILD environment variable to point
21 | echo.to the full path of the 'sphinx-build' executable. Alternatively you
22 | echo.may add the Sphinx directory to PATH.
23 | echo.
24 | echo.If you don't have Sphinx installed, grab it from
25 | echo.http://sphinx-doc.org/
26 | exit /b 1
27 | )
28 |
29 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
30 | goto end
31 |
32 | :help
33 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
34 |
35 | :end
36 | popd
37 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Luís
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | .eggs/
17 | lib/
18 | lib64/
19 | parts/
20 | sdist/
21 | var/
22 | wheels/
23 | *.egg-info/
24 | .installed.cfg
25 | *.egg
26 | MANIFEST
27 |
28 | # PyInstaller
29 | # Usually these files are written by a python script from a template
30 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
31 | *.manifest
32 | *.spec
33 |
34 | # Installer logs
35 | pip-log.txt
36 | pip-delete-this-directory.txt
37 |
38 | # Unit test / coverage reports
39 | htmlcov/
40 | .tox/
41 | .coverage
42 | .coverage.*
43 | .cache
44 | nosetests.xml
45 | coverage.xml
46 | *.cover
47 | .hypothesis/
48 | .pytest_cache/
49 |
50 | # Translations
51 | *.mo
52 | *.pot
53 |
54 | # Django stuff:
55 | *.log
56 | local_settings.py
57 | db.sqlite3
58 |
59 | # Flask stuff:
60 | instance/
61 | .webassets-cache
62 |
63 | # Scrapy stuff:
64 | .scrapy
65 |
66 | # PyBuilder
67 | target/
68 |
69 | # Jupyter Notebook
70 | .ipynb_checkpoints
71 |
72 | # pyenv
73 | .python-version
74 |
75 | # celery beat schedule file
76 | celerybeat-schedule
77 |
78 | # SageMath parsed files
79 | *.sage.py
80 |
81 | # Environments
82 | .env
83 | .venv
84 | env/
85 | venv/
86 | ENV/
87 | env.bak/
88 | venv.bak/
89 |
90 | # Spyder project settings
91 | .spyderproject
92 | .spyproject
93 |
94 | # Rope project settings
95 | .ropeproject
96 |
97 | # mkdocs documentation
98 | /site
99 |
100 | # mypy
101 | .mypy_cache/
102 |
--------------------------------------------------------------------------------
/wsipre/tissue.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | wsipre.tissue
5 | -------------
6 |
7 | Functionality to detect tissue RoIs.
8 | """
9 |
10 | import numpy as np
11 | import cv2
12 | from skimage import morphology
13 |
14 |
15 | def otsu_filter(channel, gaussian_blur=True):
16 | """Otsu filter."""
17 | if gaussian_blur:
18 | channel = cv2.GaussianBlur(channel, (5, 5), 0)
19 | channel = channel.reshape((channel.shape[0], channel.shape[1]))
20 |
21 | return cv2.threshold(
22 | channel, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]
23 |
24 |
25 | def detect_tissue(wsi, downsampling_factor=64):
26 | """Find RoIs containing tissue in WSI.
27 |
28 | Generate mask locating tissue in an WSI. Inspired by method used by
29 | Wang et al. [1]_.
30 |
31 | .. [1] Dayong Wang, Aditya Khosla, Rishab Gargeya, Humayun Irshad, Andrew
32 | H. Beck, "Deep Learning for Identifying Metastatic Breast Cancer",
33 | arXiv:1606.05718
34 |
35 | Parameters
36 | ----------
37 | wsi: OpenSlide/AnnotatedOpenSlide class instance
38 | The whole-slide image (WSI) to detect tissue in.
39 | downsampling_factor: int
40 | The desired factor to downsample the image by, since full WSIs will
41 | not fit in memory. The image's closest level downsample is found
42 | and used.
43 |
44 | Returns
45 | -------
46 | Binary mask as numpy 2D array, RGB slide image (in the used
47 | downsampling level, in case the user is visualizing output examples)
48 | and downsampling factor.
49 |
50 | """
51 | # Get a downsample of the whole slide image (to fit in memory)
52 | downsampling_factor = min(
53 | wsi.level_downsamples, key=lambda x: abs(x - downsampling_factor))
54 | level = wsi.level_downsamples.index(downsampling_factor)
55 |
56 | slide = wsi.read_region((0, 0), level, wsi.level_dimensions[level])
57 | slide = np.array(slide)[:, :, :3]
58 |
59 | # Convert from RGB to HSV color space
60 | slide_hsv = cv2.cvtColor(slide, cv2.COLOR_BGR2HSV)
61 |
62 | # Compute optimal threshold values in each channel using Otsu algorithm
63 | _, saturation, _ = np.split(slide_hsv, 3, axis=2)
64 |
65 | mask = otsu_filter(saturation, gaussian_blur=True)
66 |
67 | # Make mask boolean
68 | mask = mask != 0
69 |
70 | mask = morphology.remove_small_holes(mask, area_threshold=5000)
71 | mask = morphology.remove_small_objects(mask, min_size=5000)
72 |
73 | mask = mask.astype(np.uint8)
74 | _, mask_contours, _ = cv2.findContours(
75 | mask, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
76 |
77 | return mask_contours, slide, downsampling_factor
78 |
--------------------------------------------------------------------------------
/wsipre/annotation.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | wsipre.annotation_reader
5 | ~~~~~~~~~~~~~~~~~~~~~~~~
6 |
7 | Functionality to read whole-slide image (WSI) annotations (from XML files).
8 | """
9 |
10 | from xml.dom import minidom
11 |
12 |
13 | def asap_annotations(xml_file):
14 | """Get annotations from XML file in the ASAP style.
15 |
16 | Collects region annotations bounded by polygonal contours from an XML
17 | annotation file in the ASAP style (popularized by the CAMELYON challenge),
18 | along with their labels.
19 |
20 | Parameters
21 | ----------
22 | xml_file: str
23 | Path to XML file.
24 | Returns
25 | -------
26 | List of regions (lists of 2-tuples of x, y polygon vertex coordinates) and
27 | list of region labels.
28 | """
29 | xml = minidom.parse(xml_file)
30 | annotations = xml.getElementsByTagName('Annotation')
31 |
32 | polygons, labels = [], []
33 | for annotation in annotations:
34 | label = annotation.attributes['PartOfGroup'].value
35 | if label == 'None':
36 | continue
37 |
38 | labels.append(label)
39 | vertices = annotation.getElementsByTagName('Coordinate')
40 |
41 | polygon = []
42 | for vertex in vertices:
43 | polygon.append((float(vertex.attributes['X'].value),
44 | float(vertex.attributes['Y'].value)))
45 | polygons.append(polygon)
46 |
47 | return polygons, labels
48 |
49 |
50 | def bach_annotations(xml_file):
51 | """Get annotations in XML file from the BACH ICIAR 2018 challenge.
52 |
53 | Collects region annotations bounded by polygonal contours from an XML
54 | annotation file, along with their labels.
55 |
56 | Parameters
57 | ----------
58 | xml_file: str
59 | Path to XML file.
60 | Returns
61 | -------
62 | List of regions (lists of 2-tuples of x, y polygon vertex coordinates) and
63 | list of region labels.
64 | """
65 | xml = minidom.parse(xml_file)
66 | annotations = xml.getElementsByTagName('Region')
67 |
68 | polygons, labels = [], []
69 | for annotation in annotations:
70 | vertices = annotation.getElementsByTagName('Vertex')
71 | label = annotation.getElementsByTagName('Attribute')
72 | if label:
73 | labels.append(label[0].attributes['Value'].value)
74 | else:
75 | labels.append(annotation.getAttribute('Text'))
76 |
77 | polygon = []
78 | for vertex in vertices:
79 | polygon.append((float(vertex.attributes['X'].value),
80 | float(vertex.attributes['Y'].value)))
81 | polygons.append(polygon)
82 |
83 | return polygons, labels
84 |
--------------------------------------------------------------------------------
/environment.yml:
--------------------------------------------------------------------------------
1 | name: wsipre
2 | channels:
3 | - defaults
4 | dependencies:
5 | - ca-certificates=2018.03.07=0
6 | - certifi=2018.10.15=py37_0
7 | - libedit=3.1.20170329=h6b74fdf_2
8 | - libffi=3.2.1=hd88cf55_4
9 | - libgcc-ng=8.2.0=hdf63c60_1
10 | - libstdcxx-ng=8.2.0=hdf63c60_1
11 | - ncurses=6.1=he6710b0_1
12 | - openssl=1.1.1a=h7b6447c_0
13 | - pip=18.1=py37_0
14 | - python=3.7.1=h0371630_3
15 | - readline=7.0=h7b6447c_5
16 | - setuptools=40.6.2=py37_0
17 | - sqlite=3.25.3=h7b6447c_0
18 | - tk=8.6.8=hbc83047_0
19 | - wheel=0.32.3=py37_0
20 | - xz=5.2.4=h14c3975_4
21 | - zlib=1.2.11=h7b6447c_3
22 | - pip:
23 | - alabaster==0.7.12
24 | - babel==2.6.0
25 | - backcall==0.1.0
26 | - bleach==3.0.2
27 | - chardet==3.0.4
28 | - click==7.0
29 | - cloudpickle==0.6.1
30 | - cycler==0.10.0
31 | - dask==1.0.0
32 | - decorator==4.3.0
33 | - defusedxml==0.5.0
34 | - docutils==0.14
35 | - entrypoints==0.2.3
36 | - example-pkg-a==1.666
37 | - example-pkg-b==1.667
38 | - idna==2.7
39 | - imagesize==1.1.0
40 | - ipykernel==5.1.0
41 | - ipython==7.2.0
42 | - ipython-genutils==0.2.0
43 | - ipywidgets==7.4.2
44 | - jedi==0.13.1
45 | - jinja2==2.10
46 | - jsonschema==2.6.0
47 | - jupyter==1.0.0
48 | - jupyter-client==5.2.3
49 | - jupyter-console==6.0.0
50 | - jupyter-core==4.4.0
51 | - kiwisolver==1.0.1
52 | - livereload==2.6.0
53 | - markdown==3.0.1
54 | - markupsafe==1.1.0
55 | - matplotlib==3.0.2
56 | - mistune==0.8.4
57 | - nbconvert==5.4.0
58 | - nbformat==4.4.0
59 | - networkx==2.2
60 | - notebook==5.7.2
61 | - numpy==1.15.4
62 | - numpydoc==0.8.0
63 | - opencv-python==3.4.4.19
64 | - openslide-python==1.1.1
65 | - packaging==18.0
66 | - pandocfilters==1.4.2
67 | - parso==0.3.1
68 | - pexpect==4.6.0
69 | - pickleshare==0.7.5
70 | - pillow==5.3.0
71 | - prometheus-client==0.4.2
72 | - prompt-toolkit==2.0.7
73 | - ptyprocess==0.6.0
74 | - pygments==2.3.0
75 | - pyparsing==2.3.0
76 | - python-dateutil==2.7.5
77 | - pytz==2018.7
78 | - pywavelets==1.0.1
79 | - pyyaml==3.13
80 | - pyzmq==17.1.2
81 | - qtconsole==4.4.3
82 | - requests==2.20.1
83 | - scikit-image==0.14.1
84 | - scipy==1.1.0
85 | - send2trash==1.5.0
86 | - six==1.11.0
87 | - snowballstemmer==1.2.1
88 | - sphinx==1.8.2
89 | - sphinx-better-theme==0.1.5
90 | - sphinxcontrib-websupport==1.1.0
91 | - terminado==0.8.1
92 | - testpath==0.4.2
93 | - toolz==0.9.0
94 | - tornado==5.1.1
95 | - traitlets==4.3.2
96 | - urllib3==1.24.1
97 | - wcwidth==0.1.7
98 | - webencodings==0.5.1
99 | - widgetsnbextension==3.4.2
100 | prefix: /home/luis/anaconda3/envs/wsipre
101 |
102 |
--------------------------------------------------------------------------------
/docs/_build/html/_modules/index.html:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 | Overview: module code — wsipre 0.1.2 documentation
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
23 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
All modules for which code is available
41 |
45 |
46 |
47 |
48 |
49 |
60 |
61 |
62 |
73 |
80 |
81 |
82 |
83 |
--------------------------------------------------------------------------------
/docs/index.rst:
--------------------------------------------------------------------------------
1 | wsipre
2 | ======
3 |
4 | **wsipre** (**W**\ hole-**S**\ lide **I**\ mage **PRE**\ processing) is a small
5 | Python package to handle whole-slide images (WSI; also known as
6 | `virtual slides`_) with region-level annotations.
7 |
8 | **wsipre** is a wrapper of the `OpenSlide Python`_ package, an interface to the
9 | excellent `OpenSlide`_ C library which allows reading WSIs. **wsipre**
10 | conserves OpenSlide Python's API and extends it to handle WSI annotations and
11 | to perform processing tasks. The underlying objective is the preparation of
12 | WSIs for Machine Learning (particularly Deep Learning).
13 |
14 | Other Python projects providing overlapping functionality (non-exhaustive list):
15 |
16 | * `py-wsi`_
17 | * `WholeSlideImageSampler`_
18 |
19 | .. _virtual slides: https://en.wikipedia.org/wiki/Virtual_slide
20 | .. _py-wsi: https://github.com/ysbecca/py-wsi/
21 | .. _WholeSlideImageSampler: https://github.com/jgamper/WholeSlideImageSampler
22 |
23 | User guide
24 | ==========
25 |
26 | .. toctree::
27 | :maxdepth: 1
28 |
29 | quick_intro.rst
30 | Jupyter notebook demo
31 | beyondwsipre.rst
32 |
33 |
34 | Installation
35 | ============
36 |
37 | Main dependencies
38 | ~~~~~~~~~~~~~~~~~
39 |
40 | **wsipre** was developed in Python version 3.7.1. It has not been tested with
41 | earlier versions, but it should generally work with Python version 3.*.
42 | The main requirements are the following packages (the versions used for
43 | development are listed):
44 |
45 | * `OpenSlide`_ C library (v3.4.1)
46 | * `OpenSlide Python`_ (v1.1.1)
47 | * `Numpy`_ (v1.15.4)
48 | * `OpenCV-Python`_ (v3.4.4.19)
49 |
50 |
51 | .. note:: Some linux package managers currently distribute an outdated version
52 | of the `OpenSlide`_ C library: version 3.4.0. This version lacks support for
53 | some recent WSI formats, displaying wrong tiled downsampled views of the
54 | slides and crashing upon reading some regions. To avoid these problems
55 | please make sure you have **OpenSlide version 3.4.1**.
56 |
57 | You can check the installed version by running the following code in a
58 | Python interpreter: ::
59 |
60 | >>> import openslide
61 | >>> openslide.__library_version__
62 | '3.4.1'
63 |
64 |
65 | .. _OpenSlide: https://openslide.org/
66 | .. _OpenSlide Python: https://openslide.org/api/python/
67 | .. _Numpy: http://www.numpy.org/
68 | .. _OpenCV-Python: https://docs.opencv.org/3.0-beta/doc/py_tutorials/py_tutorials.html
69 |
70 |
71 | User installation
72 | ~~~~~~~~~~~~~~~~~
73 |
74 | **wsipre** can be installed from PyPI: ::
75 |
76 | pip install wsipre
77 |
78 | The source code is hosted on `GitHub`_.
79 |
80 | .. _GitHub: https://github.com/luisvalesilva/wsipre/
81 |
82 |
83 | License
84 | =======
85 |
86 | This project is licensed under the terms of the MIT license. See `LICENSE`_
87 | file for details.
88 |
89 | .. _LICENSE: https://github.com/luisvalesilva/wsipre/LICENSE
90 |
91 |
92 | Package reference
93 | =================
94 |
95 | .. toctree::
96 | :maxdepth: 1
97 |
98 | slide
99 | show
100 |
101 |
102 | Indices and tables
103 | ==================
104 |
105 | * :ref:`genindex`
106 | * :ref:`modindex`
107 | * :ref:`search`
108 |
--------------------------------------------------------------------------------
/docs/_build/html/_sources/index.rst.txt:
--------------------------------------------------------------------------------
1 | wsipre
2 | ======
3 |
4 | **wsipre** (**W**\ hole-**S**\ lide **I**\ mage **PRE**\ processing) is a small
5 | Python package to handle whole-slide images (WSI; also known as
6 | `virtual slides`_) with region-level annotations.
7 |
8 | **wsipre** is a wrapper of the `OpenSlide Python`_ package, an interface to the
9 | excellent `OpenSlide`_ C library which allows reading WSIs. **wsipre**
10 | conserves OpenSlide Python's API and extends it to handle WSI annotations and
11 | to perform processing tasks. The underlying objective is the preparation of
12 | WSIs for Machine Learning (particularly Deep Learning).
13 |
14 | Other Python projects providing overlapping functionality (non-exhaustive list):
15 |
16 | * `py-wsi`_
17 | * `WholeSlideImageSampler`_
18 |
19 | .. _virtual slides: https://en.wikipedia.org/wiki/Virtual_slide
20 | .. _py-wsi: https://github.com/ysbecca/py-wsi/
21 | .. _WholeSlideImageSampler: https://github.com/jgamper/WholeSlideImageSampler
22 |
23 | User guide
24 | ==========
25 |
26 | .. toctree::
27 | :maxdepth: 1
28 |
29 | quick_intro.rst
30 | Jupyter notebook demo
31 | beyondwsipre.rst
32 |
33 |
34 | Installation
35 | ============
36 |
37 | Main dependencies
38 | ~~~~~~~~~~~~~~~~~
39 |
40 | **wsipre** was developed in Python version 3.7.1. It has not been tested with
41 | earlier versions, but it should generally work with Python version 3.*.
42 | The main requirements are the following packages (the versions used for
43 | development are listed):
44 |
45 | * `OpenSlide`_ C library (v3.4.1)
46 | * `OpenSlide Python`_ (v1.1.1)
47 | * `Numpy`_ (v1.15.4)
48 | * `OpenCV-Python`_ (v3.4.4.19)
49 |
50 |
51 | .. note:: Some linux package managers currently distribute an outdated version
52 | of the `OpenSlide`_ C library: version 3.4.0. This version lacks support for
53 | some recent WSI formats, displaying wrong tiled downsampled views of the
54 | slides and crashing upon reading some regions. To avoid these problems
55 | please make sure you have **OpenSlide version 3.4.1**.
56 |
57 | You can check the installed version by running the following code in a
58 | Python interpreter: ::
59 |
60 | >>> import openslide
61 | >>> openslide.__library_version__
62 | '3.4.1'
63 |
64 |
65 | .. _OpenSlide: https://openslide.org/
66 | .. _OpenSlide Python: https://openslide.org/api/python/
67 | .. _Numpy: http://www.numpy.org/
68 | .. _OpenCV-Python: https://docs.opencv.org/3.0-beta/doc/py_tutorials/py_tutorials.html
69 |
70 |
71 | User installation
72 | ~~~~~~~~~~~~~~~~~
73 |
74 | **wsipre** can be installed from PyPI: ::
75 |
76 | pip install wsipre
77 |
78 | The source code is hosted on `GitHub`_.
79 |
80 | .. _GitHub: https://github.com/luisvalesilva/wsipre/
81 |
82 |
83 | License
84 | =======
85 |
86 | This project is licensed under the terms of the MIT license. See `LICENSE`_
87 | file for details.
88 |
89 | .. _LICENSE: https://github.com/luisvalesilva/wsipre/LICENSE
90 |
91 |
92 | Package reference
93 | =================
94 |
95 | .. toctree::
96 | :maxdepth: 1
97 |
98 | slide
99 | show
100 |
101 |
102 | Indices and tables
103 | ==================
104 |
105 | * :ref:`genindex`
106 | * :ref:`modindex`
107 | * :ref:`search`
108 |
--------------------------------------------------------------------------------
/docs/quick_intro.rst:
--------------------------------------------------------------------------------
1 | Quick introduction
2 | ==================
3 |
4 | **wsipre** has two main modules (see :ref:`modindex` for docs):
5 |
6 | * ``slide``: load and process WSIs
7 | * ``show``: visualize images generated using ``slide``
8 |
9 | The following quick intro illustrates basic usage of these modules. First, load
10 | packages (Matplotlib is only used here to plot images with no annotation). ::
11 |
12 | >>> from matplotlib import pyplot as plt
13 | >>> from wsipre import slide, show
14 |
15 |
16 | Load WSI form the CAMELYON challenge with its region-level tumor annotation. ::
17 |
18 | >>> wsi = slide.Slide(filename='patient_012_node_0.tif',
19 | ... annotation_filename='patient_012_node_0.xml',
20 | ... xml_style='asap')
21 |
22 | Generate and show a thumbnail. ::
23 |
24 | >>> thumbnail, mask, downsampling_factor = wsi.get_thumbnail_with_annotation(
25 | ... size=(3000, 3000), polygon_type='line', line_thickness=8)
26 |
27 | >>> black = (0, 0, 0)
28 | >>> red = (1, 0, 0)
29 | >>> yellow = (1, 1, 0)
30 | >>> colors = {0: black, 1: black, 2: red}
31 |
32 | >>> fig = show.Figure(image=thumbnail, annotation=mask, color_map=colors)
33 | >>> fig.show_image_with_annotation(split=False)
34 |
35 | .. image:: ../img/thumb.png
36 | :scale: 70 %
37 | :align: center
38 |
39 |
40 | Zoom in and read a smaller region from the WSI. ::
41 |
42 | >>> loc = (int(150*downsampling_factor), int(1450*downsampling_factor))
43 |
44 | >>> slide_region, mask_region = wsi.read_region_with_annotation(
45 | ... location=loc, level=2, size=(1000, 1000), polygon_type='line',
46 | ... line_thickness=20)
47 |
48 | >>> fig = show.Figure(
49 | ... image=slide_region, annotation=mask_region, color_map=colors)
50 | >>> fig.show_image_with_annotation(split=False)
51 |
52 | .. image:: ../img/region.png
53 | :scale: 70 %
54 | :align: center
55 |
56 |
57 | Locate tissue regions in the WSI automatically. ::
58 |
59 | >>> wsi.get_tissue_mask(polygon_type='line', line_thickness=15)
60 | Slide('patient_012_node_0.tif')
61 |
62 | >>> fig = show.Figure(image=wsi.downsampled_slide,
63 | ... annotation=wsi.tissue_mask,
64 | ... color_map={0: black, 1: yellow})
65 | >>> fig.show_image_with_annotation(split=False)
66 |
67 | .. image:: ../img/tissue.png
68 | :scale: 70 %
69 | :align: center
70 |
71 |
72 | Sample a random patch from tissue regions. ::
73 |
74 | >>> tissue_patch = wsi.read_random_tissue_patch(level=2, size=(224, 224),
75 | ... avoid_labels=[2])
76 | >>> plt.imshow(tissue_patch)
77 | >>> plt.show()
78 |
79 | .. image:: ../img/random_patch.png
80 | :scale: 70 %
81 | :align: center
82 |
83 |
84 | Sample a random patch from regions annotated as tumor (label 2). ::
85 |
86 | >>> slide_region, mask_region = wsi.read_random_patch(
87 | ... level=2, size=(299, 299), target_class=2,
88 | ... min_class_area_ratio=0.75, polygon_type='area')
89 |
90 | >>> fig = show.Figure(slide_region, mask_region, {0: black, 2:red})
91 |
92 | >>> fig.show_image_with_annotation(split=True)
93 |
94 | .. image:: ../img/random_tumor_patch.png
95 | :scale: 70 %
96 | :align: center
97 |
98 |
99 | Double check the mapping between class label and color. ::
100 |
101 | >>> fig.show_label_colors()
102 |
103 |
104 | .. image:: ../img/color_bars.png
105 | :scale: 90 %
106 | :align: center
107 |
--------------------------------------------------------------------------------
/docs/_build/html/_sources/quick_intro.rst.txt:
--------------------------------------------------------------------------------
1 | Quick introduction
2 | ==================
3 |
4 | **wsipre** has two main modules (see :ref:`modindex` for docs):
5 |
6 | * ``slide``: load and process WSIs
7 | * ``show``: visualize images generated using ``slide``
8 |
9 | The following quick intro illustrates basic usage of these modules. First, load
10 | packages (Matplotlib is only used here to plot images with no annotation). ::
11 |
12 | >>> from matplotlib import pyplot as plt
13 | >>> from wsipre import slide, show
14 |
15 |
16 | Load WSI form the CAMELYON challenge with its region-level tumor annotation. ::
17 |
18 | >>> wsi = slide.Slide(filename='patient_012_node_0.tif',
19 | ... annotation_filename='patient_012_node_0.xml',
20 | ... xml_style='asap')
21 |
22 | Generate and show a thumbnail. ::
23 |
24 | >>> thumbnail, mask, downsampling_factor = wsi.get_thumbnail_with_annotation(
25 | ... size=(3000, 3000), polygon_type='line', line_thickness=8)
26 |
27 | >>> black = (0, 0, 0)
28 | >>> red = (1, 0, 0)
29 | >>> yellow = (1, 1, 0)
30 | >>> colors = {0: black, 1: black, 2: red}
31 |
32 | >>> fig = show.Figure(image=thumbnail, annotation=mask, color_map=colors)
33 | >>> fig.show_image_with_annotation(split=False)
34 |
35 | .. image:: ../img/thumb.png
36 | :scale: 70 %
37 | :align: center
38 |
39 |
40 | Zoom in and read a smaller region from the WSI. ::
41 |
42 | >>> loc = (int(150*downsampling_factor), int(1450*downsampling_factor))
43 |
44 | >>> slide_region, mask_region = wsi.read_region_with_annotation(
45 | ... location=loc, level=2, size=(1000, 1000), polygon_type='line',
46 | ... line_thickness=20)
47 |
48 | >>> fig = show.Figure(
49 | ... image=slide_region, annotation=mask_region, color_map=colors)
50 | >>> fig.show_image_with_annotation(split=False)
51 |
52 | .. image:: ../img/region.png
53 | :scale: 70 %
54 | :align: center
55 |
56 |
57 | Locate tissue regions in the WSI automatically. ::
58 |
59 | >>> wsi.get_tissue_mask(polygon_type='line', line_thickness=15)
60 | Slide('patient_012_node_0.tif')
61 |
62 | >>> fig = show.Figure(image=wsi.downsampled_slide,
63 | ... annotation=wsi.tissue_mask,
64 | ... color_map={0: black, 1: yellow})
65 | >>> fig.show_image_with_annotation(split=False)
66 |
67 | .. image:: ../img/tissue.png
68 | :scale: 70 %
69 | :align: center
70 |
71 |
72 | Sample a random patch from tissue regions. ::
73 |
74 | >>> tissue_patch = wsi.read_random_tissue_patch(level=2, size=(224, 224),
75 | ... avoid_labels=[2])
76 | >>> plt.imshow(tissue_patch)
77 | >>> plt.show()
78 |
79 | .. image:: ../img/random_patch.png
80 | :scale: 70 %
81 | :align: center
82 |
83 |
84 | Sample a random patch from regions annotated as tumor (label 2). ::
85 |
86 | >>> slide_region, mask_region = wsi.read_random_patch(
87 | ... level=2, size=(299, 299), target_class=2,
88 | ... min_class_area_ratio=0.75, polygon_type='area')
89 |
90 | >>> fig = show.Figure(slide_region, mask_region, {0: black, 2:red})
91 |
92 | >>> fig.show_image_with_annotation(split=True)
93 |
94 | .. image:: ../img/random_tumor_patch.png
95 | :scale: 70 %
96 | :align: center
97 |
98 |
99 | Double check the mapping between class label and color. ::
100 |
101 | >>> fig.show_label_colors()
102 |
103 |
104 | .. image:: ../img/color_bars.png
105 | :scale: 90 %
106 | :align: center
107 |
--------------------------------------------------------------------------------
/docs/_build/html/search.html:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 | Search — wsipre 0.1.2 documentation
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
32 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
Search
50 |
51 |
52 |
53 | Please activate JavaScript to enable the search
54 | functionality.
55 |
56 |
57 |
58 | From here you can search these documents. Enter your search
59 | words into the box below and click "search". Note that the search
60 | function will automatically search for all of the words. Pages
61 | containing fewer words won't appear in the result list.
62 |
63 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
80 |
81 |
82 |
93 |
100 |
101 |
102 |
103 |
--------------------------------------------------------------------------------
/docs/_build/html/py-modindex.html:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 | Python Module Index — wsipre 0.1.2 documentation
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
24 |
25 |
26 |
27 |
30 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
Python Module Index
49 |
50 |
53 |
54 |
55 |
56 |
57 | s
58 |
59 |
60 |
61 | show
62 |
63 |
64 |
65 |
66 | slide
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
85 |
86 |
87 |
98 |
105 |
106 |
107 |
108 |
--------------------------------------------------------------------------------
/docs/_build/html/beyondwsipre.html:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 | Beyond wsipre — wsipre 0.1.2 documentation
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
25 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
Coming soon…
51 |
52 |
Beyond wsipre
53 |
Ways to use and extend wsipre ’s output.
54 |
55 |
56 |
57 |
58 |
59 |
60 |
77 |
78 |
79 |
98 |
105 |
106 |
107 |
108 |
--------------------------------------------------------------------------------
/docs/_build/html/_static/pygments.css:
--------------------------------------------------------------------------------
1 | .highlight .hll { background-color: #ffffcc }
2 | .highlight { background: #eeffcc; }
3 | .highlight .c { color: #408090; font-style: italic } /* Comment */
4 | .highlight .err { border: 1px solid #FF0000 } /* Error */
5 | .highlight .k { color: #007020; font-weight: bold } /* Keyword */
6 | .highlight .o { color: #666666 } /* Operator */
7 | .highlight .ch { color: #408090; font-style: italic } /* Comment.Hashbang */
8 | .highlight .cm { color: #408090; font-style: italic } /* Comment.Multiline */
9 | .highlight .cp { color: #007020 } /* Comment.Preproc */
10 | .highlight .cpf { color: #408090; font-style: italic } /* Comment.PreprocFile */
11 | .highlight .c1 { color: #408090; font-style: italic } /* Comment.Single */
12 | .highlight .cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */
13 | .highlight .gd { color: #A00000 } /* Generic.Deleted */
14 | .highlight .ge { font-style: italic } /* Generic.Emph */
15 | .highlight .gr { color: #FF0000 } /* Generic.Error */
16 | .highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
17 | .highlight .gi { color: #00A000 } /* Generic.Inserted */
18 | .highlight .go { color: #333333 } /* Generic.Output */
19 | .highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */
20 | .highlight .gs { font-weight: bold } /* Generic.Strong */
21 | .highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
22 | .highlight .gt { color: #0044DD } /* Generic.Traceback */
23 | .highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */
24 | .highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */
25 | .highlight .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */
26 | .highlight .kp { color: #007020 } /* Keyword.Pseudo */
27 | .highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */
28 | .highlight .kt { color: #902000 } /* Keyword.Type */
29 | .highlight .m { color: #208050 } /* Literal.Number */
30 | .highlight .s { color: #4070a0 } /* Literal.String */
31 | .highlight .na { color: #4070a0 } /* Name.Attribute */
32 | .highlight .nb { color: #007020 } /* Name.Builtin */
33 | .highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */
34 | .highlight .no { color: #60add5 } /* Name.Constant */
35 | .highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */
36 | .highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */
37 | .highlight .ne { color: #007020 } /* Name.Exception */
38 | .highlight .nf { color: #06287e } /* Name.Function */
39 | .highlight .nl { color: #002070; font-weight: bold } /* Name.Label */
40 | .highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */
41 | .highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */
42 | .highlight .nv { color: #bb60d5 } /* Name.Variable */
43 | .highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */
44 | .highlight .w { color: #bbbbbb } /* Text.Whitespace */
45 | .highlight .mb { color: #208050 } /* Literal.Number.Bin */
46 | .highlight .mf { color: #208050 } /* Literal.Number.Float */
47 | .highlight .mh { color: #208050 } /* Literal.Number.Hex */
48 | .highlight .mi { color: #208050 } /* Literal.Number.Integer */
49 | .highlight .mo { color: #208050 } /* Literal.Number.Oct */
50 | .highlight .sa { color: #4070a0 } /* Literal.String.Affix */
51 | .highlight .sb { color: #4070a0 } /* Literal.String.Backtick */
52 | .highlight .sc { color: #4070a0 } /* Literal.String.Char */
53 | .highlight .dl { color: #4070a0 } /* Literal.String.Delimiter */
54 | .highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */
55 | .highlight .s2 { color: #4070a0 } /* Literal.String.Double */
56 | .highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */
57 | .highlight .sh { color: #4070a0 } /* Literal.String.Heredoc */
58 | .highlight .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */
59 | .highlight .sx { color: #c65d09 } /* Literal.String.Other */
60 | .highlight .sr { color: #235388 } /* Literal.String.Regex */
61 | .highlight .s1 { color: #4070a0 } /* Literal.String.Single */
62 | .highlight .ss { color: #517918 } /* Literal.String.Symbol */
63 | .highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */
64 | .highlight .fm { color: #06287e } /* Name.Function.Magic */
65 | .highlight .vc { color: #bb60d5 } /* Name.Variable.Class */
66 | .highlight .vg { color: #bb60d5 } /* Name.Variable.Global */
67 | .highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */
68 | .highlight .vm { color: #bb60d5 } /* Name.Variable.Magic */
69 | .highlight .il { color: #208050 } /* Literal.Number.Integer.Long */
--------------------------------------------------------------------------------
/docs/_build/html/wsiprein5minutes.html:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 | wsipre in 5 minutes — wsipre 0.0.1 documentation
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
25 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
wsipre in 5 minutes
52 |
wsipre (W hole-S lide I mage PRE processing)
53 | is a wrapper of the excellent OpenSlide Python package, which
54 | allows reading whole-slide images (WSI), also known as virtual slides.
55 | wsipre conserves OpenSlide Python’s API and extends it to handle WSI
56 | annotations and to perform some slide processing tasks. The driving objective
57 | is the preprocessing of WSIs, with or without annotations, for Machine Learning
58 | (ML), particularly Deep Learning (DL), applications.
59 |
60 |
61 |
62 |
63 |
64 |
65 |
82 |
83 |
84 |
103 |
110 |
111 |
112 |
113 |
--------------------------------------------------------------------------------
/docs/conf.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | #
4 | # wsipre documentation build configuration file, created by
5 | # sphinx-quickstart on Thu Dec 6 08:07:27 2018.
6 | #
7 | # This file is execfile()d with the current directory set to its
8 | # containing dir.
9 | #
10 | # Note that not all possible configuration values are present in this
11 | # autogenerated file.
12 | #
13 | # All configuration values have a default; values that are commented out
14 | # serve to show the default.
15 |
16 | # If extensions (or modules to document with autodoc) are in another directory,
17 | # add these directories to sys.path here. If the directory is relative to the
18 | # documentation root, use os.path.abspath to make it absolute, like shown here.
19 | #
20 | import os
21 | import sys
22 | sys.path.insert(0, os.path.abspath('../wsipre'))
23 |
24 | # -- General configuration ------------------------------------------------
25 |
26 | # If your documentation needs a minimal Sphinx version, state it here.
27 | #
28 | # needs_sphinx = '1.0'
29 |
30 | # Add any Sphinx extension module names here, as strings. They can be
31 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
32 | # ones.
33 | extensions = [
34 | 'sphinx.ext.autodoc',
35 | 'numpydoc',
36 | 'sphinx.ext.doctest',
37 | 'sphinx.ext.todo',
38 | 'sphinx.ext.coverage',
39 | 'sphinx.ext.mathjax',
40 | 'sphinx.ext.viewcode',
41 | 'sphinx.ext.githubpages'
42 | ]
43 |
44 | # Add any paths that contain templates here, relative to this directory.
45 | templates_path = ['_templates']
46 |
47 | # The suffix(es) of source filenames.
48 | # You can specify multiple suffix as a list of string:
49 | #
50 | # source_suffix = ['.rst', '.md']
51 | source_suffix = '.rst'
52 |
53 | # The master toctree document.
54 | master_doc = 'index'
55 |
56 | # General information about the project.
57 | project = 'wsipre'
58 | copyright = '2019, Luis A. Vale Silva'
59 | author = 'Luis A. Vale Silva'
60 |
61 | # The version info for the project you're documenting, acts as replacement for
62 | # |version| and |release|, also used in various other places throughout the
63 | # built documents.
64 | #
65 | # The short X.Y version.
66 | version = '0.1'
67 | # The full version, including alpha/beta/rc tags.
68 | release = '0.1.2'
69 |
70 | # The language for content autogenerated by Sphinx. Refer to documentation
71 | # for a list of supported languages.
72 | #
73 | # This is also used if you do content translation via gettext catalogs.
74 | # Usually you set "language" from the command line for these cases.
75 | language = None
76 |
77 | # List of patterns, relative to source directory, that match files and
78 | # directories to ignore when looking for source files.
79 | # This patterns also effect to html_static_path and html_extra_path
80 | exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
81 |
82 | # The name of the Pygments (syntax highlighting) style to use.
83 | pygments_style = 'sphinx'
84 |
85 | # If true, `todo` and `todoList` produce output, else they produce nothing.
86 | todo_include_todos = True
87 |
88 |
89 | # -- Options for HTML output ----------------------------------------------
90 |
91 | # The theme to use for HTML and HTML Help pages. See the documentation for
92 | # a list of builtin themes.
93 | #
94 | #html_theme = 'alabaster'
95 | from better import better_theme_path
96 | html_theme_path = [better_theme_path]
97 | html_theme = 'better'
98 |
99 | html_short_title = "Home"
100 |
101 | # Theme options are theme-specific and customize the look and feel of a theme
102 | # further. For a list of options available for each theme, see the
103 | # documentation.
104 | #
105 | # html_theme_options = {}
106 |
107 | # Add any paths that contain custom static files (such as style sheets) here,
108 | # relative to this directory. They are copied after the builtin static files,
109 | # so a file named "default.css" will overwrite the builtin "default.css".
110 | html_static_path = ['_static']
111 |
112 | # Custom sidebar templates, must be a dictionary that maps document names
113 | # to template names.
114 | #
115 | # This is required for the alabaster theme
116 | # refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars
117 | html_sidebars = {
118 | '**': [
119 | 'relations.html', # needs 'show_related': True theme option to display
120 | 'searchbox.html',
121 | ]
122 | }
123 |
124 |
125 | # -- Options for HTMLHelp output ------------------------------------------
126 |
127 | # Output file base name for HTML help builder.
128 | htmlhelp_basename = 'wsipredoc'
129 |
130 |
131 | # -- Options for LaTeX output ---------------------------------------------
132 |
133 | latex_elements = {
134 | # The paper size ('letterpaper' or 'a4paper').
135 | #
136 | # 'papersize': 'letterpaper',
137 |
138 | # The font size ('10pt', '11pt' or '12pt').
139 | #
140 | # 'pointsize': '10pt',
141 |
142 | # Additional stuff for the LaTeX preamble.
143 | #
144 | # 'preamble': '',
145 |
146 | # Latex figure (float) alignment
147 | #
148 | # 'figure_align': 'htbp',
149 | }
150 |
151 | # Grouping the document tree into LaTeX files. List of tuples
152 | # (source start file, target name, title,
153 | # author, documentclass [howto, manual, or own class]).
154 | latex_documents = [
155 | (master_doc, 'wsipre.tex', 'wsipre Documentation',
156 | 'Luis A. Vale Silva', 'manual'),
157 | ]
158 |
159 |
160 | # -- Options for manual page output ---------------------------------------
161 |
162 | # One entry per manual page. List of tuples
163 | # (source start file, name, description, authors, manual section).
164 | man_pages = [
165 | (master_doc, 'wsipre', 'wsipre Documentation',
166 | [author], 1)
167 | ]
168 |
169 |
170 | # -- Options for Texinfo output -------------------------------------------
171 |
172 | # Grouping the document tree into Texinfo files. List of tuples
173 | # (source start file, target name, title, author,
174 | # dir menu entry, description, category)
175 | texinfo_documents = [
176 | (master_doc, 'wsipre', 'wsipre Documentation',
177 | author, 'wsipre', 'One line description of project.',
178 | 'Miscellaneous'),
179 | ]
180 |
181 |
182 |
183 |
--------------------------------------------------------------------------------
/docs/_build/html/_static/better.css:
--------------------------------------------------------------------------------
1 | @import url("better_basic.css");
2 |
3 |
4 |
5 |
6 | /* main styles */
7 |
8 | body {
9 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
10 | font-size: 100%;
11 | color: #000000;
12 | margin: 0;
13 | padding: 0;
14 | line-height: 135%;
15 | }
16 |
17 | a {
18 | color: #008;
19 | text-decoration: none;
20 | }
21 |
22 | a:visited {
23 | color: #208;
24 | text-decoration: none;
25 | }
26 |
27 | a:hover {
28 | text-decoration: underline;
29 | }
30 |
31 | a.toc-backref {
32 | color: #000000;
33 | }
34 |
35 | p {
36 | margin: 1rem 0;
37 | }
38 |
39 | h1, h2, h3, h4, h5, h6 {
40 | margin-top: 1em;
41 | margin-bottom: 0.5em;
42 | color: #000000;
43 | line-height: 135%;
44 | }
45 |
46 | .body .section:first-child > :first-child,
47 | .sphinxsidebarwrapper > :first-child,
48 | .sphinxsidebar .search:first-child
49 | {
50 | margin-top: 1rem;
51 | }
52 |
53 | h1 { font-size: 1.5rem; font-weight: bold; }
54 | h2 { font-size: 1.5rem; font-weight: normal; }
55 | h3 { font-size: 1.25rem; font-weight: bold; }
56 | h4 { font-size: 1.25rem; font-weight: normal; }
57 | h5 { font-size: 1rem; font-weight: bold; }
58 | h6 { font-size: 1rem; font-weight: normal; }
59 |
60 | /* page-level layout of containers */
61 |
62 | header#pageheader, footer#pagefooter, .related, .document {
63 | width: 100%;
64 | max-width: 60rem;
65 | margin: auto;
66 | }
67 |
68 | .documentwrapper {
69 | float: left;
70 | width: 100%;
71 | }
72 |
73 | .bodywrapper {
74 | margin: 0 0 0 15rem;
75 | }
76 |
77 | footer#pagefooter, footer#pagefooter a {
78 | color: #000000;
79 | }
80 |
81 |
82 | footer#pagefooter {
83 | padding-top: 2rem;
84 | padding-bottom: 2rem;
85 | text-align: center;
86 | }
87 |
88 | footer#pagefooter a {
89 | text-decoration: underline;
90 | }
91 |
92 | /* header styles */
93 |
94 | body > header h1 a, body > header h1 a:visited {
95 | color: #000000;
96 | }
97 |
98 | a.headerlink {
99 | font-size: 0.8em;
100 | padding: 0 4px 0 4px;
101 | text-decoration: none;
102 | }
103 |
104 | /* code styles */
105 |
106 | pre, tt {
107 | background-color: #eee;
108 | color: #333;
109 | }
110 |
111 | pre {
112 | font-family: Monaco, Consolas, "Lucida Console", monospace;
113 | margin: 1rem -5px;
114 | padding: 5px;
115 | border-left: none;
116 | border-right: none;
117 | font-size: 0.8rem;
118 | line-height: 1rem;
119 | }
120 |
121 | tt {
122 | padding: 0 1px 0 1px;
123 | font-family: Consolas, Monaco, monospace;
124 | }
125 |
126 | /* API doc styles */
127 |
128 | dl.function,
129 | dl.class,
130 | dl.method,
131 | dl.attribute,
132 | dl.data,
133 | dl.classmethod {
134 | margin-bottom: 2rem;
135 | }
136 |
137 | /* relbar */
138 |
139 | .related {
140 | line-height: 30px;
141 | width: 100%;
142 | font-size: 0.9rem;
143 | }
144 |
145 | .related.top {
146 | border-bottom: 1px solid #aaa;
147 | }
148 |
149 | .related.bottom {
150 | border-top: 1px solid #aaa;
151 | }
152 |
153 | .related ul {
154 | padding: 0;
155 | margin: 0;
156 | list-style: none;
157 | }
158 |
159 | .related li {
160 | display: inline;
161 | }
162 |
163 | nav#rellinks {
164 | float: right;
165 | }
166 |
167 | nav#rellinks li+li:before {
168 | content: "|";
169 | }
170 |
171 | nav#breadcrumbs li+li:before {
172 | content: "\00BB";
173 | }
174 |
175 | /* sidebar */
176 |
177 | .sphinxsidebarwrapper {
178 | padding: 0 1rem 0 0;
179 | }
180 |
181 | .sphinxsidebar {
182 | width: 15rem;
183 | margin-left: -100%;
184 | font-size: 0.9rem;
185 | float: left;
186 | }
187 |
188 | .sphinxsidebar h3 a {
189 | color: #000000;
190 | }
191 |
192 | .sphinxsidebar p.topless {
193 | margin: 5px 10px 10px 10px;
194 | }
195 |
196 | .sphinxsidebar ul {
197 | margin: 0;
198 | padding: 0;
199 | margin-bottom: 1rem;
200 | list-style: none;
201 | }
202 |
203 | .sphinxsidebar ul ul,
204 | .sphinxsidebar ul.want-points {
205 | margin-left: 20px;
206 | list-style: square;
207 | }
208 |
209 | .sphinxsidebar ul ul {
210 | margin-top: 0;
211 | margin-bottom: 0;
212 | }
213 |
214 | .sphinxsidebar input {
215 | box-sizing: border-box;
216 | -moz-box-sizing: border-box;
217 | -webkit-box-sizing: border-box;
218 | height: 1.5rem;
219 | font-size: 0.9rem;
220 | margin: 0;
221 |
222 | background-color: white;
223 | border: 1px solid #ccc;
224 | color: #555;
225 | }
226 |
227 | .sphinxsidebar .search {
228 | margin-top: 2rem;
229 | }
230 |
231 | .sphinxsidebar .search input[type=text] {
232 | width: 90%;
233 | display: inline-block;
234 | }
235 |
236 | .sphinxsidebar .search input[type=submit] {
237 | width: 4rem;
238 | display: inline-block;
239 | }
240 |
241 | /* paragraph-level markup */
242 |
243 | .admonition p.admonition-title + p {
244 | display: inline;
245 | }
246 |
247 | .admonition p {
248 | margin-bottom: 5px;
249 | }
250 |
251 | .admonition pre {
252 | margin-bottom: 5px;
253 | }
254 |
255 | .admonition ul, .admonition ol {
256 | margin-bottom: 5px;
257 | }
258 |
259 | p.admonition-title {
260 | display: inline;
261 | margin-right: 0;
262 | }
263 |
264 | p.admonition-title:after {
265 | content: ":";
266 | }
267 |
268 | .note {
269 | background-color: #eee;
270 | border: 1px solid #ccc;
271 | }
272 |
273 | .seealso {
274 | background-color: #ffc;
275 | border: 1px solid #ff6;
276 | }
277 |
278 | .topic {
279 | background-color: #eee;
280 | }
281 |
282 | .warning {
283 | background-color: #ffe4e4;
284 | border: 1px solid #f66;
285 | }
286 |
287 | .warning tt {
288 | background: #efc2c2;
289 | }
290 |
291 | .note tt {
292 | background: #d6d6d6;
293 | }
294 |
295 | .viewcode-block:target {
296 | background-color: #f4debf;
297 | border-top: 1px solid #ac9;
298 | border-bottom: 1px solid #ac9;
299 | }
300 |
301 | /* responsive styles */
302 |
303 | @media (max-width: 820px) {
304 | /* kill the sidebar */
305 | .bodywrapper { margin: 0; }
306 | .sphinxsidebar {
307 | display: none;
308 | }
309 | header#pageheader, footer#pagefooter, .related, .document {
310 | margin: 0 1rem;
311 | width: calc(100% - 2rem);
312 | width: -webkit-calc(100% - 2rem);
313 | }
314 | }
--------------------------------------------------------------------------------
/docs/_build/html/searchindex.js:
--------------------------------------------------------------------------------
1 | Search.setIndex({docnames:["beyondwsipre","index","quick_intro","show","slide"],envversion:{"sphinx.domains.c":1,"sphinx.domains.changeset":1,"sphinx.domains.cpp":1,"sphinx.domains.javascript":1,"sphinx.domains.math":2,"sphinx.domains.python":1,"sphinx.domains.rst":1,"sphinx.domains.std":1,"sphinx.ext.todo":1,"sphinx.ext.viewcode":1,sphinx:55},filenames:["beyondwsipre.rst","index.rst","quick_intro.rst","show.rst","slide.rst"],objects:{"":{show:[3,0,0,"-"],slide:[4,0,0,"-"]},"show.Figure":{show_annotation:[3,2,1,""],show_image:[3,2,1,""],show_image_with_annotation:[3,2,1,""],show_label_colors:[3,2,1,""]},"slide.Slide":{associated_images:[4,3,1,""],close:[4,2,1,""],detect_format:[4,4,1,""],dimensions:[4,3,1,""],get_best_level_for_downsample:[4,2,1,""],get_thumbnail:[4,2,1,""],get_thumbnail_with_annotation:[4,2,1,""],get_tissue_mask:[4,2,1,""],level_count:[4,3,1,""],level_dimensions:[4,3,1,""],level_downsamples:[4,3,1,""],properties:[4,3,1,""],read_random_patch:[4,2,1,""],read_random_tissue_patch:[4,2,1,""],read_region:[4,2,1,""],read_region_with_annotation:[4,2,1,""]},show:{Figure:[3,1,1,""]},slide:{Slide:[4,1,1,""]}},objnames:{"0":["py","module","Python module"],"1":["py","class","Python class"],"2":["py","method","Python method"],"3":["py","attribute","Python attribute"],"4":["py","classmethod","Python class method"]},objtypes:{"0":"py:module","1":"py:class","2":"py:method","3":"py:attribute","4":"py:classmethod"},terms:{"class":[2,3,4],"final":[],"float":4,"function":[1,4],"import":[1,2,3,4],"int":[2,3,4],"new":[],"return":[3,4],"true":[2,3],Added:4,The:[1,2,3,4],Then:[],__library_version__:1,__wsipre__:[],_openslid:[],about:4,access:4,accord:4,add:[],aditya:4,aim_for_tumor:[],algorithm:4,all:[],allow:[1,4],also:1,andrew:4,annot:[1,2,3,4],annotatedopenslid:4,annotation_filenam:[2,4],anoth:[],api:1,applic:[],area:[2,4],argument:4,arrai:[3,4],arxiv:4,asap:[2,4],associ:4,associated_imag:4,attribut:[3,4],automat:[2,4],avail:4,avoid:[1,4],avoid_label:[2,4],bar:3,base:4,basic:2,beck:4,been:1,best:4,between:[2,3,4],beyond:1,binari:4,black:2,bool:3,breast:4,briefli:4,build:[],camelyon:2,can:1,cancer:4,censor_mixed_class:[],central:4,challeng:[2,4],channel:4,check:[1,2],classmethod:4,close:4,closest:4,code:1,color:[2,3,4],color_map:[2,3],com:[],combin:3,come:0,compress:4,comput:4,conserv:1,consist:4,contain:4,content:4,convert:4,coordin:4,corner:[],correspond:[3,4],cover:[],crash:1,crop:4,current:1,cybern:4,data:4,data_sourc:[],dataset:4,dayong:4,deep:[1,4],defin:4,demo:1,describ:4,desir:4,detail:1,detect:4,detect_format:4,detector:4,determin:4,develop:1,dict:[3,4],differ:[],dimens:4,displai:[1,3,4],distribut:1,doc:2,document:[],doubl:2,down:4,downsampl:[1,4],downsampled_slid:[2,4],downsampling_factor:[2,4],draw:4,drive:[],dwnspl_factor:4,each:[3,4],earlier:1,easi:[],easili:[],edg:4,equal:[],exampl:[3,4],excel:1,exhaust:1,extend:[0,1],factor:4,fals:2,fig:[2,3],figur:[1,2],file:[1,4],filenam:[2,4],fill:4,first:2,fit:4,follow:[1,2,4],font:3,font_color:3,font_siz:3,form:2,format:[1,4],found:4,frame:4,from:[1,2,3,4],from_annot:[],full:4,gargeya:4,gener:[1,2,4],get:4,get_annotated_thumbnail:[],get_best_level_for_downsampl:4,get_thumbnail:4,get_thumbnail_with_annot:[2,4],get_tissue_mask:[2,4],github:1,give:4,given:4,grai:4,handl:1,has:[1,2],have:1,heavili:[],height:[3,4],here:2,histogram:4,histolog:4,hole:[1,4],host:1,hsv:4,http:[],humayun:4,identifi:4,ieee:4,illustr:[2,3],imag:[1,2,3,4],imshow:2,index:[1,2],input:3,inspir:4,instal:[],instanc:4,integ:4,interest:4,interfac:[1,4],interpret:1,intro:2,introduct:1,ipynb:[],irshad:4,iter:4,its:[2,4],jupyt:1,kei:[],khosla:4,known:1,label:[2,3,4],label_map:4,lack:1,latest:[],learn:[1,4],left:4,len:4,lesion:[],level:[1,2,4],level_count:4,level_dimens:4,level_downsampl:4,librari:1,lide:1,line:[2,4],line_thick:[2,4],linux:1,list:[1,3,4],load:[2,3],loc:2,locat:[2,4],luisvalesilva:[],machin:1,made:[],mage:1,mai:[],main:2,mainli:[],make:[1,4],man:4,manag:1,map:[2,3,4],mask:[2,3,4],mask_class_remap:[],mask_region:2,matplotlib:[2,3],maximum:4,memori:4,metadata:4,metastat:4,method:[3,4],min_area:[],min_class_area:[],min_class_area_ratio:[2,4],minimum:4,minut:[],mit:1,modul:[1,2],monospac:[],more:[],must:4,name:4,namesak:4,nobuyuki:4,non:1,none:4,note:[],notebook:1,number:4,numpi:[1,3,4],object:[1,4],one:4,onli:2,open:[3,4],opencv:1,openslid:[1,4],optim:4,option:4,org:[],origin:[],other:1,otsu:4,out:[],outdat:1,output:0,overlai:3,overlap:1,packag:2,page:1,palett:[],param:[],paramet:[3,4],part:[],particularli:1,patch:[2,4],path:4,patient_012_node_0:2,perform:1,pil:[3,4],pip:1,pixel:[3,4],pleas:1,plot:[2,3],plt:2,plu:4,polygon:4,polygon_typ:[2,4],pre:1,premultipli:4,prepar:1,preprocess:[],prob:[],probabl:[],problem:1,process:[1,2],project:1,properti:4,provid:[1,4],pypi:1,pyplot:2,python:1,quick:1,random:[2,4],ratio:4,rb7b6abb48578:[],read:[1,2,3],read_annotated_region:[],read_random_patch:[2,4],read_random_region:[],read_random_tissue_patch:[2,4],read_region:4,read_region_with_annot:[2,4],recent:1,recogn:4,rectangl:3,red:2,refer:4,region:[1,2,3,4],rel:4,releas:4,reli:[],remap:[],remap_annotation_label:[],remov:4,reproduc:[],requir:[1,4],return_patch_class:[],rgb:[3,4],rgba:4,rishab:4,roi:4,run:[1,4],sampl:2,satur:4,scale:4,search:1,see:[1,2],segment:4,select:4,should:1,show:[2,3],show_annot:3,show_imag:3,show_image_with_annot:[2,3],show_label_color:[2,3],side:3,sinc:4,singl:[],size:[2,3,4],slide:[1,2],slide_region:[2,4],small:[1,4],smaller:[2,4],some:1,soon:0,sourc:[1,3,4],space:4,specif:[],specifi:4,split:[2,3],squar:[],start:4,step:4,str:4,string:4,structur:[],support:1,sure:1,syst:4,target:4,target_class:[2,4],task:1,term:1,test:1,text:[],thi:[1,4],thick:4,threshold:4,thu:[],thumbnail:[2,3,4],tif:[2,4],tile:1,time:[],tissu:[2,4],tissue_label_map:4,tissue_mask:[2,4],tissue_patch:2,titl:[],todo:[],togeth:4,top:4,total:4,tran:4,transfer:4,triplet:3,tumor:2,tumor_001:4,tupl:4,two:2,type:4,typic:4,tytient_012_node_0:[],under:1,underli:1,underlin:[],unlik:4,updat:[],upon:1,usag:2,use:0,used:[1,2,3,4],using:[2,4],valu:[3,4],vendor:4,version:1,via:4,view:1,virtual:1,visual:[2,3,4],wai:0,wang:4,want:[],when:4,whether:3,which:1,white:[],whole:[1,4],wholeslideimagesampl:1,wide:[],width:[3,4],wise:3,within:4,without:4,work:1,wrapper:1,write:[],wrong:1,wshole:[],wsi:[1,2,3,4],wsipr:[2,3,4],xml:[2,4],xml_style:[2,4],yellow:2,you:1,zoom:2},titles:["Beyond wsipre","wsipre","Quick introduction","Figure","Slide"],titleterms:{api:[],beyond:0,depend:1,document:[],figur:3,guid:1,indic:1,instal:1,intro:[],introduct:2,licens:1,main:1,minut:[],more:[],packag:1,quick:2,refer:1,slide:4,tabl:1,titl:[],user:1,welcom:[],wsipr:[0,1]}})
--------------------------------------------------------------------------------
/wsipre/show.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Show images, such as thumbnails or regions extracted from whole-slide images
5 | (WSI; also known as virtual slides).
6 |
7 | """
8 |
9 | import numpy as np
10 | from matplotlib import pyplot as plt
11 | import matplotlib.patches as mpatch
12 |
13 |
14 | class Figure(object):
15 | """An open *annotated* WSI.
16 |
17 | Parameters
18 | ----------
19 | image: PIL Image
20 | Image to display; a thumbnail or region read from WSI.
21 | annotation: Numpy 2D array
22 | Annotation labels for each pixel in the input ``image``.
23 | color_map: dict {label int: RGB color list}
24 | Mapping of RGB color values to class labels. Colors are triplet lists
25 | of the R, G, and B values.
26 |
27 | Attributes
28 | ----------
29 | image: PIL Image
30 | The input ``image``.
31 | annotation: Numpy 2D array
32 | The input ``annotation``.
33 | color_map: dict {label: color}
34 | Mapping between each label and the color for visualization.
35 |
36 | Examples
37 | --------
38 | >>> from wsipre import show
39 | >>> colors = {0: (0, 0, 0), 2: (1, 0, 0)}
40 | >>> fig = show.Figure(image=image, annotation=mask, color_map=colors)
41 | >>> fig.color_map
42 | {0: (0, 0, 0), 2: (1, 0, 0)}
43 |
44 | >>> fig.show_label_colors(height=5)
45 |
46 | >>> fig.show_image_with_annotation()
47 |
48 | """
49 |
50 | def __init__(self, image, annotation, color_map={0: (0., 0., 0.),
51 | 1: (0., .8, 1.),
52 | 2: (1., .8, 0.),
53 | 3: (1., .4, 0.)}):
54 | self.image = image
55 | self.annotation = annotation.astype(np.float32) # In case it's boolean
56 | self.color_map = color_map
57 |
58 | # RGBA values should be within 0-1 range
59 | if all([0 <= channel <= 255 for color in self.color_map.values()
60 | for channel in color]):
61 | if any([channel > 1 for color in self.color_map.values()
62 | for channel in color]):
63 | self.color_map = {key: [channel / 255.0 for channel in color]
64 | for (key, color) in self.color_map.items()}
65 | else:
66 | raise ValueError(
67 | 'Please make sure color triplets values in "color_map" are ' +
68 | 'either between 0-1 or 0-255 range.')
69 |
70 | # Are there enough colors?
71 | labels = np.unique(self.annotation)
72 | labels_not_in_map = [label not in color_map.keys() for label in labels]
73 | if any(labels_not_in_map):
74 | raise ValueError(
75 | 'No color provided in "color_map" for label(s) ' +
76 | f' {list(labels[labels_not_in_map])}.')
77 |
78 | def show_label_colors(self, width=20, height=6, font_color='w',
79 | font_size=14):
80 | """Display a color bar with the colors and overlayed labels.
81 |
82 | Parameters
83 | ----------
84 | width: int
85 | Width of each class rectangle in plot.
86 | height: int
87 | Height of each class rectangle in plot.
88 | font_size: int
89 | Size of the font used to display class labels.
90 |
91 | Returns
92 | -------
93 | Matplotlib image illustrating mapping between class label and color.
94 |
95 | """
96 | rectangles = [mpatch.Rectangle((0 + width * i, 0), width, height,
97 | color=list(self.color_map.values())[i])
98 | for i in range(len(self.color_map.keys()))]
99 | rectangles = {list(self.color_map.keys())[i]: rect
100 | for i, rect in enumerate(rectangles)}
101 |
102 | fig, ax = plt.subplots()
103 |
104 | for r in rectangles:
105 | ax.add_artist(rectangles[r])
106 | rx, ry = rectangles[r].get_xy()
107 | cx = rx + rectangles[r].get_width() / 2.0
108 | cy = ry + rectangles[r].get_height() / 2.0
109 |
110 | ax.annotate(r, (cx, cy), color=font_color, weight='bold',
111 | fontsize=font_size, ha='center', va='center')
112 |
113 | ax.set_xlim((0, width * len(rectangles)))
114 | ax.set_ylim((0, height))
115 | ax.set_aspect('equal')
116 | ax.axis('off')
117 | plt.show()
118 |
119 | def show_image(self):
120 | """Show loaded image.
121 |
122 | Display the loaded WSI thumbnail or region.
123 |
124 | Returns
125 | -------
126 | Matplotlib image.
127 |
128 | """
129 | plt.imshow(self.image)
130 | plt.show()
131 |
132 | def _paint_annotation_mask(self):
133 | """Convert 2D mask to 3D format (RGB image)."""
134 | red = self.annotation.copy()
135 | green = self.annotation.copy()
136 | blue = self.annotation.copy()
137 |
138 | for label, color in self.color_map.items():
139 | idx = self.annotation == label
140 | red[idx], green[idx], blue[idx] = color
141 |
142 | rgb = np.stack([red, green, blue], axis=2)
143 |
144 | return rgb
145 |
146 | def show_annotation(self):
147 | """Show loaded image annotation.
148 |
149 | Display the loaded WSI thumbnail or region annotation, corresponding to
150 | a mask of pixel-wise labels.
151 |
152 | Returns
153 | -------
154 | Matplotlib image.
155 |
156 | """
157 | rgb_mask = self._paint_annotation_mask()
158 | plt.imshow(rgb_mask)
159 | plt.show()
160 |
161 | def show_image_with_annotation(self, split=True):
162 | """Show loaded image and annotation.
163 |
164 | Parameters
165 | ----------
166 | split: bool
167 | Whether to display the split image and annotation side-by-side or a
168 | combined visualization of the annotation on the image.
169 |
170 | Returns
171 | -------
172 | Matplotlib image.
173 |
174 | """
175 | if split:
176 | rgb_mask = self._paint_annotation_mask()
177 |
178 | f, (ax1, ax2) = plt.subplots(1, 2, sharey=True)
179 | ax1.imshow(np.array(self.image))
180 | ax2.imshow(rgb_mask)
181 | plt.show()
182 | else:
183 | image = np.array(self.image)[:, :, :3]
184 | if np.max(image) > 1:
185 | image = image / 255.
186 |
187 | for label, color in self.color_map.items():
188 | if label == 0:
189 | continue
190 | idx = self.annotation == label
191 | image[idx] = color
192 |
193 | plt.imshow(image)
194 | plt.show()
195 |
--------------------------------------------------------------------------------
/docs/_build/html/genindex.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
7 |
8 |
9 |
10 | Index — wsipre 0.1.2 documentation
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
24 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
Index
43 |
44 |
45 |
A
46 | |
C
47 | |
D
48 | |
F
49 | |
G
50 | |
L
51 | |
P
52 | |
R
53 | |
S
54 |
55 |
56 |
A
57 |
63 |
64 |
C
65 |
71 |
72 |
D
73 |
83 |
84 |
F
85 |
91 |
92 |
G
93 |
107 |
108 |
L
109 |
121 |
122 |
P
123 |
129 |
130 |
R
131 |
145 |
146 |
S
147 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
184 |
185 |
186 |
197 |
204 |
205 |
206 |
207 |
--------------------------------------------------------------------------------
/docs/_build/html/index.html:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 | wsipre — wsipre 0.1.2 documentation
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
24 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
wsipre
47 |
wsipre (W hole-S lide I mage PRE processing) is a small
48 | Python package to handle whole-slide images (WSI; also known as
49 | virtual slides ) with region-level annotations.
50 |
wsipre is a wrapper of the OpenSlide Python package, an interface to the
51 | excellent OpenSlide C library which allows reading WSIs. wsipre
52 | conserves OpenSlide Python’s API and extends it to handle WSI annotations and
53 | to perform processing tasks. The underlying objective is the preparation of
54 | WSIs for Machine Learning (particularly Deep Learning).
55 |
Other Python projects providing overlapping functionality (non-exhaustive list):
56 |
60 |
61 |
62 |
User guide
63 |
70 |
71 |
72 |
Installation
73 |
74 |
Main dependencies
75 |
wsipre was developed in Python version 3.7.1. It has not been tested with
76 | earlier versions, but it should generally work with Python version 3.*.
77 | The main requirements are the following packages (the versions used for
78 | development are listed):
79 |
80 |
87 |
88 |
Note
89 |
Some linux package managers currently distribute an outdated version
90 | of the OpenSlide C library: version 3.4.0. This version lacks support for
91 | some recent WSI formats, displaying wrong tiled downsampled views of the
92 | slides and crashing upon reading some regions. To avoid these problems
93 | please make sure you have OpenSlide version 3.4.1 .
94 |
You can check the installed version by running the following code in a
95 | Python interpreter:
96 |
>>> import openslide
97 | >>> openslide . __library_version__
98 | '3.4.1'
99 |
100 |
101 |
102 |
103 |
104 |
User installation
105 |
wsipre can be installed from PyPI:
106 |
109 |
The source code is hosted on GitHub .
110 |
111 |
112 |
113 |
License
114 |
This project is licensed under the terms of the MIT license. See LICENSE
115 | file for details.
116 |
117 |
118 |
Package reference
119 |
125 |
126 |
127 |
Indices and tables
128 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
153 |
154 |
155 |
170 |
177 |
178 |
179 |
180 |
--------------------------------------------------------------------------------
/docs/_build/html/_static/better_basic.css:
--------------------------------------------------------------------------------
1 | /* basic.css_t from Sphinx project modified for sphinx-better-theme */
2 |
3 | /* -- main layout ----------------------------------------------------------- */
4 |
5 | div.clearer {
6 | clear: both;
7 | }
8 |
9 | /* -- search page ----------------------------------------------------------- */
10 |
11 | ul.search {
12 | margin: 10px 0 0 20px;
13 | padding: 0;
14 | }
15 |
16 | ul.search li {
17 | padding: 5px 0 5px 20px;
18 | background-image: url(file.png);
19 | background-repeat: no-repeat;
20 | background-position: 0 7px;
21 | }
22 |
23 | ul.search li a {
24 | font-weight: bold;
25 | }
26 |
27 | ul.search li div.context {
28 | color: #888;
29 | margin: 2px 0 0 30px;
30 | text-align: left;
31 | }
32 |
33 | ul.keywordmatches li.goodmatch a {
34 | font-weight: bold;
35 | }
36 |
37 | /* -- index page ------------------------------------------------------------ */
38 |
39 | table.contentstable {
40 | width: 90%;
41 | }
42 |
43 | table.contentstable p.biglink {
44 | line-height: 150%;
45 | }
46 |
47 | a.biglink {
48 | font-size: 1.3em;
49 | }
50 |
51 | span.linkdescr {
52 | font-style: italic;
53 | padding-top: 5px;
54 | font-size: 90%;
55 | }
56 |
57 | /* -- general index --------------------------------------------------------- */
58 |
59 | table.indextable {
60 | width: 100%;
61 | }
62 |
63 | table.indextable td {
64 | text-align: left;
65 | vertical-align: top;
66 | }
67 |
68 | table.indextable dl, table.indextable dd {
69 | margin-top: 0;
70 | margin-bottom: 0;
71 | }
72 |
73 | table.indextable tr.pcap {
74 | height: 10px;
75 | }
76 |
77 | table.indextable tr.cap {
78 | margin-top: 10px;
79 | background-color: #f2f2f2;
80 | }
81 |
82 | img.toggler {
83 | margin-right: 3px;
84 | margin-top: 3px;
85 | cursor: pointer;
86 | }
87 |
88 | div.modindex-jumpbox {
89 | border-top: 1px solid #ddd;
90 | border-bottom: 1px solid #ddd;
91 | margin: 1em 0 1em 0;
92 | padding: 0.4em;
93 | }
94 |
95 | div.genindex-jumpbox {
96 | border-top: 1px solid #ddd;
97 | border-bottom: 1px solid #ddd;
98 | margin: 1em 0 1em 0;
99 | padding: 0.4em;
100 | }
101 |
102 | /* -- general body styles --------------------------------------------------- */
103 |
104 | a.headerlink {
105 | visibility: hidden;
106 | }
107 |
108 | h1:hover > a.headerlink,
109 | h2:hover > a.headerlink,
110 | h3:hover > a.headerlink,
111 | h4:hover > a.headerlink,
112 | h5:hover > a.headerlink,
113 | h6:hover > a.headerlink,
114 | dt:hover > a.headerlink {
115 | visibility: visible;
116 | }
117 |
118 | div.body p.caption {
119 | text-align: inherit;
120 | }
121 |
122 | div.body td {
123 | text-align: left;
124 | }
125 |
126 | .field-list ul {
127 | padding-left: 1em;
128 | }
129 |
130 | .first {
131 | margin-top: 0 !important;
132 | }
133 |
134 | p.rubric {
135 | margin-top: 30px;
136 | font-weight: bold;
137 | }
138 |
139 | img.align-left, .figure.align-left, object.align-left {
140 | clear: left;
141 | float: left;
142 | margin-right: 1em;
143 | }
144 |
145 | img.align-right, .figure.align-right, object.align-right {
146 | clear: right;
147 | float: right;
148 | margin-left: 1em;
149 | }
150 |
151 | img.align-center, .figure.align-center, object.align-center {
152 | display: block;
153 | margin-left: auto;
154 | margin-right: auto;
155 | }
156 |
157 | .align-left {
158 | text-align: left;
159 | }
160 |
161 | .align-center {
162 | text-align: center;
163 | }
164 |
165 | .align-right {
166 | text-align: right;
167 | }
168 |
169 | /* -- sidebars -------------------------------------------------------------- */
170 |
171 | div.sidebar {
172 | margin: 0 0 0.5em 1em;
173 | border: 1px solid #ddb;
174 | padding: 7px 7px 0 7px;
175 | background-color: #ffe;
176 | width: 40%;
177 | float: right;
178 | }
179 |
180 | p.sidebar-title {
181 | font-weight: bold;
182 | }
183 |
184 | /* -- topics ---------------------------------------------------------------- */
185 |
186 | div.topic {
187 | border: 1px solid #ccc;
188 | padding: 7px 7px 0 7px;
189 | margin: 10px 0 10px 0;
190 | }
191 |
192 | p.topic-title {
193 | font-size: 1.1em;
194 | font-weight: bold;
195 | margin-top: 10px;
196 | }
197 |
198 | /* -- admonitions ----------------------------------------------------------- */
199 |
200 | div.admonition {
201 | margin-top: 10px;
202 | margin-bottom: 10px;
203 | padding: 7px;
204 | }
205 |
206 | div.admonition dt {
207 | font-weight: bold;
208 | }
209 |
210 | div.admonition dl {
211 | margin-bottom: 0;
212 | }
213 |
214 | p.admonition-title {
215 | margin: 0px 10px 5px 0px;
216 | font-weight: bold;
217 | }
218 |
219 | div.body p.centered {
220 | text-align: center;
221 | margin-top: 25px;
222 | }
223 |
224 | /* -- tables ---------------------------------------------------------------- */
225 |
226 | table.docutils {
227 | border: 0;
228 | border-collapse: collapse;
229 | }
230 |
231 | table.docutils td, table.docutils th {
232 | padding: 1px 8px 1px 5px;
233 | border-top: 0;
234 | border-left: 0;
235 | border-right: 0;
236 | border-bottom: 1px solid #aaa;
237 | }
238 |
239 | table.field-list td, table.field-list th {
240 | border: 0 !important;
241 | }
242 |
243 | table.footnote td, table.footnote th {
244 | border: 0 !important;
245 | }
246 |
247 | th {
248 | text-align: left;
249 | padding-right: 5px;
250 | }
251 |
252 | table.citation {
253 | border-left: solid 1px gray;
254 | margin-left: 1px;
255 | }
256 |
257 | table.citation td {
258 | border-bottom: none;
259 | }
260 |
261 | /* -- other body styles ----------------------------------------------------- */
262 |
263 | ol.arabic {
264 | list-style: decimal;
265 | }
266 |
267 | ol.loweralpha {
268 | list-style: lower-alpha;
269 | }
270 |
271 | ol.upperalpha {
272 | list-style: upper-alpha;
273 | }
274 |
275 | ol.lowerroman {
276 | list-style: lower-roman;
277 | }
278 |
279 | ol.upperroman {
280 | list-style: upper-roman;
281 | }
282 |
283 | dl {
284 | margin-bottom: 15px;
285 | }
286 |
287 | dd p {
288 | margin-top: 0px;
289 | }
290 |
291 | dd ul, dd table {
292 | margin-bottom: 10px;
293 | }
294 |
295 | dd {
296 | margin-top: 3px;
297 | margin-bottom: 10px;
298 | margin-left: 30px;
299 | }
300 |
301 | dt:target, .highlighted {
302 | background-color: #fbe54e;
303 | }
304 |
305 | dl.glossary dt {
306 | font-weight: bold;
307 | font-size: 1.1em;
308 | }
309 |
310 | .field-list ul {
311 | margin: 0;
312 | padding-left: 1em;
313 | }
314 |
315 | .field-list p {
316 | margin: 0;
317 | }
318 |
319 | .refcount {
320 | color: #060;
321 | }
322 |
323 | .optional {
324 | font-size: 1.3em;
325 | }
326 |
327 | .versionmodified {
328 | font-style: italic;
329 | }
330 |
331 | .system-message {
332 | background-color: #fda;
333 | padding: 5px;
334 | border: 3px solid red;
335 | }
336 |
337 | .footnote:target {
338 | background-color: #ffa;
339 | }
340 |
341 | .line-block {
342 | display: block;
343 | margin-top: 1em;
344 | margin-bottom: 1em;
345 | }
346 |
347 | .line-block .line-block {
348 | margin-top: 0;
349 | margin-bottom: 0;
350 | margin-left: 1.5em;
351 | }
352 |
353 | .guilabel, .menuselection {
354 | font-family: sans-serif;
355 | }
356 |
357 | .accelerator {
358 | text-decoration: underline;
359 | }
360 |
361 | .classifier {
362 | font-style: oblique;
363 | }
364 |
365 | abbr, acronym {
366 | border-bottom: dotted 1px;
367 | cursor: help;
368 | }
369 |
370 | /* -- code displays --------------------------------------------------------- */
371 |
372 | pre {
373 | overflow: auto;
374 | overflow-y: hidden; /* fixes display issues on Chrome browsers */
375 | }
376 |
377 | td.linenos pre {
378 | padding: 5px 0px;
379 | border: 0;
380 | background-color: transparent;
381 | color: #aaa;
382 | }
383 |
384 | table.highlighttable {
385 | margin-left: 0.5em;
386 | }
387 |
388 | table.highlighttable td {
389 | padding: 0 0.5em 0 0.5em;
390 | }
391 |
392 | tt.descname {
393 | background-color: transparent;
394 | font-weight: bold;
395 | font-size: 1.2em;
396 | }
397 |
398 | tt.descclassname {
399 | background-color: transparent;
400 | }
401 |
402 | tt.xref, a tt {
403 | background-color: transparent;
404 | font-weight: bold;
405 | }
406 |
407 | h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
408 | background-color: transparent;
409 | }
410 |
411 | .viewcode-link {
412 | float: right;
413 | }
414 |
415 | .viewcode-back {
416 | float: right;
417 | font-family: sans-serif;
418 | }
419 |
420 | div.viewcode-block:target {
421 | margin: -1px -10px;
422 | padding: 0 10px;
423 | }
424 |
425 | /* -- math display ---------------------------------------------------------- */
426 |
427 | img.math {
428 | vertical-align: middle;
429 | }
430 |
431 | div.body div.math p {
432 | text-align: center;
433 | }
434 |
435 | span.eqno {
436 | float: right;
437 | }
438 |
439 | /* -- printout stylesheet --------------------------------------------------- */
440 |
441 | @media print {
442 | div.document,
443 | div.documentwrapper,
444 | div.bodywrapper {
445 | margin: 0 !important;
446 | width: 100%;
447 | }
448 |
449 | div.sphinxsidebar,
450 | div.related,
451 | div.footer,
452 | #top-link {
453 | display: none;
454 | }
455 | }
--------------------------------------------------------------------------------
/docs/_build/html/_static/doctools.js:
--------------------------------------------------------------------------------
1 | /*
2 | * doctools.js
3 | * ~~~~~~~~~~~
4 | *
5 | * Sphinx JavaScript utilities for all documentation.
6 | *
7 | * :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
8 | * :license: BSD, see LICENSE for details.
9 | *
10 | */
11 |
12 | /**
13 | * select a different prefix for underscore
14 | */
15 | $u = _.noConflict();
16 |
17 | /**
18 | * make the code below compatible with browsers without
19 | * an installed firebug like debugger
20 | if (!window.console || !console.firebug) {
21 | var names = ["log", "debug", "info", "warn", "error", "assert", "dir",
22 | "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace",
23 | "profile", "profileEnd"];
24 | window.console = {};
25 | for (var i = 0; i < names.length; ++i)
26 | window.console[names[i]] = function() {};
27 | }
28 | */
29 |
30 | /**
31 | * small helper function to urldecode strings
32 | */
33 | jQuery.urldecode = function(x) {
34 | return decodeURIComponent(x).replace(/\+/g, ' ');
35 | };
36 |
37 | /**
38 | * small helper function to urlencode strings
39 | */
40 | jQuery.urlencode = encodeURIComponent;
41 |
42 | /**
43 | * This function returns the parsed url parameters of the
44 | * current request. Multiple values per key are supported,
45 | * it will always return arrays of strings for the value parts.
46 | */
47 | jQuery.getQueryParameters = function(s) {
48 | if (typeof s === 'undefined')
49 | s = document.location.search;
50 | var parts = s.substr(s.indexOf('?') + 1).split('&');
51 | var result = {};
52 | for (var i = 0; i < parts.length; i++) {
53 | var tmp = parts[i].split('=', 2);
54 | var key = jQuery.urldecode(tmp[0]);
55 | var value = jQuery.urldecode(tmp[1]);
56 | if (key in result)
57 | result[key].push(value);
58 | else
59 | result[key] = [value];
60 | }
61 | return result;
62 | };
63 |
64 | /**
65 | * highlight a given string on a jquery object by wrapping it in
66 | * span elements with the given class name.
67 | */
68 | jQuery.fn.highlightText = function(text, className) {
69 | function highlight(node, addItems) {
70 | if (node.nodeType === 3) {
71 | var val = node.nodeValue;
72 | var pos = val.toLowerCase().indexOf(text);
73 | if (pos >= 0 &&
74 | !jQuery(node.parentNode).hasClass(className) &&
75 | !jQuery(node.parentNode).hasClass("nohighlight")) {
76 | var span;
77 | var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg");
78 | if (isInSVG) {
79 | span = document.createElementNS("http://www.w3.org/2000/svg", "tspan");
80 | } else {
81 | span = document.createElement("span");
82 | span.className = className;
83 | }
84 | span.appendChild(document.createTextNode(val.substr(pos, text.length)));
85 | node.parentNode.insertBefore(span, node.parentNode.insertBefore(
86 | document.createTextNode(val.substr(pos + text.length)),
87 | node.nextSibling));
88 | node.nodeValue = val.substr(0, pos);
89 | if (isInSVG) {
90 | var bbox = span.getBBox();
91 | var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
92 | rect.x.baseVal.value = bbox.x;
93 | rect.y.baseVal.value = bbox.y;
94 | rect.width.baseVal.value = bbox.width;
95 | rect.height.baseVal.value = bbox.height;
96 | rect.setAttribute('class', className);
97 | var parentOfText = node.parentNode.parentNode;
98 | addItems.push({
99 | "parent": node.parentNode,
100 | "target": rect});
101 | }
102 | }
103 | }
104 | else if (!jQuery(node).is("button, select, textarea")) {
105 | jQuery.each(node.childNodes, function() {
106 | highlight(this, addItems);
107 | });
108 | }
109 | }
110 | var addItems = [];
111 | var result = this.each(function() {
112 | highlight(this, addItems);
113 | });
114 | for (var i = 0; i < addItems.length; ++i) {
115 | jQuery(addItems[i].parent).before(addItems[i].target);
116 | }
117 | return result;
118 | };
119 |
120 | /*
121 | * backward compatibility for jQuery.browser
122 | * This will be supported until firefox bug is fixed.
123 | */
124 | if (!jQuery.browser) {
125 | jQuery.uaMatch = function(ua) {
126 | ua = ua.toLowerCase();
127 |
128 | var match = /(chrome)[ \/]([\w.]+)/.exec(ua) ||
129 | /(webkit)[ \/]([\w.]+)/.exec(ua) ||
130 | /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) ||
131 | /(msie) ([\w.]+)/.exec(ua) ||
132 | ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) ||
133 | [];
134 |
135 | return {
136 | browser: match[ 1 ] || "",
137 | version: match[ 2 ] || "0"
138 | };
139 | };
140 | jQuery.browser = {};
141 | jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true;
142 | }
143 |
144 | /**
145 | * Small JavaScript module for the documentation.
146 | */
147 | var Documentation = {
148 |
149 | init : function() {
150 | this.fixFirefoxAnchorBug();
151 | this.highlightSearchWords();
152 | this.initIndexTable();
153 | if (DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) {
154 | this.initOnKeyListeners();
155 | }
156 | },
157 |
158 | /**
159 | * i18n support
160 | */
161 | TRANSLATIONS : {},
162 | PLURAL_EXPR : function(n) { return n === 1 ? 0 : 1; },
163 | LOCALE : 'unknown',
164 |
165 | // gettext and ngettext don't access this so that the functions
166 | // can safely bound to a different name (_ = Documentation.gettext)
167 | gettext : function(string) {
168 | var translated = Documentation.TRANSLATIONS[string];
169 | if (typeof translated === 'undefined')
170 | return string;
171 | return (typeof translated === 'string') ? translated : translated[0];
172 | },
173 |
174 | ngettext : function(singular, plural, n) {
175 | var translated = Documentation.TRANSLATIONS[singular];
176 | if (typeof translated === 'undefined')
177 | return (n == 1) ? singular : plural;
178 | return translated[Documentation.PLURALEXPR(n)];
179 | },
180 |
181 | addTranslations : function(catalog) {
182 | for (var key in catalog.messages)
183 | this.TRANSLATIONS[key] = catalog.messages[key];
184 | this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')');
185 | this.LOCALE = catalog.locale;
186 | },
187 |
188 | /**
189 | * add context elements like header anchor links
190 | */
191 | addContextElements : function() {
192 | $('div[id] > :header:first').each(function() {
193 | $('').
194 | attr('href', '#' + this.id).
195 | attr('title', _('Permalink to this headline')).
196 | appendTo(this);
197 | });
198 | $('dt[id]').each(function() {
199 | $('').
200 | attr('href', '#' + this.id).
201 | attr('title', _('Permalink to this definition')).
202 | appendTo(this);
203 | });
204 | },
205 |
206 | /**
207 | * workaround a firefox stupidity
208 | * see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075
209 | */
210 | fixFirefoxAnchorBug : function() {
211 | if (document.location.hash && $.browser.mozilla)
212 | window.setTimeout(function() {
213 | document.location.href += '';
214 | }, 10);
215 | },
216 |
217 | /**
218 | * highlight the search words provided in the url in the text
219 | */
220 | highlightSearchWords : function() {
221 | var params = $.getQueryParameters();
222 | var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : [];
223 | if (terms.length) {
224 | var body = $('div.body');
225 | if (!body.length) {
226 | body = $('body');
227 | }
228 | window.setTimeout(function() {
229 | $.each(terms, function() {
230 | body.highlightText(this.toLowerCase(), 'highlighted');
231 | });
232 | }, 10);
233 | $('' + _('Hide Search Matches') + '
')
235 | .appendTo($('#searchbox'));
236 | }
237 | },
238 |
239 | /**
240 | * init the domain index toggle buttons
241 | */
242 | initIndexTable : function() {
243 | var togglers = $('img.toggler').click(function() {
244 | var src = $(this).attr('src');
245 | var idnum = $(this).attr('id').substr(7);
246 | $('tr.cg-' + idnum).toggle();
247 | if (src.substr(-9) === 'minus.png')
248 | $(this).attr('src', src.substr(0, src.length-9) + 'plus.png');
249 | else
250 | $(this).attr('src', src.substr(0, src.length-8) + 'minus.png');
251 | }).css('display', '');
252 | if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) {
253 | togglers.click();
254 | }
255 | },
256 |
257 | /**
258 | * helper function to hide the search marks again
259 | */
260 | hideSearchWords : function() {
261 | $('#searchbox .highlight-link').fadeOut(300);
262 | $('span.highlighted').removeClass('highlighted');
263 | },
264 |
265 | /**
266 | * make the url absolute
267 | */
268 | makeURL : function(relativeURL) {
269 | return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL;
270 | },
271 |
272 | /**
273 | * get the current relative url
274 | */
275 | getCurrentURL : function() {
276 | var path = document.location.pathname;
277 | var parts = path.split(/\//);
278 | $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() {
279 | if (this === '..')
280 | parts.pop();
281 | });
282 | var url = parts.join('/');
283 | return path.substring(url.lastIndexOf('/') + 1, path.length - 1);
284 | },
285 |
286 | initOnKeyListeners: function() {
287 | $(document).keyup(function(event) {
288 | var activeElementType = document.activeElement.tagName;
289 | // don't navigate when in search box or textarea
290 | if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT') {
291 | switch (event.keyCode) {
292 | case 37: // left
293 | var prevHref = $('link[rel="prev"]').prop('href');
294 | if (prevHref) {
295 | window.location.href = prevHref;
296 | return false;
297 | }
298 | case 39: // right
299 | var nextHref = $('link[rel="next"]').prop('href');
300 | if (nextHref) {
301 | window.location.href = nextHref;
302 | return false;
303 | }
304 | }
305 | }
306 | });
307 | }
308 | };
309 |
310 | // quick alias for translations
311 | _ = Documentation.gettext;
312 |
313 | $(document).ready(function() {
314 | Documentation.init();
315 | });
316 |
--------------------------------------------------------------------------------
/docs/_build/html/_static/underscore.js:
--------------------------------------------------------------------------------
1 | // Underscore.js 1.3.1
2 | // (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.
3 | // Underscore is freely distributable under the MIT license.
4 | // Portions of Underscore are inspired or borrowed from Prototype,
5 | // Oliver Steele's Functional, and John Resig's Micro-Templating.
6 | // For all details and documentation:
7 | // http://documentcloud.github.com/underscore
8 | (function(){function q(a,c,d){if(a===c)return a!==0||1/a==1/c;if(a==null||c==null)return a===c;if(a._chain)a=a._wrapped;if(c._chain)c=c._wrapped;if(a.isEqual&&b.isFunction(a.isEqual))return a.isEqual(c);if(c.isEqual&&b.isFunction(c.isEqual))return c.isEqual(a);var e=l.call(a);if(e!=l.call(c))return false;switch(e){case "[object String]":return a==String(c);case "[object Number]":return a!=+a?c!=+c:a==0?1/a==1/c:a==+c;case "[object Date]":case "[object Boolean]":return+a==+c;case "[object RegExp]":return a.source==
9 | c.source&&a.global==c.global&&a.multiline==c.multiline&&a.ignoreCase==c.ignoreCase}if(typeof a!="object"||typeof c!="object")return false;for(var f=d.length;f--;)if(d[f]==a)return true;d.push(a);var f=0,g=true;if(e=="[object Array]"){if(f=a.length,g=f==c.length)for(;f--;)if(!(g=f in a==f in c&&q(a[f],c[f],d)))break}else{if("constructor"in a!="constructor"in c||a.constructor!=c.constructor)return false;for(var h in a)if(b.has(a,h)&&(f++,!(g=b.has(c,h)&&q(a[h],c[h],d))))break;if(g){for(h in c)if(b.has(c,
10 | h)&&!f--)break;g=!f}}d.pop();return g}var r=this,G=r._,n={},k=Array.prototype,o=Object.prototype,i=k.slice,H=k.unshift,l=o.toString,I=o.hasOwnProperty,w=k.forEach,x=k.map,y=k.reduce,z=k.reduceRight,A=k.filter,B=k.every,C=k.some,p=k.indexOf,D=k.lastIndexOf,o=Array.isArray,J=Object.keys,s=Function.prototype.bind,b=function(a){return new m(a)};if(typeof exports!=="undefined"){if(typeof module!=="undefined"&&module.exports)exports=module.exports=b;exports._=b}else r._=b;b.VERSION="1.3.1";var j=b.each=
11 | b.forEach=function(a,c,d){if(a!=null)if(w&&a.forEach===w)a.forEach(c,d);else if(a.length===+a.length)for(var e=0,f=a.length;e2;a==
12 | null&&(a=[]);if(y&&a.reduce===y)return e&&(c=b.bind(c,e)),f?a.reduce(c,d):a.reduce(c);j(a,function(a,b,i){f?d=c.call(e,d,a,b,i):(d=a,f=true)});if(!f)throw new TypeError("Reduce of empty array with no initial value");return d};b.reduceRight=b.foldr=function(a,c,d,e){var f=arguments.length>2;a==null&&(a=[]);if(z&&a.reduceRight===z)return e&&(c=b.bind(c,e)),f?a.reduceRight(c,d):a.reduceRight(c);var g=b.toArray(a).reverse();e&&!f&&(c=b.bind(c,e));return f?b.reduce(g,c,d,e):b.reduce(g,c)};b.find=b.detect=
13 | function(a,c,b){var e;E(a,function(a,g,h){if(c.call(b,a,g,h))return e=a,true});return e};b.filter=b.select=function(a,c,b){var e=[];if(a==null)return e;if(A&&a.filter===A)return a.filter(c,b);j(a,function(a,g,h){c.call(b,a,g,h)&&(e[e.length]=a)});return e};b.reject=function(a,c,b){var e=[];if(a==null)return e;j(a,function(a,g,h){c.call(b,a,g,h)||(e[e.length]=a)});return e};b.every=b.all=function(a,c,b){var e=true;if(a==null)return e;if(B&&a.every===B)return a.every(c,b);j(a,function(a,g,h){if(!(e=
14 | e&&c.call(b,a,g,h)))return n});return e};var E=b.some=b.any=function(a,c,d){c||(c=b.identity);var e=false;if(a==null)return e;if(C&&a.some===C)return a.some(c,d);j(a,function(a,b,h){if(e||(e=c.call(d,a,b,h)))return n});return!!e};b.include=b.contains=function(a,c){var b=false;if(a==null)return b;return p&&a.indexOf===p?a.indexOf(c)!=-1:b=E(a,function(a){return a===c})};b.invoke=function(a,c){var d=i.call(arguments,2);return b.map(a,function(a){return(b.isFunction(c)?c||a:a[c]).apply(a,d)})};b.pluck=
15 | function(a,c){return b.map(a,function(a){return a[c]})};b.max=function(a,c,d){if(!c&&b.isArray(a))return Math.max.apply(Math,a);if(!c&&b.isEmpty(a))return-Infinity;var e={computed:-Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;b>=e.computed&&(e={value:a,computed:b})});return e.value};b.min=function(a,c,d){if(!c&&b.isArray(a))return Math.min.apply(Math,a);if(!c&&b.isEmpty(a))return Infinity;var e={computed:Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;bd?1:0}),"value")};b.groupBy=function(a,c){var d={},e=b.isFunction(c)?c:function(a){return a[c]};j(a,function(a,b){var c=e(a,b);(d[c]||(d[c]=[])).push(a)});return d};b.sortedIndex=function(a,
17 | c,d){d||(d=b.identity);for(var e=0,f=a.length;e>1;d(a[g])=0})})};b.difference=function(a){var c=b.flatten(i.call(arguments,1));return b.filter(a,function(a){return!b.include(c,a)})};b.zip=function(){for(var a=i.call(arguments),c=b.max(b.pluck(a,"length")),d=Array(c),e=0;e=0;d--)b=[a[d].apply(this,b)];return b[0]}};
24 | b.after=function(a,b){return a<=0?b():function(){if(--a<1)return b.apply(this,arguments)}};b.keys=J||function(a){if(a!==Object(a))throw new TypeError("Invalid object");var c=[],d;for(d in a)b.has(a,d)&&(c[c.length]=d);return c};b.values=function(a){return b.map(a,b.identity)};b.functions=b.methods=function(a){var c=[],d;for(d in a)b.isFunction(a[d])&&c.push(d);return c.sort()};b.extend=function(a){j(i.call(arguments,1),function(b){for(var d in b)a[d]=b[d]});return a};b.defaults=function(a){j(i.call(arguments,
25 | 1),function(b){for(var d in b)a[d]==null&&(a[d]=b[d])});return a};b.clone=function(a){return!b.isObject(a)?a:b.isArray(a)?a.slice():b.extend({},a)};b.tap=function(a,b){b(a);return a};b.isEqual=function(a,b){return q(a,b,[])};b.isEmpty=function(a){if(b.isArray(a)||b.isString(a))return a.length===0;for(var c in a)if(b.has(a,c))return false;return true};b.isElement=function(a){return!!(a&&a.nodeType==1)};b.isArray=o||function(a){return l.call(a)=="[object Array]"};b.isObject=function(a){return a===Object(a)};
26 | b.isArguments=function(a){return l.call(a)=="[object Arguments]"};if(!b.isArguments(arguments))b.isArguments=function(a){return!(!a||!b.has(a,"callee"))};b.isFunction=function(a){return l.call(a)=="[object Function]"};b.isString=function(a){return l.call(a)=="[object String]"};b.isNumber=function(a){return l.call(a)=="[object Number]"};b.isNaN=function(a){return a!==a};b.isBoolean=function(a){return a===true||a===false||l.call(a)=="[object Boolean]"};b.isDate=function(a){return l.call(a)=="[object Date]"};
27 | b.isRegExp=function(a){return l.call(a)=="[object RegExp]"};b.isNull=function(a){return a===null};b.isUndefined=function(a){return a===void 0};b.has=function(a,b){return I.call(a,b)};b.noConflict=function(){r._=G;return this};b.identity=function(a){return a};b.times=function(a,b,d){for(var e=0;e /g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/")};b.mixin=function(a){j(b.functions(a),
28 | function(c){K(c,b[c]=a[c])})};var L=0;b.uniqueId=function(a){var b=L++;return a?a+b:b};b.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var t=/.^/,u=function(a){return a.replace(/\\\\/g,"\\").replace(/\\'/g,"'")};b.template=function(a,c){var d=b.templateSettings,d="var __p=[],print=function(){__p.push.apply(__p,arguments);};with(obj||{}){__p.push('"+a.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(d.escape||t,function(a,b){return"',_.escape("+
29 | u(b)+"),'"}).replace(d.interpolate||t,function(a,b){return"',"+u(b)+",'"}).replace(d.evaluate||t,function(a,b){return"');"+u(b).replace(/[\r\n\t]/g," ")+";__p.push('"}).replace(/\r/g,"\\r").replace(/\n/g,"\\n").replace(/\t/g,"\\t")+"');}return __p.join('');",e=new Function("obj","_",d);return c?e(c,b):function(a){return e.call(this,a,b)}};b.chain=function(a){return b(a).chain()};var m=function(a){this._wrapped=a};b.prototype=m.prototype;var v=function(a,c){return c?b(a).chain():a},K=function(a,c){m.prototype[a]=
30 | function(){var a=i.call(arguments);H.call(a,this._wrapped);return v(c.apply(b,a),this._chain)}};b.mixin(b);j("pop,push,reverse,shift,sort,splice,unshift".split(","),function(a){var b=k[a];m.prototype[a]=function(){var d=this._wrapped;b.apply(d,arguments);var e=d.length;(a=="shift"||a=="splice")&&e===0&&delete d[0];return v(d,this._chain)}});j(["concat","join","slice"],function(a){var b=k[a];m.prototype[a]=function(){return v(b.apply(this._wrapped,arguments),this._chain)}});m.prototype.chain=function(){this._chain=
31 | true;return this};m.prototype.value=function(){return this._wrapped}}).call(this);
32 |
--------------------------------------------------------------------------------
/docs/_build/html/_static/documentation_options.js:
--------------------------------------------------------------------------------
1 | var DOCUMENTATION_OPTIONS = {
2 | URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'),
3 | VERSION: '0.1.2',
4 | LANGUAGE: 'None',
5 | COLLAPSE_INDEX: false,
6 | FILE_SUFFIX: '.html',
7 | HAS_SOURCE: true,
8 | SOURCELINK_SUFFIX: '.txt',
9 | NAVIGATION_WITH_KEYS: false,
10 | SEARCH_LANGUAGE_STOP_WORDS: ["a","and","are","as","at","be","but","by","for","if","in","into","is","it","near","no","not","of","on","or","such","that","the","their","then","there","these","they","this","to","was","will","with"]
11 | };
12 |
13 |
14 |
15 | /* Non-minified version JS is _stemmer.js if file is provided */
16 | /**
17 | * Porter Stemmer
18 | */
19 | var Stemmer = function() {
20 |
21 | var step2list = {
22 | ational: 'ate',
23 | tional: 'tion',
24 | enci: 'ence',
25 | anci: 'ance',
26 | izer: 'ize',
27 | bli: 'ble',
28 | alli: 'al',
29 | entli: 'ent',
30 | eli: 'e',
31 | ousli: 'ous',
32 | ization: 'ize',
33 | ation: 'ate',
34 | ator: 'ate',
35 | alism: 'al',
36 | iveness: 'ive',
37 | fulness: 'ful',
38 | ousness: 'ous',
39 | aliti: 'al',
40 | iviti: 'ive',
41 | biliti: 'ble',
42 | logi: 'log'
43 | };
44 |
45 | var step3list = {
46 | icate: 'ic',
47 | ative: '',
48 | alize: 'al',
49 | iciti: 'ic',
50 | ical: 'ic',
51 | ful: '',
52 | ness: ''
53 | };
54 |
55 | var c = "[^aeiou]"; // consonant
56 | var v = "[aeiouy]"; // vowel
57 | var C = c + "[^aeiouy]*"; // consonant sequence
58 | var V = v + "[aeiou]*"; // vowel sequence
59 |
60 | var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0
61 | var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1
62 | var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1
63 | var s_v = "^(" + C + ")?" + v; // vowel in stem
64 |
65 | this.stemWord = function (w) {
66 | var stem;
67 | var suffix;
68 | var firstch;
69 | var origword = w;
70 |
71 | if (w.length < 3)
72 | return w;
73 |
74 | var re;
75 | var re2;
76 | var re3;
77 | var re4;
78 |
79 | firstch = w.substr(0,1);
80 | if (firstch == "y")
81 | w = firstch.toUpperCase() + w.substr(1);
82 |
83 | // Step 1a
84 | re = /^(.+?)(ss|i)es$/;
85 | re2 = /^(.+?)([^s])s$/;
86 |
87 | if (re.test(w))
88 | w = w.replace(re,"$1$2");
89 | else if (re2.test(w))
90 | w = w.replace(re2,"$1$2");
91 |
92 | // Step 1b
93 | re = /^(.+?)eed$/;
94 | re2 = /^(.+?)(ed|ing)$/;
95 | if (re.test(w)) {
96 | var fp = re.exec(w);
97 | re = new RegExp(mgr0);
98 | if (re.test(fp[1])) {
99 | re = /.$/;
100 | w = w.replace(re,"");
101 | }
102 | }
103 | else if (re2.test(w)) {
104 | var fp = re2.exec(w);
105 | stem = fp[1];
106 | re2 = new RegExp(s_v);
107 | if (re2.test(stem)) {
108 | w = stem;
109 | re2 = /(at|bl|iz)$/;
110 | re3 = new RegExp("([^aeiouylsz])\\1$");
111 | re4 = new RegExp("^" + C + v + "[^aeiouwxy]$");
112 | if (re2.test(w))
113 | w = w + "e";
114 | else if (re3.test(w)) {
115 | re = /.$/;
116 | w = w.replace(re,"");
117 | }
118 | else if (re4.test(w))
119 | w = w + "e";
120 | }
121 | }
122 |
123 | // Step 1c
124 | re = /^(.+?)y$/;
125 | if (re.test(w)) {
126 | var fp = re.exec(w);
127 | stem = fp[1];
128 | re = new RegExp(s_v);
129 | if (re.test(stem))
130 | w = stem + "i";
131 | }
132 |
133 | // Step 2
134 | re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/;
135 | if (re.test(w)) {
136 | var fp = re.exec(w);
137 | stem = fp[1];
138 | suffix = fp[2];
139 | re = new RegExp(mgr0);
140 | if (re.test(stem))
141 | w = stem + step2list[suffix];
142 | }
143 |
144 | // Step 3
145 | re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/;
146 | if (re.test(w)) {
147 | var fp = re.exec(w);
148 | stem = fp[1];
149 | suffix = fp[2];
150 | re = new RegExp(mgr0);
151 | if (re.test(stem))
152 | w = stem + step3list[suffix];
153 | }
154 |
155 | // Step 4
156 | re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/;
157 | re2 = /^(.+?)(s|t)(ion)$/;
158 | if (re.test(w)) {
159 | var fp = re.exec(w);
160 | stem = fp[1];
161 | re = new RegExp(mgr1);
162 | if (re.test(stem))
163 | w = stem;
164 | }
165 | else if (re2.test(w)) {
166 | var fp = re2.exec(w);
167 | stem = fp[1] + fp[2];
168 | re2 = new RegExp(mgr1);
169 | if (re2.test(stem))
170 | w = stem;
171 | }
172 |
173 | // Step 5
174 | re = /^(.+?)e$/;
175 | if (re.test(w)) {
176 | var fp = re.exec(w);
177 | stem = fp[1];
178 | re = new RegExp(mgr1);
179 | re2 = new RegExp(meq1);
180 | re3 = new RegExp("^" + C + v + "[^aeiouwxy]$");
181 | if (re.test(stem) || (re2.test(stem) && !(re3.test(stem))))
182 | w = stem;
183 | }
184 | re = /ll$/;
185 | re2 = new RegExp(mgr1);
186 | if (re.test(w) && re2.test(w)) {
187 | re = /.$/;
188 | w = w.replace(re,"");
189 | }
190 |
191 | // and turn initial Y back to y
192 | if (firstch == "y")
193 | w = firstch.toLowerCase() + w.substr(1);
194 | return w;
195 | }
196 | }
197 |
198 |
199 |
200 |
201 |
202 | var splitChars = (function() {
203 | var result = {};
204 | var singles = [96, 180, 187, 191, 215, 247, 749, 885, 903, 907, 909, 930, 1014, 1648,
205 | 1748, 1809, 2416, 2473, 2481, 2526, 2601, 2609, 2612, 2615, 2653, 2702,
206 | 2706, 2729, 2737, 2740, 2857, 2865, 2868, 2910, 2928, 2948, 2961, 2971,
207 | 2973, 3085, 3089, 3113, 3124, 3213, 3217, 3241, 3252, 3295, 3341, 3345,
208 | 3369, 3506, 3516, 3633, 3715, 3721, 3736, 3744, 3748, 3750, 3756, 3761,
209 | 3781, 3912, 4239, 4347, 4681, 4695, 4697, 4745, 4785, 4799, 4801, 4823,
210 | 4881, 5760, 5901, 5997, 6313, 7405, 8024, 8026, 8028, 8030, 8117, 8125,
211 | 8133, 8181, 8468, 8485, 8487, 8489, 8494, 8527, 11311, 11359, 11687, 11695,
212 | 11703, 11711, 11719, 11727, 11735, 12448, 12539, 43010, 43014, 43019, 43587,
213 | 43696, 43713, 64286, 64297, 64311, 64317, 64319, 64322, 64325, 65141];
214 | var i, j, start, end;
215 | for (i = 0; i < singles.length; i++) {
216 | result[singles[i]] = true;
217 | }
218 | var ranges = [[0, 47], [58, 64], [91, 94], [123, 169], [171, 177], [182, 184], [706, 709],
219 | [722, 735], [741, 747], [751, 879], [888, 889], [894, 901], [1154, 1161],
220 | [1318, 1328], [1367, 1368], [1370, 1376], [1416, 1487], [1515, 1519], [1523, 1568],
221 | [1611, 1631], [1642, 1645], [1750, 1764], [1767, 1773], [1789, 1790], [1792, 1807],
222 | [1840, 1868], [1958, 1968], [1970, 1983], [2027, 2035], [2038, 2041], [2043, 2047],
223 | [2070, 2073], [2075, 2083], [2085, 2087], [2089, 2307], [2362, 2364], [2366, 2383],
224 | [2385, 2391], [2402, 2405], [2419, 2424], [2432, 2436], [2445, 2446], [2449, 2450],
225 | [2483, 2485], [2490, 2492], [2494, 2509], [2511, 2523], [2530, 2533], [2546, 2547],
226 | [2554, 2564], [2571, 2574], [2577, 2578], [2618, 2648], [2655, 2661], [2672, 2673],
227 | [2677, 2692], [2746, 2748], [2750, 2767], [2769, 2783], [2786, 2789], [2800, 2820],
228 | [2829, 2830], [2833, 2834], [2874, 2876], [2878, 2907], [2914, 2917], [2930, 2946],
229 | [2955, 2957], [2966, 2968], [2976, 2978], [2981, 2983], [2987, 2989], [3002, 3023],
230 | [3025, 3045], [3059, 3076], [3130, 3132], [3134, 3159], [3162, 3167], [3170, 3173],
231 | [3184, 3191], [3199, 3204], [3258, 3260], [3262, 3293], [3298, 3301], [3312, 3332],
232 | [3386, 3388], [3390, 3423], [3426, 3429], [3446, 3449], [3456, 3460], [3479, 3481],
233 | [3518, 3519], [3527, 3584], [3636, 3647], [3655, 3663], [3674, 3712], [3717, 3718],
234 | [3723, 3724], [3726, 3731], [3752, 3753], [3764, 3772], [3774, 3775], [3783, 3791],
235 | [3802, 3803], [3806, 3839], [3841, 3871], [3892, 3903], [3949, 3975], [3980, 4095],
236 | [4139, 4158], [4170, 4175], [4182, 4185], [4190, 4192], [4194, 4196], [4199, 4205],
237 | [4209, 4212], [4226, 4237], [4250, 4255], [4294, 4303], [4349, 4351], [4686, 4687],
238 | [4702, 4703], [4750, 4751], [4790, 4791], [4806, 4807], [4886, 4887], [4955, 4968],
239 | [4989, 4991], [5008, 5023], [5109, 5120], [5741, 5742], [5787, 5791], [5867, 5869],
240 | [5873, 5887], [5906, 5919], [5938, 5951], [5970, 5983], [6001, 6015], [6068, 6102],
241 | [6104, 6107], [6109, 6111], [6122, 6127], [6138, 6159], [6170, 6175], [6264, 6271],
242 | [6315, 6319], [6390, 6399], [6429, 6469], [6510, 6511], [6517, 6527], [6572, 6592],
243 | [6600, 6607], [6619, 6655], [6679, 6687], [6741, 6783], [6794, 6799], [6810, 6822],
244 | [6824, 6916], [6964, 6980], [6988, 6991], [7002, 7042], [7073, 7085], [7098, 7167],
245 | [7204, 7231], [7242, 7244], [7294, 7400], [7410, 7423], [7616, 7679], [7958, 7959],
246 | [7966, 7967], [8006, 8007], [8014, 8015], [8062, 8063], [8127, 8129], [8141, 8143],
247 | [8148, 8149], [8156, 8159], [8173, 8177], [8189, 8303], [8306, 8307], [8314, 8318],
248 | [8330, 8335], [8341, 8449], [8451, 8454], [8456, 8457], [8470, 8472], [8478, 8483],
249 | [8506, 8507], [8512, 8516], [8522, 8525], [8586, 9311], [9372, 9449], [9472, 10101],
250 | [10132, 11263], [11493, 11498], [11503, 11516], [11518, 11519], [11558, 11567],
251 | [11622, 11630], [11632, 11647], [11671, 11679], [11743, 11822], [11824, 12292],
252 | [12296, 12320], [12330, 12336], [12342, 12343], [12349, 12352], [12439, 12444],
253 | [12544, 12548], [12590, 12592], [12687, 12689], [12694, 12703], [12728, 12783],
254 | [12800, 12831], [12842, 12880], [12896, 12927], [12938, 12976], [12992, 13311],
255 | [19894, 19967], [40908, 40959], [42125, 42191], [42238, 42239], [42509, 42511],
256 | [42540, 42559], [42592, 42593], [42607, 42622], [42648, 42655], [42736, 42774],
257 | [42784, 42785], [42889, 42890], [42893, 43002], [43043, 43055], [43062, 43071],
258 | [43124, 43137], [43188, 43215], [43226, 43249], [43256, 43258], [43260, 43263],
259 | [43302, 43311], [43335, 43359], [43389, 43395], [43443, 43470], [43482, 43519],
260 | [43561, 43583], [43596, 43599], [43610, 43615], [43639, 43641], [43643, 43647],
261 | [43698, 43700], [43703, 43704], [43710, 43711], [43715, 43738], [43742, 43967],
262 | [44003, 44015], [44026, 44031], [55204, 55215], [55239, 55242], [55292, 55295],
263 | [57344, 63743], [64046, 64047], [64110, 64111], [64218, 64255], [64263, 64274],
264 | [64280, 64284], [64434, 64466], [64830, 64847], [64912, 64913], [64968, 65007],
265 | [65020, 65135], [65277, 65295], [65306, 65312], [65339, 65344], [65371, 65381],
266 | [65471, 65473], [65480, 65481], [65488, 65489], [65496, 65497]];
267 | for (i = 0; i < ranges.length; i++) {
268 | start = ranges[i][0];
269 | end = ranges[i][1];
270 | for (j = start; j <= end; j++) {
271 | result[j] = true;
272 | }
273 | }
274 | return result;
275 | })();
276 |
277 | function splitQuery(query) {
278 | var result = [];
279 | var start = -1;
280 | for (var i = 0; i < query.length; i++) {
281 | if (splitChars[query.charCodeAt(i)]) {
282 | if (start !== -1) {
283 | result.push(query.slice(start, i));
284 | start = -1;
285 | }
286 | } else if (start === -1) {
287 | start = i;
288 | }
289 | }
290 | if (start !== -1) {
291 | result.push(query.slice(start));
292 | }
293 | return result;
294 | }
295 |
296 |
297 |
--------------------------------------------------------------------------------
/docs/_build/html/show.html:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 | Figure — wsipre 0.1.2 documentation
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
23 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
Figure
42 |
43 |
44 | class show.Figure( image , annotation , color_map={0: (0.0 , 0.0 , 0.0) , 1: (0.0 , 0.8 , 1.0) , 2: (1.0 , 0.8 , 0.0) , 3: (1.0 , 0.4 , 0.0)} ) [source]
45 | An open annotated WSI.
46 |
47 |
48 |
49 |
50 | Parameters:
51 | image: PIL Image
52 | Image to display; a thumbnail or region read from WSI.
53 |
54 | annotation: Numpy 2D array
55 | Annotation labels for each pixel in the input image .
56 |
57 | color_map: dict {label int: RGB color list}
58 | Mapping of RGB color values to class labels. Colors are triplet lists
59 | of the R, G, and B values.
60 |
61 |
62 |
63 |
64 |
65 |
66 | Examples
67 | >>> from wsipre import show
68 | >>> colors = { 0 : ( 0 , 0 , 0 ), 2 : ( 1 , 0 , 0 )}
69 | >>> fig = show . Figure ( image = image , annotation = mask , color_map = colors )
70 | >>> fig . color_map
71 | {0: (0, 0, 0), 2: (1, 0, 0)}
72 |
73 |
74 | >>> fig . show_label_colors ( height = 5 )
75 |
76 |
77 | >>> fig . show_image_with_annotation ()
78 |
79 |
80 |
81 |
82 |
83 |
84 | Attributes:
85 | image: PIL Image
86 | The input image .
87 |
88 | annotation: Numpy 2D array
89 | The input annotation .
90 |
91 | color_map: dict {label: color}
92 | Mapping between each label and the color for visualization.
93 |
94 |
95 |
96 |
97 |
98 |
99 | Methods
100 |
101 |
102 |
103 |
104 |
105 |
106 | show_annotation ()
107 | Show loaded image annotation.
108 |
109 | show_image ()
110 | Show loaded image.
111 |
112 | show_image_with_annotation ([split])
113 | Show loaded image and annotation.
114 |
115 | show_label_colors ([width, height, …])
116 | Display a color bar with the colors and overlayed labels.
117 |
118 |
119 |
120 |
121 |
122 | show_annotation( ) [source]
123 | Show loaded image annotation.
124 | Display the loaded WSI thumbnail or region annotation, corresponding to
125 | a mask of pixel-wise labels.
126 |
127 |
128 |
129 |
130 | Returns:
131 | Matplotlib image.
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 | show_image( ) [source]
143 | Show loaded image.
144 | Display the loaded WSI thumbnail or region.
145 |
146 |
147 |
148 |
149 | Returns:
150 | Matplotlib image.
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 | show_image_with_annotation( split=True ) [source]
162 | Show loaded image and annotation.
163 |
164 |
165 |
166 |
167 | Parameters:
168 | split: bool
169 | Whether to display the split image and annotation side-by-side or a
170 | combined visualization of the annotation on the image.
171 |
172 |
173 |
174 |
175 | Returns:
176 | Matplotlib image.
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 | show_label_colors( width=20 , height=6 , font_color='w' , font_size=14 ) [source]
188 | Display a color bar with the colors and overlayed labels.
189 |
190 |
191 |
192 |
193 | Parameters:
194 | width: int
195 | Width of each class rectangle in plot.
196 |
197 | height: int
198 | Height of each class rectangle in plot.
199 |
200 | font_size: int
201 | Size of the font used to display class labels.
202 |
203 |
204 |
205 |
206 | Returns:
207 | Matplotlib image illustrating mapping between class label and color.
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
235 |
236 |
237 |
248 |
255 |
256 |
257 |
258 |
--------------------------------------------------------------------------------
/docs/_build/html/_static/basic.css:
--------------------------------------------------------------------------------
1 | /*
2 | * basic.css
3 | * ~~~~~~~~~
4 | *
5 | * Sphinx stylesheet -- basic theme.
6 | *
7 | * :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
8 | * :license: BSD, see LICENSE for details.
9 | *
10 | */
11 |
12 | /* -- main layout ----------------------------------------------------------- */
13 |
14 | div.clearer {
15 | clear: both;
16 | }
17 |
18 | /* -- relbar ---------------------------------------------------------------- */
19 |
20 | div.related {
21 | width: 100%;
22 | font-size: 90%;
23 | }
24 |
25 | div.related h3 {
26 | display: none;
27 | }
28 |
29 | div.related ul {
30 | margin: 0;
31 | padding: 0 0 0 10px;
32 | list-style: none;
33 | }
34 |
35 | div.related li {
36 | display: inline;
37 | }
38 |
39 | div.related li.right {
40 | float: right;
41 | margin-right: 5px;
42 | }
43 |
44 | /* -- sidebar --------------------------------------------------------------- */
45 |
46 | div.sphinxsidebarwrapper {
47 | padding: 10px 5px 0 10px;
48 | }
49 |
50 | div.sphinxsidebar {
51 | float: left;
52 | width: 15rem;
53 | margin-left: -100%;
54 | font-size: 90%;
55 | word-wrap: break-word;
56 | overflow-wrap : break-word;
57 | }
58 |
59 | div.sphinxsidebar ul {
60 | list-style: none;
61 | }
62 |
63 | div.sphinxsidebar ul ul,
64 | div.sphinxsidebar ul.want-points {
65 | margin-left: 20px;
66 | list-style: square;
67 | }
68 |
69 | div.sphinxsidebar ul ul {
70 | margin-top: 0;
71 | margin-bottom: 0;
72 | }
73 |
74 | div.sphinxsidebar form {
75 | margin-top: 10px;
76 | }
77 |
78 | div.sphinxsidebar input {
79 | border: 1px solid #98dbcc;
80 | font-family: sans-serif;
81 | font-size: 1em;
82 | }
83 |
84 | div.sphinxsidebar #searchbox form.search {
85 | overflow: hidden;
86 | }
87 |
88 | div.sphinxsidebar #searchbox input[type="text"] {
89 | float: left;
90 | width: 80%;
91 | padding: 0.25em;
92 | box-sizing: border-box;
93 | }
94 |
95 | div.sphinxsidebar #searchbox input[type="submit"] {
96 | float: left;
97 | width: 20%;
98 | border-left: none;
99 | padding: 0.25em;
100 | box-sizing: border-box;
101 | }
102 |
103 |
104 | img {
105 | border: 0;
106 | max-width: 100%;
107 | }
108 |
109 | /* -- search page ----------------------------------------------------------- */
110 |
111 | ul.search {
112 | margin: 10px 0 0 20px;
113 | padding: 0;
114 | }
115 |
116 | ul.search li {
117 | padding: 5px 0 5px 20px;
118 | background-image: url(file.png);
119 | background-repeat: no-repeat;
120 | background-position: 0 7px;
121 | }
122 |
123 | ul.search li a {
124 | font-weight: bold;
125 | }
126 |
127 | ul.search li div.context {
128 | color: #888;
129 | margin: 2px 0 0 30px;
130 | text-align: left;
131 | }
132 |
133 | ul.keywordmatches li.goodmatch a {
134 | font-weight: bold;
135 | }
136 |
137 | /* -- index page ------------------------------------------------------------ */
138 |
139 | table.contentstable {
140 | width: 90%;
141 | margin-left: auto;
142 | margin-right: auto;
143 | }
144 |
145 | table.contentstable p.biglink {
146 | line-height: 150%;
147 | }
148 |
149 | a.biglink {
150 | font-size: 1.3em;
151 | }
152 |
153 | span.linkdescr {
154 | font-style: italic;
155 | padding-top: 5px;
156 | font-size: 90%;
157 | }
158 |
159 | /* -- general index --------------------------------------------------------- */
160 |
161 | table.indextable {
162 | width: 100%;
163 | }
164 |
165 | table.indextable td {
166 | text-align: left;
167 | vertical-align: top;
168 | }
169 |
170 | table.indextable ul {
171 | margin-top: 0;
172 | margin-bottom: 0;
173 | list-style-type: none;
174 | }
175 |
176 | table.indextable > tbody > tr > td > ul {
177 | padding-left: 0em;
178 | }
179 |
180 | table.indextable tr.pcap {
181 | height: 10px;
182 | }
183 |
184 | table.indextable tr.cap {
185 | margin-top: 10px;
186 | background-color: #f2f2f2;
187 | }
188 |
189 | img.toggler {
190 | margin-right: 3px;
191 | margin-top: 3px;
192 | cursor: pointer;
193 | }
194 |
195 | div.modindex-jumpbox {
196 | border-top: 1px solid #ddd;
197 | border-bottom: 1px solid #ddd;
198 | margin: 1em 0 1em 0;
199 | padding: 0.4em;
200 | }
201 |
202 | div.genindex-jumpbox {
203 | border-top: 1px solid #ddd;
204 | border-bottom: 1px solid #ddd;
205 | margin: 1em 0 1em 0;
206 | padding: 0.4em;
207 | }
208 |
209 | /* -- domain module index --------------------------------------------------- */
210 |
211 | table.modindextable td {
212 | padding: 2px;
213 | border-collapse: collapse;
214 | }
215 |
216 | /* -- general body styles --------------------------------------------------- */
217 |
218 | div.body {
219 | min-width: 450px;
220 | max-width: 800px;
221 | }
222 |
223 | div.body p, div.body dd, div.body li, div.body blockquote {
224 | -moz-hyphens: auto;
225 | -ms-hyphens: auto;
226 | -webkit-hyphens: auto;
227 | hyphens: auto;
228 | }
229 |
230 | a.headerlink {
231 | visibility: hidden;
232 | }
233 |
234 | h1:hover > a.headerlink,
235 | h2:hover > a.headerlink,
236 | h3:hover > a.headerlink,
237 | h4:hover > a.headerlink,
238 | h5:hover > a.headerlink,
239 | h6:hover > a.headerlink,
240 | dt:hover > a.headerlink,
241 | caption:hover > a.headerlink,
242 | p.caption:hover > a.headerlink,
243 | div.code-block-caption:hover > a.headerlink {
244 | visibility: visible;
245 | }
246 |
247 | div.body p.caption {
248 | text-align: inherit;
249 | }
250 |
251 | div.body td {
252 | text-align: left;
253 | }
254 |
255 | .first {
256 | margin-top: 0 !important;
257 | }
258 |
259 | p.rubric {
260 | margin-top: 30px;
261 | font-weight: bold;
262 | }
263 |
264 | img.align-left, .figure.align-left, object.align-left {
265 | clear: left;
266 | float: left;
267 | margin-right: 1em;
268 | }
269 |
270 | img.align-right, .figure.align-right, object.align-right {
271 | clear: right;
272 | float: right;
273 | margin-left: 1em;
274 | }
275 |
276 | img.align-center, .figure.align-center, object.align-center {
277 | display: block;
278 | margin-left: auto;
279 | margin-right: auto;
280 | }
281 |
282 | .align-left {
283 | text-align: left;
284 | }
285 |
286 | .align-center {
287 | text-align: center;
288 | }
289 |
290 | .align-right {
291 | text-align: right;
292 | }
293 |
294 | /* -- sidebars -------------------------------------------------------------- */
295 |
296 | div.sidebar {
297 | margin: 0 0 0.5em 1em;
298 | border: 1px solid #ddb;
299 | padding: 7px 7px 0 7px;
300 | background-color: #ffe;
301 | width: 40%;
302 | float: right;
303 | }
304 |
305 | p.sidebar-title {
306 | font-weight: bold;
307 | }
308 |
309 | /* -- topics ---------------------------------------------------------------- */
310 |
311 | div.topic {
312 | border: 1px solid #ccc;
313 | padding: 7px 7px 0 7px;
314 | margin: 10px 0 10px 0;
315 | }
316 |
317 | p.topic-title {
318 | font-size: 1.1em;
319 | font-weight: bold;
320 | margin-top: 10px;
321 | }
322 |
323 | /* -- admonitions ----------------------------------------------------------- */
324 |
325 | div.admonition {
326 | margin-top: 10px;
327 | margin-bottom: 10px;
328 | padding: 7px;
329 | }
330 |
331 | div.admonition dt {
332 | font-weight: bold;
333 | }
334 |
335 | div.admonition dl {
336 | margin-bottom: 0;
337 | }
338 |
339 | p.admonition-title {
340 | margin: 0px 10px 5px 0px;
341 | font-weight: bold;
342 | }
343 |
344 | div.body p.centered {
345 | text-align: center;
346 | margin-top: 25px;
347 | }
348 |
349 | /* -- tables ---------------------------------------------------------------- */
350 |
351 | table.docutils {
352 | border: 0;
353 | border-collapse: collapse;
354 | }
355 |
356 | table.align-center {
357 | margin-left: auto;
358 | margin-right: auto;
359 | }
360 |
361 | table caption span.caption-number {
362 | font-style: italic;
363 | }
364 |
365 | table caption span.caption-text {
366 | }
367 |
368 | table.docutils td, table.docutils th {
369 | padding: 1px 8px 1px 5px;
370 | border-top: 0;
371 | border-left: 0;
372 | border-right: 0;
373 | border-bottom: 1px solid #aaa;
374 | }
375 |
376 | table.footnote td, table.footnote th {
377 | border: 0 !important;
378 | }
379 |
380 | th {
381 | text-align: left;
382 | padding-right: 5px;
383 | }
384 |
385 | table.citation {
386 | border-left: solid 1px gray;
387 | margin-left: 1px;
388 | }
389 |
390 | table.citation td {
391 | border-bottom: none;
392 | }
393 |
394 | /* -- figures --------------------------------------------------------------- */
395 |
396 | div.figure {
397 | margin: 0.5em;
398 | padding: 0.5em;
399 | }
400 |
401 | div.figure p.caption {
402 | padding: 0.3em;
403 | }
404 |
405 | div.figure p.caption span.caption-number {
406 | font-style: italic;
407 | }
408 |
409 | div.figure p.caption span.caption-text {
410 | }
411 |
412 | /* -- field list styles ----------------------------------------------------- */
413 |
414 | table.field-list td, table.field-list th {
415 | border: 0 !important;
416 | }
417 |
418 | .field-list ul {
419 | margin: 0;
420 | padding-left: 1em;
421 | }
422 |
423 | .field-list p {
424 | margin: 0;
425 | }
426 |
427 | .field-name {
428 | -moz-hyphens: manual;
429 | -ms-hyphens: manual;
430 | -webkit-hyphens: manual;
431 | hyphens: manual;
432 | }
433 |
434 | /* -- hlist styles ---------------------------------------------------------- */
435 |
436 | table.hlist td {
437 | vertical-align: top;
438 | }
439 |
440 |
441 | /* -- other body styles ----------------------------------------------------- */
442 |
443 | ol.arabic {
444 | list-style: decimal;
445 | }
446 |
447 | ol.loweralpha {
448 | list-style: lower-alpha;
449 | }
450 |
451 | ol.upperalpha {
452 | list-style: upper-alpha;
453 | }
454 |
455 | ol.lowerroman {
456 | list-style: lower-roman;
457 | }
458 |
459 | ol.upperroman {
460 | list-style: upper-roman;
461 | }
462 |
463 | dl {
464 | margin-bottom: 15px;
465 | }
466 |
467 | dd p {
468 | margin-top: 0px;
469 | }
470 |
471 | dd ul, dd table {
472 | margin-bottom: 10px;
473 | }
474 |
475 | dd {
476 | margin-top: 3px;
477 | margin-bottom: 10px;
478 | margin-left: 30px;
479 | }
480 |
481 | dt:target, span.highlighted {
482 | background-color: #fbe54e;
483 | }
484 |
485 | rect.highlighted {
486 | fill: #fbe54e;
487 | }
488 |
489 | dl.glossary dt {
490 | font-weight: bold;
491 | font-size: 1.1em;
492 | }
493 |
494 | .optional {
495 | font-size: 1.3em;
496 | }
497 |
498 | .sig-paren {
499 | font-size: larger;
500 | }
501 |
502 | .versionmodified {
503 | font-style: italic;
504 | }
505 |
506 | .system-message {
507 | background-color: #fda;
508 | padding: 5px;
509 | border: 3px solid red;
510 | }
511 |
512 | .footnote:target {
513 | background-color: #ffa;
514 | }
515 |
516 | .line-block {
517 | display: block;
518 | margin-top: 1em;
519 | margin-bottom: 1em;
520 | }
521 |
522 | .line-block .line-block {
523 | margin-top: 0;
524 | margin-bottom: 0;
525 | margin-left: 1.5em;
526 | }
527 |
528 | .guilabel, .menuselection {
529 | font-family: sans-serif;
530 | }
531 |
532 | .accelerator {
533 | text-decoration: underline;
534 | }
535 |
536 | .classifier {
537 | font-style: oblique;
538 | }
539 |
540 | abbr, acronym {
541 | border-bottom: dotted 1px;
542 | cursor: help;
543 | }
544 |
545 | /* -- code displays --------------------------------------------------------- */
546 |
547 | pre {
548 | overflow: auto;
549 | overflow-y: hidden; /* fixes display issues on Chrome browsers */
550 | }
551 |
552 | span.pre {
553 | -moz-hyphens: none;
554 | -ms-hyphens: none;
555 | -webkit-hyphens: none;
556 | hyphens: none;
557 | }
558 |
559 | td.linenos pre {
560 | padding: 5px 0px;
561 | border: 0;
562 | background-color: transparent;
563 | color: #aaa;
564 | }
565 |
566 | table.highlighttable {
567 | margin-left: 0.5em;
568 | }
569 |
570 | table.highlighttable td {
571 | padding: 0 0.5em 0 0.5em;
572 | }
573 |
574 | div.code-block-caption {
575 | padding: 2px 5px;
576 | font-size: small;
577 | }
578 |
579 | div.code-block-caption code {
580 | background-color: transparent;
581 | }
582 |
583 | div.code-block-caption + div > div.highlight > pre {
584 | margin-top: 0;
585 | }
586 |
587 | div.code-block-caption span.caption-number {
588 | padding: 0.1em 0.3em;
589 | font-style: italic;
590 | }
591 |
592 | div.code-block-caption span.caption-text {
593 | }
594 |
595 | div.literal-block-wrapper {
596 | padding: 1em 1em 0;
597 | }
598 |
599 | div.literal-block-wrapper div.highlight {
600 | margin: 0;
601 | }
602 |
603 | code.descname {
604 | background-color: transparent;
605 | font-weight: bold;
606 | font-size: 1.2em;
607 | }
608 |
609 | code.descclassname {
610 | background-color: transparent;
611 | }
612 |
613 | code.xref, a code {
614 | background-color: transparent;
615 | font-weight: bold;
616 | }
617 |
618 | h1 code, h2 code, h3 code, h4 code, h5 code, h6 code {
619 | background-color: transparent;
620 | }
621 |
622 | .viewcode-link {
623 | float: right;
624 | }
625 |
626 | .viewcode-back {
627 | float: right;
628 | font-family: sans-serif;
629 | }
630 |
631 | div.viewcode-block:target {
632 | margin: -1px -10px;
633 | padding: 0 10px;
634 | }
635 |
636 | /* -- math display ---------------------------------------------------------- */
637 |
638 | img.math {
639 | vertical-align: middle;
640 | }
641 |
642 | div.body div.math p {
643 | text-align: center;
644 | }
645 |
646 | span.eqno {
647 | float: right;
648 | }
649 |
650 | span.eqno a.headerlink {
651 | position: relative;
652 | left: 0px;
653 | z-index: 1;
654 | }
655 |
656 | div.math:hover a.headerlink {
657 | visibility: visible;
658 | }
659 |
660 | /* -- printout stylesheet --------------------------------------------------- */
661 |
662 | @media print {
663 | div.document,
664 | div.documentwrapper,
665 | div.bodywrapper {
666 | margin: 0 !important;
667 | width: 100%;
668 | }
669 |
670 | div.sphinxsidebar,
671 | div.related,
672 | div.footer,
673 | #top-link {
674 | display: none;
675 | }
676 | }
--------------------------------------------------------------------------------
/docs/_build/html/_static/alabaster.css:
--------------------------------------------------------------------------------
1 | @import url("basic.css");
2 |
3 | /* -- page layout ----------------------------------------------------------- */
4 |
5 | body {
6 | font-family: Georgia, serif;
7 | font-size: 17px;
8 | background-color: #fff;
9 | color: #000;
10 | margin: 0;
11 | padding: 0;
12 | }
13 |
14 |
15 | div.document {
16 | width: 940px;
17 | margin: 30px auto 0 auto;
18 | }
19 |
20 | div.documentwrapper {
21 | float: left;
22 | width: 100%;
23 | }
24 |
25 | div.bodywrapper {
26 | margin: 0 0 0 220px;
27 | }
28 |
29 | div.sphinxsidebar {
30 | width: 220px;
31 | font-size: 14px;
32 | line-height: 1.5;
33 | }
34 |
35 | hr {
36 | border: 1px solid #B1B4B6;
37 | }
38 |
39 | div.body {
40 | background-color: #fff;
41 | color: #3E4349;
42 | padding: 0 30px 0 30px;
43 | }
44 |
45 | div.body > .section {
46 | text-align: left;
47 | }
48 |
49 | div.footer {
50 | width: 940px;
51 | margin: 20px auto 30px auto;
52 | font-size: 14px;
53 | color: #888;
54 | text-align: right;
55 | }
56 |
57 | div.footer a {
58 | color: #888;
59 | }
60 |
61 | p.caption {
62 | font-family: inherit;
63 | font-size: inherit;
64 | }
65 |
66 |
67 | div.relations {
68 | display: none;
69 | }
70 |
71 |
72 | div.sphinxsidebar a {
73 | color: #444;
74 | text-decoration: none;
75 | border-bottom: 1px dotted #999;
76 | }
77 |
78 | div.sphinxsidebar a:hover {
79 | border-bottom: 1px solid #999;
80 | }
81 |
82 | div.sphinxsidebarwrapper {
83 | padding: 18px 10px;
84 | }
85 |
86 | div.sphinxsidebarwrapper p.logo {
87 | padding: 0;
88 | margin: -10px 0 0 0px;
89 | text-align: center;
90 | }
91 |
92 | div.sphinxsidebarwrapper h1.logo {
93 | margin-top: -10px;
94 | text-align: center;
95 | margin-bottom: 5px;
96 | text-align: left;
97 | }
98 |
99 | div.sphinxsidebarwrapper h1.logo-name {
100 | margin-top: 0px;
101 | }
102 |
103 | div.sphinxsidebarwrapper p.blurb {
104 | margin-top: 0;
105 | font-style: normal;
106 | }
107 |
108 | div.sphinxsidebar h3,
109 | div.sphinxsidebar h4 {
110 | font-family: Georgia, serif;
111 | color: #444;
112 | font-size: 24px;
113 | font-weight: normal;
114 | margin: 0 0 5px 0;
115 | padding: 0;
116 | }
117 |
118 | div.sphinxsidebar h4 {
119 | font-size: 20px;
120 | }
121 |
122 | div.sphinxsidebar h3 a {
123 | color: #444;
124 | }
125 |
126 | div.sphinxsidebar p.logo a,
127 | div.sphinxsidebar h3 a,
128 | div.sphinxsidebar p.logo a:hover,
129 | div.sphinxsidebar h3 a:hover {
130 | border: none;
131 | }
132 |
133 | div.sphinxsidebar p {
134 | color: #555;
135 | margin: 10px 0;
136 | }
137 |
138 | div.sphinxsidebar ul {
139 | margin: 10px 0;
140 | padding: 0;
141 | color: #000;
142 | }
143 |
144 | div.sphinxsidebar ul li.toctree-l1 > a {
145 | font-size: 120%;
146 | }
147 |
148 | div.sphinxsidebar ul li.toctree-l2 > a {
149 | font-size: 110%;
150 | }
151 |
152 | div.sphinxsidebar input {
153 | border: 1px solid #CCC;
154 | font-family: Georgia, serif;
155 | font-size: 1em;
156 | }
157 |
158 | div.sphinxsidebar hr {
159 | border: none;
160 | height: 1px;
161 | color: #AAA;
162 | background: #AAA;
163 |
164 | text-align: left;
165 | margin-left: 0;
166 | width: 50%;
167 | }
168 |
169 | div.sphinxsidebar .badge {
170 | border-bottom: none;
171 | }
172 |
173 | div.sphinxsidebar .badge:hover {
174 | border-bottom: none;
175 | }
176 |
177 | /* To address an issue with donation coming after search */
178 | div.sphinxsidebar h3.donation {
179 | margin-top: 10px;
180 | }
181 |
182 | /* -- body styles ----------------------------------------------------------- */
183 |
184 | a {
185 | color: #004B6B;
186 | text-decoration: underline;
187 | }
188 |
189 | a:hover {
190 | color: #6D4100;
191 | text-decoration: underline;
192 | }
193 |
194 | div.body h1,
195 | div.body h2,
196 | div.body h3,
197 | div.body h4,
198 | div.body h5,
199 | div.body h6 {
200 | font-family: Georgia, serif;
201 | font-weight: normal;
202 | margin: 30px 0px 10px 0px;
203 | padding: 0;
204 | }
205 |
206 | div.body h1 { margin-top: 0; padding-top: 0; font-size: 240%; }
207 | div.body h2 { font-size: 180%; }
208 | div.body h3 { font-size: 150%; }
209 | div.body h4 { font-size: 130%; }
210 | div.body h5 { font-size: 100%; }
211 | div.body h6 { font-size: 100%; }
212 |
213 | a.headerlink {
214 | color: #DDD;
215 | padding: 0 4px;
216 | text-decoration: none;
217 | }
218 |
219 | a.headerlink:hover {
220 | color: #444;
221 | background: #EAEAEA;
222 | }
223 |
224 | div.body p, div.body dd, div.body li {
225 | line-height: 1.4em;
226 | }
227 |
228 | div.admonition {
229 | margin: 20px 0px;
230 | padding: 10px 30px;
231 | background-color: #EEE;
232 | border: 1px solid #CCC;
233 | }
234 |
235 | div.admonition tt.xref, div.admonition code.xref, div.admonition a tt {
236 | background-color: #FBFBFB;
237 | border-bottom: 1px solid #fafafa;
238 | }
239 |
240 | div.admonition p.admonition-title {
241 | font-family: Georgia, serif;
242 | font-weight: normal;
243 | font-size: 24px;
244 | margin: 0 0 10px 0;
245 | padding: 0;
246 | line-height: 1;
247 | }
248 |
249 | div.admonition p.last {
250 | margin-bottom: 0;
251 | }
252 |
253 | div.highlight {
254 | background-color: #fff;
255 | }
256 |
257 | dt:target, .highlight {
258 | background: #FAF3E8;
259 | }
260 |
261 | div.warning {
262 | background-color: #FCC;
263 | border: 1px solid #FAA;
264 | }
265 |
266 | div.danger {
267 | background-color: #FCC;
268 | border: 1px solid #FAA;
269 | -moz-box-shadow: 2px 2px 4px #D52C2C;
270 | -webkit-box-shadow: 2px 2px 4px #D52C2C;
271 | box-shadow: 2px 2px 4px #D52C2C;
272 | }
273 |
274 | div.error {
275 | background-color: #FCC;
276 | border: 1px solid #FAA;
277 | -moz-box-shadow: 2px 2px 4px #D52C2C;
278 | -webkit-box-shadow: 2px 2px 4px #D52C2C;
279 | box-shadow: 2px 2px 4px #D52C2C;
280 | }
281 |
282 | div.caution {
283 | background-color: #FCC;
284 | border: 1px solid #FAA;
285 | }
286 |
287 | div.attention {
288 | background-color: #FCC;
289 | border: 1px solid #FAA;
290 | }
291 |
292 | div.important {
293 | background-color: #EEE;
294 | border: 1px solid #CCC;
295 | }
296 |
297 | div.note {
298 | background-color: #EEE;
299 | border: 1px solid #CCC;
300 | }
301 |
302 | div.tip {
303 | background-color: #EEE;
304 | border: 1px solid #CCC;
305 | }
306 |
307 | div.hint {
308 | background-color: #EEE;
309 | border: 1px solid #CCC;
310 | }
311 |
312 | div.seealso {
313 | background-color: #EEE;
314 | border: 1px solid #CCC;
315 | }
316 |
317 | div.topic {
318 | background-color: #EEE;
319 | }
320 |
321 | p.admonition-title {
322 | display: inline;
323 | }
324 |
325 | p.admonition-title:after {
326 | content: ":";
327 | }
328 |
329 | pre, tt, code {
330 | font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
331 | font-size: 0.9em;
332 | }
333 |
334 | .hll {
335 | background-color: #FFC;
336 | margin: 0 -12px;
337 | padding: 0 12px;
338 | display: block;
339 | }
340 |
341 | img.screenshot {
342 | }
343 |
344 | tt.descname, tt.descclassname, code.descname, code.descclassname {
345 | font-size: 0.95em;
346 | }
347 |
348 | tt.descname, code.descname {
349 | padding-right: 0.08em;
350 | }
351 |
352 | img.screenshot {
353 | -moz-box-shadow: 2px 2px 4px #EEE;
354 | -webkit-box-shadow: 2px 2px 4px #EEE;
355 | box-shadow: 2px 2px 4px #EEE;
356 | }
357 |
358 | table.docutils {
359 | border: 1px solid #888;
360 | -moz-box-shadow: 2px 2px 4px #EEE;
361 | -webkit-box-shadow: 2px 2px 4px #EEE;
362 | box-shadow: 2px 2px 4px #EEE;
363 | }
364 |
365 | table.docutils td, table.docutils th {
366 | border: 1px solid #888;
367 | padding: 0.25em 0.7em;
368 | }
369 |
370 | table.field-list, table.footnote {
371 | border: none;
372 | -moz-box-shadow: none;
373 | -webkit-box-shadow: none;
374 | box-shadow: none;
375 | }
376 |
377 | table.footnote {
378 | margin: 15px 0;
379 | width: 100%;
380 | border: 1px solid #EEE;
381 | background: #FDFDFD;
382 | font-size: 0.9em;
383 | }
384 |
385 | table.footnote + table.footnote {
386 | margin-top: -15px;
387 | border-top: none;
388 | }
389 |
390 | table.field-list th {
391 | padding: 0 0.8em 0 0;
392 | }
393 |
394 | table.field-list td {
395 | padding: 0;
396 | }
397 |
398 | table.field-list p {
399 | margin-bottom: 0.8em;
400 | }
401 |
402 | /* Cloned from
403 | * https://github.com/sphinx-doc/sphinx/commit/ef60dbfce09286b20b7385333d63a60321784e68
404 | */
405 | .field-name {
406 | -moz-hyphens: manual;
407 | -ms-hyphens: manual;
408 | -webkit-hyphens: manual;
409 | hyphens: manual;
410 | }
411 |
412 | table.footnote td.label {
413 | width: .1px;
414 | padding: 0.3em 0 0.3em 0.5em;
415 | }
416 |
417 | table.footnote td {
418 | padding: 0.3em 0.5em;
419 | }
420 |
421 | dl {
422 | margin: 0;
423 | padding: 0;
424 | }
425 |
426 | dl dd {
427 | margin-left: 30px;
428 | }
429 |
430 | blockquote {
431 | margin: 0 0 0 30px;
432 | padding: 0;
433 | }
434 |
435 | ul, ol {
436 | /* Matches the 30px from the narrow-screen "li > ul" selector below */
437 | margin: 10px 0 10px 30px;
438 | padding: 0;
439 | }
440 |
441 | pre {
442 | background: #EEE;
443 | padding: 7px 30px;
444 | margin: 15px 0px;
445 | line-height: 1.3em;
446 | }
447 |
448 | div.viewcode-block:target {
449 | background: #ffd;
450 | }
451 |
452 | dl pre, blockquote pre, li pre {
453 | margin-left: 0;
454 | padding-left: 30px;
455 | }
456 |
457 | tt, code {
458 | background-color: #ecf0f3;
459 | color: #222;
460 | /* padding: 1px 2px; */
461 | }
462 |
463 | tt.xref, code.xref, a tt {
464 | background-color: #FBFBFB;
465 | border-bottom: 1px solid #fff;
466 | }
467 |
468 | a.reference {
469 | text-decoration: none;
470 | border-bottom: 1px dotted #004B6B;
471 | }
472 |
473 | /* Don't put an underline on images */
474 | a.image-reference, a.image-reference:hover {
475 | border-bottom: none;
476 | }
477 |
478 | a.reference:hover {
479 | border-bottom: 1px solid #6D4100;
480 | }
481 |
482 | a.footnote-reference {
483 | text-decoration: none;
484 | font-size: 0.7em;
485 | vertical-align: top;
486 | border-bottom: 1px dotted #004B6B;
487 | }
488 |
489 | a.footnote-reference:hover {
490 | border-bottom: 1px solid #6D4100;
491 | }
492 |
493 | a:hover tt, a:hover code {
494 | background: #EEE;
495 | }
496 |
497 |
498 | @media screen and (max-width: 870px) {
499 |
500 | div.sphinxsidebar {
501 | display: none;
502 | }
503 |
504 | div.document {
505 | width: 100%;
506 |
507 | }
508 |
509 | div.documentwrapper {
510 | margin-left: 0;
511 | margin-top: 0;
512 | margin-right: 0;
513 | margin-bottom: 0;
514 | }
515 |
516 | div.bodywrapper {
517 | margin-top: 0;
518 | margin-right: 0;
519 | margin-bottom: 0;
520 | margin-left: 0;
521 | }
522 |
523 | ul {
524 | margin-left: 0;
525 | }
526 |
527 | li > ul {
528 | /* Matches the 30px from the "ul, ol" selector above */
529 | margin-left: 30px;
530 | }
531 |
532 | .document {
533 | width: auto;
534 | }
535 |
536 | .footer {
537 | width: auto;
538 | }
539 |
540 | .bodywrapper {
541 | margin: 0;
542 | }
543 |
544 | .footer {
545 | width: auto;
546 | }
547 |
548 | .github {
549 | display: none;
550 | }
551 |
552 |
553 |
554 | }
555 |
556 |
557 |
558 | @media screen and (max-width: 875px) {
559 |
560 | body {
561 | margin: 0;
562 | padding: 20px 30px;
563 | }
564 |
565 | div.documentwrapper {
566 | float: none;
567 | background: #fff;
568 | }
569 |
570 | div.sphinxsidebar {
571 | display: block;
572 | float: none;
573 | width: 102.5%;
574 | margin: 50px -30px -20px -30px;
575 | padding: 10px 20px;
576 | background: #333;
577 | color: #FFF;
578 | }
579 |
580 | div.sphinxsidebar h3, div.sphinxsidebar h4, div.sphinxsidebar p,
581 | div.sphinxsidebar h3 a {
582 | color: #fff;
583 | }
584 |
585 | div.sphinxsidebar a {
586 | color: #AAA;
587 | }
588 |
589 | div.sphinxsidebar p.logo {
590 | display: none;
591 | }
592 |
593 | div.document {
594 | width: 100%;
595 | margin: 0;
596 | }
597 |
598 | div.footer {
599 | display: none;
600 | }
601 |
602 | div.bodywrapper {
603 | margin: 0;
604 | }
605 |
606 | div.body {
607 | min-height: 0;
608 | padding: 0;
609 | }
610 |
611 | .rtd_doc_footer {
612 | display: none;
613 | }
614 |
615 | .document {
616 | width: auto;
617 | }
618 |
619 | .footer {
620 | width: auto;
621 | }
622 |
623 | .footer {
624 | width: auto;
625 | }
626 |
627 | .github {
628 | display: none;
629 | }
630 | }
631 |
632 |
633 | /* misc. */
634 |
635 | .revsys-inline {
636 | display: none!important;
637 | }
638 |
639 | /* Make nested-list/multi-paragraph items look better in Releases changelog
640 | * pages. Without this, docutils' magical list fuckery causes inconsistent
641 | * formatting between different release sub-lists.
642 | */
643 | div#changelog > div.section > ul > li > p:only-child {
644 | margin-bottom: 0;
645 | }
646 |
647 | /* Hide fugly table cell borders in ..bibliography:: directive output */
648 | table.docutils.citation, table.docutils.citation td, table.docutils.citation th {
649 | border: none;
650 | /* Below needed in some edge cases; if not applied, bottom shadows appear */
651 | -moz-box-shadow: none;
652 | -webkit-box-shadow: none;
653 | box-shadow: none;
654 | }
655 |
656 |
657 | /* relbar */
658 |
659 | .related {
660 | line-height: 30px;
661 | width: 100%;
662 | font-size: 0.9rem;
663 | }
664 |
665 | .related.top {
666 | border-bottom: 1px solid #EEE;
667 | margin-bottom: 20px;
668 | }
669 |
670 | .related.bottom {
671 | border-top: 1px solid #EEE;
672 | }
673 |
674 | .related ul {
675 | padding: 0;
676 | margin: 0;
677 | list-style: none;
678 | }
679 |
680 | .related li {
681 | display: inline;
682 | }
683 |
684 | nav#rellinks {
685 | float: right;
686 | }
687 |
688 | nav#rellinks li+li:before {
689 | content: "|";
690 | }
691 |
692 | nav#breadcrumbs li+li:before {
693 | content: "\00BB";
694 | }
695 |
696 | /* Hide certain items when printing */
697 | @media print {
698 | div.related {
699 | display: none;
700 | }
701 | }
--------------------------------------------------------------------------------
/docs/_build/html/_static/searchtools.js:
--------------------------------------------------------------------------------
1 | /*
2 | * searchtools.js
3 | * ~~~~~~~~~~~~~~~~
4 | *
5 | * Sphinx JavaScript utilities for the full-text search.
6 | *
7 | * :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
8 | * :license: BSD, see LICENSE for details.
9 | *
10 | */
11 |
12 | if (!Scorer) {
13 | /**
14 | * Simple result scoring code.
15 | */
16 | var Scorer = {
17 | // Implement the following function to further tweak the score for each result
18 | // The function takes a result array [filename, title, anchor, descr, score]
19 | // and returns the new score.
20 | /*
21 | score: function(result) {
22 | return result[4];
23 | },
24 | */
25 |
26 | // query matches the full name of an object
27 | objNameMatch: 11,
28 | // or matches in the last dotted part of the object name
29 | objPartialMatch: 6,
30 | // Additive scores depending on the priority of the object
31 | objPrio: {0: 15, // used to be importantResults
32 | 1: 5, // used to be objectResults
33 | 2: -5}, // used to be unimportantResults
34 | // Used when the priority is not in the mapping.
35 | objPrioDefault: 0,
36 |
37 | // query found in title
38 | title: 15,
39 | // query found in terms
40 | term: 5
41 | };
42 | }
43 |
44 | if (!splitQuery) {
45 | function splitQuery(query) {
46 | return query.split(/\s+/);
47 | }
48 | }
49 |
50 | /**
51 | * Search Module
52 | */
53 | var Search = {
54 |
55 | _index : null,
56 | _queued_query : null,
57 | _pulse_status : -1,
58 |
59 | init : function() {
60 | var params = $.getQueryParameters();
61 | if (params.q) {
62 | var query = params.q[0];
63 | $('input[name="q"]')[0].value = query;
64 | this.performSearch(query);
65 | }
66 | },
67 |
68 | loadIndex : function(url) {
69 | $.ajax({type: "GET", url: url, data: null,
70 | dataType: "script", cache: true,
71 | complete: function(jqxhr, textstatus) {
72 | if (textstatus != "success") {
73 | document.getElementById("searchindexloader").src = url;
74 | }
75 | }});
76 | },
77 |
78 | setIndex : function(index) {
79 | var q;
80 | this._index = index;
81 | if ((q = this._queued_query) !== null) {
82 | this._queued_query = null;
83 | Search.query(q);
84 | }
85 | },
86 |
87 | hasIndex : function() {
88 | return this._index !== null;
89 | },
90 |
91 | deferQuery : function(query) {
92 | this._queued_query = query;
93 | },
94 |
95 | stopPulse : function() {
96 | this._pulse_status = 0;
97 | },
98 |
99 | startPulse : function() {
100 | if (this._pulse_status >= 0)
101 | return;
102 | function pulse() {
103 | var i;
104 | Search._pulse_status = (Search._pulse_status + 1) % 4;
105 | var dotString = '';
106 | for (i = 0; i < Search._pulse_status; i++)
107 | dotString += '.';
108 | Search.dots.text(dotString);
109 | if (Search._pulse_status > -1)
110 | window.setTimeout(pulse, 500);
111 | }
112 | pulse();
113 | },
114 |
115 | /**
116 | * perform a search for something (or wait until index is loaded)
117 | */
118 | performSearch : function(query) {
119 | // create the required interface elements
120 | this.out = $('#search-results');
121 | this.title = $('' + _('Searching') + ' ').appendTo(this.out);
122 | this.dots = $(' ').appendTo(this.title);
123 | this.status = $('
').appendTo(this.out);
124 | this.output = $('').appendTo(this.out);
125 |
126 | $('#search-progress').text(_('Preparing search...'));
127 | this.startPulse();
128 |
129 | // index already loaded, the browser was quick!
130 | if (this.hasIndex())
131 | this.query(query);
132 | else
133 | this.deferQuery(query);
134 | },
135 |
136 | /**
137 | * execute search (requires search index to be loaded)
138 | */
139 | query : function(query) {
140 | var i;
141 | var stopwords = DOCUMENTATION_OPTIONS.SEARCH_LANGUAGE_STOP_WORDS;
142 |
143 | // stem the searchterms and add them to the correct list
144 | var stemmer = new Stemmer();
145 | var searchterms = [];
146 | var excluded = [];
147 | var hlterms = [];
148 | var tmp = splitQuery(query);
149 | var objectterms = [];
150 | for (i = 0; i < tmp.length; i++) {
151 | if (tmp[i] !== "") {
152 | objectterms.push(tmp[i].toLowerCase());
153 | }
154 |
155 | if ($u.indexOf(stopwords, tmp[i].toLowerCase()) != -1 || tmp[i].match(/^\d+$/) ||
156 | tmp[i] === "") {
157 | // skip this "word"
158 | continue;
159 | }
160 | // stem the word
161 | var word = stemmer.stemWord(tmp[i].toLowerCase());
162 | // prevent stemmer from cutting word smaller than two chars
163 | if(word.length < 3 && tmp[i].length >= 3) {
164 | word = tmp[i];
165 | }
166 | var toAppend;
167 | // select the correct list
168 | if (word[0] == '-') {
169 | toAppend = excluded;
170 | word = word.substr(1);
171 | }
172 | else {
173 | toAppend = searchterms;
174 | hlterms.push(tmp[i].toLowerCase());
175 | }
176 | // only add if not already in the list
177 | if (!$u.contains(toAppend, word))
178 | toAppend.push(word);
179 | }
180 | var highlightstring = '?highlight=' + $.urlencode(hlterms.join(" "));
181 |
182 | // console.debug('SEARCH: searching for:');
183 | // console.info('required: ', searchterms);
184 | // console.info('excluded: ', excluded);
185 |
186 | // prepare search
187 | var terms = this._index.terms;
188 | var titleterms = this._index.titleterms;
189 |
190 | // array of [filename, title, anchor, descr, score]
191 | var results = [];
192 | $('#search-progress').empty();
193 |
194 | // lookup as object
195 | for (i = 0; i < objectterms.length; i++) {
196 | var others = [].concat(objectterms.slice(0, i),
197 | objectterms.slice(i+1, objectterms.length));
198 | results = results.concat(this.performObjectSearch(objectterms[i], others));
199 | }
200 |
201 | // lookup as search terms in fulltext
202 | results = results.concat(this.performTermsSearch(searchterms, excluded, terms, titleterms));
203 |
204 | // let the scorer override scores with a custom scoring function
205 | if (Scorer.score) {
206 | for (i = 0; i < results.length; i++)
207 | results[i][4] = Scorer.score(results[i]);
208 | }
209 |
210 | // now sort the results by score (in opposite order of appearance, since the
211 | // display function below uses pop() to retrieve items) and then
212 | // alphabetically
213 | results.sort(function(a, b) {
214 | var left = a[4];
215 | var right = b[4];
216 | if (left > right) {
217 | return 1;
218 | } else if (left < right) {
219 | return -1;
220 | } else {
221 | // same score: sort alphabetically
222 | left = a[1].toLowerCase();
223 | right = b[1].toLowerCase();
224 | return (left > right) ? -1 : ((left < right) ? 1 : 0);
225 | }
226 | });
227 |
228 | // for debugging
229 | //Search.lastresults = results.slice(); // a copy
230 | //console.info('search results:', Search.lastresults);
231 |
232 | // print the results
233 | var resultCount = results.length;
234 | function displayNextItem() {
235 | // results left, load the summary and display it
236 | if (results.length) {
237 | var item = results.pop();
238 | var listItem = $(' ');
239 | if (DOCUMENTATION_OPTIONS.FILE_SUFFIX === '') {
240 | // dirhtml builder
241 | var dirname = item[0] + '/';
242 | if (dirname.match(/\/index\/$/)) {
243 | dirname = dirname.substring(0, dirname.length-6);
244 | } else if (dirname == 'index/') {
245 | dirname = '';
246 | }
247 | listItem.append($(' ').attr('href',
248 | DOCUMENTATION_OPTIONS.URL_ROOT + dirname +
249 | highlightstring + item[2]).html(item[1]));
250 | } else {
251 | // normal html builders
252 | listItem.append($(' ').attr('href',
253 | item[0] + DOCUMENTATION_OPTIONS.FILE_SUFFIX +
254 | highlightstring + item[2]).html(item[1]));
255 | }
256 | if (item[3]) {
257 | listItem.append($(' (' + item[3] + ') '));
258 | Search.output.append(listItem);
259 | listItem.slideDown(5, function() {
260 | displayNextItem();
261 | });
262 | } else if (DOCUMENTATION_OPTIONS.HAS_SOURCE) {
263 | var suffix = DOCUMENTATION_OPTIONS.SOURCELINK_SUFFIX;
264 | if (suffix === undefined) {
265 | suffix = '.txt';
266 | }
267 | $.ajax({url: DOCUMENTATION_OPTIONS.URL_ROOT + '_sources/' + item[5] + (item[5].slice(-suffix.length) === suffix ? '' : suffix),
268 | dataType: "text",
269 | complete: function(jqxhr, textstatus) {
270 | var data = jqxhr.responseText;
271 | if (data !== '' && data !== undefined) {
272 | listItem.append(Search.makeSearchSummary(data, searchterms, hlterms));
273 | }
274 | Search.output.append(listItem);
275 | listItem.slideDown(5, function() {
276 | displayNextItem();
277 | });
278 | }});
279 | } else {
280 | // no source available, just display title
281 | Search.output.append(listItem);
282 | listItem.slideDown(5, function() {
283 | displayNextItem();
284 | });
285 | }
286 | }
287 | // search finished, update title and status message
288 | else {
289 | Search.stopPulse();
290 | Search.title.text(_('Search Results'));
291 | if (!resultCount)
292 | Search.status.text(_('Your search did not match any documents. Please make sure that all words are spelled correctly and that you\'ve selected enough categories.'));
293 | else
294 | Search.status.text(_('Search finished, found %s page(s) matching the search query.').replace('%s', resultCount));
295 | Search.status.fadeIn(500);
296 | }
297 | }
298 | displayNextItem();
299 | },
300 |
301 | /**
302 | * search for object names
303 | */
304 | performObjectSearch : function(object, otherterms) {
305 | var filenames = this._index.filenames;
306 | var docnames = this._index.docnames;
307 | var objects = this._index.objects;
308 | var objnames = this._index.objnames;
309 | var titles = this._index.titles;
310 |
311 | var i;
312 | var results = [];
313 |
314 | for (var prefix in objects) {
315 | for (var name in objects[prefix]) {
316 | var fullname = (prefix ? prefix + '.' : '') + name;
317 | if (fullname.toLowerCase().indexOf(object) > -1) {
318 | var score = 0;
319 | var parts = fullname.split('.');
320 | // check for different match types: exact matches of full name or
321 | // "last name" (i.e. last dotted part)
322 | if (fullname == object || parts[parts.length - 1] == object) {
323 | score += Scorer.objNameMatch;
324 | // matches in last name
325 | } else if (parts[parts.length - 1].indexOf(object) > -1) {
326 | score += Scorer.objPartialMatch;
327 | }
328 | var match = objects[prefix][name];
329 | var objname = objnames[match[1]][2];
330 | var title = titles[match[0]];
331 | // If more than one term searched for, we require other words to be
332 | // found in the name/title/description
333 | if (otherterms.length > 0) {
334 | var haystack = (prefix + ' ' + name + ' ' +
335 | objname + ' ' + title).toLowerCase();
336 | var allfound = true;
337 | for (i = 0; i < otherterms.length; i++) {
338 | if (haystack.indexOf(otherterms[i]) == -1) {
339 | allfound = false;
340 | break;
341 | }
342 | }
343 | if (!allfound) {
344 | continue;
345 | }
346 | }
347 | var descr = objname + _(', in ') + title;
348 |
349 | var anchor = match[3];
350 | if (anchor === '')
351 | anchor = fullname;
352 | else if (anchor == '-')
353 | anchor = objnames[match[1]][1] + '-' + fullname;
354 | // add custom score for some objects according to scorer
355 | if (Scorer.objPrio.hasOwnProperty(match[2])) {
356 | score += Scorer.objPrio[match[2]];
357 | } else {
358 | score += Scorer.objPrioDefault;
359 | }
360 | results.push([docnames[match[0]], fullname, '#'+anchor, descr, score, filenames[match[0]]]);
361 | }
362 | }
363 | }
364 |
365 | return results;
366 | },
367 |
368 | /**
369 | * search for full-text terms in the index
370 | */
371 | performTermsSearch : function(searchterms, excluded, terms, titleterms) {
372 | var docnames = this._index.docnames;
373 | var filenames = this._index.filenames;
374 | var titles = this._index.titles;
375 |
376 | var i, j, file;
377 | var fileMap = {};
378 | var scoreMap = {};
379 | var results = [];
380 |
381 | // perform the search on the required terms
382 | for (i = 0; i < searchterms.length; i++) {
383 | var word = searchterms[i];
384 | var files = [];
385 | var _o = [
386 | {files: terms[word], score: Scorer.term},
387 | {files: titleterms[word], score: Scorer.title}
388 | ];
389 |
390 | // no match but word was a required one
391 | if ($u.every(_o, function(o){return o.files === undefined;})) {
392 | break;
393 | }
394 | // found search word in contents
395 | $u.each(_o, function(o) {
396 | var _files = o.files;
397 | if (_files === undefined)
398 | return
399 |
400 | if (_files.length === undefined)
401 | _files = [_files];
402 | files = files.concat(_files);
403 |
404 | // set score for the word in each file to Scorer.term
405 | for (j = 0; j < _files.length; j++) {
406 | file = _files[j];
407 | if (!(file in scoreMap))
408 | scoreMap[file] = {}
409 | scoreMap[file][word] = o.score;
410 | }
411 | });
412 |
413 | // create the mapping
414 | for (j = 0; j < files.length; j++) {
415 | file = files[j];
416 | if (file in fileMap)
417 | fileMap[file].push(word);
418 | else
419 | fileMap[file] = [word];
420 | }
421 | }
422 |
423 | // now check if the files don't contain excluded terms
424 | for (file in fileMap) {
425 | var valid = true;
426 |
427 | // check if all requirements are matched
428 | if (fileMap[file].length != searchterms.length)
429 | continue;
430 |
431 | // ensure that none of the excluded terms is in the search result
432 | for (i = 0; i < excluded.length; i++) {
433 | if (terms[excluded[i]] == file ||
434 | titleterms[excluded[i]] == file ||
435 | $u.contains(terms[excluded[i]] || [], file) ||
436 | $u.contains(titleterms[excluded[i]] || [], file)) {
437 | valid = false;
438 | break;
439 | }
440 | }
441 |
442 | // if we have still a valid result we can add it to the result list
443 | if (valid) {
444 | // select one (max) score for the file.
445 | // for better ranking, we should calculate ranking by using words statistics like basic tf-idf...
446 | var score = $u.max($u.map(fileMap[file], function(w){return scoreMap[file][w]}));
447 | results.push([docnames[file], titles[file], '', null, score, filenames[file]]);
448 | }
449 | }
450 | return results;
451 | },
452 |
453 | /**
454 | * helper function to return a node containing the
455 | * search summary for a given text. keywords is a list
456 | * of stemmed words, hlwords is the list of normal, unstemmed
457 | * words. the first one is used to find the occurrence, the
458 | * latter for highlighting it.
459 | */
460 | makeSearchSummary : function(text, keywords, hlwords) {
461 | var textLower = text.toLowerCase();
462 | var start = 0;
463 | $.each(keywords, function() {
464 | var i = textLower.indexOf(this.toLowerCase());
465 | if (i > -1)
466 | start = i;
467 | });
468 | start = Math.max(start - 120, 0);
469 | var excerpt = ((start > 0) ? '...' : '') +
470 | $.trim(text.substr(start, 240)) +
471 | ((start + 240 - text.length) ? '...' : '');
472 | var rv = $('
').text(excerpt);
473 | $.each(hlwords, function() {
474 | rv = rv.highlightText(this, 'highlighted');
475 | });
476 | return rv;
477 | }
478 | };
479 |
480 | $(document).ready(function() {
481 | Search.init();
482 | });
483 |
--------------------------------------------------------------------------------
/docs/_build/html/quick_intro.html:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 | Quick introduction — wsipre 0.1.2 documentation
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
25 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
Quick introduction
52 |
wsipre has two main modules (see Module Index for docs):
53 |
54 |
55 | slide : load and process WSIs
56 | show : visualize images generated using slide
57 |
58 |
59 |
The following quick intro illustrates basic usage of these modules. First, load
60 | packages (Matplotlib is only used here to plot images with no annotation).
61 |
>>> from matplotlib import pyplot as plt
62 | >>> from wsipre import slide , show
63 |
64 |
65 |
Load WSI form the CAMELYON challenge with its region-level tumor annotation.
66 |
>>> wsi = slide . Slide ( filename = 'patient_012_node_0.tif' ,
67 | ... annotation_filename = 'patient_012_node_0.xml' ,
68 | ... xml_style = 'asap' )
69 |
70 |
71 |
Generate and show a thumbnail.
72 |
>>> thumbnail , mask , downsampling_factor = wsi . get_thumbnail_with_annotation (
73 | ... size = ( 3000 , 3000 ), polygon_type = 'line' , line_thickness = 8 )
74 |
75 | >>> black = ( 0 , 0 , 0 )
76 | >>> red = ( 1 , 0 , 0 )
77 | >>> yellow = ( 1 , 1 , 0 )
78 | >>> colors = { 0 : black , 1 : black , 2 : red }
79 |
80 | >>> fig = show . Figure ( image = thumbnail , annotation = mask , color_map = colors )
81 | >>> fig . show_image_with_annotation ( split = False )
82 |
83 |
84 |
85 |
Zoom in and read a smaller region from the WSI.
86 |
>>> loc = ( int ( 150 * downsampling_factor ), int ( 1450 * downsampling_factor ))
87 |
88 | >>> slide_region , mask_region = wsi . read_region_with_annotation (
89 | ... location = loc , level = 2 , size = ( 1000 , 1000 ), polygon_type = 'line' ,
90 | ... line_thickness = 20 )
91 |
92 | >>> fig = show . Figure (
93 | ... image = slide_region , annotation = mask_region , color_map = colors )
94 | >>> fig . show_image_with_annotation ( split = False )
95 |
96 |
97 |
98 |
Locate tissue regions in the WSI automatically.
99 |
>>> wsi . get_tissue_mask ( polygon_type = 'line' , line_thickness = 15 )
100 | Slide('patient_012_node_0.tif')
101 |
102 | >>> fig = show . Figure ( image = wsi . downsampled_slide ,
103 | ... annotation = wsi . tissue_mask ,
104 | ... color_map = { 0 : black , 1 : yellow })
105 | >>> fig . show_image_with_annotation ( split = False )
106 |
107 |
108 |
109 |
Sample a random patch from tissue regions.
110 |
>>> tissue_patch = wsi . read_random_tissue_patch ( level = 2 , size = ( 224 , 224 ),
111 | ... avoid_labels = [ 2 ])
112 | >>> plt . imshow ( tissue_patch )
113 | >>> plt . show ()
114 |
115 |
116 |
117 |
Sample a random patch from regions annotated as tumor (label 2).
118 |
>>> slide_region , mask_region = wsi . read_random_patch (
119 | ... level = 2 , size = ( 299 , 299 ), target_class = 2 ,
120 | ... min_class_area_ratio = 0.75 , polygon_type = 'area' )
121 |
122 | >>> fig = show . Figure ( slide_region , mask_region , { 0 : black , 2 : red })
123 |
124 | >>> fig . show_image_with_annotation ( split = True )
125 |
126 |
127 |
128 |
Double check the mapping between class label and color.
129 |
>>> fig . show_label_colors ()
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
156 |
157 |
158 |
177 |
184 |
185 |
186 |
187 |
--------------------------------------------------------------------------------