├── docs
├── .nojekyll
├── build
│ ├── html
│ │ ├── .nojekyll
│ │ ├── _static
│ │ │ ├── custom.css
│ │ │ ├── up.png
│ │ │ ├── down.png
│ │ │ ├── file.png
│ │ │ ├── minus.png
│ │ │ ├── plus.png
│ │ │ ├── comment.png
│ │ │ ├── ajax-loader.gif
│ │ │ ├── up-pressed.png
│ │ │ ├── comment-close.png
│ │ │ ├── down-pressed.png
│ │ │ ├── comment-bright.png
│ │ │ ├── documentation_options.js
│ │ │ ├── pygments.css
│ │ │ ├── doctools.js
│ │ │ ├── underscore.js
│ │ │ ├── basic.css
│ │ │ ├── alabaster.css
│ │ │ ├── searchtools.js
│ │ │ └── websupport.js
│ │ ├── objects.inv
│ │ ├── .buildinfo
│ │ ├── _sources
│ │ │ └── index.rst.txt
│ │ ├── searchindex.js
│ │ ├── py-modindex.html
│ │ ├── search.html
│ │ └── genindex.html
│ └── doctrees
│ │ ├── index.doctree
│ │ └── environment.pickle
├── index.html
├── source
│ ├── index.rst
│ └── conf.py
└── Makefile
├── nn_common_modules
├── __init__.py
├── bayesian_modules.py
├── octave_convolution_block.py
├── losses.py
└── modules.py
├── .gitignore
├── dist
├── nn_common_modules-1.2-py3-none-any.whl
├── nn_common_modules-1.3-py3-none-any.whl
├── nn_common_modules-1.4-py3-none-any.whl
└── nn_common_modules-1.0-py2.py3-none-any.whl
├── setup.py
├── LICENSE
└── README.md
/docs/.nojekyll:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/build/html/.nojekyll:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/nn_common_modules/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/build/html/_static/custom.css:
--------------------------------------------------------------------------------
1 | /* This file intentionally left blank. */
2 |
--------------------------------------------------------------------------------
/docs/build/html/objects.inv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ai-med/nn-common-modules/HEAD/docs/build/html/objects.inv
--------------------------------------------------------------------------------
/docs/build/html/_static/up.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ai-med/nn-common-modules/HEAD/docs/build/html/_static/up.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *ipynb_checkpoints
2 | nn_common_modules.egg-info/
3 | *__pycache__*
4 | /.idea
5 | .vscode
6 | **.DS_Store
7 | venv/
--------------------------------------------------------------------------------
/docs/build/doctrees/index.doctree:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ai-med/nn-common-modules/HEAD/docs/build/doctrees/index.doctree
--------------------------------------------------------------------------------
/docs/build/html/_static/down.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ai-med/nn-common-modules/HEAD/docs/build/html/_static/down.png
--------------------------------------------------------------------------------
/docs/build/html/_static/file.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ai-med/nn-common-modules/HEAD/docs/build/html/_static/file.png
--------------------------------------------------------------------------------
/docs/build/html/_static/minus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ai-med/nn-common-modules/HEAD/docs/build/html/_static/minus.png
--------------------------------------------------------------------------------
/docs/build/html/_static/plus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ai-med/nn-common-modules/HEAD/docs/build/html/_static/plus.png
--------------------------------------------------------------------------------
/docs/build/html/_static/comment.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ai-med/nn-common-modules/HEAD/docs/build/html/_static/comment.png
--------------------------------------------------------------------------------
/docs/build/doctrees/environment.pickle:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ai-med/nn-common-modules/HEAD/docs/build/doctrees/environment.pickle
--------------------------------------------------------------------------------
/docs/build/html/_static/ajax-loader.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ai-med/nn-common-modules/HEAD/docs/build/html/_static/ajax-loader.gif
--------------------------------------------------------------------------------
/docs/build/html/_static/up-pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ai-med/nn-common-modules/HEAD/docs/build/html/_static/up-pressed.png
--------------------------------------------------------------------------------
/docs/build/html/_static/comment-close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ai-med/nn-common-modules/HEAD/docs/build/html/_static/comment-close.png
--------------------------------------------------------------------------------
/docs/build/html/_static/down-pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ai-med/nn-common-modules/HEAD/docs/build/html/_static/down-pressed.png
--------------------------------------------------------------------------------
/dist/nn_common_modules-1.2-py3-none-any.whl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ai-med/nn-common-modules/HEAD/dist/nn_common_modules-1.2-py3-none-any.whl
--------------------------------------------------------------------------------
/dist/nn_common_modules-1.3-py3-none-any.whl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ai-med/nn-common-modules/HEAD/dist/nn_common_modules-1.3-py3-none-any.whl
--------------------------------------------------------------------------------
/dist/nn_common_modules-1.4-py3-none-any.whl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ai-med/nn-common-modules/HEAD/dist/nn_common_modules-1.4-py3-none-any.whl
--------------------------------------------------------------------------------
/docs/build/html/_static/comment-bright.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ai-med/nn-common-modules/HEAD/docs/build/html/_static/comment-bright.png
--------------------------------------------------------------------------------
/dist/nn_common_modules-1.0-py2.py3-none-any.whl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ai-med/nn-common-modules/HEAD/dist/nn_common_modules-1.0-py2.py3-none-any.whl
--------------------------------------------------------------------------------
/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: e3698302f6d2864fabf4a9702f1ddef9
4 | tags: 645f666f9bcd5a90fca523b33c5a78b7
5 |
--------------------------------------------------------------------------------
/docs/build/html/_static/documentation_options.js:
--------------------------------------------------------------------------------
1 | var DOCUMENTATION_OPTIONS = {
2 | URL_ROOT: '',
3 | VERSION: '1.0',
4 | LANGUAGE: 'None',
5 | COLLAPSE_INDEX: false,
6 | FILE_SUFFIX: '.html',
7 | HAS_SOURCE: true,
8 | SOURCELINK_SUFFIX: '.txt'
9 | };
--------------------------------------------------------------------------------
/docs/source/index.rst:
--------------------------------------------------------------------------------
1 | nn-common-modules's documentation!
2 | =============================================
3 | .. note:: Common modules, blocks and losses which can be reused in a deep neural netwok specifically for segmentation.
4 |
5 | .. toctree::
6 | :maxdepth: 2
7 | :caption: Contents:
8 |
9 | 1. Losses
10 | ==========
11 | .. automodule:: losses
12 | :members:
13 |
14 |
15 | 2. Modules
16 | ===========
17 | .. automodule:: modules
18 | :members:
19 |
--------------------------------------------------------------------------------
/docs/build/html/_sources/index.rst.txt:
--------------------------------------------------------------------------------
1 | nn-common-modules's documentation!
2 | =============================================
3 | .. note:: Common modules, blocks and losses which can be reused in a deep neural netwok specifically for segmentation.
4 |
5 | .. toctree::
6 | :maxdepth: 2
7 | :caption: Contents:
8 |
9 | 1. Losses
10 | ==========
11 | .. automodule:: losses
12 | :members:
13 |
14 |
15 | 2. Modules
16 | ===========
17 | .. automodule:: modules
18 | :members:
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 = nn-common-modules
8 | SOURCEDIR = source
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)
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | import setuptools
2 |
3 | setuptools.setup(name="nn-common-modules",
4 | version="1.4",
5 | url="https://github.com/abhi4ssj/nn-common-modules",
6 | author="Shayan Ahmad Siddiqui, Abhijit Guha Roy",
7 | author_email="shayan.siddiqui89@gmail.com",
8 | description="Common modules, blocks and losses which can be reused in a deep neural netwok specifically for segmentation",
9 | packages=setuptools.find_packages(),
10 | install_requires=['pip>=19.0.0', 'numpy>=1.14.0', 'torch>=1.0.0',
11 | 'squeeze_and_excitation @ https://github.com/ai-med/squeeze_and_excitation/releases/download/v1.0/squeeze_and_excitation-1.0-py2.py3-none-any.whl'],
12 | python_requires='>=3.5')
13 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Shayan Ahmad Siddiqui
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.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # NN Common Modules
2 |
3 | Common modules, blocks and losses which can be reused in a deep neural netwok specifically for segmentation Please use [technical documentation](https://ai-med.github.io/nn-common-modules/build/html/) for a reference to API manual
4 |
5 | This project has 3 modules
6 | * Losses (losses.py) -> It has all the loss functions defined as python classes
7 | 1. DiceLoss
8 | 2. IoULoss
9 | 3. CrossEntropyLoss2d
10 | 4. CombinedLoss
11 | 5. FocalLoss
12 |
13 | * Modules (modules.py) -> It has all the commonly used building blocks of an FCN
14 | 1. DenseBlock
15 | 2. EncoderBlock
16 | 3. DecoderBlock
17 | 4. ClassifierBlock
18 | 5. GenericBlock
19 | 6. SDNetEncoderBlock
20 | 7. SDNetDecoderBlock
21 | 8. OctaveDenseBlock
22 | 9. OctaveEncoderBlock
23 | 10. OctaveDecoderBlock
24 |
25 | * Bayesian Modules (bayesian_modules.py) -> It has all the commonly used building blocks of a Bayesian FCN
26 | 1. BayesianConvolutionBlock
27 | 2. BayesianEncoderBlock
28 | 3. BayesianDecoderBlock
29 | 4. BayesianClassifierBlock
30 |
31 | ## Getting Started
32 |
33 | ### Pre-requisites
34 |
35 | You need to have following in order for this library to work as expected
36 | 1. Python >= 3.5
37 | 2. Pytorch >= 1.0.0
38 | 3. Numpy >= 1.14.0
39 |
40 | ### Installing
41 |
42 | Always use the latest release. Use following command with appropriate version no(v1.2) in this particular case to install. You can find the link for the latest release in the release section of this github repo
43 |
44 | ```
45 | pip install https://github.com/ai-med/nn-common-modules/releases/download/v1.2/nn_common_modules-1.4-py3-none-any.whl
46 | ```
47 |
48 | ## Authors
49 |
50 | * **Shayan Ahmad Siddiqui** - [shayansiddiqui](https://github.com/shayansiddiqui)
51 | * **Jyotirmay Senapati** - [jyotirmays](https://www.linkedin.com/in/jyotirmay-senapati-30615421)
52 | * **Abhijit Guha Roy** - [abhi4ssj](https://github.com/abhi4ssj)
53 |
54 |
55 | ## Help us improve
56 | Let us know if you face any issues. You are always welcome to report new issues and bugs and also suggest further improvements. And if you like our work hit that start button on top. Enjoy :)
57 |
--------------------------------------------------------------------------------
/docs/build/html/searchindex.js:
--------------------------------------------------------------------------------
1 | Search.setIndex({docnames:["index"],envversion:53,filenames:["index.rst"],objects:{"":{losses:[0,0,0,"-"],modules:[0,0,0,"-"]},"losses.CombinedLoss":{forward:[0,2,1,""]},"losses.CrossEntropyLoss2d":{forward:[0,2,1,""]},"losses.DiceLoss":{forward:[0,2,1,""]},"losses.FocalLoss":{forward:[0,2,1,""]},"losses.IoULoss":{forward:[0,2,1,""]},"modules.ClassifierBlock":{forward:[0,2,1,""]},"modules.DecoderBlock":{forward:[0,2,1,""]},"modules.DenseBlock":{forward:[0,2,1,""]},"modules.EncoderBlock":{forward:[0,2,1,""]},"modules.GenericBlock":{forward:[0,2,1,""]},"modules.SDnetDecoderBlock":{forward:[0,2,1,""]},"modules.SDnetEncoderBlock":{forward:[0,2,1,""]},losses:{CombinedLoss:[0,1,1,""],CrossEntropyLoss2d:[0,1,1,""],DiceLoss:[0,1,1,""],FocalLoss:[0,1,1,""],IoULoss:[0,1,1,""]},modules:{ClassifierBlock:[0,1,1,""],DecoderBlock:[0,1,1,""],DenseBlock:[0,1,1,""],EncoderBlock:[0,1,1,""],GenericBlock:[0,1,1,""],SDnetDecoderBlock:[0,1,1,""],SDnetEncoderBlock:[0,1,1,""]}},objnames:{"0":["py","module","Python module"],"1":["py","class","Python class"],"2":["py","method","Python method"]},objtypes:{"0":"py:module","1":"py:class","2":"py:method"},terms:{"class":0,"default":0,"function":[],"import":0,"int":0,"return":0,"true":0,"while":[],_build:[],addit:0,additional_loss:0,additional_modul:0,afterward:[],all:[],alpha:0,although:[],ani:0,api:[],argument:[],batch:0,batchnorm:0,binar:0,binari:0,block:0,bool:0,build:0,call:[],can:0,care:[],chaneel:0,classifi:0,classifierblock:0,classs:0,combin:0,combinedloss:0,commonli:0,comput:[],connect:0,conv:0,convolut:0,cross:0,crossentropyloss2d:0,crossentropyloss:0,cse:0,csse:0,custom:0,decod:0,decoderblock:0,deep:0,defin:0,dens:0,dense_block:0,denseblock:0,depend:0,detect:0,dice:0,diceloss:0,dict:0,drop_out:0,encod:0,encoderblock:0,entropi:0,everi:[],excit:0,fals:0,few:[],floattensor:0,focal:0,focalloss:0,former:[],forward:0,from:0,gamma:0,gener:0,genericblock:0,github:[],hook:[],html:[],http:[],ignor:0,ignore_index:0,includ:0,index:0,indic:0,input:0,instanc:[],instanti:0,instead:[],iou:0,iouloss:0,kernel_c:0,kernel_h:0,kernel_w:0,last:0,latter:[],layer:0,learn:[],librari:0,logit:0,longtensor:0,loss:[],manual:[],maxpool:0,maxunpool:0,mean:0,need:[],netwok:0,network:0,neural:0,nn_common_modul:0,none:0,num_channel:0,num_class:0,num_filt:0,nxc:0,nxcxhxw:0,nxhxw:0,object:0,one:0,oper:0,option:0,out_block:0,output:0,overridden:[],packag:0,page:[],param:0,paramet:0,parent:0,part:0,particularli:0,pass:0,perform:[],pleas:[],pool:0,prelu:0,pytorch:0,recip:[],reduc:0,reduct:0,refer:[],regist:[],regress:0,relu:[],reus:0,rtype:[],run:[],sampl:0,scalar:0,sdnetdecoderblock:0,sdnetencoderblock:0,se_block:0,se_block_typ:0,search:[],segment:0,selay:0,shape:0,shayansiddiqui:[],shot:[],should:[],silent:[],sinc:[],size_averag:0,skip:0,skipconnect:0,spatial:[],specif:0,squeez:0,sse:0,standard:0,str:0,stride_conv:0,stride_pool:0,subclass:[],summari:[],take:[],target:0,technic:[],tensor:0,them:[],thi:[],tonsor:0,torch:0,tweak:[],type:0,unpool:0,usag:[],use:[],used:0,valid:0,valu:0,variabl:[],want:0,weight:0,which:0,within:[],without:0,you:0},titles:["nn-common-modules\u2019s documentation!"],titleterms:{common:0,descript:0,document:0,indic:[],loss:0,member:0,modul:0,tabl:[],usag:0,welcom:[]}})
--------------------------------------------------------------------------------
/docs/build/html/py-modindex.html:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 | Python Module Index — nn-common-modules 1.0 documentation
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
Python Module Index
40 |
41 |
45 |
46 |
47 |
48 |
49 | l
50 |
51 |
52 |
53 | losses
54 |
55 |
56 |
57 | m
58 |
59 |
60 |
61 | modules
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
--------------------------------------------------------------------------------
/docs/build/html/search.html:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 | Search — nn-common-modules 1.0 documentation
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
Search
40 |
41 |
42 |
43 | Please activate JavaScript to enable the search
44 | functionality.
45 |
46 |
47 |
48 | From here you can search these documents. Enter your search
49 | words into the box below and click "search". Note that the search
50 | function will automatically search for all of the words. Pages
51 | containing fewer words won't appear in the result list.
52 |
53 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
--------------------------------------------------------------------------------
/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/source/conf.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | #
3 | # Configuration file for the Sphinx documentation builder.
4 | #
5 | # This file does only contain a selection of the most common options. For a
6 | # full list see the documentation:
7 | # http://www.sphinx-doc.org/en/master/config
8 |
9 | # -- Path setup --------------------------------------------------------------
10 |
11 | # If extensions (or modules to document with autodoc) are in another directory,
12 | # add these directories to sys.path here. If the directory is relative to the
13 | # documentation root, use os.path.abspath to make it absolute, like shown here.
14 | #
15 | import os
16 | import sys
17 | sys.path.insert(0, os.path.abspath('../../nn_common_modules'))
18 |
19 |
20 | # -- Project information -----------------------------------------------------
21 |
22 | project = 'nn-common-modules'
23 | copyright = '2019, Shayan Siddiqui'
24 | author = 'Shayan Siddiqui'
25 |
26 | # The short X.Y version
27 | version = ''
28 | # The full version, including alpha/beta/rc tags
29 | release = '1.0'
30 |
31 |
32 | # -- General configuration ---------------------------------------------------
33 |
34 | # If your documentation needs a minimal Sphinx version, state it here.
35 | #
36 | # needs_sphinx = '1.0'
37 |
38 | # Add any Sphinx extension module names here, as strings. They can be
39 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
40 | # ones.
41 | extensions = [
42 | 'sphinx.ext.autodoc',
43 | 'sphinx.ext.githubpages',
44 | ]
45 |
46 | # Add any paths that contain templates here, relative to this directory.
47 | templates_path = ['_templates']
48 |
49 | # The suffix(es) of source filenames.
50 | # You can specify multiple suffix as a list of string:
51 | #
52 | # source_suffix = ['.rst', '.md']
53 | source_suffix = '.rst'
54 |
55 | # The master toctree document.
56 | master_doc = 'index'
57 |
58 | # The language for content autogenerated by Sphinx. Refer to documentation
59 | # for a list of supported languages.
60 | #
61 | # This is also used if you do content translation via gettext catalogs.
62 | # Usually you set "language" from the command line for these cases.
63 | language = None
64 |
65 | # List of patterns, relative to source directory, that match files and
66 | # directories to ignore when looking for source files.
67 | # This pattern also affects html_static_path and html_extra_path .
68 | exclude_patterns = []
69 |
70 | # The name of the Pygments (syntax highlighting) style to use.
71 | pygments_style = 'sphinx'
72 |
73 |
74 | # -- Options for HTML output -------------------------------------------------
75 |
76 | # The theme to use for HTML and HTML Help pages. See the documentation for
77 | # a list of builtin themes.
78 | #
79 | html_theme = 'alabaster'
80 |
81 | # Theme options are theme-specific and customize the look and feel of a theme
82 | # further. For a list of options available for each theme, see the
83 | # documentation.
84 | #
85 | html_theme_options = {
86 | 'nosidebar': True,
87 | 'github_user': 'shayansiddiqui',
88 | 'github_repo': 'nn-additional-losses',
89 | 'codecov_button': True,
90 | 'github_banner': True,
91 | 'github_button': True,
92 | }
93 |
94 | # Add any paths that contain custom static files (such as style sheets) here,
95 | # relative to this directory. They are copied after the builtin static files,
96 | # so a file named "default.css" will overwrite the builtin "default.css".
97 | html_static_path = ['_static']
98 |
99 | # Custom sidebar templates, must be a dictionary that maps document names
100 | # to template names.
101 | #
102 | # The default sidebars (for documents that don't match any pattern) are
103 | # defined by theme itself. Builtin themes are using these templates by
104 | # default: ``['localtoc.html', 'relations.html', 'sourcelink.html',
105 | # 'searchbox.html']``.
106 | #
107 | # html_sidebars = {}
108 |
109 |
110 | # -- Options for HTMLHelp output ---------------------------------------------
111 |
112 | # Output file base name for HTML help builder.
113 | htmlhelp_basename = 'nn-common-modulesdoc'
114 |
115 |
116 | # -- Options for LaTeX output ------------------------------------------------
117 |
118 | latex_elements = {
119 | # The paper size ('letterpaper' or 'a4paper').
120 | #
121 | # 'papersize': 'letterpaper',
122 |
123 | # The font size ('10pt', '11pt' or '12pt').
124 | #
125 | # 'pointsize': '10pt',
126 |
127 | # Additional stuff for the LaTeX preamble.
128 | #
129 | # 'preamble': '',
130 |
131 | # Latex figure (float) alignment
132 | #
133 | # 'figure_align': 'htbp',
134 | }
135 |
136 | # Grouping the document tree into LaTeX files. List of tuples
137 | # (source start file, target name, title,
138 | # author, documentclass [howto, manual, or own class]).
139 | latex_documents = [
140 | (master_doc, 'nn-common-modules.tex', 'nn-common-modules Documentation',
141 | 'Shayan Siddiqui', 'manual'),
142 | ]
143 |
144 |
145 | # -- Options for manual page output ------------------------------------------
146 |
147 | # One entry per manual page. List of tuples
148 | # (source start file, name, description, authors, manual section).
149 | man_pages = [
150 | (master_doc, 'nn-common-modules', 'nn-common-modules Documentation',
151 | [author], 1)
152 | ]
153 |
154 |
155 | # -- Options for Texinfo output ----------------------------------------------
156 |
157 | # Grouping the document tree into Texinfo files. List of tuples
158 | # (source start file, target name, title, author,
159 | # dir menu entry, description, category)
160 | texinfo_documents = [
161 | (master_doc, 'nn-common-modules', 'nn-common-modules Documentation',
162 | author, 'nn-common-modules', 'One line description of project.',
163 | 'Miscellaneous'),
164 | ]
165 |
166 |
167 | # -- Extension configuration -------------------------------------------------
--------------------------------------------------------------------------------
/nn_common_modules/bayesian_modules.py:
--------------------------------------------------------------------------------
1 | """
2 | Description
3 | ++++++++++++++++++++++
4 | Building blocks of segmentation neural network
5 |
6 | Usage
7 | ++++++++++++++++++++++
8 | Import the package and Instantiate any module/block class you want to you::
9 |
10 | from nn_common_modules import modules as additional_modules
11 | dense_block = additional_modules.DenseBlock(params, se_block_type = 'SSE')
12 |
13 | Members
14 | ++++++++++++++++++++++
15 | """
16 | import torch
17 | import torch.nn as nn
18 | import torch.distributions as tdist
19 | from torch.nn.utils import weight_norm
20 |
21 |
22 | class BayesianConv(nn.Module):
23 | """Bayesian Convolution
24 |
25 | :param params: {
26 | 'num_channels':1,
27 | 'num_filters':64,
28 | 'kernel_h':5,
29 | 'kernel_w':5,
30 | 'stride_conv':1,
31 | 'pool':2,
32 | 'stride_pool':2,
33 | 'num_classes':28,
34 | 'se_block': se.SELayer.None,
35 | 'drop_out':0,2}
36 | :type params: dict
37 | :return: forward passed tensor
38 | :rtype: torch.tonsor [FloatTensor]
39 |
40 | """
41 |
42 | def __init__(self, params):
43 | super(BayesianConv, self).__init__()
44 |
45 | padding_h = int((params['kernel_h'] - 1) / 2)
46 | padding_w = int((params['kernel_w'] - 1) / 2)
47 |
48 | # conv_out_size = int(params['num_channels'] + params['num_filters'])
49 |
50 | self.conv_mean = nn.Conv2d(in_channels=params['num_channels'], out_channels=params['num_filters'],
51 | kernel_size=(params['kernel_h'], params['kernel_w']),
52 | padding=(padding_h, padding_w),
53 | stride=params['stride_conv'])
54 |
55 | self.conv_sigma = nn.Conv2d(in_channels=params['num_channels'], out_channels=params['num_filters'],
56 | kernel_size=(params['kernel_h'], params['kernel_w']),
57 | padding=(padding_h, padding_w),
58 | stride=params['stride_conv'])
59 | # weights = 0.0001 * torch.ones(
60 | # (params['num_filters'], params['num_channels'], params['kernel_h'], params['kernel_w']))
61 | # bias = 0.0001 * torch.ones(params['num_filters'])
62 | # self.conv_sigma.weight = nn.Parameter(weights)
63 | # self.conv_sigma.bias = nn.Parameter(bias)
64 | # self.conv_mean = weight_norm(self.conv_mean)
65 | # self.conv_sigma = weight_norm(self.conv_sigma)
66 | self.normal = tdist.Normal(torch.tensor([0.0]), torch.tensor([1.0]))
67 | self.sigmoid = nn.Sigmoid()
68 |
69 | def forward(self, input, switch=False):
70 |
71 | if switch is True:
72 | x_mean = self.sigmoid(self.conv_mean(input))
73 | x_sigma = self.sigmoid(self.conv_sigma(torch.mul(input, input)))
74 | sz = x_sigma.size()
75 | # TODO: insert Cuda check, Remove harcoded cuda device
76 | # x_sigma_noise = torch.mul(torch.sqrt(torch.exp(x_sigma)), self.normal.sample(sz).squeeze().cuda())
77 | x_sigma_noise = torch.mul(torch.sqrt(x_sigma), self.normal.sample(sz).squeeze().cuda())
78 | out = x_mean + x_sigma_noise
79 | kl_loss = torch.mean(x_sigma + (x_mean ** 2) - torch.log(x_sigma) - 1)
80 | # kl_loss = torch.mean(torch.exp(x_sigma + (x_mean ** 2) - x_sigma - 1)
81 | return out, kl_loss
82 | else:
83 | x_mean = self.conv_mean(input)
84 | return x_mean, None
85 |
86 |
87 | class EncoderBayesianBlock(nn.Module):
88 | """
89 | Encoder Block for Bayesian Network
90 | """
91 |
92 | def __init__(self, params):
93 | super(EncoderBayesianBlock, self).__init__()
94 | self.bayconv = BayesianConv(params)
95 | self.relu = nn.ReLU()
96 | self.maxpool = nn.MaxPool2d(
97 | kernel_size=params['pool'], stride=params['stride_pool'], return_indices=True)
98 |
99 | def forward(self, input, pool_required=True, switch=False):
100 | out, kl_loss = self.bayconv(input, switch)
101 | out = self.relu(out)
102 | if pool_required:
103 | pool, ind = self.maxpool(out)
104 | else:
105 | pool, ind = None, None
106 |
107 | return pool, out, ind, kl_loss
108 |
109 |
110 | class DecoderBayesianBlock(nn.Module):
111 | """
112 | Decoder Block for Bayesian Network
113 | """
114 |
115 | def __init__(self, params):
116 | super(DecoderBayesianBlock, self).__init__()
117 | self.unpool = nn.MaxUnpool2d(
118 | kernel_size=params['pool'], stride=params['stride_pool'])
119 | self.bayconv = BayesianConv(params)
120 | self.relu = nn.ReLU()
121 |
122 | def forward(self, input, out_block=None, indices=None, switch=False):
123 | unpool = self.unpool(input, indices)
124 | if out_block is not None:
125 | concat = torch.cat((out_block, unpool), dim=1)
126 | else:
127 | concat = unpool
128 | out_conv, kl_loss = self.bayconv(concat, switch)
129 | out_conv = self.relu(out_conv)
130 | return out_conv, kl_loss
131 |
132 |
133 | class ClassifierBayesianBlock(BayesianConv):
134 | """
135 | Classifier Bayesian Block
136 | """
137 |
138 | def __init__(self, params):
139 | super(ClassifierBayesianBlock, self).__init__(params)
140 | self.conv_mean = nn.Conv2d(params['num_channels'], params['num_class'], params['kernel_c'],
141 | params['stride_conv'])
142 |
143 | self.conv_sigma = nn.Conv2d(params['num_channels'], params['num_class'], params['kernel_c'],
144 | params['stride_conv'])
145 |
146 | def forward(self, input, switch=False):
147 | return super().forward(input, switch=switch)
148 |
--------------------------------------------------------------------------------
/nn_common_modules/octave_convolution_block.py:
--------------------------------------------------------------------------------
1 |
2 | import torch
3 | import torch.nn as nn
4 | import torch.nn.functional as F
5 | from math import ceil,floor
6 |
7 | from torch.nn.modules.utils import _single, _pair, _triple
8 |
9 | class OctConv2d(nn.modules.conv._ConvNd):
10 | """Unofficial implementation of the Octave Convolution in the "Drop an Octave" paper.
11 | oct_type (str): The type of OctConv you'd like to use. ['first', 'A'] both stand for the the first Octave Convolution.
12 | ['last', 'C'] both stand for th last Octave Convolution. And 'regular' stand for the regular ones.
13 | """
14 |
15 | def __init__(self, oct_type, in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, bias=True, alpha_in=0.5, alpha_out=0.5):
16 |
17 | if oct_type not in ('regular', 'first', 'last', 'A', 'C'):
18 | raise InvalidOctType("Invalid oct_type was chosen!")
19 |
20 | oct_type_dict = {'first': (0, alpha_out), 'A': (0, alpha_out), 'last': (alpha_in, 0), 'C': (alpha_in, 0),
21 | 'regular': (alpha_in, alpha_out)}
22 |
23 | kernel_size = _pair(kernel_size)
24 | stride = _pair(stride)
25 |
26 | # TODO: Make it work with any padding
27 | padding = _pair(int((kernel_size[0] - 1) / 2))
28 | # padding = _pair(padding)
29 | dilation = _pair(dilation)
30 | super(OctConv2d, self).__init__(in_channels, out_channels, kernel_size, stride, padding, dilation, False, _pair(0), 1, bias, padding_mode='zeros')
31 |
32 | # Get alphas from the oct_type_dict
33 | self.oct_type = oct_type
34 | self.alpha_in, self.alpha_out = oct_type_dict[self.oct_type]
35 |
36 | self.num_high_in_channels = int((1 - self.alpha_in) * in_channels)
37 | self.num_low_in_channels = int(self.alpha_in * in_channels)
38 | self.num_high_out_channels = int((1 - self.alpha_out) * out_channels)
39 | self.num_low_out_channels = int(self.alpha_out * out_channels)
40 |
41 | self.high_hh_weight = self.weight[:self.num_high_out_channels, :self.num_high_in_channels, :, :].clone()
42 | self.high_hh_bias = self.bias[:self.num_high_out_channels].clone()
43 |
44 | self.high_hl_weight = self.weight[self.num_high_out_channels:, :self.num_high_in_channels, :, :].clone()
45 | self.high_hl_bias = self.bias[self.num_high_out_channels:].clone()
46 |
47 | self.low_lh_weight = self.weight[:self.num_high_out_channels, self.num_high_in_channels:, :, :].clone()
48 | self.low_lh_bias = self.bias[:self.num_high_out_channels].clone()
49 |
50 | self.low_ll_weight = self.weight[self.num_high_out_channels:, self.num_high_in_channels:, :, :].clone()
51 | self.low_ll_bias = self.bias[self.num_high_out_channels:].clone()
52 |
53 | self.high_hh_weight.data, self.high_hl_weight.data, self.low_lh_weight.data, self.low_ll_weight.data = \
54 | self._apply_noise(self.high_hh_weight.data), self._apply_noise(self.high_hl_weight.data), \
55 | self._apply_noise(self.low_lh_weight.data), self._apply_noise(self.low_ll_weight.data)
56 |
57 | self.high_hh_weight, self.high_hl_weight, self.low_lh_weight, self.low_ll_weight = \
58 | nn.Parameter(self.high_hh_weight), nn.Parameter(self.high_hl_weight), nn.Parameter(self.low_lh_weight), nn.Parameter(self.low_ll_weight)
59 |
60 | self.high_hh_bias, self.high_hl_bias, self.low_lh_bias, self.low_ll_bias = \
61 | nn.Parameter(self.high_hh_bias), nn.Parameter(self.high_hl_bias), nn.Parameter(self.low_lh_bias), nn.Parameter(self.low_ll_bias)
62 |
63 |
64 | self.avgpool = nn.AvgPool2d(2)
65 |
66 | def forward(self, x):
67 | if self.oct_type in ('first', 'A'):
68 | high_group, low_group = x[:, :self.num_high_in_channels, :, :], x[:, self.num_high_in_channels:, :, :]
69 | else:
70 | high_group, low_group = x
71 |
72 | high_group_hh = F.conv2d(high_group, self.high_hh_weight, self.high_hh_bias, self.stride,
73 | self.padding, self.dilation, self.groups)
74 | high_group_pooled = self.avgpool(high_group)
75 |
76 | if self.oct_type in ('first', 'A'):
77 | high_group_hl = F.conv2d(high_group_pooled, self.high_hl_weight, self.high_hl_bias, self.stride,
78 | self.padding, self.dilation, self.groups)
79 | high_group_out, low_group_out = high_group_hh, high_group_hl
80 |
81 | return high_group_out, low_group_out
82 |
83 | elif self.oct_type in ('last', 'C'):
84 | low_group_lh = F.conv2d(low_group, self.low_lh_weight, self.low_lh_bias, self.stride,
85 | self.padding, self.dilation, self.groups)
86 | low_group_upsampled = F.interpolate(low_group_lh, scale_factor=2)
87 | high_group_out = high_group_hh + low_group_upsampled
88 |
89 | return high_group_out
90 |
91 | else:
92 | high_group_hl = F.conv2d(high_group_pooled, self.high_hl_weight, self.high_hl_bias, self.stride,
93 | self.padding, self.dilation, self.groups)
94 | low_group_lh = F.conv2d(low_group, self.low_lh_weight, self.low_lh_bias, self.stride,
95 | self.padding, self.dilation, self.groups)
96 | low_group_upsampled = F.interpolate(low_group_lh, scale_factor=2)
97 | low_group_ll = F.conv2d(low_group, self.low_ll_weight, self.low_ll_bias, self.stride,
98 | self.padding, self.dilation, self.groups)
99 |
100 | high_group_out = high_group_hh + low_group_upsampled
101 | low_group_out = high_group_hl + low_group_ll
102 |
103 | return high_group_out, low_group_out
104 |
105 | @staticmethod
106 | def _apply_noise(tensor, mu=0, sigma=0.0001):
107 | noise = torch.normal(mean=torch.ones_like(tensor) * mu, std=torch.ones_like(tensor) * sigma)
108 |
109 | return tensor + noise
110 |
111 |
112 | class OctReLU(nn.Module):
113 | def __init__(self, inplace=False):
114 | super().__init__()
115 | self.relu_h, self.relu_l = nn.ReLU(inplace), nn.ReLU(inplace)
116 |
117 | def forward(self, x):
118 | h, l = x
119 |
120 | return self.relu_h(h), self.relu_l(l)
121 |
122 |
123 | class OctMaxPool2d(nn.Module):
124 | def __init__(self, kernel_size, stride=None, padding=0, dilation=1, return_indices=False, ceil_mode=False):
125 | super().__init__()
126 | self.maxpool_h = nn.MaxPool2d(kernel_size, stride=None, padding=0, dilation=1, return_indices=False, ceil_mode=False)
127 | self.maxpool_l = nn.MaxPool2d(kernel_size, stride=None, padding=0, dilation=1, return_indices=False, ceil_mode=False)
128 |
129 | def forward(self, x):
130 | h, l = x
131 |
132 | return self.maxpool_h(h), self.maxpool_l(l)
133 |
134 |
135 | class Error(Exception):
136 | """Base-class for all exceptions rased by this module."""
137 |
138 |
139 | class InvalidOctType(Error):
140 | """There was a problem in the OctConv type."""
--------------------------------------------------------------------------------
/docs/build/html/genindex.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
7 |
8 |
9 |
10 | Index — nn-common-modules 1.0 documentation
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
Index
34 |
35 |
36 |
C
37 | |
D
38 | |
E
39 | |
F
40 | |
G
41 | |
I
42 | |
L
43 | |
M
44 | |
S
45 |
46 |
47 |
C
48 |
60 |
61 |
D
62 |
74 |
75 |
E
76 |
82 |
83 |
F
84 |
116 |
117 |
G
118 |
124 |
125 |
I
126 |
132 |
133 |
L
134 |
140 |
141 |
M
142 |
148 |
149 |
S
150 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
--------------------------------------------------------------------------------
/nn_common_modules/losses.py:
--------------------------------------------------------------------------------
1 | """
2 | Description
3 | ++++++++++++++++++++++
4 | Addition losses module defines classses which are commonly used particularly in segmentation and are not part of standard pytorch library.
5 |
6 | Usage
7 | ++++++++++++++++++++++
8 | Import the package and Instantiate any loss class you want to you::
9 |
10 | from nn_common_modules import losses as additional_losses
11 | loss = additional_losses.DiceLoss()
12 |
13 | Note: If you use DiceLoss, insert Softmax layer in the architecture. In case of combined loss, do not put softmax as it is in-built
14 |
15 | Members
16 | ++++++++++++++++++++++
17 | """
18 | import torch
19 | import torch.nn as nn
20 | import torch.nn.functional as F
21 | from torch.nn.modules.loss import _Loss, _WeightedLoss
22 | import numpy as np
23 | from torch.autograd import Variable
24 |
25 |
26 | class DiceLoss(_WeightedLoss):
27 | """
28 | Dice Loss for a batch of samples
29 | """
30 |
31 | def forward(self, output, target, weights=None, binary=False):
32 | """
33 | Forward pass
34 |
35 | :param output: NxCxHxW logits
36 | :param target: NxHxW LongTensor
37 | :param weights: C FloatTensor
38 | :param binary: bool for binarized one chaneel(C=1) input
39 | :return: torch.tensor
40 | """
41 | output = F.softmax(output, dim=1)
42 | if binary:
43 | return self._dice_loss_binary(output, target)
44 | return self._dice_loss_multichannel(output, target, weights)
45 |
46 | @staticmethod
47 | def _dice_loss_binary(output, target):
48 | """
49 | Dice loss for one channel binarized input
50 |
51 | :param output: Nx1xHxW logits
52 | :param target: NxHxW LongTensor
53 | :return:
54 | """
55 | eps = 0.0001
56 |
57 | intersection = output * target
58 | numerator = 2 * intersection.sum(0).sum(1).sum(1)
59 | denominator = output + target
60 | denominator = denominator.sum(0).sum(1).sum(1) + eps
61 | loss_per_channel = 1 - (numerator / denominator)
62 |
63 | return loss_per_channel.sum() / output.size(1)
64 |
65 | @staticmethod
66 | def _dice_loss_multichannel(output, target, weights=None):
67 | """
68 | Forward pass
69 |
70 | :param output: NxCxHxW Variable
71 | :param target: NxHxW LongTensor
72 | :param weights: C FloatTensor
73 | :param binary: bool for binarized one chaneel(C=1) input
74 | :return:
75 | """
76 |
77 | output = F.softmax(output, dim=1)
78 | eps = 0.0001
79 | target = target.unsqueeze(1)
80 | encoded_target = torch.zeros_like(output)
81 |
82 | encoded_target = encoded_target.scatter(1, target, 1)
83 |
84 | intersection = output * encoded_target
85 | intersection = intersection.sum(2).sum(2)
86 |
87 | num_union_pixels = output + encoded_target
88 | num_union_pixels = num_union_pixels.sum(2).sum(2)
89 |
90 | loss_per_class = 1 - ((2 * intersection) / (num_union_pixels + eps))
91 | # loss_per_class = 1 - ((2 * intersection + 1) / (num_union_pixels + 1))
92 | if weights is None:
93 | weights = torch.ones_like(loss_per_class)
94 | loss_per_class *= weights
95 |
96 | return (loss_per_class.sum(1) / (num_union_pixels != 0).sum(1).float()).mean()
97 |
98 |
99 | class IoULoss(_WeightedLoss):
100 | """
101 | IoU Loss for a batch of samples
102 | """
103 |
104 | def forward(self, output, target, weights=None, ignore_index=None):
105 | """Forward pass
106 |
107 | :param output: shape = NxCxHxW
108 | :type output: torch.tensor [FloatTensor]
109 | :param target: shape = NxHxW
110 | :type target: torch.tensor [LongTensor]
111 | :param weights: shape = C, defaults to None
112 | :type weights: torch.tensor [FloatTensor], optional
113 | :param ignore_index: index to ignore from loss, defaults to None
114 | :type ignore_index: int, optional
115 | :return: loss value
116 | :rtype: torch.tensor
117 | """
118 |
119 | output = F.softmax(output, dim=1)
120 |
121 | eps = 0.0001
122 | encoded_target = output.detach() * 0
123 |
124 | if ignore_index is not None:
125 | mask = target == ignore_index
126 | target = target.clone()
127 | target[mask] = 0
128 | encoded_target.scatter_(1, target.unsqueeze(1), 1)
129 | mask = mask.unsqueeze(1).expand_as(encoded_target)
130 | encoded_target[mask] = 0
131 | else:
132 | encoded_target.scatter_(1, target.unsqueeze(1), 1)
133 |
134 | if weights is None:
135 | weights = 1
136 |
137 | intersection = output * encoded_target
138 | numerator = intersection.sum(0).sum(1).sum(1)
139 | denominator = (output + encoded_target) - (output * encoded_target)
140 |
141 | if ignore_index is not None:
142 | denominator[mask] = 0
143 | denominator = denominator.sum(0).sum(1).sum(1) + eps
144 | loss_per_channel = weights * (1 - (numerator / denominator))
145 |
146 | return loss_per_channel.sum() / output.size(1)
147 |
148 |
149 | class CrossEntropyLoss2d(_WeightedLoss):
150 | """
151 | Standard pytorch weighted nn.CrossEntropyLoss
152 | """
153 |
154 | def __init__(self, weight=None):
155 | super(CrossEntropyLoss2d, self).__init__()
156 | self.nll_loss = nn.CrossEntropyLoss(weight)
157 |
158 | def forward(self, inputs, targets):
159 | """
160 | Forward pass
161 |
162 | :param inputs: torch.tensor (NxC)
163 | :param targets: torch.tensor (N)
164 | :return: scalar
165 | """
166 | return self.nll_loss(inputs, targets)
167 |
168 |
169 | class CombinedLoss(_Loss):
170 | """
171 | A combination of dice and cross entropy loss
172 | """
173 |
174 | def __init__(self):
175 | super(CombinedLoss, self).__init__()
176 | self.cross_entropy_loss = nn.CrossEntropyLoss(reduction='none') # CrossEntropyLoss2d()
177 | self.dice_loss = DiceLoss()
178 | self.focal_loss = FocalLoss()
179 | self.l2_loss = nn.MSELoss()
180 |
181 | def forward(self, input, target, weight=None):
182 | """
183 | Forward pass
184 |
185 | :param input: torch.tensor (NxCxHxW)
186 | :param target: torch.tensor (NxHxW)
187 | :param weight: torch.tensor (NxHxW)
188 | :return: scalar
189 | """
190 | # input_soft = F.softmax(input, dim=1)
191 | y_2 = torch.mean(self.dice_loss(input, target))
192 | if weight is None:
193 | y_1 = torch.mean(self.cross_entropy_loss.forward(input, target))
194 | else:
195 | y_1 = torch.mean(
196 | torch.mul(self.cross_entropy_loss.forward(input, target), weight))
197 | return y_1 + y_2
198 |
199 |
200 | class CombinedLoss_KLdiv(_Loss):
201 | """
202 | A combination of dice and cross entropy loss
203 | """
204 |
205 | def __init__(self):
206 | super(CombinedLoss_KLdiv, self).__init__()
207 | self.cross_entropy_loss = CrossEntropyLoss2d()
208 | self.dice_loss = DiceLoss()
209 |
210 | def forward(self, input, target, weight=None):
211 | """
212 | Forward pass
213 |
214 | """
215 | input, kl_div_loss = input
216 | # input_soft = F.softmax(input, dim=1)
217 | y_2 = torch.mean(self.dice_loss(input, target))
218 | if weight is None:
219 | y_1 = torch.mean(self.cross_entropy_loss.forward(input, target))
220 | else:
221 | y_1 = torch.mean(
222 | torch.mul(self.cross_entropy_loss.forward(input, target), weight))
223 | return y_1, y_2, kl_div_loss
224 |
225 |
226 | # Credit to https://github.com/clcarwin/focal_loss_pytorch
227 | class FocalLoss(nn.Module):
228 | """
229 | Focal Loss for Dense Object Detection
230 | """
231 |
232 | def __init__(self, gamma=2, alpha=None, size_average=True):
233 |
234 | super(FocalLoss, self).__init__()
235 | self.gamma = gamma
236 | self.alpha = alpha
237 | if isinstance(alpha, (float, int)):
238 | self.alpha = torch.Tensor([alpha, 1 - alpha])
239 | if isinstance(alpha, list):
240 | self.alpha = torch.Tensor(alpha)
241 | self.size_average = size_average
242 |
243 | def forward(self, input, target):
244 | """Forward pass
245 |
246 | :param input: shape = NxCxHxW
247 | :type input: torch.tensor
248 | :param target: shape = NxHxW
249 | :type target: torch.tensor
250 | :return: loss value
251 | :rtype: torch.tensor
252 | """
253 |
254 | if input.dim() > 2:
255 | # N,C,H,W => N,C,H*W
256 | input = input.view(input.size(0), input.size(1), -1)
257 | input = input.transpose(1, 2) # N,C,H*W => N,H*W,C
258 | input = input.contiguous().view(-1, input.size(2)) # N,H*W,C => N*H*W,C
259 | target = target.view(-1, 1)
260 |
261 | logpt = F.log_softmax(input, dim=1)
262 | logpt = logpt.gather(1, target)
263 | logpt = logpt.view(-1)
264 | pt = Variable(logpt.data.exp())
265 |
266 | if self.alpha is not None:
267 | if self.alpha.type() != input.data.type():
268 | self.alpha = self.alpha.type_as(input.data)
269 | at = self.alpha.gather(0, target.data.view(-1))
270 | logpt = logpt * Variable(at)
271 |
272 | loss = -1 * (1 - pt) ** self.gamma * logpt
273 | if self.size_average:
274 | return loss.mean()
275 | else:
276 | return loss.sum()
277 |
--------------------------------------------------------------------------------
/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 |
154 | },
155 |
156 | /**
157 | * i18n support
158 | */
159 | TRANSLATIONS : {},
160 | PLURAL_EXPR : function(n) { return n === 1 ? 0 : 1; },
161 | LOCALE : 'unknown',
162 |
163 | // gettext and ngettext don't access this so that the functions
164 | // can safely bound to a different name (_ = Documentation.gettext)
165 | gettext : function(string) {
166 | var translated = Documentation.TRANSLATIONS[string];
167 | if (typeof translated === 'undefined')
168 | return string;
169 | return (typeof translated === 'string') ? translated : translated[0];
170 | },
171 |
172 | ngettext : function(singular, plural, n) {
173 | var translated = Documentation.TRANSLATIONS[singular];
174 | if (typeof translated === 'undefined')
175 | return (n == 1) ? singular : plural;
176 | return translated[Documentation.PLURALEXPR(n)];
177 | },
178 |
179 | addTranslations : function(catalog) {
180 | for (var key in catalog.messages)
181 | this.TRANSLATIONS[key] = catalog.messages[key];
182 | this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')');
183 | this.LOCALE = catalog.locale;
184 | },
185 |
186 | /**
187 | * add context elements like header anchor links
188 | */
189 | addContextElements : function() {
190 | $('div[id] > :header:first').each(function() {
191 | $('').
192 | attr('href', '#' + this.id).
193 | attr('title', _('Permalink to this headline')).
194 | appendTo(this);
195 | });
196 | $('dt[id]').each(function() {
197 | $('').
198 | attr('href', '#' + this.id).
199 | attr('title', _('Permalink to this definition')).
200 | appendTo(this);
201 | });
202 | },
203 |
204 | /**
205 | * workaround a firefox stupidity
206 | * see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075
207 | */
208 | fixFirefoxAnchorBug : function() {
209 | if (document.location.hash && $.browser.mozilla)
210 | window.setTimeout(function() {
211 | document.location.href += '';
212 | }, 10);
213 | },
214 |
215 | /**
216 | * highlight the search words provided in the url in the text
217 | */
218 | highlightSearchWords : function() {
219 | var params = $.getQueryParameters();
220 | var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : [];
221 | if (terms.length) {
222 | var body = $('div.body');
223 | if (!body.length) {
224 | body = $('body');
225 | }
226 | window.setTimeout(function() {
227 | $.each(terms, function() {
228 | body.highlightText(this.toLowerCase(), 'highlighted');
229 | });
230 | }, 10);
231 | $('' + _('Hide Search Matches') + '
')
233 | .appendTo($('#searchbox'));
234 | }
235 | },
236 |
237 | /**
238 | * init the domain index toggle buttons
239 | */
240 | initIndexTable : function() {
241 | var togglers = $('img.toggler').click(function() {
242 | var src = $(this).attr('src');
243 | var idnum = $(this).attr('id').substr(7);
244 | $('tr.cg-' + idnum).toggle();
245 | if (src.substr(-9) === 'minus.png')
246 | $(this).attr('src', src.substr(0, src.length-9) + 'plus.png');
247 | else
248 | $(this).attr('src', src.substr(0, src.length-8) + 'minus.png');
249 | }).css('display', '');
250 | if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) {
251 | togglers.click();
252 | }
253 | },
254 |
255 | /**
256 | * helper function to hide the search marks again
257 | */
258 | hideSearchWords : function() {
259 | $('#searchbox .highlight-link').fadeOut(300);
260 | $('span.highlighted').removeClass('highlighted');
261 | },
262 |
263 | /**
264 | * make the url absolute
265 | */
266 | makeURL : function(relativeURL) {
267 | return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL;
268 | },
269 |
270 | /**
271 | * get the current relative url
272 | */
273 | getCurrentURL : function() {
274 | var path = document.location.pathname;
275 | var parts = path.split(/\//);
276 | $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() {
277 | if (this === '..')
278 | parts.pop();
279 | });
280 | var url = parts.join('/');
281 | return path.substring(url.lastIndexOf('/') + 1, path.length - 1);
282 | },
283 |
284 | initOnKeyListeners: function() {
285 | $(document).keyup(function(event) {
286 | var activeElementType = document.activeElement.tagName;
287 | // don't navigate when in search box or textarea
288 | if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT') {
289 | switch (event.keyCode) {
290 | case 37: // left
291 | var prevHref = $('link[rel="prev"]').prop('href');
292 | if (prevHref) {
293 | window.location.href = prevHref;
294 | return false;
295 | }
296 | case 39: // right
297 | var nextHref = $('link[rel="next"]').prop('href');
298 | if (nextHref) {
299 | window.location.href = nextHref;
300 | return false;
301 | }
302 | }
303 | }
304 | });
305 | }
306 | };
307 |
308 | // quick alias for translations
309 | _ = Documentation.gettext;
310 |
311 | $(document).ready(function() {
312 | Documentation.init();
313 | });
--------------------------------------------------------------------------------
/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/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: 230px;
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 input[type="text"] {
85 | float: left;
86 | width: 80%;
87 | padding: 0.25em;
88 | box-sizing: border-box;
89 | }
90 |
91 | div.sphinxsidebar #searchbox input[type="submit"] {
92 | float: left;
93 | width: 20%;
94 | border-left: none;
95 | padding: 0.25em;
96 | box-sizing: border-box;
97 | }
98 |
99 |
100 | img {
101 | border: 0;
102 | max-width: 100%;
103 | }
104 |
105 | /* -- search page ----------------------------------------------------------- */
106 |
107 | ul.search {
108 | margin: 10px 0 0 20px;
109 | padding: 0;
110 | }
111 |
112 | ul.search li {
113 | padding: 5px 0 5px 20px;
114 | background-image: url(file.png);
115 | background-repeat: no-repeat;
116 | background-position: 0 7px;
117 | }
118 |
119 | ul.search li a {
120 | font-weight: bold;
121 | }
122 |
123 | ul.search li div.context {
124 | color: #888;
125 | margin: 2px 0 0 30px;
126 | text-align: left;
127 | }
128 |
129 | ul.keywordmatches li.goodmatch a {
130 | font-weight: bold;
131 | }
132 |
133 | /* -- index page ------------------------------------------------------------ */
134 |
135 | table.contentstable {
136 | width: 90%;
137 | margin-left: auto;
138 | margin-right: auto;
139 | }
140 |
141 | table.contentstable p.biglink {
142 | line-height: 150%;
143 | }
144 |
145 | a.biglink {
146 | font-size: 1.3em;
147 | }
148 |
149 | span.linkdescr {
150 | font-style: italic;
151 | padding-top: 5px;
152 | font-size: 90%;
153 | }
154 |
155 | /* -- general index --------------------------------------------------------- */
156 |
157 | table.indextable {
158 | width: 100%;
159 | }
160 |
161 | table.indextable td {
162 | text-align: left;
163 | vertical-align: top;
164 | }
165 |
166 | table.indextable ul {
167 | margin-top: 0;
168 | margin-bottom: 0;
169 | list-style-type: none;
170 | }
171 |
172 | table.indextable > tbody > tr > td > ul {
173 | padding-left: 0em;
174 | }
175 |
176 | table.indextable tr.pcap {
177 | height: 10px;
178 | }
179 |
180 | table.indextable tr.cap {
181 | margin-top: 10px;
182 | background-color: #f2f2f2;
183 | }
184 |
185 | img.toggler {
186 | margin-right: 3px;
187 | margin-top: 3px;
188 | cursor: pointer;
189 | }
190 |
191 | div.modindex-jumpbox {
192 | border-top: 1px solid #ddd;
193 | border-bottom: 1px solid #ddd;
194 | margin: 1em 0 1em 0;
195 | padding: 0.4em;
196 | }
197 |
198 | div.genindex-jumpbox {
199 | border-top: 1px solid #ddd;
200 | border-bottom: 1px solid #ddd;
201 | margin: 1em 0 1em 0;
202 | padding: 0.4em;
203 | }
204 |
205 | /* -- domain module index --------------------------------------------------- */
206 |
207 | table.modindextable td {
208 | padding: 2px;
209 | border-collapse: collapse;
210 | }
211 |
212 | /* -- general body styles --------------------------------------------------- */
213 |
214 | div.body {
215 | min-width: 450px;
216 | max-width: 800px;
217 | }
218 |
219 | div.body p, div.body dd, div.body li, div.body blockquote {
220 | -moz-hyphens: auto;
221 | -ms-hyphens: auto;
222 | -webkit-hyphens: auto;
223 | hyphens: auto;
224 | }
225 |
226 | a.headerlink {
227 | visibility: hidden;
228 | }
229 |
230 | h1:hover > a.headerlink,
231 | h2:hover > a.headerlink,
232 | h3:hover > a.headerlink,
233 | h4:hover > a.headerlink,
234 | h5:hover > a.headerlink,
235 | h6:hover > a.headerlink,
236 | dt:hover > a.headerlink,
237 | caption:hover > a.headerlink,
238 | p.caption:hover > a.headerlink,
239 | div.code-block-caption:hover > a.headerlink {
240 | visibility: visible;
241 | }
242 |
243 | div.body p.caption {
244 | text-align: inherit;
245 | }
246 |
247 | div.body td {
248 | text-align: left;
249 | }
250 |
251 | .first {
252 | margin-top: 0 !important;
253 | }
254 |
255 | p.rubric {
256 | margin-top: 30px;
257 | font-weight: bold;
258 | }
259 |
260 | img.align-left, .figure.align-left, object.align-left {
261 | clear: left;
262 | float: left;
263 | margin-right: 1em;
264 | }
265 |
266 | img.align-right, .figure.align-right, object.align-right {
267 | clear: right;
268 | float: right;
269 | margin-left: 1em;
270 | }
271 |
272 | img.align-center, .figure.align-center, object.align-center {
273 | display: block;
274 | margin-left: auto;
275 | margin-right: auto;
276 | }
277 |
278 | .align-left {
279 | text-align: left;
280 | }
281 |
282 | .align-center {
283 | text-align: center;
284 | }
285 |
286 | .align-right {
287 | text-align: right;
288 | }
289 |
290 | /* -- sidebars -------------------------------------------------------------- */
291 |
292 | div.sidebar {
293 | margin: 0 0 0.5em 1em;
294 | border: 1px solid #ddb;
295 | padding: 7px 7px 0 7px;
296 | background-color: #ffe;
297 | width: 40%;
298 | float: right;
299 | }
300 |
301 | p.sidebar-title {
302 | font-weight: bold;
303 | }
304 |
305 | /* -- topics ---------------------------------------------------------------- */
306 |
307 | div.topic {
308 | border: 1px solid #ccc;
309 | padding: 7px 7px 0 7px;
310 | margin: 10px 0 10px 0;
311 | }
312 |
313 | p.topic-title {
314 | font-size: 1.1em;
315 | font-weight: bold;
316 | margin-top: 10px;
317 | }
318 |
319 | /* -- admonitions ----------------------------------------------------------- */
320 |
321 | div.admonition {
322 | margin-top: 10px;
323 | margin-bottom: 10px;
324 | padding: 7px;
325 | }
326 |
327 | div.admonition dt {
328 | font-weight: bold;
329 | }
330 |
331 | div.admonition dl {
332 | margin-bottom: 0;
333 | }
334 |
335 | p.admonition-title {
336 | margin: 0px 10px 5px 0px;
337 | font-weight: bold;
338 | }
339 |
340 | div.body p.centered {
341 | text-align: center;
342 | margin-top: 25px;
343 | }
344 |
345 | /* -- tables ---------------------------------------------------------------- */
346 |
347 | table.docutils {
348 | border: 0;
349 | border-collapse: collapse;
350 | }
351 |
352 | table.align-center {
353 | margin-left: auto;
354 | margin-right: auto;
355 | }
356 |
357 | table caption span.caption-number {
358 | font-style: italic;
359 | }
360 |
361 | table caption span.caption-text {
362 | }
363 |
364 | table.docutils td, table.docutils th {
365 | padding: 1px 8px 1px 5px;
366 | border-top: 0;
367 | border-left: 0;
368 | border-right: 0;
369 | border-bottom: 1px solid #aaa;
370 | }
371 |
372 | table.footnote td, table.footnote th {
373 | border: 0 !important;
374 | }
375 |
376 | th {
377 | text-align: left;
378 | padding-right: 5px;
379 | }
380 |
381 | table.citation {
382 | border-left: solid 1px gray;
383 | margin-left: 1px;
384 | }
385 |
386 | table.citation td {
387 | border-bottom: none;
388 | }
389 |
390 | /* -- figures --------------------------------------------------------------- */
391 |
392 | div.figure {
393 | margin: 0.5em;
394 | padding: 0.5em;
395 | }
396 |
397 | div.figure p.caption {
398 | padding: 0.3em;
399 | }
400 |
401 | div.figure p.caption span.caption-number {
402 | font-style: italic;
403 | }
404 |
405 | div.figure p.caption span.caption-text {
406 | }
407 |
408 | /* -- field list styles ----------------------------------------------------- */
409 |
410 | table.field-list td, table.field-list th {
411 | border: 0 !important;
412 | }
413 |
414 | .field-list ul {
415 | margin: 0;
416 | padding-left: 1em;
417 | }
418 |
419 | .field-list p {
420 | margin: 0;
421 | }
422 |
423 | .field-name {
424 | -moz-hyphens: manual;
425 | -ms-hyphens: manual;
426 | -webkit-hyphens: manual;
427 | hyphens: manual;
428 | }
429 |
430 | /* -- other body styles ----------------------------------------------------- */
431 |
432 | ol.arabic {
433 | list-style: decimal;
434 | }
435 |
436 | ol.loweralpha {
437 | list-style: lower-alpha;
438 | }
439 |
440 | ol.upperalpha {
441 | list-style: upper-alpha;
442 | }
443 |
444 | ol.lowerroman {
445 | list-style: lower-roman;
446 | }
447 |
448 | ol.upperroman {
449 | list-style: upper-roman;
450 | }
451 |
452 | dl {
453 | margin-bottom: 15px;
454 | }
455 |
456 | dd p {
457 | margin-top: 0px;
458 | }
459 |
460 | dd ul, dd table {
461 | margin-bottom: 10px;
462 | }
463 |
464 | dd {
465 | margin-top: 3px;
466 | margin-bottom: 10px;
467 | margin-left: 30px;
468 | }
469 |
470 | dt:target, span.highlighted {
471 | background-color: #fbe54e;
472 | }
473 |
474 | rect.highlighted {
475 | fill: #fbe54e;
476 | }
477 |
478 | dl.glossary dt {
479 | font-weight: bold;
480 | font-size: 1.1em;
481 | }
482 |
483 | .optional {
484 | font-size: 1.3em;
485 | }
486 |
487 | .sig-paren {
488 | font-size: larger;
489 | }
490 |
491 | .versionmodified {
492 | font-style: italic;
493 | }
494 |
495 | .system-message {
496 | background-color: #fda;
497 | padding: 5px;
498 | border: 3px solid red;
499 | }
500 |
501 | .footnote:target {
502 | background-color: #ffa;
503 | }
504 |
505 | .line-block {
506 | display: block;
507 | margin-top: 1em;
508 | margin-bottom: 1em;
509 | }
510 |
511 | .line-block .line-block {
512 | margin-top: 0;
513 | margin-bottom: 0;
514 | margin-left: 1.5em;
515 | }
516 |
517 | .guilabel, .menuselection {
518 | font-family: sans-serif;
519 | }
520 |
521 | .accelerator {
522 | text-decoration: underline;
523 | }
524 |
525 | .classifier {
526 | font-style: oblique;
527 | }
528 |
529 | abbr, acronym {
530 | border-bottom: dotted 1px;
531 | cursor: help;
532 | }
533 |
534 | /* -- code displays --------------------------------------------------------- */
535 |
536 | pre {
537 | overflow: auto;
538 | overflow-y: hidden; /* fixes display issues on Chrome browsers */
539 | }
540 |
541 | span.pre {
542 | -moz-hyphens: none;
543 | -ms-hyphens: none;
544 | -webkit-hyphens: none;
545 | hyphens: none;
546 | }
547 |
548 | td.linenos pre {
549 | padding: 5px 0px;
550 | border: 0;
551 | background-color: transparent;
552 | color: #aaa;
553 | }
554 |
555 | table.highlighttable {
556 | margin-left: 0.5em;
557 | }
558 |
559 | table.highlighttable td {
560 | padding: 0 0.5em 0 0.5em;
561 | }
562 |
563 | div.code-block-caption {
564 | padding: 2px 5px;
565 | font-size: small;
566 | }
567 |
568 | div.code-block-caption code {
569 | background-color: transparent;
570 | }
571 |
572 | div.code-block-caption + div > div.highlight > pre {
573 | margin-top: 0;
574 | }
575 |
576 | div.code-block-caption span.caption-number {
577 | padding: 0.1em 0.3em;
578 | font-style: italic;
579 | }
580 |
581 | div.code-block-caption span.caption-text {
582 | }
583 |
584 | div.literal-block-wrapper {
585 | padding: 1em 1em 0;
586 | }
587 |
588 | div.literal-block-wrapper div.highlight {
589 | margin: 0;
590 | }
591 |
592 | code.descname {
593 | background-color: transparent;
594 | font-weight: bold;
595 | font-size: 1.2em;
596 | }
597 |
598 | code.descclassname {
599 | background-color: transparent;
600 | }
601 |
602 | code.xref, a code {
603 | background-color: transparent;
604 | font-weight: bold;
605 | }
606 |
607 | h1 code, h2 code, h3 code, h4 code, h5 code, h6 code {
608 | background-color: transparent;
609 | }
610 |
611 | .viewcode-link {
612 | float: right;
613 | }
614 |
615 | .viewcode-back {
616 | float: right;
617 | font-family: sans-serif;
618 | }
619 |
620 | div.viewcode-block:target {
621 | margin: -1px -10px;
622 | padding: 0 10px;
623 | }
624 |
625 | /* -- math display ---------------------------------------------------------- */
626 |
627 | img.math {
628 | vertical-align: middle;
629 | }
630 |
631 | div.body div.math p {
632 | text-align: center;
633 | }
634 |
635 | span.eqno {
636 | float: right;
637 | }
638 |
639 | span.eqno a.headerlink {
640 | position: relative;
641 | left: 0px;
642 | z-index: 1;
643 | }
644 |
645 | div.math:hover a.headerlink {
646 | visibility: visible;
647 | }
648 |
649 | /* -- printout stylesheet --------------------------------------------------- */
650 |
651 | @media print {
652 | div.document,
653 | div.documentwrapper,
654 | div.bodywrapper {
655 | margin: 0 !important;
656 | width: 100%;
657 | }
658 |
659 | div.sphinxsidebar,
660 | div.related,
661 | div.footer,
662 | #top-link {
663 | display: none;
664 | }
665 | }
--------------------------------------------------------------------------------
/docs/build/html/_static/alabaster.css:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 | @import url("basic.css");
54 |
55 | /* -- page layout ----------------------------------------------------------- */
56 |
57 | body {
58 | font-family: 'goudy old style', 'minion pro', 'bell mt', Georgia, 'Hiragino Mincho Pro', serif;
59 | font-size: 17px;
60 | background-color: #fff;
61 | color: #000;
62 | margin: 0;
63 | padding: 0;
64 | }
65 |
66 |
67 | div.document {
68 | width: 940px;
69 | margin: 30px auto 0 auto;
70 | }
71 |
72 | div.documentwrapper {
73 | float: left;
74 | width: 100%;
75 | }
76 |
77 | div.bodywrapper {
78 | margin: 0 0 0 220px;
79 | }
80 |
81 | div.sphinxsidebar {
82 | width: 220px;
83 | font-size: 14px;
84 | line-height: 1.5;
85 | }
86 |
87 | hr {
88 | border: 1px solid #B1B4B6;
89 | }
90 |
91 | div.body {
92 | background-color: #fff;
93 | color: #3E4349;
94 | padding: 0 30px 0 30px;
95 | }
96 |
97 | div.body > .section {
98 | text-align: left;
99 | }
100 |
101 | div.footer {
102 | width: 940px;
103 | margin: 20px auto 30px auto;
104 | font-size: 14px;
105 | color: #888;
106 | text-align: right;
107 | }
108 |
109 | div.footer a {
110 | color: #888;
111 | }
112 |
113 | p.caption {
114 | font-family: inherit;
115 | font-size: inherit;
116 | }
117 |
118 |
119 | div.relations {
120 | display: none;
121 | }
122 |
123 |
124 | div.sphinxsidebar a {
125 | color: #444;
126 | text-decoration: none;
127 | border-bottom: 1px dotted #999;
128 | }
129 |
130 | div.sphinxsidebar a:hover {
131 | border-bottom: 1px solid #999;
132 | }
133 |
134 | div.sphinxsidebarwrapper {
135 | padding: 18px 10px;
136 | }
137 |
138 | div.sphinxsidebarwrapper p.logo {
139 | padding: 0;
140 | margin: -10px 0 0 0px;
141 | text-align: center;
142 | }
143 |
144 | div.sphinxsidebarwrapper h1.logo {
145 | margin-top: -10px;
146 | text-align: center;
147 | margin-bottom: 5px;
148 | text-align: left;
149 | }
150 |
151 | div.sphinxsidebarwrapper h1.logo-name {
152 | margin-top: 0px;
153 | }
154 |
155 | div.sphinxsidebarwrapper p.blurb {
156 | margin-top: 0;
157 | font-style: normal;
158 | }
159 |
160 | div.sphinxsidebar h3,
161 | div.sphinxsidebar h4 {
162 | font-family: 'Garamond', 'Georgia', serif;
163 | color: #444;
164 | font-size: 24px;
165 | font-weight: normal;
166 | margin: 0 0 5px 0;
167 | padding: 0;
168 | }
169 |
170 | div.sphinxsidebar h4 {
171 | font-size: 20px;
172 | }
173 |
174 | div.sphinxsidebar h3 a {
175 | color: #444;
176 | }
177 |
178 | div.sphinxsidebar p.logo a,
179 | div.sphinxsidebar h3 a,
180 | div.sphinxsidebar p.logo a:hover,
181 | div.sphinxsidebar h3 a:hover {
182 | border: none;
183 | }
184 |
185 | div.sphinxsidebar p {
186 | color: #555;
187 | margin: 10px 0;
188 | }
189 |
190 | div.sphinxsidebar ul {
191 | margin: 10px 0;
192 | padding: 0;
193 | color: #000;
194 | }
195 |
196 | div.sphinxsidebar ul li.toctree-l1 > a {
197 | font-size: 120%;
198 | }
199 |
200 | div.sphinxsidebar ul li.toctree-l2 > a {
201 | font-size: 110%;
202 | }
203 |
204 | div.sphinxsidebar input {
205 | border: 1px solid #CCC;
206 | font-family: 'goudy old style', 'minion pro', 'bell mt', Georgia, 'Hiragino Mincho Pro', serif;
207 | font-size: 1em;
208 | }
209 |
210 | div.sphinxsidebar hr {
211 | border: none;
212 | height: 1px;
213 | color: #AAA;
214 | background: #AAA;
215 |
216 | text-align: left;
217 | margin-left: 0;
218 | width: 50%;
219 | }
220 |
221 | /* -- body styles ----------------------------------------------------------- */
222 |
223 | a {
224 | color: #004B6B;
225 | text-decoration: underline;
226 | }
227 |
228 | a:hover {
229 | color: #6D4100;
230 | text-decoration: underline;
231 | }
232 |
233 | div.body h1,
234 | div.body h2,
235 | div.body h3,
236 | div.body h4,
237 | div.body h5,
238 | div.body h6 {
239 | font-family: 'Garamond', 'Georgia', serif;
240 | font-weight: normal;
241 | margin: 30px 0px 10px 0px;
242 | padding: 0;
243 | }
244 |
245 | div.body h1 { margin-top: 0; padding-top: 0; font-size: 240%; }
246 | div.body h2 { font-size: 180%; }
247 | div.body h3 { font-size: 150%; }
248 | div.body h4 { font-size: 130%; }
249 | div.body h5 { font-size: 100%; }
250 | div.body h6 { font-size: 100%; }
251 |
252 | a.headerlink {
253 | color: #DDD;
254 | padding: 0 4px;
255 | text-decoration: none;
256 | }
257 |
258 | a.headerlink:hover {
259 | color: #444;
260 | background: #EAEAEA;
261 | }
262 |
263 | div.body p, div.body dd, div.body li {
264 | line-height: 1.4em;
265 | }
266 |
267 | div.admonition {
268 | margin: 20px 0px;
269 | padding: 10px 30px;
270 | background-color: #EEE;
271 | border: 1px solid #CCC;
272 | }
273 |
274 | div.admonition tt.xref, div.admonition code.xref, div.admonition a tt {
275 | background-color: #FBFBFB;
276 | border-bottom: 1px solid #fafafa;
277 | }
278 |
279 | div.admonition p.admonition-title {
280 | font-family: 'Garamond', 'Georgia', serif;
281 | font-weight: normal;
282 | font-size: 24px;
283 | margin: 0 0 10px 0;
284 | padding: 0;
285 | line-height: 1;
286 | }
287 |
288 | div.admonition p.last {
289 | margin-bottom: 0;
290 | }
291 |
292 | div.highlight {
293 | background-color: #fff;
294 | }
295 |
296 | dt:target, .highlight {
297 | background: #FAF3E8;
298 | }
299 |
300 | div.warning {
301 | background-color: #FCC;
302 | border: 1px solid #FAA;
303 | }
304 |
305 | div.danger {
306 | background-color: #FCC;
307 | border: 1px solid #FAA;
308 | -moz-box-shadow: 2px 2px 4px #D52C2C;
309 | -webkit-box-shadow: 2px 2px 4px #D52C2C;
310 | box-shadow: 2px 2px 4px #D52C2C;
311 | }
312 |
313 | div.error {
314 | background-color: #FCC;
315 | border: 1px solid #FAA;
316 | -moz-box-shadow: 2px 2px 4px #D52C2C;
317 | -webkit-box-shadow: 2px 2px 4px #D52C2C;
318 | box-shadow: 2px 2px 4px #D52C2C;
319 | }
320 |
321 | div.caution {
322 | background-color: #FCC;
323 | border: 1px solid #FAA;
324 | }
325 |
326 | div.attention {
327 | background-color: #FCC;
328 | border: 1px solid #FAA;
329 | }
330 |
331 | div.important {
332 | background-color: #EEE;
333 | border: 1px solid #CCC;
334 | }
335 |
336 | div.note {
337 | background-color: #EEE;
338 | border: 1px solid #CCC;
339 | }
340 |
341 | div.tip {
342 | background-color: #EEE;
343 | border: 1px solid #CCC;
344 | }
345 |
346 | div.hint {
347 | background-color: #EEE;
348 | border: 1px solid #CCC;
349 | }
350 |
351 | div.seealso {
352 | background-color: #EEE;
353 | border: 1px solid #CCC;
354 | }
355 |
356 | div.topic {
357 | background-color: #EEE;
358 | }
359 |
360 | p.admonition-title {
361 | display: inline;
362 | }
363 |
364 | p.admonition-title:after {
365 | content: ":";
366 | }
367 |
368 | pre, tt, code {
369 | font-family: 'Consolas', 'Menlo', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
370 | font-size: 0.9em;
371 | }
372 |
373 | .hll {
374 | background-color: #FFC;
375 | margin: 0 -12px;
376 | padding: 0 12px;
377 | display: block;
378 | }
379 |
380 | img.screenshot {
381 | }
382 |
383 | tt.descname, tt.descclassname, code.descname, code.descclassname {
384 | font-size: 0.95em;
385 | }
386 |
387 | tt.descname, code.descname {
388 | padding-right: 0.08em;
389 | }
390 |
391 | img.screenshot {
392 | -moz-box-shadow: 2px 2px 4px #EEE;
393 | -webkit-box-shadow: 2px 2px 4px #EEE;
394 | box-shadow: 2px 2px 4px #EEE;
395 | }
396 |
397 | table.docutils {
398 | border: 1px solid #888;
399 | -moz-box-shadow: 2px 2px 4px #EEE;
400 | -webkit-box-shadow: 2px 2px 4px #EEE;
401 | box-shadow: 2px 2px 4px #EEE;
402 | }
403 |
404 | table.docutils td, table.docutils th {
405 | border: 1px solid #888;
406 | padding: 0.25em 0.7em;
407 | }
408 |
409 | table.field-list, table.footnote {
410 | border: none;
411 | -moz-box-shadow: none;
412 | -webkit-box-shadow: none;
413 | box-shadow: none;
414 | }
415 |
416 | table.footnote {
417 | margin: 15px 0;
418 | width: 100%;
419 | border: 1px solid #EEE;
420 | background: #FDFDFD;
421 | font-size: 0.9em;
422 | }
423 |
424 | table.footnote + table.footnote {
425 | margin-top: -15px;
426 | border-top: none;
427 | }
428 |
429 | table.field-list th {
430 | padding: 0 0.8em 0 0;
431 | }
432 |
433 | table.field-list td {
434 | padding: 0;
435 | }
436 |
437 | table.field-list p {
438 | margin-bottom: 0.8em;
439 | }
440 |
441 | /* Cloned from
442 | * https://github.com/sphinx-doc/sphinx/commit/ef60dbfce09286b20b7385333d63a60321784e68
443 | */
444 | .field-name {
445 | -moz-hyphens: manual;
446 | -ms-hyphens: manual;
447 | -webkit-hyphens: manual;
448 | hyphens: manual;
449 | }
450 |
451 | table.footnote td.label {
452 | width: .1px;
453 | padding: 0.3em 0 0.3em 0.5em;
454 | }
455 |
456 | table.footnote td {
457 | padding: 0.3em 0.5em;
458 | }
459 |
460 | dl {
461 | margin: 0;
462 | padding: 0;
463 | }
464 |
465 | dl dd {
466 | margin-left: 30px;
467 | }
468 |
469 | blockquote {
470 | margin: 0 0 0 30px;
471 | padding: 0;
472 | }
473 |
474 | ul, ol {
475 | /* Matches the 30px from the narrow-screen "li > ul" selector below */
476 | margin: 10px 0 10px 30px;
477 | padding: 0;
478 | }
479 |
480 | pre {
481 | background: #EEE;
482 | padding: 7px 30px;
483 | margin: 15px 0px;
484 | line-height: 1.3em;
485 | }
486 |
487 | div.viewcode-block:target {
488 | background: #ffd;
489 | }
490 |
491 | dl pre, blockquote pre, li pre {
492 | margin-left: 0;
493 | padding-left: 30px;
494 | }
495 |
496 | tt, code {
497 | background-color: #ecf0f3;
498 | color: #222;
499 | /* padding: 1px 2px; */
500 | }
501 |
502 | tt.xref, code.xref, a tt {
503 | background-color: #FBFBFB;
504 | border-bottom: 1px solid #fff;
505 | }
506 |
507 | a.reference {
508 | text-decoration: none;
509 | border-bottom: 1px dotted #004B6B;
510 | }
511 |
512 | /* Don't put an underline on images */
513 | a.image-reference, a.image-reference:hover {
514 | border-bottom: none;
515 | }
516 |
517 | a.reference:hover {
518 | border-bottom: 1px solid #6D4100;
519 | }
520 |
521 | a.footnote-reference {
522 | text-decoration: none;
523 | font-size: 0.7em;
524 | vertical-align: top;
525 | border-bottom: 1px dotted #004B6B;
526 | }
527 |
528 | a.footnote-reference:hover {
529 | border-bottom: 1px solid #6D4100;
530 | }
531 |
532 | a:hover tt, a:hover code {
533 | background: #EEE;
534 | }
535 |
536 |
537 | @media screen and (max-width: 870px) {
538 |
539 | div.sphinxsidebar {
540 | display: none;
541 | }
542 |
543 | div.document {
544 | width: 100%;
545 |
546 | }
547 |
548 | div.documentwrapper {
549 | margin-left: 0;
550 | margin-top: 0;
551 | margin-right: 0;
552 | margin-bottom: 0;
553 | }
554 |
555 | div.bodywrapper {
556 | margin-top: 0;
557 | margin-right: 0;
558 | margin-bottom: 0;
559 | margin-left: 0;
560 | }
561 |
562 | ul {
563 | margin-left: 0;
564 | }
565 |
566 | li > ul {
567 | /* Matches the 30px from the "ul, ol" selector above */
568 | margin-left: 30px;
569 | }
570 |
571 | .document {
572 | width: auto;
573 | }
574 |
575 | .footer {
576 | width: auto;
577 | }
578 |
579 | .bodywrapper {
580 | margin: 0;
581 | }
582 |
583 | .footer {
584 | width: auto;
585 | }
586 |
587 | .github {
588 | display: none;
589 | }
590 |
591 |
592 |
593 | }
594 |
595 |
596 |
597 | @media screen and (max-width: 875px) {
598 |
599 | body {
600 | margin: 0;
601 | padding: 20px 30px;
602 | }
603 |
604 | div.documentwrapper {
605 | float: none;
606 | background: #fff;
607 | }
608 |
609 | div.sphinxsidebar {
610 | display: block;
611 | float: none;
612 | width: 102.5%;
613 | margin: 50px -30px -20px -30px;
614 | padding: 10px 20px;
615 | background: #333;
616 | color: #FFF;
617 | }
618 |
619 | div.sphinxsidebar h3, div.sphinxsidebar h4, div.sphinxsidebar p,
620 | div.sphinxsidebar h3 a {
621 | color: #fff;
622 | }
623 |
624 | div.sphinxsidebar a {
625 | color: #AAA;
626 | }
627 |
628 | div.sphinxsidebar p.logo {
629 | display: none;
630 | }
631 |
632 | div.document {
633 | width: 100%;
634 | margin: 0;
635 | }
636 |
637 | div.footer {
638 | display: none;
639 | }
640 |
641 | div.bodywrapper {
642 | margin: 0;
643 | }
644 |
645 | div.body {
646 | min-height: 0;
647 | padding: 0;
648 | }
649 |
650 | .rtd_doc_footer {
651 | display: none;
652 | }
653 |
654 | .document {
655 | width: auto;
656 | }
657 |
658 | .footer {
659 | width: auto;
660 | }
661 |
662 | .footer {
663 | width: auto;
664 | }
665 |
666 | .github {
667 | display: none;
668 | }
669 | }
670 |
671 |
672 | /* misc. */
673 |
674 | .revsys-inline {
675 | display: none!important;
676 | }
677 |
678 | /* Make nested-list/multi-paragraph items look better in Releases changelog
679 | * pages. Without this, docutils' magical list fuckery causes inconsistent
680 | * formatting between different release sub-lists.
681 | */
682 | div#changelog > div.section > ul > li > p:only-child {
683 | margin-bottom: 0;
684 | }
685 |
686 | /* Hide fugly table cell borders in ..bibliography:: directive output */
687 | table.docutils.citation, table.docutils.citation td, table.docutils.citation th {
688 | border: none;
689 | /* Below needed in some edge cases; if not applied, bottom shadows appear */
690 | -moz-box-shadow: none;
691 | -webkit-box-shadow: none;
692 | box-shadow: none;
693 | }
--------------------------------------------------------------------------------
/docs/build/html/_static/searchtools.js:
--------------------------------------------------------------------------------
1 | /*
2 | * searchtools.js_t
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 |
13 | /* Non-minified version JS is _stemmer.js if file is provided */
14 | /**
15 | * Porter Stemmer
16 | */
17 | var Stemmer = function() {
18 |
19 | var step2list = {
20 | ational: 'ate',
21 | tional: 'tion',
22 | enci: 'ence',
23 | anci: 'ance',
24 | izer: 'ize',
25 | bli: 'ble',
26 | alli: 'al',
27 | entli: 'ent',
28 | eli: 'e',
29 | ousli: 'ous',
30 | ization: 'ize',
31 | ation: 'ate',
32 | ator: 'ate',
33 | alism: 'al',
34 | iveness: 'ive',
35 | fulness: 'ful',
36 | ousness: 'ous',
37 | aliti: 'al',
38 | iviti: 'ive',
39 | biliti: 'ble',
40 | logi: 'log'
41 | };
42 |
43 | var step3list = {
44 | icate: 'ic',
45 | ative: '',
46 | alize: 'al',
47 | iciti: 'ic',
48 | ical: 'ic',
49 | ful: '',
50 | ness: ''
51 | };
52 |
53 | var c = "[^aeiou]"; // consonant
54 | var v = "[aeiouy]"; // vowel
55 | var C = c + "[^aeiouy]*"; // consonant sequence
56 | var V = v + "[aeiou]*"; // vowel sequence
57 |
58 | var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0
59 | var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1
60 | var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1
61 | var s_v = "^(" + C + ")?" + v; // vowel in stem
62 |
63 | this.stemWord = function (w) {
64 | var stem;
65 | var suffix;
66 | var firstch;
67 | var origword = w;
68 |
69 | if (w.length < 3)
70 | return w;
71 |
72 | var re;
73 | var re2;
74 | var re3;
75 | var re4;
76 |
77 | firstch = w.substr(0,1);
78 | if (firstch == "y")
79 | w = firstch.toUpperCase() + w.substr(1);
80 |
81 | // Step 1a
82 | re = /^(.+?)(ss|i)es$/;
83 | re2 = /^(.+?)([^s])s$/;
84 |
85 | if (re.test(w))
86 | w = w.replace(re,"$1$2");
87 | else if (re2.test(w))
88 | w = w.replace(re2,"$1$2");
89 |
90 | // Step 1b
91 | re = /^(.+?)eed$/;
92 | re2 = /^(.+?)(ed|ing)$/;
93 | if (re.test(w)) {
94 | var fp = re.exec(w);
95 | re = new RegExp(mgr0);
96 | if (re.test(fp[1])) {
97 | re = /.$/;
98 | w = w.replace(re,"");
99 | }
100 | }
101 | else if (re2.test(w)) {
102 | var fp = re2.exec(w);
103 | stem = fp[1];
104 | re2 = new RegExp(s_v);
105 | if (re2.test(stem)) {
106 | w = stem;
107 | re2 = /(at|bl|iz)$/;
108 | re3 = new RegExp("([^aeiouylsz])\\1$");
109 | re4 = new RegExp("^" + C + v + "[^aeiouwxy]$");
110 | if (re2.test(w))
111 | w = w + "e";
112 | else if (re3.test(w)) {
113 | re = /.$/;
114 | w = w.replace(re,"");
115 | }
116 | else if (re4.test(w))
117 | w = w + "e";
118 | }
119 | }
120 |
121 | // Step 1c
122 | re = /^(.+?)y$/;
123 | if (re.test(w)) {
124 | var fp = re.exec(w);
125 | stem = fp[1];
126 | re = new RegExp(s_v);
127 | if (re.test(stem))
128 | w = stem + "i";
129 | }
130 |
131 | // Step 2
132 | re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/;
133 | if (re.test(w)) {
134 | var fp = re.exec(w);
135 | stem = fp[1];
136 | suffix = fp[2];
137 | re = new RegExp(mgr0);
138 | if (re.test(stem))
139 | w = stem + step2list[suffix];
140 | }
141 |
142 | // Step 3
143 | re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/;
144 | if (re.test(w)) {
145 | var fp = re.exec(w);
146 | stem = fp[1];
147 | suffix = fp[2];
148 | re = new RegExp(mgr0);
149 | if (re.test(stem))
150 | w = stem + step3list[suffix];
151 | }
152 |
153 | // Step 4
154 | re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/;
155 | re2 = /^(.+?)(s|t)(ion)$/;
156 | if (re.test(w)) {
157 | var fp = re.exec(w);
158 | stem = fp[1];
159 | re = new RegExp(mgr1);
160 | if (re.test(stem))
161 | w = stem;
162 | }
163 | else if (re2.test(w)) {
164 | var fp = re2.exec(w);
165 | stem = fp[1] + fp[2];
166 | re2 = new RegExp(mgr1);
167 | if (re2.test(stem))
168 | w = stem;
169 | }
170 |
171 | // Step 5
172 | re = /^(.+?)e$/;
173 | if (re.test(w)) {
174 | var fp = re.exec(w);
175 | stem = fp[1];
176 | re = new RegExp(mgr1);
177 | re2 = new RegExp(meq1);
178 | re3 = new RegExp("^" + C + v + "[^aeiouwxy]$");
179 | if (re.test(stem) || (re2.test(stem) && !(re3.test(stem))))
180 | w = stem;
181 | }
182 | re = /ll$/;
183 | re2 = new RegExp(mgr1);
184 | if (re.test(w) && re2.test(w)) {
185 | re = /.$/;
186 | w = w.replace(re,"");
187 | }
188 |
189 | // and turn initial Y back to y
190 | if (firstch == "y")
191 | w = firstch.toLowerCase() + w.substr(1);
192 | return w;
193 | }
194 | }
195 |
196 |
197 |
198 | /**
199 | * Simple result scoring code.
200 | */
201 | var Scorer = {
202 | // Implement the following function to further tweak the score for each result
203 | // The function takes a result array [filename, title, anchor, descr, score]
204 | // and returns the new score.
205 | /*
206 | score: function(result) {
207 | return result[4];
208 | },
209 | */
210 |
211 | // query matches the full name of an object
212 | objNameMatch: 11,
213 | // or matches in the last dotted part of the object name
214 | objPartialMatch: 6,
215 | // Additive scores depending on the priority of the object
216 | objPrio: {0: 15, // used to be importantResults
217 | 1: 5, // used to be objectResults
218 | 2: -5}, // used to be unimportantResults
219 | // Used when the priority is not in the mapping.
220 | objPrioDefault: 0,
221 |
222 | // query found in title
223 | title: 15,
224 | // query found in terms
225 | term: 5
226 | };
227 |
228 |
229 |
230 |
231 |
232 | var splitChars = (function() {
233 | var result = {};
234 | var singles = [96, 180, 187, 191, 215, 247, 749, 885, 903, 907, 909, 930, 1014, 1648,
235 | 1748, 1809, 2416, 2473, 2481, 2526, 2601, 2609, 2612, 2615, 2653, 2702,
236 | 2706, 2729, 2737, 2740, 2857, 2865, 2868, 2910, 2928, 2948, 2961, 2971,
237 | 2973, 3085, 3089, 3113, 3124, 3213, 3217, 3241, 3252, 3295, 3341, 3345,
238 | 3369, 3506, 3516, 3633, 3715, 3721, 3736, 3744, 3748, 3750, 3756, 3761,
239 | 3781, 3912, 4239, 4347, 4681, 4695, 4697, 4745, 4785, 4799, 4801, 4823,
240 | 4881, 5760, 5901, 5997, 6313, 7405, 8024, 8026, 8028, 8030, 8117, 8125,
241 | 8133, 8181, 8468, 8485, 8487, 8489, 8494, 8527, 11311, 11359, 11687, 11695,
242 | 11703, 11711, 11719, 11727, 11735, 12448, 12539, 43010, 43014, 43019, 43587,
243 | 43696, 43713, 64286, 64297, 64311, 64317, 64319, 64322, 64325, 65141];
244 | var i, j, start, end;
245 | for (i = 0; i < singles.length; i++) {
246 | result[singles[i]] = true;
247 | }
248 | var ranges = [[0, 47], [58, 64], [91, 94], [123, 169], [171, 177], [182, 184], [706, 709],
249 | [722, 735], [741, 747], [751, 879], [888, 889], [894, 901], [1154, 1161],
250 | [1318, 1328], [1367, 1368], [1370, 1376], [1416, 1487], [1515, 1519], [1523, 1568],
251 | [1611, 1631], [1642, 1645], [1750, 1764], [1767, 1773], [1789, 1790], [1792, 1807],
252 | [1840, 1868], [1958, 1968], [1970, 1983], [2027, 2035], [2038, 2041], [2043, 2047],
253 | [2070, 2073], [2075, 2083], [2085, 2087], [2089, 2307], [2362, 2364], [2366, 2383],
254 | [2385, 2391], [2402, 2405], [2419, 2424], [2432, 2436], [2445, 2446], [2449, 2450],
255 | [2483, 2485], [2490, 2492], [2494, 2509], [2511, 2523], [2530, 2533], [2546, 2547],
256 | [2554, 2564], [2571, 2574], [2577, 2578], [2618, 2648], [2655, 2661], [2672, 2673],
257 | [2677, 2692], [2746, 2748], [2750, 2767], [2769, 2783], [2786, 2789], [2800, 2820],
258 | [2829, 2830], [2833, 2834], [2874, 2876], [2878, 2907], [2914, 2917], [2930, 2946],
259 | [2955, 2957], [2966, 2968], [2976, 2978], [2981, 2983], [2987, 2989], [3002, 3023],
260 | [3025, 3045], [3059, 3076], [3130, 3132], [3134, 3159], [3162, 3167], [3170, 3173],
261 | [3184, 3191], [3199, 3204], [3258, 3260], [3262, 3293], [3298, 3301], [3312, 3332],
262 | [3386, 3388], [3390, 3423], [3426, 3429], [3446, 3449], [3456, 3460], [3479, 3481],
263 | [3518, 3519], [3527, 3584], [3636, 3647], [3655, 3663], [3674, 3712], [3717, 3718],
264 | [3723, 3724], [3726, 3731], [3752, 3753], [3764, 3772], [3774, 3775], [3783, 3791],
265 | [3802, 3803], [3806, 3839], [3841, 3871], [3892, 3903], [3949, 3975], [3980, 4095],
266 | [4139, 4158], [4170, 4175], [4182, 4185], [4190, 4192], [4194, 4196], [4199, 4205],
267 | [4209, 4212], [4226, 4237], [4250, 4255], [4294, 4303], [4349, 4351], [4686, 4687],
268 | [4702, 4703], [4750, 4751], [4790, 4791], [4806, 4807], [4886, 4887], [4955, 4968],
269 | [4989, 4991], [5008, 5023], [5109, 5120], [5741, 5742], [5787, 5791], [5867, 5869],
270 | [5873, 5887], [5906, 5919], [5938, 5951], [5970, 5983], [6001, 6015], [6068, 6102],
271 | [6104, 6107], [6109, 6111], [6122, 6127], [6138, 6159], [6170, 6175], [6264, 6271],
272 | [6315, 6319], [6390, 6399], [6429, 6469], [6510, 6511], [6517, 6527], [6572, 6592],
273 | [6600, 6607], [6619, 6655], [6679, 6687], [6741, 6783], [6794, 6799], [6810, 6822],
274 | [6824, 6916], [6964, 6980], [6988, 6991], [7002, 7042], [7073, 7085], [7098, 7167],
275 | [7204, 7231], [7242, 7244], [7294, 7400], [7410, 7423], [7616, 7679], [7958, 7959],
276 | [7966, 7967], [8006, 8007], [8014, 8015], [8062, 8063], [8127, 8129], [8141, 8143],
277 | [8148, 8149], [8156, 8159], [8173, 8177], [8189, 8303], [8306, 8307], [8314, 8318],
278 | [8330, 8335], [8341, 8449], [8451, 8454], [8456, 8457], [8470, 8472], [8478, 8483],
279 | [8506, 8507], [8512, 8516], [8522, 8525], [8586, 9311], [9372, 9449], [9472, 10101],
280 | [10132, 11263], [11493, 11498], [11503, 11516], [11518, 11519], [11558, 11567],
281 | [11622, 11630], [11632, 11647], [11671, 11679], [11743, 11822], [11824, 12292],
282 | [12296, 12320], [12330, 12336], [12342, 12343], [12349, 12352], [12439, 12444],
283 | [12544, 12548], [12590, 12592], [12687, 12689], [12694, 12703], [12728, 12783],
284 | [12800, 12831], [12842, 12880], [12896, 12927], [12938, 12976], [12992, 13311],
285 | [19894, 19967], [40908, 40959], [42125, 42191], [42238, 42239], [42509, 42511],
286 | [42540, 42559], [42592, 42593], [42607, 42622], [42648, 42655], [42736, 42774],
287 | [42784, 42785], [42889, 42890], [42893, 43002], [43043, 43055], [43062, 43071],
288 | [43124, 43137], [43188, 43215], [43226, 43249], [43256, 43258], [43260, 43263],
289 | [43302, 43311], [43335, 43359], [43389, 43395], [43443, 43470], [43482, 43519],
290 | [43561, 43583], [43596, 43599], [43610, 43615], [43639, 43641], [43643, 43647],
291 | [43698, 43700], [43703, 43704], [43710, 43711], [43715, 43738], [43742, 43967],
292 | [44003, 44015], [44026, 44031], [55204, 55215], [55239, 55242], [55292, 55295],
293 | [57344, 63743], [64046, 64047], [64110, 64111], [64218, 64255], [64263, 64274],
294 | [64280, 64284], [64434, 64466], [64830, 64847], [64912, 64913], [64968, 65007],
295 | [65020, 65135], [65277, 65295], [65306, 65312], [65339, 65344], [65371, 65381],
296 | [65471, 65473], [65480, 65481], [65488, 65489], [65496, 65497]];
297 | for (i = 0; i < ranges.length; i++) {
298 | start = ranges[i][0];
299 | end = ranges[i][1];
300 | for (j = start; j <= end; j++) {
301 | result[j] = true;
302 | }
303 | }
304 | return result;
305 | })();
306 |
307 | function splitQuery(query) {
308 | var result = [];
309 | var start = -1;
310 | for (var i = 0; i < query.length; i++) {
311 | if (splitChars[query.charCodeAt(i)]) {
312 | if (start !== -1) {
313 | result.push(query.slice(start, i));
314 | start = -1;
315 | }
316 | } else if (start === -1) {
317 | start = i;
318 | }
319 | }
320 | if (start !== -1) {
321 | result.push(query.slice(start));
322 | }
323 | return result;
324 | }
325 |
326 |
327 |
328 |
329 | /**
330 | * Search Module
331 | */
332 | var Search = {
333 |
334 | _index : null,
335 | _queued_query : null,
336 | _pulse_status : -1,
337 |
338 | init : function() {
339 | var params = $.getQueryParameters();
340 | if (params.q) {
341 | var query = params.q[0];
342 | $('input[name="q"]')[0].value = query;
343 | this.performSearch(query);
344 | }
345 | },
346 |
347 | loadIndex : function(url) {
348 | $.ajax({type: "GET", url: url, data: null,
349 | dataType: "script", cache: true,
350 | complete: function(jqxhr, textstatus) {
351 | if (textstatus != "success") {
352 | document.getElementById("searchindexloader").src = url;
353 | }
354 | }});
355 | },
356 |
357 | setIndex : function(index) {
358 | var q;
359 | this._index = index;
360 | if ((q = this._queued_query) !== null) {
361 | this._queued_query = null;
362 | Search.query(q);
363 | }
364 | },
365 |
366 | hasIndex : function() {
367 | return this._index !== null;
368 | },
369 |
370 | deferQuery : function(query) {
371 | this._queued_query = query;
372 | },
373 |
374 | stopPulse : function() {
375 | this._pulse_status = 0;
376 | },
377 |
378 | startPulse : function() {
379 | if (this._pulse_status >= 0)
380 | return;
381 | function pulse() {
382 | var i;
383 | Search._pulse_status = (Search._pulse_status + 1) % 4;
384 | var dotString = '';
385 | for (i = 0; i < Search._pulse_status; i++)
386 | dotString += '.';
387 | Search.dots.text(dotString);
388 | if (Search._pulse_status > -1)
389 | window.setTimeout(pulse, 500);
390 | }
391 | pulse();
392 | },
393 |
394 | /**
395 | * perform a search for something (or wait until index is loaded)
396 | */
397 | performSearch : function(query) {
398 | // create the required interface elements
399 | this.out = $('#search-results');
400 | this.title = $('' + _('Searching') + ' ').appendTo(this.out);
401 | this.dots = $(' ').appendTo(this.title);
402 | this.status = $('
').appendTo(this.out);
403 | this.output = $('').appendTo(this.out);
404 |
405 | $('#search-progress').text(_('Preparing search...'));
406 | this.startPulse();
407 |
408 | // index already loaded, the browser was quick!
409 | if (this.hasIndex())
410 | this.query(query);
411 | else
412 | this.deferQuery(query);
413 | },
414 |
415 | /**
416 | * execute search (requires search index to be loaded)
417 | */
418 | query : function(query) {
419 | var i;
420 | var stopwords = ["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"];
421 |
422 | // stem the searchterms and add them to the correct list
423 | var stemmer = new Stemmer();
424 | var searchterms = [];
425 | var excluded = [];
426 | var hlterms = [];
427 | var tmp = splitQuery(query);
428 | var objectterms = [];
429 | for (i = 0; i < tmp.length; i++) {
430 | if (tmp[i] !== "") {
431 | objectterms.push(tmp[i].toLowerCase());
432 | }
433 |
434 | if ($u.indexOf(stopwords, tmp[i].toLowerCase()) != -1 || tmp[i].match(/^\d+$/) ||
435 | tmp[i] === "") {
436 | // skip this "word"
437 | continue;
438 | }
439 | // stem the word
440 | var word = stemmer.stemWord(tmp[i].toLowerCase());
441 | // prevent stemmer from cutting word smaller than two chars
442 | if(word.length < 3 && tmp[i].length >= 3) {
443 | word = tmp[i];
444 | }
445 | var toAppend;
446 | // select the correct list
447 | if (word[0] == '-') {
448 | toAppend = excluded;
449 | word = word.substr(1);
450 | }
451 | else {
452 | toAppend = searchterms;
453 | hlterms.push(tmp[i].toLowerCase());
454 | }
455 | // only add if not already in the list
456 | if (!$u.contains(toAppend, word))
457 | toAppend.push(word);
458 | }
459 | var highlightstring = '?highlight=' + $.urlencode(hlterms.join(" "));
460 |
461 | // console.debug('SEARCH: searching for:');
462 | // console.info('required: ', searchterms);
463 | // console.info('excluded: ', excluded);
464 |
465 | // prepare search
466 | var terms = this._index.terms;
467 | var titleterms = this._index.titleterms;
468 |
469 | // array of [filename, title, anchor, descr, score]
470 | var results = [];
471 | $('#search-progress').empty();
472 |
473 | // lookup as object
474 | for (i = 0; i < objectterms.length; i++) {
475 | var others = [].concat(objectterms.slice(0, i),
476 | objectterms.slice(i+1, objectterms.length));
477 | results = results.concat(this.performObjectSearch(objectterms[i], others));
478 | }
479 |
480 | // lookup as search terms in fulltext
481 | results = results.concat(this.performTermsSearch(searchterms, excluded, terms, titleterms));
482 |
483 | // let the scorer override scores with a custom scoring function
484 | if (Scorer.score) {
485 | for (i = 0; i < results.length; i++)
486 | results[i][4] = Scorer.score(results[i]);
487 | }
488 |
489 | // now sort the results by score (in opposite order of appearance, since the
490 | // display function below uses pop() to retrieve items) and then
491 | // alphabetically
492 | results.sort(function(a, b) {
493 | var left = a[4];
494 | var right = b[4];
495 | if (left > right) {
496 | return 1;
497 | } else if (left < right) {
498 | return -1;
499 | } else {
500 | // same score: sort alphabetically
501 | left = a[1].toLowerCase();
502 | right = b[1].toLowerCase();
503 | return (left > right) ? -1 : ((left < right) ? 1 : 0);
504 | }
505 | });
506 |
507 | // for debugging
508 | //Search.lastresults = results.slice(); // a copy
509 | //console.info('search results:', Search.lastresults);
510 |
511 | // print the results
512 | var resultCount = results.length;
513 | function displayNextItem() {
514 | // results left, load the summary and display it
515 | if (results.length) {
516 | var item = results.pop();
517 | var listItem = $(' ');
518 | if (DOCUMENTATION_OPTIONS.FILE_SUFFIX === '') {
519 | // dirhtml builder
520 | var dirname = item[0] + '/';
521 | if (dirname.match(/\/index\/$/)) {
522 | dirname = dirname.substring(0, dirname.length-6);
523 | } else if (dirname == 'index/') {
524 | dirname = '';
525 | }
526 | listItem.append($(' ').attr('href',
527 | DOCUMENTATION_OPTIONS.URL_ROOT + dirname +
528 | highlightstring + item[2]).html(item[1]));
529 | } else {
530 | // normal html builders
531 | listItem.append($(' ').attr('href',
532 | item[0] + DOCUMENTATION_OPTIONS.FILE_SUFFIX +
533 | highlightstring + item[2]).html(item[1]));
534 | }
535 | if (item[3]) {
536 | listItem.append($(' (' + item[3] + ') '));
537 | Search.output.append(listItem);
538 | listItem.slideDown(5, function() {
539 | displayNextItem();
540 | });
541 | } else if (DOCUMENTATION_OPTIONS.HAS_SOURCE) {
542 | var suffix = DOCUMENTATION_OPTIONS.SOURCELINK_SUFFIX;
543 | if (suffix === undefined) {
544 | suffix = '.txt';
545 | }
546 | $.ajax({url: DOCUMENTATION_OPTIONS.URL_ROOT + '_sources/' + item[5] + (item[5].slice(-suffix.length) === suffix ? '' : suffix),
547 | dataType: "text",
548 | complete: function(jqxhr, textstatus) {
549 | var data = jqxhr.responseText;
550 | if (data !== '' && data !== undefined) {
551 | listItem.append(Search.makeSearchSummary(data, searchterms, hlterms));
552 | }
553 | Search.output.append(listItem);
554 | listItem.slideDown(5, function() {
555 | displayNextItem();
556 | });
557 | }});
558 | } else {
559 | // no source available, just display title
560 | Search.output.append(listItem);
561 | listItem.slideDown(5, function() {
562 | displayNextItem();
563 | });
564 | }
565 | }
566 | // search finished, update title and status message
567 | else {
568 | Search.stopPulse();
569 | Search.title.text(_('Search Results'));
570 | if (!resultCount)
571 | 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.'));
572 | else
573 | Search.status.text(_('Search finished, found %s page(s) matching the search query.').replace('%s', resultCount));
574 | Search.status.fadeIn(500);
575 | }
576 | }
577 | displayNextItem();
578 | },
579 |
580 | /**
581 | * search for object names
582 | */
583 | performObjectSearch : function(object, otherterms) {
584 | var filenames = this._index.filenames;
585 | var docnames = this._index.docnames;
586 | var objects = this._index.objects;
587 | var objnames = this._index.objnames;
588 | var titles = this._index.titles;
589 |
590 | var i;
591 | var results = [];
592 |
593 | for (var prefix in objects) {
594 | for (var name in objects[prefix]) {
595 | var fullname = (prefix ? prefix + '.' : '') + name;
596 | if (fullname.toLowerCase().indexOf(object) > -1) {
597 | var score = 0;
598 | var parts = fullname.split('.');
599 | // check for different match types: exact matches of full name or
600 | // "last name" (i.e. last dotted part)
601 | if (fullname == object || parts[parts.length - 1] == object) {
602 | score += Scorer.objNameMatch;
603 | // matches in last name
604 | } else if (parts[parts.length - 1].indexOf(object) > -1) {
605 | score += Scorer.objPartialMatch;
606 | }
607 | var match = objects[prefix][name];
608 | var objname = objnames[match[1]][2];
609 | var title = titles[match[0]];
610 | // If more than one term searched for, we require other words to be
611 | // found in the name/title/description
612 | if (otherterms.length > 0) {
613 | var haystack = (prefix + ' ' + name + ' ' +
614 | objname + ' ' + title).toLowerCase();
615 | var allfound = true;
616 | for (i = 0; i < otherterms.length; i++) {
617 | if (haystack.indexOf(otherterms[i]) == -1) {
618 | allfound = false;
619 | break;
620 | }
621 | }
622 | if (!allfound) {
623 | continue;
624 | }
625 | }
626 | var descr = objname + _(', in ') + title;
627 |
628 | var anchor = match[3];
629 | if (anchor === '')
630 | anchor = fullname;
631 | else if (anchor == '-')
632 | anchor = objnames[match[1]][1] + '-' + fullname;
633 | // add custom score for some objects according to scorer
634 | if (Scorer.objPrio.hasOwnProperty(match[2])) {
635 | score += Scorer.objPrio[match[2]];
636 | } else {
637 | score += Scorer.objPrioDefault;
638 | }
639 | results.push([docnames[match[0]], fullname, '#'+anchor, descr, score, filenames[match[0]]]);
640 | }
641 | }
642 | }
643 |
644 | return results;
645 | },
646 |
647 | /**
648 | * search for full-text terms in the index
649 | */
650 | performTermsSearch : function(searchterms, excluded, terms, titleterms) {
651 | var docnames = this._index.docnames;
652 | var filenames = this._index.filenames;
653 | var titles = this._index.titles;
654 |
655 | var i, j, file;
656 | var fileMap = {};
657 | var scoreMap = {};
658 | var results = [];
659 |
660 | // perform the search on the required terms
661 | for (i = 0; i < searchterms.length; i++) {
662 | var word = searchterms[i];
663 | var files = [];
664 | var _o = [
665 | {files: terms[word], score: Scorer.term},
666 | {files: titleterms[word], score: Scorer.title}
667 | ];
668 |
669 | // no match but word was a required one
670 | if ($u.every(_o, function(o){return o.files === undefined;})) {
671 | break;
672 | }
673 | // found search word in contents
674 | $u.each(_o, function(o) {
675 | var _files = o.files;
676 | if (_files === undefined)
677 | return
678 |
679 | if (_files.length === undefined)
680 | _files = [_files];
681 | files = files.concat(_files);
682 |
683 | // set score for the word in each file to Scorer.term
684 | for (j = 0; j < _files.length; j++) {
685 | file = _files[j];
686 | if (!(file in scoreMap))
687 | scoreMap[file] = {}
688 | scoreMap[file][word] = o.score;
689 | }
690 | });
691 |
692 | // create the mapping
693 | for (j = 0; j < files.length; j++) {
694 | file = files[j];
695 | if (file in fileMap)
696 | fileMap[file].push(word);
697 | else
698 | fileMap[file] = [word];
699 | }
700 | }
701 |
702 | // now check if the files don't contain excluded terms
703 | for (file in fileMap) {
704 | var valid = true;
705 |
706 | // check if all requirements are matched
707 | if (fileMap[file].length != searchterms.length)
708 | continue;
709 |
710 | // ensure that none of the excluded terms is in the search result
711 | for (i = 0; i < excluded.length; i++) {
712 | if (terms[excluded[i]] == file ||
713 | titleterms[excluded[i]] == file ||
714 | $u.contains(terms[excluded[i]] || [], file) ||
715 | $u.contains(titleterms[excluded[i]] || [], file)) {
716 | valid = false;
717 | break;
718 | }
719 | }
720 |
721 | // if we have still a valid result we can add it to the result list
722 | if (valid) {
723 | // select one (max) score for the file.
724 | // for better ranking, we should calculate ranking by using words statistics like basic tf-idf...
725 | var score = $u.max($u.map(fileMap[file], function(w){return scoreMap[file][w]}));
726 | results.push([docnames[file], titles[file], '', null, score, filenames[file]]);
727 | }
728 | }
729 | return results;
730 | },
731 |
732 | /**
733 | * helper function to return a node containing the
734 | * search summary for a given text. keywords is a list
735 | * of stemmed words, hlwords is the list of normal, unstemmed
736 | * words. the first one is used to find the occurrence, the
737 | * latter for highlighting it.
738 | */
739 | makeSearchSummary : function(text, keywords, hlwords) {
740 | var textLower = text.toLowerCase();
741 | var start = 0;
742 | $.each(keywords, function() {
743 | var i = textLower.indexOf(this.toLowerCase());
744 | if (i > -1)
745 | start = i;
746 | });
747 | start = Math.max(start - 120, 0);
748 | var excerpt = ((start > 0) ? '...' : '') +
749 | $.trim(text.substr(start, 240)) +
750 | ((start + 240 - text.length) ? '...' : '');
751 | var rv = $('
').text(excerpt);
752 | $.each(hlwords, function() {
753 | rv = rv.highlightText(this, 'highlighted');
754 | });
755 | return rv;
756 | }
757 | };
758 |
759 | $(document).ready(function() {
760 | Search.init();
761 | });
--------------------------------------------------------------------------------
/docs/build/html/_static/websupport.js:
--------------------------------------------------------------------------------
1 | /*
2 | * websupport.js
3 | * ~~~~~~~~~~~~~
4 | *
5 | * sphinx.websupport 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 | (function($) {
13 | $.fn.autogrow = function() {
14 | return this.each(function() {
15 | var textarea = this;
16 |
17 | $.fn.autogrow.resize(textarea);
18 |
19 | $(textarea)
20 | .focus(function() {
21 | textarea.interval = setInterval(function() {
22 | $.fn.autogrow.resize(textarea);
23 | }, 500);
24 | })
25 | .blur(function() {
26 | clearInterval(textarea.interval);
27 | });
28 | });
29 | };
30 |
31 | $.fn.autogrow.resize = function(textarea) {
32 | var lineHeight = parseInt($(textarea).css('line-height'), 10);
33 | var lines = textarea.value.split('\n');
34 | var columns = textarea.cols;
35 | var lineCount = 0;
36 | $.each(lines, function() {
37 | lineCount += Math.ceil(this.length / columns) || 1;
38 | });
39 | var height = lineHeight * (lineCount + 1);
40 | $(textarea).css('height', height);
41 | };
42 | })(jQuery);
43 |
44 | (function($) {
45 | var comp, by;
46 |
47 | function init() {
48 | initEvents();
49 | initComparator();
50 | }
51 |
52 | function initEvents() {
53 | $(document).on("click", 'a.comment-close', function(event) {
54 | event.preventDefault();
55 | hide($(this).attr('id').substring(2));
56 | });
57 | $(document).on("click", 'a.vote', function(event) {
58 | event.preventDefault();
59 | handleVote($(this));
60 | });
61 | $(document).on("click", 'a.reply', function(event) {
62 | event.preventDefault();
63 | openReply($(this).attr('id').substring(2));
64 | });
65 | $(document).on("click", 'a.close-reply', function(event) {
66 | event.preventDefault();
67 | closeReply($(this).attr('id').substring(2));
68 | });
69 | $(document).on("click", 'a.sort-option', function(event) {
70 | event.preventDefault();
71 | handleReSort($(this));
72 | });
73 | $(document).on("click", 'a.show-proposal', function(event) {
74 | event.preventDefault();
75 | showProposal($(this).attr('id').substring(2));
76 | });
77 | $(document).on("click", 'a.hide-proposal', function(event) {
78 | event.preventDefault();
79 | hideProposal($(this).attr('id').substring(2));
80 | });
81 | $(document).on("click", 'a.show-propose-change', function(event) {
82 | event.preventDefault();
83 | showProposeChange($(this).attr('id').substring(2));
84 | });
85 | $(document).on("click", 'a.hide-propose-change', function(event) {
86 | event.preventDefault();
87 | hideProposeChange($(this).attr('id').substring(2));
88 | });
89 | $(document).on("click", 'a.accept-comment', function(event) {
90 | event.preventDefault();
91 | acceptComment($(this).attr('id').substring(2));
92 | });
93 | $(document).on("click", 'a.delete-comment', function(event) {
94 | event.preventDefault();
95 | deleteComment($(this).attr('id').substring(2));
96 | });
97 | $(document).on("click", 'a.comment-markup', function(event) {
98 | event.preventDefault();
99 | toggleCommentMarkupBox($(this).attr('id').substring(2));
100 | });
101 | }
102 |
103 | /**
104 | * Set comp, which is a comparator function used for sorting and
105 | * inserting comments into the list.
106 | */
107 | function setComparator() {
108 | // If the first three letters are "asc", sort in ascending order
109 | // and remove the prefix.
110 | if (by.substring(0,3) == 'asc') {
111 | var i = by.substring(3);
112 | comp = function(a, b) { return a[i] - b[i]; };
113 | } else {
114 | // Otherwise sort in descending order.
115 | comp = function(a, b) { return b[by] - a[by]; };
116 | }
117 |
118 | // Reset link styles and format the selected sort option.
119 | $('a.sel').attr('href', '#').removeClass('sel');
120 | $('a.by' + by).removeAttr('href').addClass('sel');
121 | }
122 |
123 | /**
124 | * Create a comp function. If the user has preferences stored in
125 | * the sortBy cookie, use those, otherwise use the default.
126 | */
127 | function initComparator() {
128 | by = 'rating'; // Default to sort by rating.
129 | // If the sortBy cookie is set, use that instead.
130 | if (document.cookie.length > 0) {
131 | var start = document.cookie.indexOf('sortBy=');
132 | if (start != -1) {
133 | start = start + 7;
134 | var end = document.cookie.indexOf(";", start);
135 | if (end == -1) {
136 | end = document.cookie.length;
137 | by = unescape(document.cookie.substring(start, end));
138 | }
139 | }
140 | }
141 | setComparator();
142 | }
143 |
144 | /**
145 | * Show a comment div.
146 | */
147 | function show(id) {
148 | $('#ao' + id).hide();
149 | $('#ah' + id).show();
150 | var context = $.extend({id: id}, opts);
151 | var popup = $(renderTemplate(popupTemplate, context)).hide();
152 | popup.find('textarea[name="proposal"]').hide();
153 | popup.find('a.by' + by).addClass('sel');
154 | var form = popup.find('#cf' + id);
155 | form.submit(function(event) {
156 | event.preventDefault();
157 | addComment(form);
158 | });
159 | $('#s' + id).after(popup);
160 | popup.slideDown('fast', function() {
161 | getComments(id);
162 | });
163 | }
164 |
165 | /**
166 | * Hide a comment div.
167 | */
168 | function hide(id) {
169 | $('#ah' + id).hide();
170 | $('#ao' + id).show();
171 | var div = $('#sc' + id);
172 | div.slideUp('fast', function() {
173 | div.remove();
174 | });
175 | }
176 |
177 | /**
178 | * Perform an ajax request to get comments for a node
179 | * and insert the comments into the comments tree.
180 | */
181 | function getComments(id) {
182 | $.ajax({
183 | type: 'GET',
184 | url: opts.getCommentsURL,
185 | data: {node: id},
186 | success: function(data, textStatus, request) {
187 | var ul = $('#cl' + id);
188 | var speed = 100;
189 | $('#cf' + id)
190 | .find('textarea[name="proposal"]')
191 | .data('source', data.source);
192 |
193 | if (data.comments.length === 0) {
194 | ul.html('No comments yet. ');
195 | ul.data('empty', true);
196 | } else {
197 | // If there are comments, sort them and put them in the list.
198 | var comments = sortComments(data.comments);
199 | speed = data.comments.length * 100;
200 | appendComments(comments, ul);
201 | ul.data('empty', false);
202 | }
203 | $('#cn' + id).slideUp(speed + 200);
204 | ul.slideDown(speed);
205 | },
206 | error: function(request, textStatus, error) {
207 | showError('Oops, there was a problem retrieving the comments.');
208 | },
209 | dataType: 'json'
210 | });
211 | }
212 |
213 | /**
214 | * Add a comment via ajax and insert the comment into the comment tree.
215 | */
216 | function addComment(form) {
217 | var node_id = form.find('input[name="node"]').val();
218 | var parent_id = form.find('input[name="parent"]').val();
219 | var text = form.find('textarea[name="comment"]').val();
220 | var proposal = form.find('textarea[name="proposal"]').val();
221 |
222 | if (text == '') {
223 | showError('Please enter a comment.');
224 | return;
225 | }
226 |
227 | // Disable the form that is being submitted.
228 | form.find('textarea,input').attr('disabled', 'disabled');
229 |
230 | // Send the comment to the server.
231 | $.ajax({
232 | type: "POST",
233 | url: opts.addCommentURL,
234 | dataType: 'json',
235 | data: {
236 | node: node_id,
237 | parent: parent_id,
238 | text: text,
239 | proposal: proposal
240 | },
241 | success: function(data, textStatus, error) {
242 | // Reset the form.
243 | if (node_id) {
244 | hideProposeChange(node_id);
245 | }
246 | form.find('textarea')
247 | .val('')
248 | .add(form.find('input'))
249 | .removeAttr('disabled');
250 | var ul = $('#cl' + (node_id || parent_id));
251 | if (ul.data('empty')) {
252 | $(ul).empty();
253 | ul.data('empty', false);
254 | }
255 | insertComment(data.comment);
256 | var ao = $('#ao' + node_id);
257 | ao.find('img').attr({'src': opts.commentBrightImage});
258 | if (node_id) {
259 | // if this was a "root" comment, remove the commenting box
260 | // (the user can get it back by reopening the comment popup)
261 | $('#ca' + node_id).slideUp();
262 | }
263 | },
264 | error: function(request, textStatus, error) {
265 | form.find('textarea,input').removeAttr('disabled');
266 | showError('Oops, there was a problem adding the comment.');
267 | }
268 | });
269 | }
270 |
271 | /**
272 | * Recursively append comments to the main comment list and children
273 | * lists, creating the comment tree.
274 | */
275 | function appendComments(comments, ul) {
276 | $.each(comments, function() {
277 | var div = createCommentDiv(this);
278 | ul.append($(document.createElement('li')).html(div));
279 | appendComments(this.children, div.find('ul.comment-children'));
280 | // To avoid stagnating data, don't store the comments children in data.
281 | this.children = null;
282 | div.data('comment', this);
283 | });
284 | }
285 |
286 | /**
287 | * After adding a new comment, it must be inserted in the correct
288 | * location in the comment tree.
289 | */
290 | function insertComment(comment) {
291 | var div = createCommentDiv(comment);
292 |
293 | // To avoid stagnating data, don't store the comments children in data.
294 | comment.children = null;
295 | div.data('comment', comment);
296 |
297 | var ul = $('#cl' + (comment.node || comment.parent));
298 | var siblings = getChildren(ul);
299 |
300 | var li = $(document.createElement('li'));
301 | li.hide();
302 |
303 | // Determine where in the parents children list to insert this comment.
304 | for(var i=0; i < siblings.length; i++) {
305 | if (comp(comment, siblings[i]) <= 0) {
306 | $('#cd' + siblings[i].id)
307 | .parent()
308 | .before(li.html(div));
309 | li.slideDown('fast');
310 | return;
311 | }
312 | }
313 |
314 | // If we get here, this comment rates lower than all the others,
315 | // or it is the only comment in the list.
316 | ul.append(li.html(div));
317 | li.slideDown('fast');
318 | }
319 |
320 | function acceptComment(id) {
321 | $.ajax({
322 | type: 'POST',
323 | url: opts.acceptCommentURL,
324 | data: {id: id},
325 | success: function(data, textStatus, request) {
326 | $('#cm' + id).fadeOut('fast');
327 | $('#cd' + id).removeClass('moderate');
328 | },
329 | error: function(request, textStatus, error) {
330 | showError('Oops, there was a problem accepting the comment.');
331 | }
332 | });
333 | }
334 |
335 | function deleteComment(id) {
336 | $.ajax({
337 | type: 'POST',
338 | url: opts.deleteCommentURL,
339 | data: {id: id},
340 | success: function(data, textStatus, request) {
341 | var div = $('#cd' + id);
342 | if (data == 'delete') {
343 | // Moderator mode: remove the comment and all children immediately
344 | div.slideUp('fast', function() {
345 | div.remove();
346 | });
347 | return;
348 | }
349 | // User mode: only mark the comment as deleted
350 | div
351 | .find('span.user-id:first')
352 | .text('[deleted]').end()
353 | .find('div.comment-text:first')
354 | .text('[deleted]').end()
355 | .find('#cm' + id + ', #dc' + id + ', #ac' + id + ', #rc' + id +
356 | ', #sp' + id + ', #hp' + id + ', #cr' + id + ', #rl' + id)
357 | .remove();
358 | var comment = div.data('comment');
359 | comment.username = '[deleted]';
360 | comment.text = '[deleted]';
361 | div.data('comment', comment);
362 | },
363 | error: function(request, textStatus, error) {
364 | showError('Oops, there was a problem deleting the comment.');
365 | }
366 | });
367 | }
368 |
369 | function showProposal(id) {
370 | $('#sp' + id).hide();
371 | $('#hp' + id).show();
372 | $('#pr' + id).slideDown('fast');
373 | }
374 |
375 | function hideProposal(id) {
376 | $('#hp' + id).hide();
377 | $('#sp' + id).show();
378 | $('#pr' + id).slideUp('fast');
379 | }
380 |
381 | function showProposeChange(id) {
382 | $('#pc' + id).hide();
383 | $('#hc' + id).show();
384 | var textarea = $('#pt' + id);
385 | textarea.val(textarea.data('source'));
386 | $.fn.autogrow.resize(textarea[0]);
387 | textarea.slideDown('fast');
388 | }
389 |
390 | function hideProposeChange(id) {
391 | $('#hc' + id).hide();
392 | $('#pc' + id).show();
393 | var textarea = $('#pt' + id);
394 | textarea.val('').removeAttr('disabled');
395 | textarea.slideUp('fast');
396 | }
397 |
398 | function toggleCommentMarkupBox(id) {
399 | $('#mb' + id).toggle();
400 | }
401 |
402 | /** Handle when the user clicks on a sort by link. */
403 | function handleReSort(link) {
404 | var classes = link.attr('class').split(/\s+/);
405 | for (var i=0; iThank you! Your comment will show up '
558 | + 'once it is has been approved by a moderator.');
559 | }
560 | // Prettify the comment rating.
561 | comment.pretty_rating = comment.rating + ' point' +
562 | (comment.rating == 1 ? '' : 's');
563 | // Make a class (for displaying not yet moderated comments differently)
564 | comment.css_class = comment.displayed ? '' : ' moderate';
565 | // Create a div for this comment.
566 | var context = $.extend({}, opts, comment);
567 | var div = $(renderTemplate(commentTemplate, context));
568 |
569 | // If the user has voted on this comment, highlight the correct arrow.
570 | if (comment.vote) {
571 | var direction = (comment.vote == 1) ? 'u' : 'd';
572 | div.find('#' + direction + 'v' + comment.id).hide();
573 | div.find('#' + direction + 'u' + comment.id).show();
574 | }
575 |
576 | if (opts.moderator || comment.text != '[deleted]') {
577 | div.find('a.reply').show();
578 | if (comment.proposal_diff)
579 | div.find('#sp' + comment.id).show();
580 | if (opts.moderator && !comment.displayed)
581 | div.find('#cm' + comment.id).show();
582 | if (opts.moderator || (opts.username == comment.username))
583 | div.find('#dc' + comment.id).show();
584 | }
585 | return div;
586 | }
587 |
588 | /**
589 | * A simple template renderer. Placeholders such as <%id%> are replaced
590 | * by context['id'] with items being escaped. Placeholders such as <#id#>
591 | * are not escaped.
592 | */
593 | function renderTemplate(template, context) {
594 | var esc = $(document.createElement('div'));
595 |
596 | function handle(ph, escape) {
597 | var cur = context;
598 | $.each(ph.split('.'), function() {
599 | cur = cur[this];
600 | });
601 | return escape ? esc.text(cur || "").html() : cur;
602 | }
603 |
604 | return template.replace(/<([%#])([\w\.]*)\1>/g, function() {
605 | return handle(arguments[2], arguments[1] == '%' ? true : false);
606 | });
607 | }
608 |
609 | /** Flash an error message briefly. */
610 | function showError(message) {
611 | $(document.createElement('div')).attr({'class': 'popup-error'})
612 | .append($(document.createElement('div'))
613 | .attr({'class': 'error-message'}).text(message))
614 | .appendTo('body')
615 | .fadeIn("slow")
616 | .delay(2000)
617 | .fadeOut("slow");
618 | }
619 |
620 | /** Add a link the user uses to open the comments popup. */
621 | $.fn.comment = function() {
622 | return this.each(function() {
623 | var id = $(this).attr('id').substring(1);
624 | var count = COMMENT_METADATA[id];
625 | var title = count + ' comment' + (count == 1 ? '' : 's');
626 | var image = count > 0 ? opts.commentBrightImage : opts.commentImage;
627 | var addcls = count == 0 ? ' nocomment' : '';
628 | $(this)
629 | .append(
630 | $(document.createElement('a')).attr({
631 | href: '#',
632 | 'class': 'sphinx-comment-open' + addcls,
633 | id: 'ao' + id
634 | })
635 | .append($(document.createElement('img')).attr({
636 | src: image,
637 | alt: 'comment',
638 | title: title
639 | }))
640 | .click(function(event) {
641 | event.preventDefault();
642 | show($(this).attr('id').substring(2));
643 | })
644 | )
645 | .append(
646 | $(document.createElement('a')).attr({
647 | href: '#',
648 | 'class': 'sphinx-comment-close hidden',
649 | id: 'ah' + id
650 | })
651 | .append($(document.createElement('img')).attr({
652 | src: opts.closeCommentImage,
653 | alt: 'close',
654 | title: 'close'
655 | }))
656 | .click(function(event) {
657 | event.preventDefault();
658 | hide($(this).attr('id').substring(2));
659 | })
660 | );
661 | });
662 | };
663 |
664 | var opts = {
665 | processVoteURL: '/_process_vote',
666 | addCommentURL: '/_add_comment',
667 | getCommentsURL: '/_get_comments',
668 | acceptCommentURL: '/_accept_comment',
669 | deleteCommentURL: '/_delete_comment',
670 | commentImage: '/static/_static/comment.png',
671 | closeCommentImage: '/static/_static/comment-close.png',
672 | loadingImage: '/static/_static/ajax-loader.gif',
673 | commentBrightImage: '/static/_static/comment-bright.png',
674 | upArrow: '/static/_static/up.png',
675 | downArrow: '/static/_static/down.png',
676 | upArrowPressed: '/static/_static/up-pressed.png',
677 | downArrowPressed: '/static/_static/down-pressed.png',
678 | voting: false,
679 | moderator: false
680 | };
681 |
682 | if (typeof COMMENT_OPTIONS != "undefined") {
683 | opts = jQuery.extend(opts, COMMENT_OPTIONS);
684 | }
685 |
686 | var popupTemplate = '\
687 | ';
723 |
724 | var commentTemplate = '\
725 | \
768 | ';
769 |
770 | var replyTemplate = '\
771 | \
772 | \
773 | \
780 |
\
781 | ';
782 |
783 | $(document).ready(function() {
784 | init();
785 | });
786 | })(jQuery);
787 |
788 | $(document).ready(function() {
789 | // add comment anchors for all paragraphs that are commentable
790 | $('.sphinx-has-comment').comment();
791 |
792 | // highlight search words in search results
793 | $("div.context").each(function() {
794 | var params = $.getQueryParameters();
795 | var terms = (params.q) ? params.q[0].split(/\s+/) : [];
796 | var result = $(this);
797 | $.each(terms, function() {
798 | result.highlightText(this.toLowerCase(), 'highlighted');
799 | });
800 | });
801 |
802 | // directly open comment window if requested
803 | var anchor = document.location.hash;
804 | if (anchor.substring(0, 9) == '#comment-') {
805 | $('#ao' + anchor.substring(9)).click();
806 | document.location.hash = '#s' + anchor.substring(9);
807 | }
808 | });
809 |
--------------------------------------------------------------------------------
/nn_common_modules/modules.py:
--------------------------------------------------------------------------------
1 | """
2 | Description
3 | ++++++++++++++++++++++
4 | Building blocks of segmentation neural network
5 |
6 | Usage
7 | ++++++++++++++++++++++
8 | Import the package and Instantiate any module/block class you want to you::
9 |
10 | from nn_common_modules import modules as additional_modules
11 | dense_block = additional_modules.DenseBlock(params, se_block_type = 'SSE')
12 |
13 | Members
14 | ++++++++++++++++++++++
15 | """
16 | import torch
17 | import torch.nn as nn
18 | from squeeze_and_excitation import squeeze_and_excitation as se
19 | import torch.nn.functional as F
20 | from octave_convolution_block import *
21 |
22 | class DenseBlock(nn.Module):
23 | """Block with dense connections
24 |
25 | :param params: {
26 | 'num_channels':1,
27 | 'num_filters':64,
28 | 'kernel_h':5,
29 | 'kernel_w':5,
30 | 'stride_conv':1,
31 | 'pool':2,
32 | 'stride_pool':2,
33 | 'num_classes':28,
34 | 'se_block': se.SELayer.None,
35 | 'drop_out':0,2}
36 | :type params: dict
37 | :param se_block_type: Squeeze and Excite block type to be included, defaults to None
38 | :type se_block_type: str, valid options are {'NONE', 'CSE', 'SSE', 'CSSE'}, optional
39 | :return: forward passed tensor
40 | :rtype: torch.tonsor [FloatTensor]
41 | """
42 |
43 | def __init__(self, params, se_block_type=None):
44 | super(DenseBlock, self).__init__()
45 |
46 | if se_block_type == se.SELayer.CSE.value:
47 | self.SELayer = se.ChannelSELayer(params['num_filters'])
48 |
49 | elif se_block_type == se.SELayer.SSE.value:
50 | self.SELayer = se.SpatialSELayer(params['num_filters'])
51 |
52 | elif se_block_type == se.SELayer.CSSE.value:
53 | self.SELayer = se.ChannelSpatialSELayer(params['num_filters'])
54 | else:
55 | self.SELayer = None
56 | print(se.SELayer.CSE.value, se_block_type)
57 |
58 | padding_h = int((params['kernel_h'] - 1) / 2)
59 | padding_w = int((params['kernel_w'] - 1) / 2)
60 |
61 | conv1_out_size = int(params['num_channels'] + params['num_filters'])
62 | conv2_out_size = int(
63 | params['num_channels'] + params['num_filters'] + params['num_filters'])
64 |
65 | self.conv1 = nn.Conv2d(in_channels=params['num_channels'], out_channels=params['num_filters'],
66 | kernel_size=(
67 | params['kernel_h'], params['kernel_w']),
68 | padding=(padding_h, padding_w),
69 | stride=params['stride_conv'])
70 | self.conv2 = nn.Conv2d(in_channels=conv1_out_size, out_channels=params['num_filters'],
71 | kernel_size=(
72 | params['kernel_h'], params['kernel_w']),
73 | padding=(padding_h, padding_w),
74 | stride=params['stride_conv'])
75 | self.conv3 = nn.Conv2d(in_channels=conv2_out_size, out_channels=params['num_filters'],
76 | kernel_size=(1, 1),
77 | padding=(0, 0),
78 | stride=params['stride_conv'])
79 | self.batchnorm1 = nn.BatchNorm2d(num_features=params['num_channels'])
80 | self.batchnorm2 = nn.BatchNorm2d(num_features=conv1_out_size)
81 | self.batchnorm3 = nn.BatchNorm2d(num_features=conv2_out_size)
82 | self.prelu = nn.PReLU()
83 | if params['drop_out'] > 0:
84 | self.drop_out_needed = True
85 | self.drop_out = nn.Dropout2d(params['drop_out'])
86 | else:
87 | self.drop_out_needed = False
88 |
89 | def forward(self, input):
90 | """Forward pass
91 |
92 | :param input: Input tensor, shape = (N x C x H x W)
93 | :type input: torch.tensor [FloatTensor]
94 | :return: Forward passed tensor
95 | :rtype: torch.tensor [FloatTensor]
96 | """
97 |
98 | o1 = self.batchnorm1(input)
99 | o2 = self.prelu(o1)
100 | o3 = self.conv1(o2)
101 | o4 = torch.cat((input, o3), dim=1)
102 | o5 = self.batchnorm2(o4)
103 | o6 = self.prelu(o5)
104 | o7 = self.conv2(o6)
105 | o8 = torch.cat((input, o3, o7), dim=1)
106 | o9 = self.batchnorm3(o8)
107 | o10 = self.prelu(o9)
108 | out = self.conv3(o10)
109 | return out
110 |
111 |
112 | class EncoderBlock(DenseBlock):
113 | """Dense encoder block with maxpool and an optional SE block
114 |
115 | :param params: {
116 | 'num_channels':1,
117 | 'num_filters':64,
118 | 'kernel_h':5,
119 | 'kernel_w':5,
120 | 'stride_conv':1,
121 | 'pool':2,
122 | 'stride_pool':2,
123 | 'num_classes':28,
124 | 'se_block': se.SELayer.None,
125 | 'drop_out':0,2}
126 | :type params: dict
127 | :param se_block_type: Squeeze and Excite block type to be included, defaults to None
128 | :type se_block_type: str, valid options are {'NONE', 'CSE', 'SSE', 'CSSE'}, optional
129 | :return: output tensor with maxpool, output tensor without maxpool, indices for unpooling
130 | :rtype: torch.tensor [FloatTensor], torch.tensor [FloatTensor], torch.tensor [LongTensor]
131 | """
132 |
133 | def __init__(self, params, se_block_type=None):
134 | super(EncoderBlock, self).__init__(params, se_block_type=se_block_type)
135 | self.maxpool = nn.MaxPool2d(
136 | kernel_size=params['pool'], stride=params['stride_pool'], return_indices=True)
137 |
138 | def forward(self, input, weights=None):
139 | """Forward pass
140 |
141 | :param input: Input tensor, shape = (N x C x H x W)
142 | :type input: torch.tensor [FloatTensor]
143 | :param weights: Weights used for squeeze and excitation, shape depends on the type of SE block, defaults to None
144 | :type weights: torch.tensor, optional
145 | :return: output tensor with maxpool, output tensor without maxpool, indices for unpooling
146 | :rtype: torch.tensor [FloatTensor], torch.tensor [FloatTensor], torch.tensor [LongTensor]
147 | """
148 |
149 | out_block = super(EncoderBlock, self).forward(input)
150 | if self.SELayer:
151 | out_block = self.SELayer(out_block, weights)
152 |
153 | if self.drop_out_needed:
154 | out_block = self.drop_out(out_block)
155 |
156 | out_encoder, indices = self.maxpool(out_block)
157 | return out_encoder, out_block, indices
158 |
159 |
160 | class DecoderBlock(DenseBlock):
161 | """Dense decoder block with maxunpool and an optional skip connections and SE block
162 |
163 | :param params: {
164 | 'num_channels':1,
165 | 'num_filters':64,
166 | 'kernel_h':5,
167 | 'kernel_w':5,
168 | 'stride_conv':1,
169 | 'pool':2,
170 | 'stride_pool':2,
171 | 'num_classes':28,
172 | 'se_block': se.SELayer.None,
173 | 'drop_out':0,2}
174 | :type params: dict
175 | :param se_block_type: Squeeze and Excite block type to be included, defaults to None
176 | :type se_block_type: str, valid options are {'NONE', 'CSE', 'SSE', 'CSSE'}, optional
177 | :return: forward passed tensor
178 | :rtype: torch.tensor [FloatTensor]
179 | """
180 |
181 | def __init__(self, params, se_block_type=None):
182 | super(DecoderBlock, self).__init__(params, se_block_type=se_block_type)
183 | self.unpool = nn.MaxUnpool2d(
184 | kernel_size=params['pool'], stride=params['stride_pool'])
185 |
186 | def forward(self, input, out_block=None, indices=None, weights=None):
187 | """Forward pass
188 |
189 | :param input: Input tensor, shape = (N x C x H x W)
190 | :type input: torch.tensor [FloatTensor]
191 | :param out_block: Tensor for skip connection, shape = (N x C x H x W), defaults to None
192 | :type out_block: torch.tensor [FloatTensor], optional
193 | :param indices: Indices used for unpooling operation, defaults to None
194 | :type indices: torch.tensor, optional
195 | :param weights: Weights used for squeeze and excitation, shape depends on the type of SE block, defaults to None
196 | :type weights: torch.tensor, optional
197 | :return: Forward passed tensor
198 | :rtype: torch.tensor [FloatTensor]
199 | """
200 | if indices is not None:
201 | unpool = self.unpool(input, indices, out_block.shape)
202 | else:
203 | # TODO: Implement Conv Transpose
204 | print("You have to use Conv Transpose")
205 |
206 | if out_block is not None:
207 | concat = torch.cat((out_block, unpool), dim=1)
208 | else:
209 | concat = unpool
210 | out_block = super(DecoderBlock, self).forward(concat)
211 |
212 | if self.SELayer:
213 | out_block = self.SELayer(out_block, weights)
214 |
215 | if self.drop_out_needed:
216 | out_block = self.drop_out(out_block)
217 | return out_block
218 |
219 |
220 | class ClassifierBlock(nn.Module):
221 | """
222 | Last layer
223 |
224 | :param params: {
225 | 'num_channels':1,
226 | 'num_filters':64,
227 | 'kernel_c':5,
228 | 'stride_conv':1,
229 | 'pool':2,
230 | 'stride_pool':2,
231 | 'num_classes':28,
232 | 'se_block': se.SELayer.None,
233 | 'drop_out':0,2}
234 | :type params: dict
235 | :return: forward passed tensor
236 | :rtype: torch.tensor [FloatTensor]
237 | """
238 |
239 | def __init__(self, params):
240 | super(ClassifierBlock, self).__init__()
241 | self.conv = nn.Conv2d(
242 | params['num_channels'], params['num_class'], params['kernel_c'], params['stride_conv'])
243 |
244 | def forward(self, input, weights=None):
245 | """Forward pass
246 |
247 | :param input: Input tensor, shape = (N x C x H x W)
248 | :type input: torch.tensor [FloatTensor]
249 | :param weights: Weights for classifier regression, defaults to None
250 | :type weights: torch.tensor (N), optional
251 | :return: logits
252 | :rtype: torch.tensor
253 | """
254 | batch_size, channel, a, b = input.size()
255 | if weights is not None:
256 | weights, _ = torch.max(weights, dim=0)
257 | weights = weights.view(1, channel, 1, 1)
258 | out_conv = F.conv2d(input, weights)
259 | else:
260 | out_conv = self.conv(input)
261 | return out_conv
262 |
263 |
264 | class GenericBlock(nn.Module):
265 | """
266 | Generic parent class for a conv encoder/decoder block.
267 |
268 | :param params: {'kernel_h': 5
269 | 'kernel_w': 5
270 | 'num_channels':64
271 | 'num_filters':64
272 | 'stride_conv':1
273 | }
274 | :type params: dict
275 | :param se_block_type: Squeeze and Excite block type to be included, defaults to None
276 | :type se_block_type: str, valid options are {'NONE', 'CSE', 'SSE', 'CSSE'}, optional
277 | :return: forward passed tensor
278 | :rtype: torch.tensor [FloatTensor]
279 | """
280 |
281 | def __init__(self, params, se_block_type=None):
282 | super(GenericBlock, self).__init__()
283 | if se_block_type == se.SELayer.CSE.value:
284 | self.SELayer = se.ChannelSpatialSELayer(params['num_filters'])
285 |
286 | elif se_block_type == se.SELayer.SSE.value:
287 | self.SELayer = se.SpatialSELayer(params['num_filters'])
288 |
289 | elif se_block_type == se.SELayer.CSSE.value:
290 | self.SELayer = se.ChannelSpatialSELayer(params['num_filters'])
291 | else:
292 | self.SELayer = None
293 | padding_h = int((params['kernel_h'] - 1) / 2)
294 | padding_w = int((params['kernel_w'] - 1) / 2)
295 | self.out_channel = params['num_filters']
296 | self.conv = nn.Conv2d(in_channels=params['num_channels'], out_channels=params['num_filters'],
297 | kernel_size=(
298 | params['kernel_h'], params['kernel_w']),
299 | padding=(padding_h, padding_w),
300 | stride=params['stride_conv'])
301 | self.prelu = nn.PReLU()
302 | self.batchnorm = nn.BatchNorm2d(num_features=params['num_filters'])
303 | if params['drop_out'] > 0:
304 | self.drop_out_needed = True
305 | self.drop_out = nn.Dropout2d(params['drop_out'])
306 | else:
307 | self.drop_out_needed = False
308 |
309 | def forward(self, input, weights=None):
310 | """Forward pass
311 |
312 | :param input: Input tensor, shape = (N x C x H x W)
313 | :type input: torch.tensor [FloatTensor]
314 | :param weights: Custom weights for convolution, defaults to None
315 | :type weights: torch.tensor [FloatTensor], optional
316 | :return: [description]
317 | :rtype: [type]
318 | """
319 |
320 | _, c, h, w = input.shape
321 | if weights is None:
322 | x1 = self.conv(input)
323 | else:
324 | weights, _ = torch.max(weights, dim=0)
325 | weights = weights.view(self.out_channel, c, 1, 1)
326 | x1 = F.conv2d(input, weights)
327 | x2 = self.prelu(x1)
328 | x3 = self.batchnorm(x2)
329 | return x3
330 |
331 |
332 | class SDnetEncoderBlock(GenericBlock):
333 | """
334 | A standard conv -> prelu -> batchnorm-> maxpool block without dense connections
335 |
336 | :param params: {
337 | 'num_channels':1,
338 | 'num_filters':64,
339 | 'kernel_h':5,
340 | 'kernel_w':5,
341 | 'stride_conv':1,
342 | 'pool':2,
343 | 'stride_pool':2,
344 | 'num_classes':28,
345 | 'se_block': se.SELayer.None,
346 | 'drop_out':0,2}
347 | :type params: dict
348 | :param se_block_type: Squeeze and Excite block type to be included, defaults to None
349 | :type se_block_type: str, valid options are {'NONE', 'CSE', 'SSE', 'CSSE'}, optional
350 | :return: output tensor with maxpool, output tensor without maxpool, indices for unpooling
351 | :rtype: torch.tensor [FloatTensor], torch.tensor [FloatTensor], torch.tensor [LongTensor]
352 | """
353 |
354 | def __init__(self, params, se_block_type=None):
355 | super(SDnetEncoderBlock, self).__init__(params, se_block_type)
356 | self.maxpool = nn.MaxPool2d(
357 | kernel_size=params['pool'], stride=params['stride_pool'], return_indices=True)
358 |
359 | def forward(self, input, weights=None):
360 | """Forward pass
361 |
362 | :param input: Input tensor, shape = (N x C x H x W)
363 | :type input: torch.tensor [FloatTensor]
364 | :param weights: Weights used for squeeze and excitation, shape depends on the type of SE block, defaults to None
365 | :type weights: torch.tensor, optional
366 | :return: output tensor with maxpool, output tensor without maxpool, indices for unpooling
367 | :rtype: torch.tensor [FloatTensor], torch.tensor [FloatTensor], torch.tensor [LongTensor]
368 | """
369 |
370 | out_block = super(SDnetEncoderBlock, self).forward(input, weights)
371 |
372 | if self.SELayer:
373 | out_block = self.SELayer(out_block, weights)
374 | if self.drop_out_needed:
375 | out_block = self.drop_out(out_block)
376 |
377 | out_encoder, indices = self.maxpool(out_block)
378 | return out_encoder, out_block, indices
379 |
380 |
381 | class SDnetDecoderBlock(GenericBlock):
382 | """Standard decoder block with maxunpool -> skipconnections -> conv -> prelu -> batchnorm, without dense connections and an optional SE blocks
383 |
384 | :param params: {
385 | 'num_channels':1,
386 | 'num_filters':64,
387 | 'kernel_h':5,
388 | 'kernel_w':5,
389 | 'stride_conv':1,
390 | 'pool':2,
391 | 'stride_pool':2,
392 | 'num_classes':28,
393 | 'se_block': se.SELayer.None,
394 | 'drop_out':0,2}
395 | :type params: dict
396 | :param se_block_type: Squeeze and Excite block type to be included, defaults to None
397 | :type se_block_type: str, valid options are {'NONE', 'CSE', 'SSE', 'CSSE'}, optional
398 | :return: forward passed tensor
399 | :rtype: torch.tensor [FloatTensor]
400 | """
401 |
402 | def __init__(self, params, se_block_type=None):
403 | super(SDnetDecoderBlock, self).__init__(params, se_block_type)
404 | self.unpool = nn.MaxUnpool2d(
405 | kernel_size=params['pool'], stride=params['stride_pool'])
406 |
407 | def forward(self, input, out_block=None, indices=None, weights=None):
408 | """Forward pass
409 |
410 | :param input: Input tensor, shape = (N x C x H x W)
411 | :type input: torch.tensor [FloatTensor]
412 | :param out_block: Tensor for skip connection, shape = (N x C x H x W), defaults to None
413 | :type out_block: torch.tensor [FloatTensor], optional
414 | :param indices: Indices used for unpooling operation, defaults to None
415 | :type indices: torch.tensor, optional
416 | :param weights: Weights used for squeeze and excitation, shape depends on the type of SE block, defaults to None
417 | :type weights: torch.tensor, optional
418 | :return: Forward pass
419 | :rtype: torch.tensor
420 | """
421 |
422 | unpool = self.unpool(input, indices, out_block.shape)
423 | if out_block is not None:
424 | concat = torch.cat((out_block, unpool), dim=1)
425 | else:
426 | concat = unpool
427 | out_block = super(SDnetDecoderBlock, self).forward(concat, weights)
428 | if self.SELayer:
429 | out_block = self.SELayer(out_block, weights)
430 |
431 | if self.drop_out_needed:
432 | out_block = self.drop_out(out_block)
433 | return out_block
434 |
435 |
436 | class SDNetNoBNEncoderBlock(nn.Module):
437 | """
438 | Encoder Block for Bayesian Network
439 | """
440 |
441 | def __init__(self, params):
442 | super(SDNetNoBNEncoderBlock, self).__init__()
443 | padding_h = int((params['kernel_h'] - 1) / 2)
444 | padding_w = int((params['kernel_w'] - 1) / 2)
445 | self.out_channel = params['num_filters']
446 | self.conv = nn.Conv2d(in_channels=params['num_channels'], out_channels=params['num_filters'],
447 | kernel_size=(
448 | params['kernel_h'], params['kernel_w']),
449 | padding=(padding_h, padding_w),
450 | stride=params['stride_conv'])
451 | self.relu = nn.ReLU()
452 | self.maxpool = nn.MaxPool2d(
453 | kernel_size=params['pool'], stride=params['stride_pool'], return_indices=True)
454 |
455 | def forward(self, input):
456 | x1 = self.conv(input)
457 | x2 = self.relu(x1)
458 | out_encoder, indices = self.maxpool(x2)
459 | return out_encoder, x2, indices
460 |
461 |
462 | class SDNetNoBNDecoderBlock(nn.Module):
463 | """
464 | Decoder Block for Bayesian Network
465 | """
466 |
467 | def __init__(self, params):
468 | super(SDNetNoBNDecoderBlock, self).__init__()
469 | padding_h = int((params['kernel_h'] - 1) / 2)
470 | padding_w = int((params['kernel_w'] - 1) / 2)
471 | self.out_channel = params['num_filters']
472 |
473 | self.conv = nn.Conv2d(in_channels=params['num_channels'], out_channels=params['num_filters'],
474 | kernel_size=(
475 | params['kernel_h'], params['kernel_w']),
476 | padding=(padding_h, padding_w),
477 | stride=params['stride_conv'])
478 | self.relu = nn.ReLU()
479 |
480 | self.unpool = nn.MaxUnpool2d(
481 | kernel_size=params['pool'], stride=params['stride_pool'])
482 |
483 | def forward(self, input, out_block=None, indices=None):
484 | unpool = self.unpool(input, indices, out_block.shape)
485 | if out_block is not None:
486 | concat = torch.cat((out_block, unpool), dim=1)
487 | else:
488 | concat = unpool
489 | x1 = self.conv(concat)
490 | x2 = self.relu(x1)
491 | return x2
492 |
493 |
494 | class OctaveDenseBlock(nn.Module):
495 | """Block with dense connections
496 |
497 | :param params: {
498 | 'num_channels':1,
499 | 'num_filters':64,
500 | 'kernel_h':5,
501 | 'kernel_w':5,
502 | 'stride_conv':1,
503 | 'pool':2,
504 | 'stride_pool':2,
505 | 'num_classes':28,
506 | 'se_block': se.SELayer.None,
507 | 'drop_out':0,2}
508 | :type params: dict
509 | :param se_block_type: Squeeze and Excite block type to be included, defaults to None
510 | :type se_block_type: str, valid options are {'NONE', 'CSE', 'SSE', 'CSSE'}, optional
511 | :return: forward passed tensor
512 | :rtype: torch.tonsor [FloatTensor]
513 | """
514 |
515 | def __init__(self, params, se_block_type=None, is_decoder=False):
516 | super(OctaveDenseBlock, self).__init__()
517 | print(se_block_type)
518 | if se_block_type == se.SELayer.CSE.value:
519 | self.SELayer = se.ChannelSELayer(params['num_filters'])
520 |
521 | elif se_block_type == se.SELayer.SSE.value:
522 | self.SELayer = se.SpatialSELayer(params['num_filters'])
523 |
524 | elif se_block_type == se.SELayer.CSSE.value:
525 | self.SELayer = se.ChannelSpatialSELayer(params['num_filters'])
526 | else:abdominal_segmentation_2] - 1) / 2)
527 | padding_w = int((params['kernel_w'] - 1) / 2)
528 |
529 | conv1_out_size = int(params['num_channels'] + params['num_filters'])
530 | conv2_out_size = int(
531 | params['num_channels'] + params['num_filters'] + params['num_filters'])
532 |
533 | self.conv1 = OctConv2d('first', in_channels=params['num_channels'], out_channels=params['num_filters'], kernel_size=(
534 | params['kernel_h'], params['kernel_w']), padding=(padding_h, padding_w),
535 | stride=params['stride_conv'])
536 |
537 |
538 | self.conv2 = OctConv2d('regular', in_channels=conv1_out_size, out_channels=params['num_filters'], kernel_size=(
539 | params['kernel_h'], params['kernel_w']), padding=(padding_h, padding_w),
540 | stride=params['stride_conv'])
541 |
542 |
543 | self.conv3 = OctConv2d('last', in_channels=conv2_out_size, out_channels=params['num_filters'], kernel_size=(
544 | params['kernel_h'], params['kernel_w']), padding=(padding_h, padding_w),
545 | stride=params['stride_conv'])
546 |
547 | self.avgpool1 = nn.AvgPool2d(2)
548 |
549 | alpha_in, alpha_out = 0.5, 0.5
550 |
551 | if is_decoder:
552 | # Channel sizes for dcoder blocks
553 | self.batchnorm1 = nn.BatchNorm2d(params['num_channels'])
554 | oct_unit_decoder_channel_size = params['num_channels'] // 4 #128
555 | self.batchnorm2_h = nn.BatchNorm2d(int(oct_unit_decoder_channel_size*3)) #conv1_out_size * (1 - alpha_out))+1)
556 | self.batchnorm2_l = nn.BatchNorm2d(int(oct_unit_decoder_channel_size*3)) #conv1_out_size-1))
557 |
558 | self.batchnorm3_h = nn.BatchNorm2d(int(oct_unit_decoder_channel_size*4)) #conv2_out_size * (1 - alpha_out))+1)
559 | self.batchnorm3_l = nn.BatchNorm2d(int(oct_unit_decoder_channel_size*4)) #conv2_out_size-1))
560 | else:
561 | # channel sizes for encoder blocks
562 | self.batchnorm1 = nn.BatchNorm2d(params['num_channels'])
563 | oct_unit_encoder_channel_size = params['num_channels'] // 2 #64
564 | self.batchnorm2_h = nn.BatchNorm2d(int(oct_unit_encoder_channel_size*2)) #conv1_out_size * (1 - alpha_out)
565 | self.batchnorm2_l = nn.BatchNorm2d(int(oct_unit_encoder_channel_size*2)) #(conv1_out_size * alpha_out))
566 |
567 | self.batchnorm3_h = nn.BatchNorm2d(int(oct_unit_encoder_channel_size*3)) #conv2_out_size * (1 - alpha_out)))
568 | self.batchnorm3_l = nn.BatchNorm2d(int(oct_unit_encoder_channel_size*3)) #conv2_out_size * alpha_out))
569 |
570 | self.prelu = nn.PReLU()
571 | self.prelu_h = nn.PReLU()
572 | self.prelu_l = nn.PReLU()
573 |
574 | if params['drop_out'] > 0:
575 | self.drop_out_needed = True
576 | self.drop_out = nn.Dropout2d(params['drop_out'])
577 | else:
578 | self.drop_out_needed = False
579 |
580 | def forward(self, input):
581 | """Forward pass
582 |
583 | :param input: Input tensor, shape = (N x C x H x W)
584 | :type input: torch.tensor [FloatTensor]
585 | :return: Forward passed tensor
586 | :rtype: torch.tensor [FloatTensor]
587 | """
588 |
589 | o1 = self.batchnorm1(input)
590 | o2 = self.prelu(o1)
591 |
592 | ch = input.shape[1] // 2
593 | inp_h, inp_l = input[:, :ch, :, :], input[:, ch:, :, :]
594 | inp_ll = self.avgpool1(inp_l)
595 |
596 | o3_h, o3_l = self.conv1(o2)
597 | o4_h = torch.cat((inp_h, o3_h), dim=1)
598 | o4_l = torch.cat((inp_ll, o3_l), dim=1)
599 | o5_h = self.batchnorm2_h(o4_h)
600 | o5_l = self.batchnorm2_l(o4_l)
601 | o6_h = self.prelu_h(o5_h)
602 | o6_l = self.prelu_l(o5_l)
603 | o7_h, o7_l = self.conv2((o6_h, o6_l))
604 |
605 | o8_h = torch.cat((inp_h, o3_h, o7_h), dim=1)
606 | o8_l = torch.cat((inp_ll, o3_l, o7_l), dim=1)
607 |
608 | o9_h = self.batchnorm3_h(o8_h)
609 | o9_l = self.batchnorm3_l(o8_l)
610 | o10_h = self.prelu_h(o9_h)
611 | o10_l = self.prelu_l(o9_l)
612 | out = self.conv3((o10_h, o10_l))
613 |
614 | return out
615 |
616 |
617 | class OctaveEncoderBlock(OctaveDenseBlock):
618 | """Dense encoder block with maxpool and an optional SE block
619 |
620 | :param params: {
621 | 'num_channels':1,
622 | 'num_filters':64,
623 | 'kernel_h':5,
624 | 'kernel_w':5,
625 | 'stride_conv':1,
626 | 'pool':2,
627 | 'stride_pool':2,
628 | 'num_classes':28,
629 | 'se_block': se.SELayer.None,
630 | 'drop_out':0,2}
631 | :type params: dict
632 | :param se_block_type: Squeeze and Excite block type to be included, defaults to None
633 | :type se_block_type: str, valid options are {'NONE', 'CSE', 'SSE', 'CSSE'}, optional
634 | :return: output tensor with maxpool, output tensor without maxpool, indices for unpooling
635 | :rtype: torch.tensor [FloatTensor], torch.tensor [FloatTensor], torch.tensor [LongTensor]
636 | """
637 |
638 | def __init__(self, params, se_block_type=None):
639 | super(OctaveEncoderBlock, self).__init__(params, se_block_type=se_block_type, is_decoder=False)
640 | self.maxpool = nn.MaxPool2d(
641 | kernel_size=params['pool'], stride=params['stride_pool'], return_indices=True)
642 |
643 | def forward(self, input, weights=None):
644 | """Forward pass
645 |
646 | :param input: Input tensor, shape = (N x C x H x W)
647 | :type input: torch.tensor [FloatTensor]
648 | :param weights: Weights used for squeeze and excitation, shape depends on the type of SE block, defaults to None
649 | :type weights: torch.tensor, optional
650 | :return: output tensor with maxpool, output tensor without maxpool, indices for unpooling
651 | :rtype: torch.tensor [FloatTensor], torch.tensor [FloatTensor], torch.tensor [LongTensor]
652 | """
653 |
654 | out_block = super(OctaveEncoderBlock, self).forward(input)
655 | if self.SELayer:
656 | out_block = self.SELayer(out_block)
657 |
658 | if self.drop_out_needed:
659 | out_block = self.drop_out(out_block)
660 |
661 | out_encoder, indices = self.maxpool(out_block)
662 | return out_encoder, out_block, indices
663 |
664 |
665 | class OctaveDecoderBlock(OctaveDenseBlock):
666 | """Dense decoder block with maxunpool and an optional skip connections and SE block
667 |
668 | :param params: {
669 | 'num_channels':1,
670 | 'num_filters':64,
671 | 'kernel_h':5,
672 | 'kernel_w':5,
673 | 'stride_conv':1,
674 | 'pool':2,
675 | 'stride_pool':2,
676 | 'num_classes':28,
677 | 'se_block': se.SELayer.None,
678 | 'drop_out':0,2}
679 | :type params: dict
680 | :param se_block_type: Squeeze and Excite block type to be included, defaults to None
681 | :type se_block_type: str, valid options are {'NONE', 'CSE', 'SSE', 'CSSE'}, optional
682 | :return: forward passed tensor
683 | :rtype: torch.tensor [FloatTensor]
684 | """
685 |
686 | def __init__(self, params, se_block_type=None):
687 | super(OctaveDecoderBlock, self).__init__(params, se_block_type=se_block_type, is_decoder=True)
688 | self.unpool = nn.MaxUnpool2d(
689 | kernel_size=params['pool'], stride=params['stride_pool'])
690 |
691 | def forward(self, input, out_block=None, indices=None, weights=None):
692 | """Forward pass
693 |
694 | :param input: Input tensor, shape = (N x C x H x W)
695 | :type input: torch.tensor [FloatTensor]
696 | :param out_block: Tensor for skip connection, shape = (N x C x H x W), defaults to None
697 | :type out_block: torch.tensor [FloatTensor], optional
698 | :param indices: Indices used for unpooling operation, defaults to None
699 | :type indices: torch.tensor, optional
700 | :param weights: Weights used for squeeze and excitation, shape depends on the type of SE block, defaults to None
701 | :type weights: torch.tensor, optional
702 | :return: Forward passed tensor
703 | :rtype: torch.tensor [FloatTensor]
704 | """
705 | if indices is not None:
706 | unpool = self.unpool(input, indices)
707 | else:
708 | # TODO: Implement Conv Transpose
709 | print("You have to use Conv Transpose")
710 |
711 | if out_block is not None:
712 | concat = torch.cat((out_block, unpool), dim=1)
713 | else:
714 | concat = unpool
715 | out_block = super(OctaveDecoderBlock, self).forward(concat)
716 |
717 | if self.SELayer:
718 | out_block = self.SELayer(out_block)
719 |
720 | if self.drop_out_needed:
721 | out_block = self.drop_out(out_block)
722 | return out_block
723 |
--------------------------------------------------------------------------------
\ 689 | Sort by:\ 690 | best rated\ 691 | newest\ 692 | oldest\ 693 |
\ 694 |\ 698 |
Add a comment\ 700 | (markup):
\ 701 |``code``, \ 704 | code blocks:::and an indented block after blank line