From 8308d64057621504b2090c5961f002cd7a2c0fca Mon Sep 17 00:00:00 2001 From: Aykut Argun <48754174+argunaykut@users.noreply.github.com> Date: Mon, 9 Nov 2020 17:50:51 +0100 Subject: [PATCH 01/78] Video link added Video link added trial --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 49c085ece..1649cf70e 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ Additionally, we have seven more case studies which are less documented, but giv ### Video Tutorials -[TBA] +DeepTrack introduction tutorial: https://www.youtube.com/watch?v=hyfaxF8q6VE&t=16s ### In-depth dives From 679a0816ce97008cc1400d5412430b23250968dd Mon Sep 17 00:00:00 2001 From: Aykut Argun <48754174+argunaykut@users.noreply.github.com> Date: Mon, 9 Nov 2020 17:53:16 +0100 Subject: [PATCH 02/78] Video link update Some more video tutorial links added --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1649cf70e..10043772e 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,9 @@ Additionally, we have seven more case studies which are less documented, but giv ### Video Tutorials -DeepTrack introduction tutorial: https://www.youtube.com/watch?v=hyfaxF8q6VE&t=16s +DeepTrack 2.0 introduction tutorial video: https://www.youtube.com/watch?v=hyfaxF8q6VE&t=16s +DeepTrack 2.0 single particle tracking tutorial video: https://www.youtube.com/watch?v=6Cntik6AfBI&t=1s +DeepTrack 2.0 multiple particle tracking tutorial video: https://www.youtube.com/watch?v=wFV2VqzpeZs ### In-depth dives From fb317f5d29bb7a3a56f10e0896cd8b5b597a7df7 Mon Sep 17 00:00:00 2001 From: Aykut Argun <48754174+argunaykut@users.noreply.github.com> Date: Mon, 9 Nov 2020 17:54:24 +0100 Subject: [PATCH 03/78] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 10043772e..d9daf7b6c 100644 --- a/README.md +++ b/README.md @@ -47,9 +47,9 @@ Additionally, we have seven more case studies which are less documented, but giv ### Video Tutorials -DeepTrack 2.0 introduction tutorial video: https://www.youtube.com/watch?v=hyfaxF8q6VE&t=16s -DeepTrack 2.0 single particle tracking tutorial video: https://www.youtube.com/watch?v=6Cntik6AfBI&t=1s -DeepTrack 2.0 multiple particle tracking tutorial video: https://www.youtube.com/watch?v=wFV2VqzpeZs +DeepTrack 2.0 introduction tutorial video: https://www.youtube.com/watch?v=hyfaxF8q6VE&t=16s. +DeepTrack 2.0 single particle tracking tutorial video: https://www.youtube.com/watch?v=6Cntik6AfBI&t=1s. +DeepTrack 2.0 multiple particle tracking tutorial video: https://www.youtube.com/watch?v=wFV2VqzpeZs. ### In-depth dives From 2a3d889725745f0d9f8d882e532dd91cb0481a0e Mon Sep 17 00:00:00 2001 From: Aykut Argun <48754174+argunaykut@users.noreply.github.com> Date: Mon, 9 Nov 2020 17:57:43 +0100 Subject: [PATCH 04/78] Video links update --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index d9daf7b6c..91b253ee0 100644 --- a/README.md +++ b/README.md @@ -47,9 +47,9 @@ Additionally, we have seven more case studies which are less documented, but giv ### Video Tutorials -DeepTrack 2.0 introduction tutorial video: https://www.youtube.com/watch?v=hyfaxF8q6VE&t=16s. -DeepTrack 2.0 single particle tracking tutorial video: https://www.youtube.com/watch?v=6Cntik6AfBI&t=1s. -DeepTrack 2.0 multiple particle tracking tutorial video: https://www.youtube.com/watch?v=wFV2VqzpeZs. +DeepTrack 2.0 introduction tutorial video: https://www.youtube.com/watch?v=hyfaxF8q6VE&t=16s +DeepTrack 2.0 single particle tracking tutorial video: https://www.youtube.com/watch?v=6Cntik6AfBI&t=1s +DeepTrack 2.0 multiple particle tracking tutorial video: https://www.youtube.com/watch?v=wFV2VqzpeZs ### In-depth dives From 9eae63748222747eb71e5f88cd037d8c31887458 Mon Sep 17 00:00:00 2001 From: Aykut Argun <48754174+argunaykut@users.noreply.github.com> Date: Mon, 9 Nov 2020 18:00:28 +0100 Subject: [PATCH 05/78] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 91b253ee0..bf16b2f42 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,8 @@ DeepTrack 2.0 introduction tutorial video: https://www.youtube.com/watch?v=hyfax DeepTrack 2.0 single particle tracking tutorial video: https://www.youtube.com/watch?v=6Cntik6AfBI&t=1s DeepTrack 2.0 multiple particle tracking tutorial video: https://www.youtube.com/watch?v=wFV2VqzpeZs + + ### In-depth dives The examples folder contains notebooks which explains the different modules in more detail. These can be read in any order, but we provide a recommended order where more fundamental topics are introduced early. From 48e089a60667f86e4199b769c2619ade2a708d2c Mon Sep 17 00:00:00 2001 From: Aykut Argun <48754174+argunaykut@users.noreply.github.com> Date: Mon, 9 Nov 2020 18:03:29 +0100 Subject: [PATCH 06/78] Update README.md --- README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index bf16b2f42..b21a0c01f 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,13 @@ DeepTrack 2.0 introduction tutorial video: https://www.youtube.com/watch?v=hyfax DeepTrack 2.0 single particle tracking tutorial video: https://www.youtube.com/watch?v=6Cntik6AfBI&t=1s DeepTrack 2.0 multiple particle tracking tutorial video: https://www.youtube.com/watch?v=wFV2VqzpeZs - + + + + + ### In-depth dives From ccf8b5299c29ed247cc11baa7c543f049b419d27 Mon Sep 17 00:00:00 2001 From: Aykut Argun <48754174+argunaykut@users.noreply.github.com> Date: Mon, 9 Nov 2020 18:06:02 +0100 Subject: [PATCH 07/78] Update README.md --- README.md | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/README.md b/README.md index b21a0c01f..9908da1c2 100644 --- a/README.md +++ b/README.md @@ -51,13 +51,7 @@ DeepTrack 2.0 introduction tutorial video: https://www.youtube.com/watch?v=hyfax DeepTrack 2.0 single particle tracking tutorial video: https://www.youtube.com/watch?v=6Cntik6AfBI&t=1s DeepTrack 2.0 multiple particle tracking tutorial video: https://www.youtube.com/watch?v=wFV2VqzpeZs - - - - - +https://img.youtube.com/vi/wFV2VqzpeZs/sddefault.jpg ### In-depth dives From cb4440ab58e44d93ef3432097a35707dd03e3723 Mon Sep 17 00:00:00 2001 From: Aykut Argun <48754174+argunaykut@users.noreply.github.com> Date: Mon, 9 Nov 2020 18:08:28 +0100 Subject: [PATCH 08/78] Update README.md --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 9908da1c2..bf7892e79 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,9 @@ DeepTrack 2.0 introduction tutorial video: https://www.youtube.com/watch?v=hyfax DeepTrack 2.0 single particle tracking tutorial video: https://www.youtube.com/watch?v=6Cntik6AfBI&t=1s DeepTrack 2.0 multiple particle tracking tutorial video: https://www.youtube.com/watch?v=wFV2VqzpeZs -https://img.youtube.com/vi/wFV2VqzpeZs/sddefault.jpg + + +[![DEEPTRACK 2.0 Introduction Tutorial](http://img.youtube.com/vi/wFV2VqzpeZs/0.jpg)](http://www.youtube.com/watch?v=wFV2VqzpeZs) ### In-depth dives From afc09821e9755d5d711bbac794e5e564b4f90795 Mon Sep 17 00:00:00 2001 From: Aykut Argun <48754174+argunaykut@users.noreply.github.com> Date: Mon, 9 Nov 2020 18:10:38 +0100 Subject: [PATCH 09/78] Update README.md --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index bf7892e79..23e1b9785 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,12 @@ Additionally, we have seven more case studies which are less documented, but giv DeepTrack 2.0 introduction tutorial video: https://www.youtube.com/watch?v=hyfaxF8q6VE&t=16s DeepTrack 2.0 single particle tracking tutorial video: https://www.youtube.com/watch?v=6Cntik6AfBI&t=1s -DeepTrack 2.0 multiple particle tracking tutorial video: https://www.youtube.com/watch?v=wFV2VqzpeZs + + +DeepTrack 2.0 multiple particle tracking tutorial video: + From d3b1a4fe15293466164716a6d63692690e95d80b Mon Sep 17 00:00:00 2001 From: Aykut Argun <48754174+argunaykut@users.noreply.github.com> Date: Mon, 9 Nov 2020 18:14:03 +0100 Subject: [PATCH 10/78] Update README.md --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 23e1b9785..a323a32b2 100644 --- a/README.md +++ b/README.md @@ -53,12 +53,11 @@ DeepTrack 2.0 single particle tracking tutorial video: https://www.youtube.com/w DeepTrack 2.0 multiple particle tracking tutorial video: Tutorial -[![DEEPTRACK 2.0 Introduction Tutorial](http://img.youtube.com/vi/wFV2VqzpeZs/0.jpg)](http://www.youtube.com/watch?v=wFV2VqzpeZs) ### In-depth dives From 8c725762dbf48d51b015f301229c715aac6cee76 Mon Sep 17 00:00:00 2001 From: Aykut Argun <48754174+argunaykut@users.noreply.github.com> Date: Mon, 9 Nov 2020 18:15:36 +0100 Subject: [PATCH 11/78] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a323a32b2..0d9c05bba 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ DeepTrack 2.0 introduction tutorial video: https://www.youtube.com/watch?v=hyfax DeepTrack 2.0 single particle tracking tutorial video: https://www.youtube.com/watch?v=6Cntik6AfBI&t=1s -DeepTrack 2.0 multiple particle tracking tutorial video: +DeepTrack 2.0 multiple particle tracking tutorial video: https://youtu.be/wFV2VqzpeZs Tutorial From 9f015a2a1cb9bda5d0b784cbe9ad3db0f11149f3 Mon Sep 17 00:00:00 2001 From: Aykut Argun <48754174+argunaykut@users.noreply.github.com> Date: Mon, 9 Nov 2020 18:16:55 +0100 Subject: [PATCH 12/78] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0d9c05bba..7564443b6 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ DeepTrack 2.0 single particle tracking tutorial video: https://www.youtube.com/w DeepTrack 2.0 multiple particle tracking tutorial video: https://youtu.be/wFV2VqzpeZs Tutorial From 2245cbd003f2a1646166720695e5140367b62b50 Mon Sep 17 00:00:00 2001 From: Aykut Argun <48754174+argunaykut@users.noreply.github.com> Date: Mon, 9 Nov 2020 18:17:52 +0100 Subject: [PATCH 13/78] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7564443b6..ce24a5cb9 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ DeepTrack 2.0 single particle tracking tutorial video: https://www.youtube.com/w DeepTrack 2.0 multiple particle tracking tutorial video: https://youtu.be/wFV2VqzpeZs Tutorial From e31cc65385da9c7d1c15504125c1c364b482d1a0 Mon Sep 17 00:00:00 2001 From: Aykut Argun <48754174+argunaykut@users.noreply.github.com> Date: Mon, 9 Nov 2020 18:19:47 +0100 Subject: [PATCH 14/78] Update README.md --- README.md | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ce24a5cb9..50afda858 100644 --- a/README.md +++ b/README.md @@ -47,8 +47,15 @@ Additionally, we have seven more case studies which are less documented, but giv ### Video Tutorials -DeepTrack 2.0 introduction tutorial video: https://www.youtube.com/watch?v=hyfaxF8q6VE&t=16s -DeepTrack 2.0 single particle tracking tutorial video: https://www.youtube.com/watch?v=6Cntik6AfBI&t=1s +DeepTrack 2.0 introduction tutorial video: https://youtu.be/hyfaxF8q6VE + + +DeepTrack 2.0 single particle tracking tutorial video: https://youtu.be/6Cntik6AfBI + DeepTrack 2.0 multiple particle tracking tutorial video: https://youtu.be/wFV2VqzpeZs From ddb29ea884376722e34367c82038e236a72e5eee Mon Sep 17 00:00:00 2001 From: Aykut Argun <48754174+argunaykut@users.noreply.github.com> Date: Mon, 9 Nov 2020 18:21:12 +0100 Subject: [PATCH 15/78] Video links added --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 50afda858..3c31b07c4 100644 --- a/README.md +++ b/README.md @@ -47,12 +47,12 @@ Additionally, we have seven more case studies which are less documented, but giv ### Video Tutorials -DeepTrack 2.0 introduction tutorial video: https://youtu.be/hyfaxF8q6VE +DeepTrack 2.0 introduction tutorial video: https://youtu.be/hyfaxF8q6VE Tutorial -DeepTrack 2.0 single particle tracking tutorial video: https://youtu.be/6Cntik6AfBI +DeepTrack 2.0 single particle tracking tutorial video: https://youtu.be/6Cntik6AfBI Tutorial From 8fb2787e15cbada3559de8fe917ca47cb2d4d00a Mon Sep 17 00:00:00 2001 From: Benjamin Midtvedt Date: Fri, 20 Nov 2020 20:37:59 +0100 Subject: [PATCH 16/78] Set ndim=5 --- tutorials/analyzing_video_tutorial.ipynb | 4513 +--------------------- 1 file changed, 199 insertions(+), 4314 deletions(-) diff --git a/tutorials/analyzing_video_tutorial.ipynb b/tutorials/analyzing_video_tutorial.ipynb index 10627b3d2..748eda632 100644 --- a/tutorials/analyzing_video_tutorial.ipynb +++ b/tutorials/analyzing_video_tutorial.ipynb @@ -199,1338 +199,33 @@ "metadata": {}, "outputs": [ { + "output_type": "display_data", "data": { - "text/html": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "
\n", - " \n", - "
\n", - " \n", - "
\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
\n", - "
\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
\n", - "
\n", - "
\n", - "\n", - "\n", - "\n" - ], - "text/plain": [ - "" - ] + "text/plain": "", + "text/html": "\n\n\n\n\n\n
\n \n
\n \n
\n \n \n \n \n \n \n \n \n \n
\n
\n \n \n \n \n \n \n
\n
\n
\n\n\n\n" }, - "metadata": {}, - "output_type": "display_data" + "metadata": {} }, { + "output_type": "execute_result", "data": { "text/plain": [ - "" + "" ] }, - "execution_count": 8, "metadata": {}, - "output_type": "execute_result" + "execution_count": 8 }, { + "output_type": "display_data", "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] + "text/plain": "
", + "image/svg+xml": "\r\n\r\n\r\n\r\n \r\n \r\n \r\n \r\n 2020-11-20T15:09:33.990915\r\n image/svg+xml\r\n \r\n \r\n Matplotlib v3.3.0, https://matplotlib.org/\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAOcAAADnCAYAAADl9EEgAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy86wFpkAAAACXBIWXMAAAsTAAALEwEAmpwYAAAOQklEQVR4nO3d6W4b1xXA8TsLV0leYitx0BYoin5p36OP0KfsI/RFCgRFgQYNEju2NkrcZ/ohDc9CcTxkSfmI/P8+DT3D4SIf3nPmLpPVdZ0AxJN/6TcA4HEEJxAUwQkERXACQRGcQFBl086/5H/lUi5wYH+v/pY99u+0nEBQBCcQFMEJBEVwAkERnEBQBCcQFMEJBEVwAkERnEBQBCcQFMEJBEVwAkERnEBQBCcQFMEJBEVwAkERnEBQBCcQFMEJBEVwAkERnEBQBCcQFMEJBEVwAkERnEBQBCcQFMEJBEVwAkERnEBQBCcQFMEJBEVwAkERnEBQBCcQFMEJBEVwAkERnEBQBCcQFMEJBEVwAkGVX/oNYA+ybPvn1PX+3wf2ipYTCIrgBIIirf3SdklJo7wuqfFB0XICQRGcQFAEJxAUNechfKk68qm1/ZzUpjuh5QSCIjiBoEhrt/Ec0tWs4fe2rp7ufWhN3xsp70a0nEBQBCcQFGmt99Spa1MaGv219pEmk/JuRMsJBEVwAkERnEBQ1Jwp7b/OPEAdmeVPVwvXVcta79DdNvrvcoL1Jy0nEBTBCQR1mmntvtLYHdLX1unpU3axrL10u5S0Mf3dd8rr/2YnkObScgJBEZxAUAQnENRp1py7alkHNtaVTedoeF524GGFtanhCtlsqCubatPW9eiuXS4n0M1CywkERXACQZ1OWrtrWrjvVNYdZ9LVvOG12h7XVmXTSfOudJqY2eM2pr8pmRRYp7xbdbl8qQnhAdFyAkERnEBQBCcQ1OnUnG1tMWzO1Jm71pUb9q11nRSqvvP17S7rx/o6UNd6al+9XNqXMudw9aj+aJX6LNt0uezSzXKkQ/toOYGgCE4gqONOa/c8qmatu2RDKtucktrfw6zIHz+utH+aTD/P7Uv6HE0jZ/TjhU1Xk0pf68VCTrcsNh/XkPLWSe2rduwu2cdIomeMlhMIiuAEgjrutLathiu0G6/IprQ5lS1sKpjpx25f6nbkuI5s1/2uOaxWx9Vd+2erO3LOulDvw10JzZaSGmZTl5LO5mrfTHbo7ZRSPVfHuTS/1ufX/55cCt1wJbf1+kVNjmRQPC0nEBTBCQRFcAJBUXNuo2nkj6olM19XduRrzrq2lkz93mqzOhustpcXPXPYcijnWAzt+Zc9eR91vrneKubyuJjYfeVIasniXrbz0dgcl42ncnpXj2ZJHtfm362mbpaNs1lOcPYKLScQFMEJBHVcaW3bEUFtu04+c6wZ7aO3O250j0pla5W6ppRS9XK42p6/6q+2p6/tOaYv5Pzzc/sel/K0VKmMN3O9CIVkpKl8sDu7d/LE3rV023Sv7Psor1X67r7vutZdKTLKqPYTuzOdhtv36HtdThktJxAUwQkERXACQR1XzXkILWebZGqmiB6Gl5KtM6tXZ2bf5FL2jS/lHOO39rWmr6VGXFzYGq7qq8elnjTtun5m8ltcjOzvcvdGHg/O5HmDnj1uoL4P/5/HzEoZSxdM5obkmUXC3MwWXeM3LhLWdsbKM56ITcsJBEVwAkGR1qbPzDzR/ERpM0JI7evb0T31uaSu0zd9s+/hG/kT3H8r55t87WZrvJHRN+cv7KidF33pI+mV0oWxdKNv7mfSpXMzcu/jWh4vB5KuLztutFOSzzZwqWapJnBnasK2n5StU8217pj0fNLOQ6PlBIIiOIGgnn9au4dRQc2n1ylvw9VaPVF6YNPaxUt5PHljv/KHb+Sc428l/eu+ezDH/e7N9Wr7t2fXZt/b7mi1PSwk/Z1XNiW9XshopB8uXpp9/x6+Wm1flRdqj73yXMzVFd+JHcRfjCU11pO3k0pxU0opqUnZjescnfhoIVpOICiCEwiK4ASCev415775WSmbZp6kZLtP1AJc1dDWYrMXsm/ylT3H5K3UWOXX0kXyh8uP5rg/vfhR9g0+mH2X5e1qu59JrTev7Z/3eik15zfdr8y+YSm16j/Uv1/NbW1aPsg5OyNb03bu5HN37lWtOvELnsl3sNbNYg488EJgwdFyAkERnEBQpLVbaBr4XqsJ1lXfdj/MzuU3cPbCnmL5SroZ3r2SLpE/XtjU9c/DH1bbv+/afW9y6XbpZZImVm71nutKunQuCjvKSHtYSHo6urcjiWY38plnn+z5F2cq5dXr8brbR9S6myXbvC7TqY8WouUEgiI4gaAITiAoas6U2g/ta1i3Vtecy57tOpgP5bj5ua2jOufShfHuTLpEftf/ZI77TedKjitGZt9lId0MPfVZ5m4S8jCzQwK1u67MnPlpKIXx9+e2K+XqTGrQtfVz+/LalbqfS+G7oPT36Pc1da2cGFpOICiCEwiKtPZzmma9ZI+nZ1XHPqfqPL6dUkr9nnSlvOxMZNt1dVzk8vhlblO/80y6PnqZ6tLxC9cmOf9FbW+l8KqQlPeilOPOunNz3KeupMpV16a1Vak+d/n4Xb/RHi0nEBTBCQR1kmnt2i0XduWvNK5ewN/SQT/Hppq5GtCdqzS0SPZKa0eN/PGr+hTq9YqGJSML9UYKN/qmyORY81puwLn+OV+7lcKmr7XthHgYtJxAUAQnEBTBCQR1kjWnn6ib+SKurerxhar87QdUCZeyhZvJsZAXHy/VpOza9rk8qBklk3xq9k1qt4DW/yzd4lkTVYNOajshfKL6ePT7mC3dl7NUa866l810eapf+xndAiESWk4gKIITCOok09qt6JTMr1uj96lbEeQz14WhstBi4u4eNpYU8tNU1vh5P7ezst+VN6vti3ySLBnt01c59NwddafWsf24tHc7+7CQ1/swO19t347tZOv8QX7PS/c2iqm6s/Vc5fJL1x2jv8eq4Q5hJ46WEwiK4ASCIjiBoKg5U3LD3Nr3q9RLXWNJv0IxsX0MXbWGq1/rdXYrXRo/3sk9Sv7Vf2OOOy98nSnu1ORrvW7tcm2BL6lpv5/Z8/9zcin7Rq9X2/e3tubs3snveWfkhgCO1fcxU9+Bn0DddCdqrNByAkERnEBQpLWe7y5Rw15qN9Ilq1S6ptLa/MFOZNa3Kehd2d/D+YU8vhpKF8Z3ncu0yWhoU823paS1vVzS2qq2ae2Nuh3D9xN7O4bvbuX1/vNR1g3Kf7YjiXpXavvWpqflSD53NpX3US9cWlttHj3kv+PVv5/A7Rc8Wk4gKIITCIq0dht+NIu6ClnPJY3LHuzA9O6NpIaDM7+cpDyuOurKbf3aHDeZyRXf9xcXZt9XPVn/Z1Dou4zZ397bmSx/+WFsRwi9/yQjhKr3kjYP3ttzDH5Wy3Be2TFIxb1K56dqu7JprUldm0YInfhVXVpOICiCEwiK4ASCev41p65fmhaS0vWLu/2CvkzvJ17r+ijzl/31CKGFdKVkE9uVUtzK6J5+x631WuiuCjXxem4nW988SPfGzYuh2dcbSO1XluoWgJX9PmZTOediZM9fXsl/heHP8rzhT/YzDz7I5yyvbW2d3cvauuY2f36EUFOdeYJdJpvQcgJBEZxAUM8/rd03f/m+Ur9fmdun02jdrTK1aW12ryYou7VudYKaLyXFLSb2uOmtpLyLc5saL/qyvtC81GsZ2bQ2V29reG/3dWUud+pfyeccfHSD+D9K6prfubuWTVSaq9L82k+2VuXBphFBKX1mVFDbbpZnvH4RLScQFMEJBEVwAkFRc25hbVaKrp10t0qyNWetSjP/a9hR3Qq5WhSrvLezQfrXUmfOh/YsSyk5U1WodWVduaUmrKTOg7sXy0ged29U18ytneSd36lbE47tPj2E0XSfNHWlrC2adtpD9jRaTiAoghMI6rjSWn/ZfNOIIZ86qRFDa7dq0LfAq9xvme9a+fUc7rFOc2vX+5CpdLhQo2r6Dz1znJ7ZUvXczJaOev8NaW22ULcYdOsc5WM9WVy6RLKJHQWkZ5v4LiPTnaRTWTciyJQH7m9xipOqN6HlBIIiOIGgjiutPQAzKN7d5bnWdw9rOofaXruSa9YhkrQ2d4PnczVQvS5tWtvRj5sG/+v0cm7TWr20Z1LptbkCm1LzyB99fp3i+nJjl9R1m6u4z3hUkEbLCQRFcAJBEZxAUNScKTVOxG77vNb159oiYWpkka7TFu620arbIit8l07TK+oXf3xE0y+7dL34eO34y/PU47VacsMavw2jgPYy8+RI0XICQRGcQFDHnda2XV/IPGeb0UPqnBtSXP8+Mv8+dKpZbUgtU0pZprow/HvOW342zX2WjWvJtk1dHzmnHMgooF3QcgJBEZxAUAQnENRx15z70HK9W80P89OzWWpfMW6qR30XRt7wO7pDV0qjprrSHNduovRWNeYu3SdHMlzPo+UEgiI4gaBOJ63dpVtl7Rybu1nsYQ0Ttr2mlNec9AlTtx1H7ezURXLio4Ca0HICQRGcQFCnk9Zqbdca+ux52g2Yb0735Kps1jTSx4860rYZrP+rHdPJMKnrkV6h1Wg5gaAITiAoghMI6jRrTu8Q3Sxay5pw99kaTQXpEzpkt8gJ1JgeLScQFMEJBEVa6+2rm8Wcc4d0b5fukUN46hE8J5i+bhLkfwAAj+AEgiI4gaCoOT+nqQbaRz268XWPeLYGdWUrtJxAUAQnEBRp7f+jbXp2yPQ3EtLVvaLlBIIiOIGgCE4gKGrOp/Cca1PqyC+GlhMIiuAEgiKtjYQUEgotJxAUwQkERXACQRGcQFAEJxAUwQkERXACQRGcQFAEJxAUwQkERXACQRGcQFAEJxAUwQkERXACQRGcQFAEJxAUwQkERXACQRGcQFAEJxAUwQkERXACQRGcQFAEJxAUwQkERXACQRGcQFAEJxAUwQkERXACQRGcQFAEJxBUVnM3ZSAkWk4gKIITCIrgBIIiOIGgCE4gKIITCOq/HfdUDjBA+yMAAAAASUVORK5CYII=\n" }, "metadata": { "needs_background": "light" - }, - "output_type": "display_data" + } } ], "source": [ @@ -1602,2750 +297,33 @@ "metadata": {}, "outputs": [ { + "output_type": "display_data", "data": { - "text/html": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "
\n", - " \n", - "
\n", - " \n", - "
\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
\n", - "
\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
\n", - "
\n", - "
\n", - "\n", - "\n", - "\n" - ], - "text/plain": [ - "" - ] + "text/plain": "", + "text/html": "\n\n\n\n\n\n
\n \n
\n \n
\n \n \n \n \n \n \n \n \n \n
\n
\n \n \n \n \n \n \n
\n
\n
\n\n\n\n" }, - "metadata": {}, - "output_type": "display_data" + "metadata": {} }, { + "output_type": "execute_result", "data": { "text/plain": [ - "" + "" ] }, - "execution_count": 11, "metadata": {}, - "output_type": "execute_result" + "execution_count": 11 }, { + "output_type": "display_data", "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] + "text/plain": "
", + "image/svg+xml": "\r\n\r\n\r\n\r\n \r\n \r\n \r\n \r\n 2020-11-20T15:09:35.199957\r\n image/svg+xml\r\n \r\n \r\n Matplotlib v3.3.0, https://matplotlib.org/\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n", + "image/png": "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\n" }, "metadata": { "needs_background": "light" - }, - "output_type": "display_data" + } } ], "source": [ @@ -4386,7 +364,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 16, "metadata": {}, "outputs": [], "source": [ @@ -4398,7 +376,8 @@ " get_intensity_of_particle, \n", " batch_size=16,\n", " min_data_size=512,\n", - " max_data_size=1024\n", + " max_data_size=1024,\n", + " ndim=5\n", ")" ] }, @@ -4417,426 +396,332 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 17, "metadata": {}, "outputs": [ { - "name": "stdout", "output_type": "stream", + "name": "stdout", "text": [ - "Generating 527 / 512 samples before starting training\n", + "Generating 521 / 512 samples before starting training\n", "Epoch 1/200\n", - "32/32 [==============================] - 1s 17ms/step - loss: 16.9874\n", + "32/32 [==============================] - 1s 20ms/step - loss: 17.7132\n", "Epoch 2/200\n", - "32/32 [==============================] - 1s 17ms/step - loss: 7.1719\n", + "32/32 [==============================] - 1s 19ms/step - loss: 6.7169\n", "Epoch 3/200\n", - "32/32 [==============================] - 1s 18ms/step - loss: 6.9469\n", + "32/32 [==============================] - 1s 19ms/step - loss: 6.9233\n", "Epoch 4/200\n", - "32/32 [==============================] - 1s 18ms/step - loss: 6.9290\n", + "32/32 [==============================] - 1s 19ms/step - loss: 6.6571\n", "Epoch 5/200\n", - "32/32 [==============================] - 1s 18ms/step - loss: 7.1216\n", + "32/32 [==============================] - 1s 19ms/step - loss: 6.6846\n", "Epoch 6/200\n", - "32/32 [==============================] - 1s 18ms/step - loss: 7.0064\n", + "32/32 [==============================] - 1s 20ms/step - loss: 6.5536\n", "Epoch 7/200\n", - "32/32 [==============================] - 1s 19ms/step - loss: 6.9390\n", + "32/32 [==============================] - 1s 20ms/step - loss: 6.6952\n", "Epoch 8/200\n", - "32/32 [==============================] - 1s 18ms/step - loss: 7.2026\n", + "32/32 [==============================] - 1s 20ms/step - loss: 6.7723\n", "Epoch 9/200\n", - "32/32 [==============================] - 1s 18ms/step - loss: 7.1431\n", + "32/32 [==============================] - 1s 20ms/step - loss: 6.5794\n", "Epoch 10/200\n", - "32/32 [==============================] - 1s 18ms/step - loss: 7.2430\n", + "32/32 [==============================] - 1s 20ms/step - loss: 6.4534\n", "Epoch 11/200\n", - "32/32 [==============================] - 1s 18ms/step - loss: 7.0248\n", + "32/32 [==============================] - 1s 20ms/step - loss: 6.5635\n", "Epoch 12/200\n", - "32/32 [==============================] - 1s 19ms/step - loss: 7.1553\n", + "32/32 [==============================] - 1s 20ms/step - loss: 6.3594\n", "Epoch 13/200\n", - "32/32 [==============================] - 1s 19ms/step - loss: 7.0088\n", + "32/32 [==============================] - 1s 20ms/step - loss: 6.7536\n", "Epoch 14/200\n", - "32/32 [==============================] - 1s 20ms/step - loss: 7.2726\n", + "32/32 [==============================] - 1s 20ms/step - loss: 6.7599\n", "Epoch 15/200\n", - "32/32 [==============================] - 1s 19ms/step - loss: 7.0784\n", + "32/32 [==============================] - 1s 20ms/step - loss: 6.6185\n", "Epoch 16/200\n", - "32/32 [==============================] - 1s 19ms/step - loss: 6.9181\n", + "32/32 [==============================] - 1s 20ms/step - loss: 6.2487\n", "Epoch 17/200\n", - "32/32 [==============================] - 1s 19ms/step - loss: 6.9388\n", + "32/32 [==============================] - 1s 20ms/step - loss: 6.6370\n", "Epoch 18/200\n", - "32/32 [==============================] - 1s 20ms/step - loss: 6.9529\n", + "32/32 [==============================] - 1s 20ms/step - loss: 4.7344\n", "Epoch 19/200\n", - "32/32 [==============================] - 1s 19ms/step - loss: 6.6827\n", + "32/32 [==============================] - 1s 21ms/step - loss: 1.8829\n", "Epoch 20/200\n", - "32/32 [==============================] - 1s 19ms/step - loss: 7.0267\n", + "32/32 [==============================] - 1s 21ms/step - loss: 0.7131\n", "Epoch 21/200\n", - "32/32 [==============================] - 1s 19ms/step - loss: 7.0308\n", + "32/32 [==============================] - 1s 20ms/step - loss: 0.2448\n", "Epoch 22/200\n", - "32/32 [==============================] - 1s 22ms/step - loss: 6.5830\n", + "32/32 [==============================] - 1s 22ms/step - loss: 0.0938\n", "Epoch 23/200\n", - "32/32 [==============================] - 1s 19ms/step - loss: 6.4464\n", + "32/32 [==============================] - 1s 21ms/step - loss: 0.0431\n", "Epoch 24/200\n", - "32/32 [==============================] - 1s 19ms/step - loss: 4.6743\n", + "32/32 [==============================] - 1s 21ms/step - loss: 0.0506\n", "Epoch 25/200\n", - "32/32 [==============================] - 1s 22ms/step - loss: 1.5881\n", + "32/32 [==============================] - 1s 21ms/step - loss: 0.0338\n", "Epoch 26/200\n", - "32/32 [==============================] - 1s 21ms/step - loss: 0.3412\n", + "32/32 [==============================] - 1s 21ms/step - loss: 0.0226\n", "Epoch 27/200\n", - "32/32 [==============================] - 1s 21ms/step - loss: 0.2024\n", + "32/32 [==============================] - 1s 21ms/step - loss: 0.0235\n", "Epoch 28/200\n", - "32/32 [==============================] - 1s 20ms/step - loss: 0.1177\n", + "32/32 [==============================] - 1s 21ms/step - loss: 0.0225\n", "Epoch 29/200\n", - "32/32 [==============================] - 1s 27ms/step - loss: 0.1353\n", + "32/32 [==============================] - 1s 21ms/step - loss: 0.0126\n", "Epoch 30/200\n", - "32/32 [==============================] - 1s 24ms/step - loss: 0.3202\n", + "32/32 [==============================] - 1s 21ms/step - loss: 0.0101\n", "Epoch 31/200\n", - "32/32 [==============================] - 1s 21ms/step - loss: 0.1485: 0s - loss\n", + "32/32 [==============================] - 1s 21ms/step - loss: 0.0103\n", "Epoch 32/200\n", - "32/32 [==============================] - 1s 21ms/step - loss: 0.0320\n", + "32/32 [==============================] - 1s 21ms/step - loss: 0.0122\n", "Epoch 33/200\n", - "32/32 [==============================] - 1s 22ms/step - loss: 0.0298\n", + "32/32 [==============================] - 1s 21ms/step - loss: 0.0135\n", "Epoch 34/200\n", - "32/32 [==============================] - 1s 20ms/step - loss: 0.0468\n", + "32/32 [==============================] - 1s 21ms/step - loss: 0.0169\n", "Epoch 35/200\n", - "32/32 [==============================] - 1s 22ms/step - loss: 0.0189\n", + "32/32 [==============================] - 1s 21ms/step - loss: 0.0143\n", "Epoch 36/200\n", - "32/32 [==============================] - 1s 21ms/step - loss: 0.0193\n", + "32/32 [==============================] - 1s 25ms/step - loss: 0.0088\n", "Epoch 37/200\n", - "32/32 [==============================] - 1s 22ms/step - loss: 0.0639\n", + "32/32 [==============================] - 1s 22ms/step - loss: 0.0118\n", "Epoch 38/200\n", - "32/32 [==============================] - 1s 20ms/step - loss: 0.0641\n", + "32/32 [==============================] - 1s 21ms/step - loss: 0.0093\n", "Epoch 39/200\n", - "32/32 [==============================] - 1s 21ms/step - loss: 0.0537\n", + "32/32 [==============================] - 1s 22ms/step - loss: 0.0083\n", "Epoch 40/200\n", - "32/32 [==============================] - 1s 20ms/step - loss: 0.0296\n", + "32/32 [==============================] - 1s 22ms/step - loss: 0.0072\n", "Epoch 41/200\n", - "32/32 [==============================] - 1s 21ms/step - loss: 0.0125\n", + "32/32 [==============================] - 1s 22ms/step - loss: 0.0121\n", "Epoch 42/200\n", - "32/32 [==============================] - 1s 22ms/step - loss: 0.0151: 0s - loss: 0\n", + "32/32 [==============================] - 1s 22ms/step - loss: 0.0151\n", "Epoch 43/200\n", - "32/32 [==============================] - 1s 25ms/step - loss: 0.0220\n", + "32/32 [==============================] - 1s 22ms/step - loss: 0.0303\n", "Epoch 44/200\n", - "32/32 [==============================] - 1s 29ms/step - loss: 0.0284\n", + "32/32 [==============================] - 1s 22ms/step - loss: 0.0124\n", "Epoch 45/200\n", - "32/32 [==============================] - 1s 21ms/step - loss: 0.0117\n", + "32/32 [==============================] - 1s 23ms/step - loss: 0.0100\n", "Epoch 46/200\n", - "32/32 [==============================] - 1s 21ms/step - loss: 0.0086\n", + "32/32 [==============================] - 1s 23ms/step - loss: 0.0076\n", "Epoch 47/200\n", - "32/32 [==============================] - 1s 21ms/step - loss: 0.0230\n", + "32/32 [==============================] - 1s 23ms/step - loss: 0.0223\n", "Epoch 48/200\n", - "32/32 [==============================] - 1s 22ms/step - loss: 0.0236\n", + "32/32 [==============================] - 1s 24ms/step - loss: 0.0557\n", "Epoch 49/200\n", - "32/32 [==============================] - 1s 21ms/step - loss: 0.0110: 0s - loss: 0\n", + "32/32 [==============================] - 1s 23ms/step - loss: 0.0575\n", "Epoch 50/200\n", - "32/32 [==============================] - 1s 26ms/step - loss: 0.0060\n", + "32/32 [==============================] - 1s 23ms/step - loss: 0.0112\n", "Epoch 51/200\n", - "32/32 [==============================] - 1s 22ms/step - loss: 0.0115\n", + "32/32 [==============================] - 1s 24ms/step - loss: 0.0082\n", "Epoch 52/200\n", - "32/32 [==============================] - 1s 21ms/step - loss: 0.0266\n", + "32/32 [==============================] - 1s 23ms/step - loss: 0.0077\n", "Epoch 53/200\n", - "32/32 [==============================] - 1s 22ms/step - loss: 0.0073\n", + "32/32 [==============================] - 1s 23ms/step - loss: 0.0102\n", "Epoch 54/200\n", - "32/32 [==============================] - 1s 23ms/step - loss: 0.0077\n", + "32/32 [==============================] - 1s 25ms/step - loss: 0.0170\n", "Epoch 55/200\n", - "32/32 [==============================] - 1s 26ms/step - loss: 0.0087\n", + "32/32 [==============================] - 1s 23ms/step - loss: 0.0246\n", "Epoch 56/200\n", - "32/32 [==============================] - 1s 24ms/step - loss: 0.0043\n", + "32/32 [==============================] - 1s 23ms/step - loss: 0.0094\n", "Epoch 57/200\n", - "32/32 [==============================] - 1s 24ms/step - loss: 0.0048\n", + "32/32 [==============================] - 1s 23ms/step - loss: 0.0076\n", "Epoch 58/200\n", - "32/32 [==============================] - 1s 23ms/step - loss: 0.0044\n", + "32/32 [==============================] - 1s 22ms/step - loss: 0.0092\n", "Epoch 59/200\n", - "32/32 [==============================] - 1s 26ms/step - loss: 0.0097\n", + "32/32 [==============================] - 1s 24ms/step - loss: 0.0161\n", "Epoch 60/200\n", - "32/32 [==============================] - 1s 23ms/step - loss: 0.0180\n", + "32/32 [==============================] - 1s 23ms/step - loss: 0.0523\n", "Epoch 61/200\n", - "32/32 [==============================] - 1s 21ms/step - loss: 0.0583\n", + "32/32 [==============================] - 1s 24ms/step - loss: 0.0208\n", "Epoch 62/200\n", - "32/32 [==============================] - 1s 23ms/step - loss: 0.1798\n", + "32/32 [==============================] - 1s 24ms/step - loss: 0.0124\n", "Epoch 63/200\n", - "32/32 [==============================] - 1s 27ms/step - loss: 0.3053\n", + "32/32 [==============================] - 1s 23ms/step - loss: 0.0079\n", "Epoch 64/200\n", - "32/32 [==============================] - 1s 27ms/step - loss: 0.1941\n", + "32/32 [==============================] - 1s 23ms/step - loss: 0.0047\n", "Epoch 65/200\n", - "32/32 [==============================] - 1s 26ms/step - loss: 0.0361\n", + "32/32 [==============================] - 1s 23ms/step - loss: 0.0055\n", "Epoch 66/200\n", - "32/32 [==============================] - 1s 25ms/step - loss: 0.0158\n", + "32/32 [==============================] - 1s 24ms/step - loss: 0.0025\n", "Epoch 67/200\n", - "32/32 [==============================] - 1s 23ms/step - loss: 0.0103\n", + "32/32 [==============================] - 1s 25ms/step - loss: 0.0028\n", "Epoch 68/200\n", - "32/32 [==============================] - 1s 27ms/step - loss: 0.0052\n", + "32/32 [==============================] - 1s 23ms/step - loss: 0.0026\n", "Epoch 69/200\n", - "32/32 [==============================] - 1s 23ms/step - loss: 0.0043\n", + "32/32 [==============================] - 1s 23ms/step - loss: 0.0028\n", "Epoch 70/200\n", - "32/32 [==============================] - 1s 22ms/step - loss: 0.0052\n", + "32/32 [==============================] - 1s 25ms/step - loss: 0.0026\n", "Epoch 71/200\n", - "32/32 [==============================] - 1s 22ms/step - loss: 0.0048\n", + "32/32 [==============================] - 1s 23ms/step - loss: 0.0075\n", "Epoch 72/200\n", - "32/32 [==============================] - 1s 22ms/step - loss: 0.0039\n", + "32/32 [==============================] - 1s 24ms/step - loss: 0.0237\n", "Epoch 73/200\n", - "32/32 [==============================] - 1s 24ms/step - loss: 0.0085\n", + "32/32 [==============================] - 1s 23ms/step - loss: 0.0137\n", "Epoch 74/200\n", - "32/32 [==============================] - 1s 22ms/step - loss: 0.0058\n", + "32/32 [==============================] - 1s 23ms/step - loss: 0.0064\n", "Epoch 75/200\n", - "32/32 [==============================] - 1s 23ms/step - loss: 0.0074\n", + "32/32 [==============================] - 1s 23ms/step - loss: 0.0055\n", "Epoch 76/200\n", - "32/32 [==============================] - 1s 22ms/step - loss: 0.0042\n", + "32/32 [==============================] - 1s 25ms/step - loss: 0.0070\n", "Epoch 77/200\n", - "32/32 [==============================] - 1s 22ms/step - loss: 0.0079\n", + "32/32 [==============================] - 1s 24ms/step - loss: 0.0084\n", "Epoch 78/200\n", - "32/32 [==============================] - 1s 21ms/step - loss: 0.0135\n", + "32/32 [==============================] - 1s 25ms/step - loss: 0.0139\n", "Epoch 79/200\n", - "32/32 [==============================] - 1s 21ms/step - loss: 0.0057\n", + "32/32 [==============================] - 1s 25ms/step - loss: 0.0061\n", "Epoch 80/200\n", - "32/32 [==============================] - 1s 23ms/step - loss: 0.0091\n", + "32/32 [==============================] - 1s 32ms/step - loss: 0.0027\n", "Epoch 81/200\n", - "32/32 [==============================] - 1s 21ms/step - loss: 0.0064\n", + "32/32 [==============================] - 1s 25ms/step - loss: 0.0022\n", "Epoch 82/200\n", - "32/32 [==============================] - 1s 22ms/step - loss: 0.0063\n", + "32/32 [==============================] - 1s 25ms/step - loss: 0.0032\n", "Epoch 83/200\n", - "32/32 [==============================] - 1s 21ms/step - loss: 0.0155\n", + "32/32 [==============================] - 1s 24ms/step - loss: 0.0052\n", "Epoch 84/200\n", - "32/32 [==============================] - 1s 23ms/step - loss: 0.0040\n", + "32/32 [==============================] - 1s 25ms/step - loss: 0.0113\n", "Epoch 85/200\n", - "32/32 [==============================] - 1s 22ms/step - loss: 0.0035\n", + "32/32 [==============================] - 1s 24ms/step - loss: 0.0104\n", "Epoch 86/200\n", - "32/32 [==============================] - 1s 25ms/step - loss: 0.0027\n", + "32/32 [==============================] - 1s 24ms/step - loss: 0.0095\n", "Epoch 87/200\n", - "32/32 [==============================] - 1s 21ms/step - loss: 0.0090\n", + "32/32 [==============================] - 1s 24ms/step - loss: 0.0190\n", "Epoch 88/200\n", - "32/32 [==============================] - 1s 21ms/step - loss: 0.0296\n", + "32/32 [==============================] - 1s 27ms/step - loss: 0.0529\n", "Epoch 89/200\n", - "32/32 [==============================] - 1s 22ms/step - loss: 0.0107\n", + "32/32 [==============================] - 1s 24ms/step - loss: 0.0301\n", "Epoch 90/200\n", - "32/32 [==============================] - 1s 21ms/step - loss: 0.0032\n", + "32/32 [==============================] - 1s 25ms/step - loss: 0.0211\n", "Epoch 91/200\n", - "32/32 [==============================] - 1s 22ms/step - loss: 0.0040\n", + "32/32 [==============================] - 1s 24ms/step - loss: 0.0121\n", "Epoch 92/200\n", - "32/32 [==============================] - 1s 22ms/step - loss: 0.0052: 0s - loss: 0.00\n", + "32/32 [==============================] - 1s 24ms/step - loss: 0.0168\n", "Epoch 93/200\n", - "32/32 [==============================] - 1s 23ms/step - loss: 0.0130\n", + "32/32 [==============================] - 1s 26ms/step - loss: 0.0109\n", "Epoch 94/200\n", - "32/32 [==============================] - 1s 21ms/step - loss: 0.0574\n", + "32/32 [==============================] - 1s 26ms/step - loss: 0.0044\n", "Epoch 95/200\n", - "32/32 [==============================] - 1s 23ms/step - loss: 0.0683\n", + "32/32 [==============================] - 1s 29ms/step - loss: 0.0042\n", "Epoch 96/200\n", - "32/32 [==============================] - 1s 21ms/step - loss: 0.0131\n", + "32/32 [==============================] - 1s 25ms/step - loss: 0.0031\n", "Epoch 97/200\n", - "32/32 [==============================] - 1s 21ms/step - loss: 0.0059\n", + "32/32 [==============================] - 1s 26ms/step - loss: 0.0040\n", "Epoch 98/200\n", - "32/32 [==============================] - 1s 21ms/step - loss: 0.0089\n", - "Epoch 99/200\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "32/32 [==============================] - 1s 22ms/step - loss: 0.0171\n", + "32/32 [==============================] - 1s 24ms/step - loss: 0.0107\n", + "Epoch 99/200\n", + "32/32 [==============================] - 1s 23ms/step - loss: 0.0086\n", "Epoch 100/200\n", - "32/32 [==============================] - 1s 22ms/step - loss: 0.0136\n", + "32/32 [==============================] - 1s 24ms/step - loss: 0.0039\n", "Epoch 101/200\n", - "32/32 [==============================] - 1s 20ms/step - loss: 0.0159: 0s - los\n", + "32/32 [==============================] - 1s 31ms/step - loss: 0.0043\n", "Epoch 102/200\n", - "32/32 [==============================] - 1s 22ms/step - loss: 0.0068\n", + "32/32 [==============================] - 1s 29ms/step - loss: 0.0022\n", "Epoch 103/200\n", - "32/32 [==============================] - 1s 21ms/step - loss: 0.0307\n", + "32/32 [==============================] - 1s 26ms/step - loss: 0.0029\n", "Epoch 104/200\n", - "32/32 [==============================] - 1s 21ms/step - loss: 0.0186\n", + "32/32 [==============================] - 1s 28ms/step - loss: 0.0049\n", "Epoch 105/200\n", - "32/32 [==============================] - 1s 22ms/step - loss: 0.0072: 0s - loss: 0.007\n", + "32/32 [==============================] - 1s 24ms/step - loss: 0.0026\n", "Epoch 106/200\n", - "32/32 [==============================] - 1s 21ms/step - loss: 0.0063\n", + "32/32 [==============================] - 1s 25ms/step - loss: 0.0028\n", "Epoch 107/200\n", - "32/32 [==============================] - 1s 22ms/step - loss: 0.0083\n", + "32/32 [==============================] - 1s 25ms/step - loss: 0.0038\n", "Epoch 108/200\n", - "32/32 [==============================] - 1s 21ms/step - loss: 0.0034: 0s - loss: 0.003\n", + "32/32 [==============================] - 1s 25ms/step - loss: 0.0079\n", "Epoch 109/200\n", - "32/32 [==============================] - 1s 22ms/step - loss: 0.0032\n", + "32/32 [==============================] - 1s 24ms/step - loss: 0.0077\n", "Epoch 110/200\n", - "32/32 [==============================] - 1s 21ms/step - loss: 0.0064\n", + "32/32 [==============================] - 1s 25ms/step - loss: 0.0054\n", "Epoch 111/200\n", - "32/32 [==============================] - 2s 67ms/step - loss: 0.0133\n", + "32/32 [==============================] - 1s 25ms/step - loss: 0.0164\n", "Epoch 112/200\n", - "32/32 [==============================] - 1s 21ms/step - loss: 0.0117\n", + "32/32 [==============================] - 1s 25ms/step - loss: 0.0114\n", "Epoch 113/200\n", - "32/32 [==============================] - 1s 24ms/step - loss: 0.0329\n", + "32/32 [==============================] - 1s 27ms/step - loss: 0.0104\n", "Epoch 114/200\n", - "32/32 [==============================] - 1s 26ms/step - loss: 0.0113\n", + "32/32 [==============================] - 1s 29ms/step - loss: 0.0126\n", "Epoch 115/200\n", - "32/32 [==============================] - 1s 28ms/step - loss: 0.0033\n", + "32/32 [==============================] - 1s 32ms/step - loss: 0.0109\n", "Epoch 116/200\n", - "32/32 [==============================] - 1s 24ms/step - loss: 0.0096\n", + "32/32 [==============================] - 1s 29ms/step - loss: 0.0100\n", "Epoch 117/200\n", - "32/32 [==============================] - 1s 27ms/step - loss: 0.0284\n", + "32/32 [==============================] - 1s 27ms/step - loss: 0.0075\n", "Epoch 118/200\n", - "32/32 [==============================] - 1s 28ms/step - loss: 0.0268\n", + "32/32 [==============================] - 1s 29ms/step - loss: 0.0037\n", "Epoch 119/200\n", - "32/32 [==============================] - 1s 24ms/step - loss: 0.0332\n", + "32/32 [==============================] - 1s 27ms/step - loss: 0.0025\n", "Epoch 120/200\n", - "32/32 [==============================] - 1s 26ms/step - loss: 0.0195\n", + "32/32 [==============================] - 1s 26ms/step - loss: 0.0032\n", "Epoch 121/200\n", - "32/32 [==============================] - 1s 22ms/step - loss: 0.0174\n", + "32/32 [==============================] - 1s 28ms/step - loss: 0.0018\n", "Epoch 122/200\n", - "32/32 [==============================] - 1s 28ms/step - loss: 0.0495\n", + "32/32 [==============================] - 1s 28ms/step - loss: 0.0032\n", "Epoch 123/200\n", - "32/32 [==============================] - 1s 25ms/step - loss: 0.0261\n", + "32/32 [==============================] - 1s 28ms/step - loss: 0.0025\n", "Epoch 124/200\n", - "32/32 [==============================] - 1s 22ms/step - loss: 0.0095\n", + "32/32 [==============================] - 1s 28ms/step - loss: 0.0015\n", "Epoch 125/200\n", - "32/32 [==============================] - 1s 22ms/step - loss: 0.0112\n", + "32/32 [==============================] - 1s 29ms/step - loss: 0.0032\n", "Epoch 126/200\n", - "32/32 [==============================] - 1s 22ms/step - loss: 0.0059\n", + "32/32 [==============================] - 1s 29ms/step - loss: 0.0036\n", "Epoch 127/200\n", - "32/32 [==============================] - 1s 26ms/step - loss: 0.0031\n", + "32/32 [==============================] - 1s 28ms/step - loss: 0.0016\n", "Epoch 128/200\n", - "32/32 [==============================] - 1s 24ms/step - loss: 0.0043\n", + "32/32 [==============================] - 1s 28ms/step - loss: 0.0013\n", "Epoch 129/200\n", - "32/32 [==============================] - 1s 24ms/step - loss: 0.0074\n", + "32/32 [==============================] - 1s 28ms/step - loss: 0.0022\n", "Epoch 130/200\n", - "32/32 [==============================] - 1s 22ms/step - loss: 0.0028\n", + "32/32 [==============================] - 1s 28ms/step - loss: 0.0075\n", "Epoch 131/200\n", - "32/32 [==============================] - 1s 23ms/step - loss: 0.0024\n", + "32/32 [==============================] - 1s 28ms/step - loss: 0.0188\n", "Epoch 132/200\n", - "32/32 [==============================] - 1s 21ms/step - loss: 0.0023\n", + "32/32 [==============================] - 1s 29ms/step - loss: 2.4492\n", "Epoch 133/200\n", - "32/32 [==============================] - 1s 23ms/step - loss: 0.0030\n", + "32/32 [==============================] - 1s 29ms/step - loss: 1.1936\n", "Epoch 134/200\n", - "32/32 [==============================] - 1s 21ms/step - loss: 0.0061\n", + "32/32 [==============================] - 1s 29ms/step - loss: 0.0763\n", "Epoch 135/200\n", - "32/32 [==============================] - 1s 22ms/step - loss: 0.0030\n", + "32/32 [==============================] - 1s 28ms/step - loss: 0.0421\n", "Epoch 136/200\n", - "32/32 [==============================] - 1s 26ms/step - loss: 0.0080\n", + "32/32 [==============================] - 1s 28ms/step - loss: 0.0418\n", "Epoch 137/200\n", - "32/32 [==============================] - 1s 26ms/step - loss: 0.0070\n", + "32/32 [==============================] - 1s 25ms/step - loss: 0.0182\n", "Epoch 138/200\n", - "32/32 [==============================] - 1s 25ms/step - loss: 0.0041\n", + "32/32 [==============================] - 1s 26ms/step - loss: 0.0128\n", "Epoch 139/200\n", - "32/32 [==============================] - 1s 23ms/step - loss: 0.0513\n", + "32/32 [==============================] - 1s 26ms/step - loss: 0.0181\n", "Epoch 140/200\n", - "32/32 [==============================] - 1s 26ms/step - loss: 0.0304\n", + "32/32 [==============================] - 1s 26ms/step - loss: 0.0152\n", "Epoch 141/200\n", - "32/32 [==============================] - 1s 23ms/step - loss: 0.0092\n", + "32/32 [==============================] - 1s 27ms/step - loss: 0.0097\n", "Epoch 142/200\n", - "32/32 [==============================] - 1s 22ms/step - loss: 0.0068\n", + "32/32 [==============================] - 1s 26ms/step - loss: 0.0060\n", "Epoch 143/200\n", - "32/32 [==============================] - 1s 30ms/step - loss: 0.0074\n", + "32/32 [==============================] - 1s 25ms/step - loss: 0.0103\n", "Epoch 144/200\n", - "32/32 [==============================] - 1s 24ms/step - loss: 0.0034\n", + "32/32 [==============================] - 1s 26ms/step - loss: 0.0101\n", "Epoch 145/200\n", - "32/32 [==============================] - 1s 27ms/step - loss: 0.0140\n", + "32/32 [==============================] - 1s 26ms/step - loss: 0.0057\n", "Epoch 146/200\n", - "32/32 [==============================] - 1s 24ms/step - loss: 0.0446\n", + "32/32 [==============================] - 1s 28ms/step - loss: 0.0042\n", "Epoch 147/200\n", - "32/32 [==============================] - 1s 24ms/step - loss: 0.0169\n", + "32/32 [==============================] - 1s 29ms/step - loss: 0.0067\n", "Epoch 148/200\n", - "32/32 [==============================] - 1s 28ms/step - loss: 0.0535\n", + "32/32 [==============================] - 1s 29ms/step - loss: 0.0072\n", "Epoch 149/200\n", - "32/32 [==============================] - 1s 25ms/step - loss: 0.3677\n", - "Epoch 150/200\n", - "32/32 [==============================] - 1s 23ms/step - loss: 0.2460\n", - "Epoch 151/200\n", - "32/32 [==============================] - 1s 21ms/step - loss: 0.1256\n", - "Epoch 152/200\n", - "32/32 [==============================] - 1s 22ms/step - loss: 0.0803\n", - "Epoch 153/200\n", - "32/32 [==============================] - 1s 21ms/step - loss: 0.0087\n", - "Epoch 154/200\n", - "32/32 [==============================] - 1s 22ms/step - loss: 0.0056\n", - "Epoch 155/200\n", - "32/32 [==============================] - 1s 28ms/step - loss: 0.0049\n", - "Epoch 156/200\n", - "32/32 [==============================] - 1s 21ms/step - loss: 0.0042\n", - "Epoch 157/200\n", - "32/32 [==============================] - 1s 23ms/step - loss: 0.0042\n", - "Epoch 158/200\n", - "32/32 [==============================] - 1s 21ms/step - loss: 0.0035\n", - "Epoch 159/200\n", - "32/32 [==============================] - 1s 24ms/step - loss: 0.0026\n", - "Epoch 160/200\n", - "32/32 [==============================] - 1s 21ms/step - loss: 0.0040\n", - "Epoch 161/200\n", - "32/32 [==============================] - 1s 22ms/step - loss: 0.0025\n", - "Epoch 162/200\n", - "32/32 [==============================] - 1s 23ms/step - loss: 0.0034\n", - "Epoch 163/200\n", - "32/32 [==============================] - 1s 21ms/step - loss: 0.0030\n", - "Epoch 164/200\n", - "32/32 [==============================] - 1s 23ms/step - loss: 0.0048\n", - "Epoch 165/200\n", - "32/32 [==============================] - 1s 21ms/step - loss: 0.0050\n", - "Epoch 166/200\n", - "32/32 [==============================] - 1s 24ms/step - loss: 0.0028\n", - "Epoch 167/200\n", - "32/32 [==============================] - 1s 25ms/step - loss: 0.0031\n", - "Epoch 168/200\n", - "32/32 [==============================] - 1s 27ms/step - loss: 0.0021\n", - "Epoch 169/200\n", - "32/32 [==============================] - 1s 24ms/step - loss: 0.0028\n", - "Epoch 170/200\n", - "32/32 [==============================] - 1s 24ms/step - loss: 0.0072\n", - "Epoch 171/200\n", - "32/32 [==============================] - 1s 25ms/step - loss: 0.0032\n", - "Epoch 172/200\n", - "32/32 [==============================] - 1s 21ms/step - loss: 0.0029\n", - "Epoch 173/200\n", - "32/32 [==============================] - 1s 24ms/step - loss: 0.0052\n", - "Epoch 174/200\n", - "32/32 [==============================] - 1s 22ms/step - loss: 0.0196\n", - "Epoch 175/200\n", - "32/32 [==============================] - 1s 22ms/step - loss: 0.0210\n", - "Epoch 176/200\n", - "32/32 [==============================] - 1s 23ms/step - loss: 0.0247\n", - "Epoch 177/200\n", - "32/32 [==============================] - 1s 21ms/step - loss: 0.0111\n", - "Epoch 178/200\n", - "32/32 [==============================] - 1s 24ms/step - loss: 0.0036\n", - "Epoch 179/200\n", - "32/32 [==============================] - 1s 24ms/step - loss: 0.0026\n", - "Epoch 180/200\n", - "32/32 [==============================] - 1s 28ms/step - loss: 0.0021\n", - "Epoch 181/200\n", - "32/32 [==============================] - 1s 25ms/step - loss: 0.0024\n", - "Epoch 182/200\n", - "32/32 [==============================] - 1s 22ms/step - loss: 0.0026\n", - "Epoch 183/200\n", - "32/32 [==============================] - 1s 36ms/step - loss: 0.0020: 0s - loss: 0.\n", - "Epoch 184/200\n", - "32/32 [==============================] - 1s 25ms/step - loss: 0.0047\n", - "Epoch 185/200\n", - "32/32 [==============================] - 1s 33ms/step - loss: 0.0023\n", - "Epoch 186/200\n", - "32/32 [==============================] - 1s 25ms/step - loss: 0.0030\n", - "Epoch 187/200\n", - "32/32 [==============================] - 1s 28ms/step - loss: 0.0393\n", - "Epoch 188/200\n", - "32/32 [==============================] - 1s 31ms/step - loss: 0.0101\n", - "Epoch 189/200\n", - "32/32 [==============================] - 1s 27ms/step - loss: 0.0269\n", - "Epoch 190/200\n", - "32/32 [==============================] - 1s 33ms/step - loss: 0.0332\n", - "Epoch 191/200\n", - "32/32 [==============================] - 1s 25ms/step - loss: 0.0071\n", - "Epoch 192/200\n", - "32/32 [==============================] - 1s 24ms/step - loss: 0.0051\n", - "Epoch 193/200\n", - "32/32 [==============================] - 1s 25ms/step - loss: 0.0030\n", - "Epoch 194/200\n", - "32/32 [==============================] - 1s 22ms/step - loss: 0.0024\n", - "Epoch 195/200\n", - "32/32 [==============================] - 1s 26ms/step - loss: 0.0025\n", - "Epoch 196/200\n", - "32/32 [==============================] - 1s 25ms/step - loss: 0.0014\n" + " 1/32 [..............................] - ETA: 0s - loss: 0.0053" ] }, { - "name": "stdout", - "output_type": "stream", - "text": [ - "Epoch 197/200\n", - "32/32 [==============================] - 1s 25ms/step - loss: 0.0018\n", - "Epoch 198/200\n", - "32/32 [==============================] - 1s 27ms/step - loss: 0.0030\n", - "Epoch 199/200\n", - "32/32 [==============================] - 1s 24ms/step - loss: 0.0021\n", - "Epoch 200/200\n", - "32/32 [==============================] - 1s 26ms/step - loss: 0.0019\n" + "output_type": "error", + "ename": "KeyboardInterrupt", + "evalue": "", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", + "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[1;32mwith\u001b[0m \u001b[0mgenerator\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 2\u001b[1;33m \u001b[0mmodel\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mfit\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mgenerator\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mepochs\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;36m200\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[1;32m~\\AppData\\Local\\Programs\\Python\\Python37\\lib\\site-packages\\tensorflow\\python\\keras\\engine\\training.py\u001b[0m in \u001b[0;36m_method_wrapper\u001b[1;34m(self, *args, **kwargs)\u001b[0m\n\u001b[0;32m 106\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0m_method_wrapper\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m*\u001b[0m\u001b[0margs\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 107\u001b[0m \u001b[1;32mif\u001b[0m \u001b[1;32mnot\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_in_multi_worker_mode\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m \u001b[1;31m# pylint: disable=protected-access\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 108\u001b[1;33m \u001b[1;32mreturn\u001b[0m \u001b[0mmethod\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m*\u001b[0m\u001b[0margs\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 109\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 110\u001b[0m \u001b[1;31m# Running inside `run_distribute_coordinator` already.\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", + "\u001b[1;32m~\\AppData\\Local\\Programs\\Python\\Python37\\lib\\site-packages\\tensorflow\\python\\keras\\engine\\training.py\u001b[0m in \u001b[0;36mfit\u001b[1;34m(self, x, y, batch_size, epochs, verbose, callbacks, validation_split, validation_data, shuffle, class_weight, sample_weight, initial_epoch, steps_per_epoch, validation_steps, validation_batch_size, validation_freq, max_queue_size, workers, use_multiprocessing)\u001b[0m\n\u001b[0;32m 1096\u001b[0m batch_size=batch_size):\n\u001b[0;32m 1097\u001b[0m \u001b[0mcallbacks\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mon_train_batch_begin\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mstep\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m-> 1098\u001b[1;33m \u001b[0mtmp_logs\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mtrain_function\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0miterator\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 1099\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mdata_handler\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mshould_sync\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 1100\u001b[0m \u001b[0mcontext\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0masync_wait\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", + "\u001b[1;32m~\\AppData\\Local\\Programs\\Python\\Python37\\lib\\site-packages\\tensorflow\\python\\eager\\def_function.py\u001b[0m in \u001b[0;36m__call__\u001b[1;34m(self, *args, **kwds)\u001b[0m\n\u001b[0;32m 778\u001b[0m \u001b[1;32melse\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 779\u001b[0m \u001b[0mcompiler\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;34m\"nonXla\"\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 780\u001b[1;33m \u001b[0mresult\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_call\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m*\u001b[0m\u001b[0margs\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m**\u001b[0m\u001b[0mkwds\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 781\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 782\u001b[0m \u001b[0mnew_tracing_count\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_get_tracing_count\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", + "\u001b[1;32m~\\AppData\\Local\\Programs\\Python\\Python37\\lib\\site-packages\\tensorflow\\python\\eager\\def_function.py\u001b[0m in \u001b[0;36m_call\u001b[1;34m(self, *args, **kwds)\u001b[0m\n\u001b[0;32m 805\u001b[0m \u001b[1;31m# In this case we have created variables on the first call, so we run the\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 806\u001b[0m \u001b[1;31m# defunned version which is guaranteed to never create variables.\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 807\u001b[1;33m \u001b[1;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_stateless_fn\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m*\u001b[0m\u001b[0margs\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m**\u001b[0m\u001b[0mkwds\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;31m# pylint: disable=not-callable\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 808\u001b[0m \u001b[1;32melif\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_stateful_fn\u001b[0m \u001b[1;32mis\u001b[0m \u001b[1;32mnot\u001b[0m \u001b[1;32mNone\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 809\u001b[0m \u001b[1;31m# Release the lock early so that multiple threads can perform the call\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", + "\u001b[1;32m~\\AppData\\Local\\Programs\\Python\\Python37\\lib\\site-packages\\tensorflow\\python\\eager\\function.py\u001b[0m in \u001b[0;36m__call__\u001b[1;34m(self, *args, **kwargs)\u001b[0m\n\u001b[0;32m 2827\u001b[0m \u001b[1;32mwith\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_lock\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 2828\u001b[0m \u001b[0mgraph_function\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0margs\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mkwargs\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_maybe_define_function\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0margs\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mkwargs\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m-> 2829\u001b[1;33m \u001b[1;32mreturn\u001b[0m \u001b[0mgraph_function\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_filtered_call\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0margs\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mkwargs\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;31m# pylint: disable=protected-access\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 2830\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 2831\u001b[0m \u001b[1;33m@\u001b[0m\u001b[0mproperty\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", + "\u001b[1;32m~\\AppData\\Local\\Programs\\Python\\Python37\\lib\\site-packages\\tensorflow\\python\\eager\\function.py\u001b[0m in \u001b[0;36m_filtered_call\u001b[1;34m(self, args, kwargs, cancellation_manager)\u001b[0m\n\u001b[0;32m 1846\u001b[0m resource_variable_ops.BaseResourceVariable))],\n\u001b[0;32m 1847\u001b[0m \u001b[0mcaptured_inputs\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mcaptured_inputs\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m-> 1848\u001b[1;33m cancellation_manager=cancellation_manager)\n\u001b[0m\u001b[0;32m 1849\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 1850\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0m_call_flat\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0margs\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mcaptured_inputs\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mcancellation_manager\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;32mNone\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", + "\u001b[1;32m~\\AppData\\Local\\Programs\\Python\\Python37\\lib\\site-packages\\tensorflow\\python\\eager\\function.py\u001b[0m in \u001b[0;36m_call_flat\u001b[1;34m(self, args, captured_inputs, cancellation_manager)\u001b[0m\n\u001b[0;32m 1922\u001b[0m \u001b[1;31m# No tape is watching; skip to running the function.\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 1923\u001b[0m return self._build_call_outputs(self._inference_function.call(\n\u001b[1;32m-> 1924\u001b[1;33m ctx, args, cancellation_manager=cancellation_manager))\n\u001b[0m\u001b[0;32m 1925\u001b[0m forward_backward = self._select_forward_and_backward_functions(\n\u001b[0;32m 1926\u001b[0m \u001b[0margs\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", + "\u001b[1;32m~\\AppData\\Local\\Programs\\Python\\Python37\\lib\\site-packages\\tensorflow\\python\\eager\\function.py\u001b[0m in \u001b[0;36mcall\u001b[1;34m(self, ctx, args, cancellation_manager)\u001b[0m\n\u001b[0;32m 548\u001b[0m \u001b[0minputs\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0margs\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 549\u001b[0m \u001b[0mattrs\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mattrs\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 550\u001b[1;33m ctx=ctx)\n\u001b[0m\u001b[0;32m 551\u001b[0m \u001b[1;32melse\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 552\u001b[0m outputs = execute.execute_with_cancellation(\n", + "\u001b[1;32m~\\AppData\\Local\\Programs\\Python\\Python37\\lib\\site-packages\\tensorflow\\python\\eager\\execute.py\u001b[0m in \u001b[0;36mquick_execute\u001b[1;34m(op_name, num_outputs, inputs, attrs, ctx, name)\u001b[0m\n\u001b[0;32m 58\u001b[0m \u001b[0mctx\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mensure_initialized\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 59\u001b[0m tensors = pywrap_tfe.TFE_Py_Execute(ctx._handle, device_name, op_name,\n\u001b[1;32m---> 60\u001b[1;33m inputs, attrs, num_outputs)\n\u001b[0m\u001b[0;32m 61\u001b[0m \u001b[1;32mexcept\u001b[0m \u001b[0mcore\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_NotOkStatusException\u001b[0m \u001b[1;32mas\u001b[0m \u001b[0me\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 62\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mname\u001b[0m \u001b[1;32mis\u001b[0m \u001b[1;32mnot\u001b[0m \u001b[1;32mNone\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", + "\u001b[1;31mKeyboardInterrupt\u001b[0m: " ] } ], @@ -4909,9 +794,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.8" + "version": "3.7.8-final" } }, "nbformat": 4, "nbformat_minor": 2 -} +} \ No newline at end of file From 3ff3f0180a035a2150ca3796526ea29722625e63 Mon Sep 17 00:00:00 2001 From: Giovanni Volpe <46021832+giovannivolpe@users.noreply.github.com> Date: Fri, 20 Nov 2020 20:59:20 +0100 Subject: [PATCH 17/78] Create LICENSE --- LICENSE | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..795fdb722 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 Soft Matter Lab + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. From c76f57e8bf7fdff1204c6d43ba02484ee38cb1e5 Mon Sep 17 00:00:00 2001 From: Benjamin Midtvedt Date: Wed, 2 Dec 2020 17:47:48 +0100 Subject: [PATCH 18/78] merged changes from the apdiocyte challenge --- deeptrack/aberrations.py | 4 +- deeptrack/augmentations.py | 123 ++++++++++++++++++++++------ deeptrack/features.py | 148 +++++++++++++++++++++++++++------ deeptrack/generators.py | 27 +++--- deeptrack/image.py | 2 +- deeptrack/layers.py | 33 ++++---- deeptrack/losses.py | 4 +- deeptrack/math.py | 28 +++---- deeptrack/models.py | 163 +++++++++++++++++++------------------ deeptrack/noises.py | 4 +- deeptrack/optics.py | 54 +++++++++--- deeptrack/properties.py | 44 +++++----- deeptrack/scatterers.py | 101 +++++++++++++---------- deeptrack/sequences.py | 14 ++-- deeptrack/utils.py | 6 +- 15 files changed, 488 insertions(+), 267 deletions(-) diff --git a/deeptrack/aberrations.py b/deeptrack/aberrations.py index 7a9ef09c8..f170a53f5 100644 --- a/deeptrack/aberrations.py +++ b/deeptrack/aberrations.py @@ -33,8 +33,8 @@ """ import numpy as np -from deeptrack.features import Feature -from deeptrack.utils import as_list +from .features import Feature +from .utils import as_list class Aberration(Feature): diff --git a/deeptrack/augmentations.py b/deeptrack/augmentations.py index ad0124571..e8584403e 100644 --- a/deeptrack/augmentations.py +++ b/deeptrack/augmentations.py @@ -19,12 +19,16 @@ Flips images diagonally. """ -from deeptrack.features import Feature -from deeptrack.image import Image +from .features import Feature +from .image import Image +from . import utils + import numpy as np -from typing import Callable +import scipy.ndimage as ndimage from scipy.ndimage.interpolation import map_coordinates from scipy.ndimage.filters import gaussian_filter + +from typing import Callable import warnings @@ -72,7 +76,7 @@ def __init__( **kwargs ): - if load_size is not 1: + if load_size != 1: warnings.warn( "Using an augmentation with a load size other than one is no longer supported", DeprecationWarning, @@ -115,6 +119,7 @@ def _process_and_get(self, *args, update_properties=None, **kwargs): not hasattr(self, "cache") or kwargs["update_tally"] - self.last_update >= kwargs["updates_per_reload"] ): + if isinstance(self.feature, list): self.cache = [feature.resolve() for feature in self.feature] else: @@ -151,11 +156,15 @@ def _process_and_get(self, *args, update_properties=None, **kwargs): ] ) else: - new_list_of_lists.append( - Image(self.get(Image(image_list), **kwargs)).merge_properties_from( - image_list - ) - ) + # DANGEROUS + # if not isinstance(image_list, Image): + image_list = Image(image_list) + + output = self.get(image_list, **kwargs) + + if not isinstance(output, Image): + output = Image(output) + new_list_of_lists.append(output.merge_properties_from(image_list)) if update_properties: if not isinstance(new_list_of_lists, list): @@ -252,7 +261,10 @@ def update_properties(self, image, number_of_updates, **kwargs): for prop in image.properties: if "position" in prop: position = prop["position"] - new_position = (image.shape[0] - position[0] - 1, *position[1:]) + new_position = ( + image.shape[0] - position[0] - 1, + *position[1:], + ) prop["position"] = new_position @@ -279,13 +291,6 @@ def update_properties(self, image, number_of_updates, **kwargs): prop["position"] = new_position -from deeptrack.utils import get_kwarg_names -import warnings - -import scipy.ndimage as ndimage -import deeptrack.utils as utils - - class Affine(Augmentation): """ Augmenter to apply affine transformations to images. @@ -386,7 +391,9 @@ def get(self, image, scale, translate, rotate, shear, **kwargs): assert ( image.ndim == 2 or image.ndim == 3 - ), "Affine only supports 2-dimensional or 3-dimension inputs." + ), "Affine only supports 2-dimensional or 3-dimension inputs, got {0}".format( + image.ndim + ) dx, dy = translate fx, fy = scale @@ -551,7 +558,10 @@ def get(self, image, sigma, alpha, ignore_last_dim, **kwargs): for dim in shape: deltas.append( gaussian_filter( - (np.random.rand(*shape) * 2 - 1), sigma, mode="constant", cval=0 + (np.random.rand(*shape) * 2 - 1), + sigma, + mode="constant", + cval=0, ) * alpha ) @@ -619,6 +629,8 @@ def get(self, image, corner, crop, crop_mode, **kwargs): if isinstance(crop, int): crop = (crop,) * image.ndim + crop = [c if c is not None else image.shape[i] for i, c in enumerate(crop)] + # Get amount to crop from image if crop_mode == "retain": crop_amount = np.array(image.shape) - np.array(crop) @@ -631,12 +643,9 @@ def get(self, image, corner, crop, crop_mode, **kwargs): crop_amount = np.amax((np.array(crop_amount), [0] * image.ndim), axis=0) crop_amount = np.amin((np.array(image.shape) - 1, crop_amount), axis=0) # Get corner of crop - if corner == "random": + if isinstance(corner, str) and corner == "random": # Ensure seed is consistent - slice_start = np.random.randint( - [0] * crop_amount.size, - crop_amount + 1, - ) + slice_start = [np.random.randint(m + 1) for m in crop_amount] elif callable(corner): slice_start = corner(image) else: @@ -654,6 +663,7 @@ def get(self, image, corner, crop, crop_mode, **kwargs): for slice_start_i, slice_end_i in zip(slice_start, slice_end) ] ) + cropped_image = image[slices] # Update positions @@ -729,15 +739,74 @@ def __init__(self, px=(0, 0, 0, 0), mode="constant", cval=0, **kwargs): def get(self, image, px, **kwargs): padding = [] - if isinstance(px, int): + if callable(px): + px = px(image) + elif isinstance(px, int): padding = [(px, px)] * image.ndom + for idx in range(0, len(px), 2): padding.append((px[idx], px[idx + 1])) while len(padding) < image.ndim: padding.append((0, 0)) - return utils.safe_call(np.pad, positional_args=(image, padding), **kwargs) + return ( + utils.safe_call(np.pad, positional_args=(image, padding), **kwargs), + padding, + ) + + def _process_and_get(self, images, **kwargs): + results = [self.get(image, **kwargs) for image in images] + for idx, result in enumerate(results): + if isinstance(result, tuple): + shape = result[0].shape + padding = result[1] + de_pad = tuple( + slice(p[0], shape[dim] - p[1]) for dim, p in enumerate(padding) + ) + results[idx] = ( + Image(result[0]).merge_properties_from(images[idx]), + {"undo_padding": de_pad}, + ) + else: + Image(results[idx]).merge_properties_from(images[idx]) + return results + + +class PadToMultiplesOf(Pad): + """Pad images until their height/width is a multiple of a value. + + Parameters + ---------- + multiple : int or tuple of (int or None) + Images will be padded until their width is a multiple of + this value. If a tuple, it is assumed to be a multiple per axis. + A value of None or -1 indicates to skip that axis. + + """ + + def __init__(self, multiple=1, **kwargs): + def amount_to_pad(image): + shape = image.shape + multiple = self.multiple.current_value + + if not isinstance(multiple, (list, tuple, np.ndarray)): + multiple = (multiple,) * image.ndim + new_shape = [0] * (image.ndim * 2) + idx = 0 + for dim, mul in zip(shape, multiple): + if mul is not None and mul is not -1: + to_add = -dim % mul + to_add_first = to_add // 2 + to_add_after = to_add - to_add_first + new_shape[idx * 2] = to_add_first + new_shape[idx * 2 + 1] = to_add_after + + idx += 1 + + return new_shape + + super().__init__(multiple=multiple, px=lambda: amount_to_pad, **kwargs) -# TODO: add resizing by rescaling \ No newline at end of file +# TODO: add resizing by rescaling diff --git a/deeptrack/features.py b/deeptrack/features.py index 03e6df5ec..379116149 100644 --- a/deeptrack/features.py +++ b/deeptrack/features.py @@ -9,28 +9,26 @@ StructuralFeature Abstract extension of feature for interactions between features. Branch - Implementation of `StructuralFeature` that resolves two features + Implementation of `StructuralFeature` that resolves two features sequentially. Probability - Implementation of `StructuralFeature` that randomly resolves a feature + Implementation of `StructuralFeature` that randomly resolves a feature with a certain probability. Duplicate - Implementation of `StructuralFeature` that sequentially resolves an + Implementation of `StructuralFeature` that sequentially resolves an integer number of deep-copies of a feature. """ import copy +import enum -from abc import ABC, abstractmethod from typing import List import numpy as np -import time import threading -from deeptrack.image import Image -from deeptrack.properties import Property, PropertyDict -from deeptrack.utils import isiterable, hasmethod, get_kwarg_names, kwarg_has_default +from .image import Image +from .properties import Property, PropertyDict MERGE_STRATEGY_OVERRIDE = 0 @@ -200,8 +198,12 @@ def resolve(self, image_list: Image or List[Image] = None, **global_kwargs): property_verbosity = global_kwargs.get("property_memorability", 1) feature_input["name"] = type(self).__name__ if self.__property_memorability__ <= property_verbosity: - for image in new_list: - image.append(feature_input) + for index, image in enumerate(new_list): + if isinstance(image, tuple): + image[0].append({**feature_input, **image[1]}) + new_list[index] = image[0] + else: + image.append(feature_input) # Merge input and new_list if self.__list_merge_strategy__ == MERGE_STRATEGY_OVERRIDE: @@ -305,11 +307,11 @@ def plot( display(HTML(anim.to_jshtml())) return anim - except NameError as e: + except NameError: # Not in an notebook plt.show() - except RuntimeError as e: + except RuntimeError: # In notebook, but animation failed import ipywidgets as widgets @@ -333,18 +335,27 @@ def _process_and_get(self, image_list, **feature_input) -> List[Image]: if self.__distributed__: # Call get on each image in list, and merge properties from corresponding image - return [ - Image(self.get(image, **feature_input)).merge_properties_from(image) - for image in image_list - ] + + results = [] + + for image in image_list: + output = self.get(image, **feature_input) + if not isinstance(output, Image): + output = Image(output) + results.append(output) + + return results + else: # Call get on entire list. new_list = self.get(image_list, **feature_input) if not isinstance(new_list, list): - new_list = [Image(new_list)] + new_list = [new_list] - new_list = [Image(image) for image in new_list] + for idx, image in enumerate(new_list): + if not isinstance(image, Image): + new_list[idx] = Image(image) return new_list def _format_input(self, image_list, **kwargs) -> List[Image]: @@ -567,6 +578,61 @@ def get(self, image_list, features, **kwargs): return [feature.resolve(image_list, **kwargs) for feature in features] +class Bind(StructuralFeature): + """Binds a feature with property arguments. + + When the feature is resolved, the kwarg arguments are passed + to the child feature. + + Parameters + ---------- + feature : Feature + The child feature + **kwargs + Properties to send to child + + """ + + __distributed__ = False + + def __init__(self, feature: Feature, **kwargs): + super().__init__(feature=feature, **kwargs) + + def get(self, image, feature, **kwargs): + return feature.resolve(image, **kwargs) + + +BindResolve = Bind + + +class BindUpdate(StructuralFeature): + """Binds a feature with certain arguments. + + When the feature is updated, the child feature + + Parameters + ---------- + feature : Feature + The child feature + **kwargs + Properties to send to child + + """ + + __distributed__ = False + + def __init__(self, feature: Feature, **kwargs): + self.feature = feature + super().__init__(**kwargs) + + def _update(self, **kwargs): + super()._update(**kwargs) + self.feature._update(**{**kwargs, **self.properties}) + + def get(self, image, **kwargs): + return self.feature.resolve(image, **kwargs) + + class ConditionalSetProperty(StructuralFeature): """Conditionally overrides the properties of child features @@ -818,30 +884,32 @@ def get( get_one_random, **kwargs ): + if not isinstance(path, List): + path = [path] if load_options is None: load_options = {} try: - image = np.load(path, **load_options) + image = [np.load(file, **load_options) for file in path] except (IOError, ValueError): try: from skimage import io - image = io.imread(path) + image = [io.imread(file) for file in path] except (IOError, ImportError, AttributeError): try: import PIL.Image - omage = np.array(PIL.Image.open(path, **load_options)) + image = [PIL.Image.open(file, **load_options) for file in path] except (IOError, ImportError): import cv2 - image = np.array(cv2.imread(path, **load_options)) + image = [cv2.imread(file, **load_options) for file in path] if not image: raise IOError( "No filereader available for file {0}".format(path) ) - image = np.squeeze(image) + image = np.stack(image, axis=-1) if to_grayscale: try: @@ -974,7 +1042,8 @@ def _process_and_get(self, images, **kwargs): p0 = p0.astype(np.int) output_slice = output[ - p0[0] : p0[0] + labelarg.shape[0], p0[1] : p0[1] + labelarg.shape[1] + p0[0] : p0[0] + labelarg.shape[0], + p0[1] : p0[1] + labelarg.shape[1], ] for label_index in range(kwargs["number_of_masks"]): @@ -1024,7 +1093,8 @@ def _process_and_get(self, images, **kwargs): p0[1] : p0[1] + labelarg.shape[1], label_index, ] = merge( - output_slice[..., label_index], labelarg[..., label_index] + output_slice[..., label_index], + labelarg[..., label_index], ) output = Image(output) for label in list_of_labels: @@ -1038,7 +1108,7 @@ def _get_position(image, mode="corner", return_z=False): if mode == "corner": shift = (np.array(image.shape) - 1) / 2 else: - shift = np.zeros((num_outputs)) + shift = np.zeros((3 if return_z else 2)) positions = image.get_property("position", False, []) @@ -1054,7 +1124,11 @@ def _get_position(image, mode="corner", return_z=False): if return_z: outp = ( np.array( - [position[0], position[1], image.get_property("z", default=0)] + [ + position[0], + position[1], + image.get_property("z", default=0), + ] ) - shift ) @@ -1063,3 +1137,23 @@ def _get_position(image, mode="corner", return_z=False): positions_out.append(position - shift[0:2]) return positions_out + + +class AsType(Feature): + """Converts the data type of images + + Accepts same types as numpy arrays. Common types include + + `float64, int32, uint16, int16, uint8, int8` + + Parameters + ---------- + dtype : str + dtype string. Same as numpy dtype. + """ + + def __init__(self, dtype="float64", **kwargs): + super().__init__(dtype=dtype, **kwargs) + + def get(self, image, dtype, **kwargs): + return image.astype(dtype) \ No newline at end of file diff --git a/deeptrack/generators.py b/deeptrack/generators.py index 8c8d4412d..6b569673f 100644 --- a/deeptrack/generators.py +++ b/deeptrack/generators.py @@ -12,8 +12,8 @@ from typing import List import tensorflow.keras as keras -from deeptrack.features import Feature -from deeptrack.image import Image +from .features import Feature +from .image import Image import threading import random import time @@ -107,10 +107,12 @@ def generate( if sub_batch.ndim > ndim: dims_to_remove = sub_batch.ndim - ndim sub_batch = np.reshape( - sub_batch, (-1, *sub_batch.shape[dims_to_remove + 1 :]) + sub_batch, + (-1, *sub_batch.shape[dims_to_remove + 1 :]), ) sub_labels = np.reshape( - sub_labels, (-1, *sub_labels.shape[dims_to_remove + 1 :]) + sub_labels, + (-1, *sub_labels.shape[dims_to_remove + 1 :]), ) elif sub_batch.ndim < ndim: @@ -302,11 +304,11 @@ def __getitem__(self, idx): return outputs def __len__(self): - l = int((len(self.current_data) // self._batch_size)) + steps = int((len(self.current_data) // self._batch_size)) assert ( - l > 0 + steps > 0 ), "There needs to be at least batch_size number of datapoints. Try increasing min_data_size." - return l + return steps def _continuous_get_training_data(self): index = 0 @@ -317,11 +319,11 @@ def _continuous_get_training_data(self): new_image = self._get(self.feature, self.feature_kwargs) - if self.label_function: - new_label = Image(self.label_function(new_image)) + # if self.label_function: + new_label = self.label_function(new_image) if self.batch_function: - new_image = Image(self.batch_function(new_image)) + new_image = self.batch_function(new_image) if new_image.ndim < self.ndim: new_image = [new_image] @@ -329,7 +331,10 @@ def _continuous_get_training_data(self): for new_image_i, new_label_i in zip(new_image, new_label): if len(self.data) >= self.max_data_size: - self.data[index % self.max_data_size] = (new_image_i, new_label_i) + self.data[index % self.max_data_size] = ( + new_image_i, + new_label_i, + ) else: self.data.append((new_image_i, new_label_i)) diff --git a/deeptrack/image.py b/deeptrack/image.py index be20fba44..72984ca3a 100644 --- a/deeptrack/image.py +++ b/deeptrack/image.py @@ -176,7 +176,7 @@ def __array_wrap__(self, image_after_function, context=None): for arg in input_args: - if not arg is self and isinstance(arg, Image): + if arg is not self and isinstance(arg, Image): self.merge_properties_from(arg) return image_with_restored_properties diff --git a/deeptrack/layers.py b/deeptrack/layers.py index 5e68ec756..fe90f98c5 100644 --- a/deeptrack/layers.py +++ b/deeptrack/layers.py @@ -1,17 +1,16 @@ """ Standardized layers implemented in keras. """ -import tensorflow -from tensorflow.keras import layers, activations -from tensorflow.keras.initializers import RandomNormal + +from tensorflow.keras import layers try: from tensorflow_addons.layers import InstanceNormalization -except: +except Exception: import warnings - InstanceNormalization = layers.Layer() + InstanceNormalization = layers.Layer warnings.warn( "DeepTrack not installed with tensorflow addons. Instance normalization will not work. Consider upgrading to tensorflow >= 2.0.", ImportWarning, @@ -37,10 +36,12 @@ def as_block(x): def _as_activation(x): if x is None: return layers.Layer() - if isinstance(x, layers.Layer): + elif isinstance(x, str): + return layers.Activation(x) + elif isinstance(x, layers.Layer): return x else: - return layers.Activation(x) + return layers.Layers(x) def _single_layer_call(x, layer, instance_norm, activation): @@ -225,6 +226,7 @@ def StaticUpsampleBlock( kernel_size=(1, 1), strides=1, padding="same", + with_conv=True, **kwargs ): """A single no-trainable 2d deconvolutional layer. @@ -247,21 +249,24 @@ def StaticUpsampleBlock( def Layer(filters, **kwargs_inner): kwargs_inner.update(kwargs) - layer = layers.UpSampling2D( - size=size, interpolation=interpolation, **kwargs_inner - ) + layer = layers.UpSampling2D(size=size, interpolation=interpolation) + conv = layers.Conv2D( filters, kernel_size=kernel_size, strides=strides, padding=padding, + **kwargs_inner ) def call(x): y = layer(x) - return _single_layer_call( - y, conv, _instance_norm(instance_norm, filters), activation - ) + if with_conv: + return _single_layer_call( + y, conv, _instance_norm(instance_norm, filters), activation + ) + else: + return layer(x) return call @@ -359,4 +364,4 @@ def Layer(filters, **kwargs_inner): "deconvolutional": DeconvolutionalBlock(), "none": Identity(), "identity": Identity(), -} \ No newline at end of file +} diff --git a/deeptrack/losses.py b/deeptrack/losses.py index 2a6117af0..ced7f5ddd 100644 --- a/deeptrack/losses.py +++ b/deeptrack/losses.py @@ -2,7 +2,7 @@ Functions --------- -flatten +flatten Flattends the inputs before calling the loss function. sigmoid Adds a signmoid transformation to the prediction before calling the loss function. @@ -117,4 +117,4 @@ def unet_crossentropy(T, P): # Wrap standard keras loss function with flatten. for keras_loss_function in _COMPATIBLE_LOSS_FUNCTIONS: deeptrack_loss_function = flatten(keras_loss_function) - globals()[deeptrack_loss_function.__name__] = deeptrack_loss_function \ No newline at end of file + globals()[deeptrack_loss_function.__name__] = deeptrack_loss_function diff --git a/deeptrack/math.py b/deeptrack/math.py index dfcf2fd5f..bb24d453e 100644 --- a/deeptrack/math.py +++ b/deeptrack/math.py @@ -8,9 +8,13 @@ Min-max image normalization. """ -from deeptrack.features import Feature -from deeptrack.image import Image +from .features import Feature +from .image import Image +from . import utils import numpy as np +import skimage +import skimage.measure +import scipy.ndimage as ndimage class Add(Feature): @@ -164,16 +168,10 @@ def get(self, image, min, max, **kwargs): return image -import deeptrack.utils as utils -import skimage - -import scipy.ndimage as ndimage - - class Blur(Feature): def __init__(self, filter_function, mode="reflect", **kwargs): self.filter = filter_function - super().__init__(borderType=borderType, **kwargs) + super().__init__(borderType=mode, **kwargs) def get(self, image, **kwargs): kwargs.pop("input", False) @@ -203,7 +201,7 @@ def get(self, input, ksize, **kwargs): weights = np.ones(ksize) / np.prod(ksize) - return safe_call(ndimage, input=input, weights=weights, **kwargs) + return utils.safe_call(ndimage, input=input, weights=weights, **kwargs) class GaussianBlur(Blur): @@ -231,12 +229,10 @@ class MedianBlur(Blur): """ def __init__(self, ksize=3, **kwargs): - super().__init__(ndimage.median_filter, k=k, **kwargs) + super().__init__(ndimage.median_filter, k=ksize, **kwargs) -## POOLING - -import skimage.measure +# POOLING class Pool(Feature): @@ -291,7 +287,7 @@ def __init__(self, ksize=3, **kwargs): super().__init__(np.mean, ksize=ksize, **kwargs) -### OPENCV2 blur +# OPENCV2 blur try: import cv2 @@ -363,4 +359,4 @@ def __init__(self, d=3, sigma_color=50, sigma_space=50, **kwargs): sigma_color=sigma_color, sigma_space=sigma_space, **kwargs - ) \ No newline at end of file + ) diff --git a/deeptrack/models.py b/deeptrack/models.py index 03f2dcee0..5c7df96a9 100644 --- a/deeptrack/models.py +++ b/deeptrack/models.py @@ -2,7 +2,7 @@ Classes ------- -ModelFeature +ModelFeature Base model feature class. Convolutional, convolutional Creates and compiles a convolutional neural network. @@ -12,12 +12,13 @@ Creates and compiles a recurrent neural network. """ -from deeptrack.losses import nd_mean_absolute_error -from deeptrack.features import Feature -from deeptrack.layers import as_block -from tensorflow.keras import models, layers, optimizers +import tensorflow +from .losses import nd_mean_absolute_error +from .features import Feature +from .layers import as_block +from tensorflow.keras import models, layers, backend as K +import tensorflow as tf import numpy as np -import warnings def _compile( @@ -143,7 +144,7 @@ def FullyConnected( dense_block = as_block(dense_block) - ### INITIALIZE DEEP LEARNING NETWORK + # INITIALIZE DEEP LEARNING NETWORK input_layer = layers.Input(shape=input_shape) layer = input_layer @@ -155,7 +156,7 @@ def FullyConnected( range(len(dense_layers_dimensions)), dense_layers_dimensions ): - if dense_layer_number is 0 and not flatten_input: + if dense_layer_number == 0 and not flatten_input: layer = dense_block(dense_layer_dimension, input_shape=input_shape)(layer) else: layer = dense_block(dense_layer_dimension)(layer) @@ -184,6 +185,7 @@ def Convolutional( output_activation=None, output_kernel_size=3, loss=nd_mean_absolute_error, + input_layer=None, convolution_block="convolutional", pooling_block="pooling", dense_block="dense", @@ -232,6 +234,9 @@ def Convolutional( layer = inputs + if input_layer: + layer = input_layer(layer) + ### CONVOLUTIONAL BASIS for conv_layer_dimension in conv_layers_dimensions: @@ -284,6 +289,7 @@ def UNet( output_kernel_size=3, output_activation=None, loss=nd_mean_absolute_error, + input_layer=None, encoder_convolution_block="convolutional", base_convolution_block="convolutional", decoder_convolution_block="convolutional", @@ -340,6 +346,9 @@ def UNet( layer = unet_input + if input_layer: + layer = input_layer(layer) + # Downsampling path for conv_layer_dimension in conv_layers_dimensions: for _ in range(steps_per_pooling): @@ -423,10 +432,10 @@ def RNN( Deep learning network. """ - ### INITIALIZE DEEP LEARNING NETWORK + # INITIALIZE DEEP LEARNING NETWORK network = models.Sequential() - ### CONVOLUTIONAL BASIS + # CONVOLUTIONAL BASIS for conv_layer_number, conv_layer_dimension in zip( range(len(conv_layers_dimensions)), conv_layers_dimensions ): @@ -506,7 +515,7 @@ def RNN( rnn = RNN -class cgan(Model): +class cgan(tf.keras.Model): def __init__( self, generator=None, @@ -517,8 +526,10 @@ def __init__( assemble_loss=None, assemble_optimizer=None, assemble_loss_weights=None, + metrics=[], **kwargs ): + super().__init__() # Build and compile the discriminator self.discriminator = discriminator @@ -545,79 +556,73 @@ def __init__( # The assembled model (stacked generator and discriminator) # Trains the generator to fool the discriminator - self.assemble = models.Model(self.model_input, [validity, img]) + self.assemble = tf.keras.models.Model(self.model_input, [validity, img]) + + self.num_losses = len(assemble_loss) + self.assemble.compile( loss=assemble_loss, optimizer=assemble_optimizer, loss_weights=assemble_loss_weights, + metrics=metrics, + ) + self._metrics = [tf.metrics.get(m) for m in metrics] + + def train_step(self, data): + + # Compute data and labels + batch_x, batch_y = data + gen_imgs = self.generator(batch_x) + + # Train the discriminator + with tf.GradientTape() as tape: + # Train in two steps + disc_pred_1 = self.discriminator([batch_y, batch_x]) + disc_pred_2 = self.discriminator([gen_imgs, batch_x]) + shape = tf.shape(disc_pred_1) + valid, fake = tf.ones(shape), tf.zeros(shape) + d_loss = ( + self.discriminator.compiled_loss(disc_pred_1, valid) + + self.discriminator.compiled_loss(disc_pred_2, fake) + ) / 2 + + # Compute gradient and apply gradient + grads = tape.gradient(d_loss, self.discriminator.trainable_weights) + self.discriminator.optimizer.apply_gradients( + zip(grads, self.discriminator.trainable_weights) ) - super().__init__(self.generator, **kwargs) + # Train the assembly - def fit(self, data_generator, epochs, steps_per_epoch=None, **kwargs): - for key in kwargs.keys(): - warnings.warn( - "{0} not implemented for cgan. Does not affect the execution.".format( - key - ) - ) - for epoch in range(epochs): - if not steps_per_epoch: - try: - steps = len(data_generator) - except: - steps = 1 - else: - steps = steps_per_epoch - - d_loss = 0 - g_loss = 0 - - for step in range(steps): - # update data - try: - data, labels = next(data_generator) - except: - data, labels = data_generator[step] - - # Grab disriminator labels - shape = (data.shape[0], *self.discriminator.output.shape[1:]) - valid, fake = np.ones(shape), np.zeros(shape) - - # --------------------- - # Train Discriminator - # --------------------- - - # Generate a batch of new images - gen_imgs = self.generator(data) - - # Train the discriminator - d_loss_real = self.discriminator.train_on_batch([labels, data], valid) - d_loss_fake = self.discriminator.train_on_batch([gen_imgs, data], fake) - d_loss += 0.5 * np.add(d_loss_real, d_loss_fake) - - # --------------------- - # Train Generator - # --------------------- - - # Train the generator (to have the discriminator label samples as valid) - g_loss += np.array(self.assemble.train_on_batch(data, [valid, labels])) - - # Plot the progress - - try: - data_generator.on_epoch_end() - except: - pass - - print( - "%d [D loss: %f, acc.: %.2f%%] [G loss: %f, %f, %f]" - % ( - epoch, - d_loss[0] / steps, - 100 * d_loss[1] / steps, - g_loss[0] / steps, - g_loss[1] / steps, - g_loss[2] / steps, - ) + with tf.GradientTape() as tape: + assemble_output = self.assemble(batch_x) + + generated_image_copies = [assemble_output[1]] * (self.num_losses - 1) + + batch_y_copies = [batch_y] * (self.num_losses - 1) + + g_loss = self.assemble.compiled_loss( + [assemble_output[0], *generated_image_copies], + [valid, *batch_y_copies], ) + + # Compute gradient and apply gradient + grads = tape.gradient(g_loss, self.assemble.trainable_weights) + self.assemble.optimizer.apply_gradients( + zip(grads, self.assemble.trainable_weights) + ) + + # Update the metrics + self.compiled_metrics.update_state(assemble_output[1], batch_y) + + # Define output + loss = { + "d_loss": d_loss, + "g_loss": g_loss, + **{m.name: m.result() for m in self.metrics}, + } + + return loss + + def call(self, *args, **kwargs): + return self.generator.call(*args, **kwargs) diff --git a/deeptrack/noises.py b/deeptrack/noises.py index d53541a27..6801b3f5d 100644 --- a/deeptrack/noises.py +++ b/deeptrack/noises.py @@ -13,8 +13,8 @@ """ import numpy as np -from deeptrack.features import Feature -from deeptrack.image import Image +from .features import Feature +from .image import Image class Noise(Feature): diff --git a/deeptrack/optics.py b/deeptrack/optics.py index f4e970533..fac9fd15f 100644 --- a/deeptrack/optics.py +++ b/deeptrack/optics.py @@ -16,10 +16,9 @@ """ import numpy as np -from deeptrack.features import Feature, StructuralFeature -from deeptrack.image import Image, pad_image_to_fft +from .features import Feature, StructuralFeature +from .image import Image, pad_image_to_fft -from scipy.interpolate import RectBivariateSpline from scipy.ndimage import convolve @@ -78,7 +77,13 @@ def get(self, image, sample, objective, **kwargs): if upscale > 1: mean_imaged_sample = np.reshape( imaged_sample, - (shape[0] // upscale, upscale, shape[1] // upscale, upscale, shape[2]), + ( + shape[0] // upscale, + upscale, + shape[1] // upscale, + upscale, + shape[2], + ), ).mean(axis=(3, 1)) imaged_sample = Image(mean_imaged_sample).merge_properties_from( @@ -97,7 +102,10 @@ def get(self, image, sample, objective, **kwargs): def _update(self, **kwargs): self.properties["sample"].update( - **{**kwargs, **self.objective.update(**kwargs).current_value.properties} + **{ + **kwargs, + **self.objective.update(**kwargs).current_value.properties, + } ) super()._update(**kwargs) @@ -282,11 +290,15 @@ def _pad_volume( new_limits[i, :] = ( np.min([new_limits[i, 0], upscaled_output_region[i] - padding[1]]), np.max( - [new_limits[i, 1], upscaled_output_region[i + 2] + padding[i + 2]] + [ + new_limits[i, 1], + upscaled_output_region[i + 2] + padding[i + 2], + ] ), ) new_volume = np.zeros( - np.diff(new_limits, axis=1)[:, 0].astype(np.int32), dtype=np.complex + np.diff(new_limits, axis=1)[:, 0].astype(np.int32), + dtype=np.complex, ) old_region = (limits - new_limits).astype(np.int32) @@ -370,7 +382,9 @@ def get(self, illuminated_volume, limits, **kwargs): ) padded_volume = padded_volume[ - output_region[0] : output_region[2], output_region[1] : output_region[3], : + output_region[0] : output_region[2], + output_region[1] : output_region[3], + :, ] z_limits = limits[2, :] @@ -380,7 +394,10 @@ def get(self, illuminated_volume, limits, **kwargs): # Get planes in volume where not all values are 0. z_iterator = np.linspace( - z_limits[0], z_limits[1], num=padded_volume.shape[2], endpoint=False + z_limits[0], + z_limits[1], + num=padded_volume.shape[2], + endpoint=False, ) zero_plane = np.all(padded_volume == 0, axis=(0, 1), keepdims=False) z_values = z_iterator[~zero_plane] @@ -496,7 +513,9 @@ def get(self, illuminated_volume, limits, fields, **kwargs): ) padded_volume = padded_volume[ - output_region[0] : output_region[2], output_region[1] : output_region[3], : + output_region[0] : output_region[2], + output_region[1] : output_region[3], + :, ] z_limits = limits[2, :] @@ -504,7 +523,10 @@ def get(self, illuminated_volume, limits, fields, **kwargs): index_iterator = range(padded_volume.shape[2]) z_iterator = np.linspace( - z_limits[0], z_limits[1], num=padded_volume.shape[2], endpoint=False + z_limits[0], + z_limits[1], + num=padded_volume.shape[2], + endpoint=False, ) zero_plane = np.all(padded_volume == 0, axis=(0, 1), keepdims=False) @@ -766,7 +788,12 @@ def _create_volume( continue padded_scatterer = Image( - np.pad(scatterer, [(2, 2), (2, 2), (2, 2)], "constant", constant_values=0) + np.pad( + scatterer, + [(2, 2), (2, 2), (2, 2)], + "constant", + constant_values=0, + ) ) padded_scatterer.properties = scatterer.properties scatterer = padded_scatterer @@ -815,7 +842,8 @@ def _create_volume( if not (np.array(new_limits) == np.array(limits)).all(): new_volume = np.zeros( - np.diff(new_limits, axis=1)[:, 0].astype(np.int32), dtype=np.complex + np.diff(new_limits, axis=1)[:, 0].astype(np.int32), + dtype=np.complex, ) old_region = (limits - new_limits).astype(np.int32) limits = limits.astype(np.int32) diff --git a/deeptrack/properties.py b/deeptrack/properties.py index 300308c90..4ce380389 100644 --- a/deeptrack/properties.py +++ b/deeptrack/properties.py @@ -18,9 +18,16 @@ """ import numpy as np -from deeptrack.utils import isiterable, hasmethod, get_kwarg_names, kwarg_has_default -import deeptrack +from .utils import ( + isiterable, + get_kwarg_names, + kwarg_has_default, +) + +from . import features + import copy +import collections class Property: @@ -72,11 +79,11 @@ def current_value(self): @current_value.setter def current_value(self, updated_current_value): self._current_value = updated_current_value - if id(self) not in deeptrack.UPDATE_MEMO["memoization"]: + if id(self) not in features.UPDATE_MEMO["memoization"]: # Some values work, some don't. self, updated_current_value and self._current_value work # Best guess is an error in the gc reference counter causing it to dereference # But then again, I don't think it should be the same reference anyway - deeptrack.UPDATE_MEMO["memoization"][id(self)] = updated_current_value + features.UPDATE_MEMO["memoization"][id(self)] = updated_current_value @current_value.getter def current_value(self): @@ -109,15 +116,15 @@ def update(self, **kwargs) -> "Property": # a = 1+1 if ( - deeptrack.UPDATE_LOCK.locked() - and my_id in deeptrack.UPDATE_MEMO["memoization"] + features.UPDATE_LOCK.locked() + and my_id in features.UPDATE_MEMO["memoization"] ): return self if self.parent: kwargs.update(self.parent) - kwargs.update(deeptrack.UPDATE_MEMO["user_arguments"]) + kwargs.update(features.UPDATE_MEMO["user_arguments"]) self.current_value = self.sample(self.sampling_rule, **kwargs) return self @@ -155,7 +162,7 @@ def sample(self, sampling_rule, **kwargs): """ - if isinstance(sampling_rule, deeptrack.Feature): + if isinstance(sampling_rule, features.Feature): # I am worried passing kwargs may lead to name clash sampling_rule._update(**kwargs) return sampling_rule @@ -229,7 +236,7 @@ def sample(self, sampling_rule, **kwargs): return sampling_rule def __deepcopy__(self, memo): - is_in = id(self) in deeptrack.UPDATE_MEMO["memoization"] + is_in = id(self) in features.UPDATE_MEMO["memoization"] if is_in: return self else: @@ -309,12 +316,12 @@ def update(self, sequence_length=0, **kwargs): """ my_id = id(self) if ( - deeptrack.UPDATE_LOCK.locked() - and my_id in deeptrack.UPDATE_MEMO["memoization"] + features.UPDATE_LOCK.locked() + and my_id in features.UPDATE_MEMO["memoization"] ): return self - kwargs.update(deeptrack.UPDATE_MEMO["user_arguments"]) + kwargs.update(features.UPDATE_MEMO["user_arguments"]) new_current_value = [] @@ -338,13 +345,10 @@ def update(self, sequence_length=0, **kwargs): new_current_value.append(next_value) self.current_value = new_current_value - deeptrack.UPDATE_MEMO["memoization"][my_id] = new_current_value + features.UPDATE_MEMO["memoization"][my_id] = new_current_value return self -import collections - - class PropertyDict(collections.OrderedDict): """Dictionary with Property elements @@ -382,7 +386,7 @@ def current_value_dict(self, **kwargs) -> dict: # of the current timestep if isinstance(property, SequentialProperty): sequence_step = kwargs.get("sequence_step", None) - if not sequence_step is None: + if sequence_step is not None: property_value = property_value[sequence_step] current_value_dict[key] = property_value @@ -402,11 +406,11 @@ def update(self, **kwargs) -> "PropertyDict": """ property_arguments = collections.OrderedDict(self) property_arguments.update(kwargs) - property_arguments.update(deeptrack.UPDATE_MEMO["user_arguments"]) + property_arguments.update(features.UPDATE_MEMO["user_arguments"]) for key, prop in self.items(): if isinstance(property_arguments[key], Property): prop.update(**property_arguments) - elif id(prop) not in deeptrack.UPDATE_MEMO["memoization"]: + elif id(prop) not in features.UPDATE_MEMO["memoization"]: prop.current_value = property_arguments[key] return self @@ -447,4 +451,4 @@ def sample(self, **kwargs) -> dict: for key, property in self.items(): sample_dict[key] = property.sample(**kwargs) - return sample_dict \ No newline at end of file + return sample_dict diff --git a/deeptrack/scatterers.py b/deeptrack/scatterers.py index de9063b9a..b28958985 100644 --- a/deeptrack/scatterers.py +++ b/deeptrack/scatterers.py @@ -1,6 +1,6 @@ """Implementations of Feature the model scattering objects. -Provides some basic implementations of scattering objects +Provides some basic implementations of scattering objects that are frequently used. Classes @@ -18,14 +18,13 @@ """ -from threading import Lock import numpy as np -# from scipy.special import jv as jn, spherical_jn as jv, h1vp, eval_legendre as leg, jvp -import deeptrack.backend as D -from deeptrack.features import Feature, MERGE_STRATEGY_APPEND -from deeptrack.image import Image -import deeptrack.image +from . import backend as D +from .features import Feature, MERGE_STRATEGY_APPEND +from .image import Image +from . import image +import warnings class Scatterer(Feature): @@ -60,8 +59,8 @@ class Scatterer(Feature): Other Parameters ---------------- upsample_axes : tuple of ints - Sets the axes along which the calculation is upsampled (default is None, - which implies all axes are upsampled). + Sets the axes along which the calculation is upsampled (default is + None, which implies all axes are upsampled). crop_zeros : bool Whether to remove slices in which all elements are zero. """ @@ -112,10 +111,11 @@ def _process_and_get( # Post processes the created object to handle upsampling, # as well as cropping empty slices. if not self._processed_properties: - import warnings warnings.warn( - "Overridden _process_properties method does not call super. This is likely to result in errors if used with Optics.upscale != 1." + "Overridden _process_properties method does not call super. " + + "This is likely to result in errors if used with " + + "Optics.upscale != 1." ) # Calculates upsampled voxel_size @@ -134,7 +134,10 @@ def _process_and_get( if new_image.size == 0: warnings.warn( - "Scatterer created that is smaller than a pixel. This may yield inconsistent results. Consider using upsample on the scatterer, or upscale on the optics.", + "Scatterer created that is smaller than a pixel. " + + "This may yield inconsistent results." + + " Consider using upsample on the scatterer," + + " or upscale on the optics.", Warning, ) @@ -346,7 +349,8 @@ def _process_properties(self, propertydict): length 3. If the radius is a single value, the particle is made a sphere - If the radius are two values, the smallest value is appended as the third value + If the radius are two values, the smallest value is appended as the + third value The rotation vector is padded with zeros until it is of length 3 """ @@ -426,12 +430,13 @@ def get(self, image, radius, rotation, voxel_size, **kwargs): class MieScatterer(Scatterer): """Base implementation of a Mie particle. - New Mie-theory scatterers can be implemented by extending this class, and passing - a function that calculates the coefficients of the harmonics up to order `L`. To be - precise, the feature expects a wrapper function that takes the current values of the - properties, as well as a inner function that takes an integer as the only parameter, - and calculates the coefficients up to that integer. The return format is expected to - be a tuple with two values, corresponding to `an` and `bn`. See + New Mie-theory scatterers can be implemented by extending this class, and + passing a function that calculates the coefficients of the harmonics up to + order `L`. To beprecise, the feature expects a wrapper function that takes + the current values of the properties, as well as a inner function that + takes an integer as the only parameter, and calculates the coefficients up + to that integer. The return format is expected to be a tuple with two + values, corresponding to `an` and `bn`. See `deeptrack.backend.mie_coefficients` for an example. Parameters @@ -439,11 +444,13 @@ class MieScatterer(Scatterer): coefficients : Callable[int] -> Tuple[ndarray, ndarray] Function that returns the harmonics coefficients. offset_z : "auto" or float - Distance from the particle in the z direction the field is evaluated. If "auto", - this is calculated from the pixel size and `collection_angle` + Distance from the particle in the z direction the field is evaluated. + If "auto", this is calculated from the pixel size and + `collection_angle` collection_angle : "auto" or float The maximum collection angle in radians. If "auto", this - is calculated from the objective NA (which is true if the objective is the limiting + is calculated from the objective NA (which is true if the objective is + the limiting aperature). polarization_angle : float Angle of the polarization of the incoming light relative to the x-axis. @@ -507,7 +514,7 @@ def _process_properties(self, properties): def get( self, - image, + inp, position, upscaled_output_region, voxel_size, @@ -535,7 +542,7 @@ def get( - upscaled_output_region[1] + padding[1] ) - arr = deeptrack.image.pad_image_to_fft(np.zeros((xSize, ySize))) + arr = image.pad_image_to_fft(np.zeros((xSize, ySize))) # Evluation grid x = np.arange(-padding[0], arr.shape[0] - padding[0]) - (position[1]) * upscale @@ -561,11 +568,11 @@ def get( PI, TAU = D.mie_harmonics(ct, L) # Normalization factor - E = [(2 * l + 1) / (l * (l + 1)) for l in range(1, L + 1)] + E = [(2 * i + 1) / (i * (i + 1)) for i in range(1, L + 1)] # Scattering terms - S1 = sum([E[l] * A[l] * TAU[l] + E[l] * B[l] * PI[l] for l in range(0, L)]) - S2 = sum([E[l] * B[l] * TAU[l] + E[l] * A[l] * PI[l] for l in range(0, L)]) + S1 = sum([E[i] * A[i] * TAU[i] + E[i] * B[i] * PI[i] for i in range(0, L)]) + S2 = sum([E[i] * B[i] * TAU[i] + E[i] * A[i] * PI[i] for i in range(0, L)]) field = ( (ct > ct_max) @@ -581,11 +588,13 @@ def get( class MieSphere(MieScatterer): """Scattered field by a sphere - Should be calculated on at least a 64 by 64 grid. Use padding in the optics if necessary + Should be calculated on at least a 64 by 64 grid. Use padding in the + optics if necessary. - Calculates the scattered field by a spherical particle in a homogenous medium, - as predicted by Mie theory. Note that the induced phase shift is calculated - in comparison to the `refractive_index_medium` property of the optical device. + Calculates the scattered field by a spherical particle in a homogenous + medium, as predicted by Mie theory. Note that the induced phase shift is + calculated in comparison to the `refractive_index_medium` property of the + optical device. Parameters ---------- @@ -604,12 +613,13 @@ class MieSphere(MieScatterer): The position in the direction normal to the camera plane. Used if `position` is of length 2. offset_z : "auto" or float - Distance from the particle in the z direction the field is evaluated. If "auto", - this is calculated from the pixel size and `collection_angle` + Distance from the particle in the z direction the field is evaluated. + If "auto", this is calculated from the pixel size and + `collection_angle` collection_angle : "auto" or float The maximum collection angle in radians. If "auto", this - is calculated from the objective NA (which is true if the objective is the limiting - aperature). + is calculated from the objective NA (which is true if the objective + is the limiting aperature). polarization_angle : float Angle of the polarization of the incoming light relative to the x-axis. """ @@ -649,13 +659,15 @@ def inner(L): class MieStratifiedSphere(MieScatterer): """Scattered field by a stratified sphere - A stratified sphere is a sphere with several concentric shells of uniform refractive index. + A stratified sphere is a sphere with several concentric shells of uniform + refractive index. - Should be calculated on at least a 64 by 64 grid. Use padding in the optics if necessary + Should be calculated on at least a 64 by 64 grid. Use padding in the + optics if necessary - Calculates the scattered field by in a homogenous medium, as predicted by Mie theory. - Note that the induced phase shift is calculated in comparison to the - `refractive_index_medium` property of the optical device. + Calculates the scattered field by in a homogenous medium, as predicted by + Mie theory. Note that the induced phase shift is calculated in comparison + to the `refractive_index_medium` property of the optical device. Parameters ---------- @@ -674,12 +686,13 @@ class MieStratifiedSphere(MieScatterer): The position in the direction normal to the camera plane. Used if `position` is of length 2. offset_z : "auto" or float - Distance from the particle in the z direction the field is evaluated. If "auto", - this is calculated from the pixel size and `collection_angle` + Distance from the particle in the z direction the field is evaluated. + If "auto", this is calculated from the pixel size and + `collection_angle` collection_angle : "auto" or float The maximum collection angle in radians. If "auto", this - is calculated from the objective NA (which is true if the objective is the limiting - aperature). + is calculated from the objective NA (which is true if the objective + is the limiting aperature). polarization_angle : float Angle of the polarization of the incoming light relative to the x-axis. """ diff --git a/deeptrack/sequences.py b/deeptrack/sequences.py index 8858d2c26..462284138 100644 --- a/deeptrack/sequences.py +++ b/deeptrack/sequences.py @@ -11,8 +11,8 @@ Converts a feature to be resolved as a sequence. """ -from deeptrack.features import Feature -from deeptrack.properties import SequentialProperty +from .features import Feature +from .properties import SequentialProperty class Sequence(Feature): @@ -67,11 +67,13 @@ def update(self, **kwargs): def Sequential(feature: Feature, **kwargs): """Converts a feature to be resolved as a sequence. - Should be called on individual features, not combinations of features. All keyword - arguments will be trated as sequential properties and will be passed to the parent feature. + Should be called on individual features, not combinations of features. All + keyword arguments will be trated as sequential properties and will be + passed to the parent feature. - If a property from the keyword argument already exists on the feature, the existing property - will be used to initilize the passed property (that is, it will be used for the first timestep). + If a property from the keyword argument already exists on the feature, the + existing property will be used to initilize the passed property (that is, + it will be used for the first timestep). Parameters ---------- diff --git a/deeptrack/utils.py b/deeptrack/utils.py index c35d3f077..9ced9f335 100644 --- a/deeptrack/utils.py +++ b/deeptrack/utils.py @@ -11,7 +11,7 @@ isiterable(obj: any) Return True if the object is iterable. Else, return False. as_list(obj: any) - If the input is iterable, convert it to list. + If the input is iterable, convert it to list. Otherwise, wrap the input in a list. get_kwarg_names(function: Callable) Return the names of the keyword arguments the function accepts. @@ -142,8 +142,8 @@ def kwarg_has_default(function: Callable, argument: str) -> bool: def safe_call(function, positional_args=[], **kwargs): """Calls a function, using keyword arguments from a dictionary of arguments. - If the function does not accept one of the argument provided, it will not be passed. Does not support - non-keyword arguments. + If the function does not accept one of the argument provided, it will not + be passed. Does not support non-keyword arguments. Parameters ---------- From 1e4e0f3321966eafc025ccc03399633ec2b3300e Mon Sep 17 00:00:00 2001 From: Benjamin Midtvedt Date: Wed, 2 Dec 2020 17:58:29 +0100 Subject: [PATCH 19/78] Rebuilt documentation --- _src/source/augmentations.rst | 7 + _src/source/features.rst | 28 +++ docs/_sources/augmentations.rst.txt | 7 + docs/_sources/features.rst.txt | 28 +++ docs/augmentations.html | 55 +++++ docs/features.html | 154 +++++++++++++- docs/genindex.html | 24 ++- docs/layers.html | 2 +- docs/losses.html | 2 +- docs/models.html | 305 +++++++++++++++++++++++++--- docs/objects.inv | Bin 1841 -> 1887 bytes docs/scatterers.html | 67 +++--- docs/searchindex.js | 2 +- docs/sequences.html | 10 +- docs/utils.html | 6 +- 15 files changed, 624 insertions(+), 73 deletions(-) diff --git a/_src/source/augmentations.rst b/_src/source/augmentations.rst index e37c74a9d..6d007ab44 100644 --- a/_src/source/augmentations.rst +++ b/_src/source/augmentations.rst @@ -69,6 +69,13 @@ Pad :members: :exclude-members: get +PadToMultiplesOf +^^^^^^^^^^^^^^^^ + +.. autoclass:: deeptrack.augmentations.PadToMultiplesOf + :members: + :exclude-members: get + PreLoad ^^^^^^^ diff --git a/_src/source/features.rst b/_src/source/features.rst index d989b39f1..bc4a0de55 100644 --- a/_src/source/features.rst +++ b/_src/source/features.rst @@ -6,6 +6,34 @@ features Module classes <<<<<<<<<<<<<< +AsType +^^^^^^ + +.. autoclass:: deeptrack.features.AsType + :members: + :exclude-members: get + +Bind +^^^^ + +.. autoclass:: deeptrack.features.Bind + :members: + :exclude-members: get + +BindResolve +^^^^^^^^^^^ + +.. autoclass:: deeptrack.features.BindResolve + :members: + :exclude-members: get + +BindUpdate +^^^^^^^^^^ + +.. autoclass:: deeptrack.features.BindUpdate + :members: + :exclude-members: get + Branch ^^^^^^ diff --git a/docs/_sources/augmentations.rst.txt b/docs/_sources/augmentations.rst.txt index e37c74a9d..6d007ab44 100644 --- a/docs/_sources/augmentations.rst.txt +++ b/docs/_sources/augmentations.rst.txt @@ -69,6 +69,13 @@ Pad :members: :exclude-members: get +PadToMultiplesOf +^^^^^^^^^^^^^^^^ + +.. autoclass:: deeptrack.augmentations.PadToMultiplesOf + :members: + :exclude-members: get + PreLoad ^^^^^^^ diff --git a/docs/_sources/features.rst.txt b/docs/_sources/features.rst.txt index d989b39f1..bc4a0de55 100644 --- a/docs/_sources/features.rst.txt +++ b/docs/_sources/features.rst.txt @@ -6,6 +6,34 @@ features Module classes <<<<<<<<<<<<<< +AsType +^^^^^^ + +.. autoclass:: deeptrack.features.AsType + :members: + :exclude-members: get + +Bind +^^^^ + +.. autoclass:: deeptrack.features.Bind + :members: + :exclude-members: get + +BindResolve +^^^^^^^^^^^ + +.. autoclass:: deeptrack.features.BindResolve + :members: + :exclude-members: get + +BindUpdate +^^^^^^^^^^ + +.. autoclass:: deeptrack.features.BindUpdate + :members: + :exclude-members: get + Branch ^^^^^^ diff --git a/docs/augmentations.html b/docs/augmentations.html index 879a1f7eb..ade943ad9 100644 --- a/docs/augmentations.html +++ b/docs/augmentations.html @@ -264,6 +264,10 @@ Pad +
  • + PadToMultiplesOf +
  • +
  • PreLoad
  • @@ -838,6 +842,57 @@

    Pad + +
    +

    PadToMultiplesOf

    +
    +
    +class deeptrack.augmentations.PadToMultiplesOf(multiple=1, **kwargs)
    +

    Pad images until their height/width is a multiple of a value.

    +
    +
    Parameters
    +
    +
    multipleint or tuple of (int or None)

    Images will be padded until their width is a multiple of +this value. If a tuple, it is assumed to be a multiple per axis. +A value of None or -1 indicates to skip that axis.

    +
    +
    +
    +
    +

    Methods

    + ++++ + + + + + + + + + + + + + + +

    plot([input_image, resolve_kwargs, interval])

    Visualizes the output of the feature.

    resolve([image_list])

    Creates the image.

    sample(**kwargs)

    Returns the feature

    update(**kwargs)

    Updates the state of all properties.

    + ++++ + + + + + +

    update_properties

    +
    +

    PreLoad

    diff --git a/docs/features.html b/docs/features.html index 0e03ecae4..7fadb7060 100644 --- a/docs/features.html +++ b/docs/features.html @@ -228,6 +228,22 @@
  • Module classes - +
      +
    • BindResolve (in module deeptrack.features) +
    • +
    • BindUpdate (class in deeptrack.features) +
    • Blur (class in deeptrack.math)
    • BlurCV2 (class in deeptrack.math) @@ -216,6 +224,8 @@

      B

      C

        +
      • ContinuousGenerator (class in deeptrack.generators) +
      • Convolutional() (in module deeptrack.models)
      • convolutional() (in module deeptrack.models) @@ -626,6 +636,8 @@

        P

      • Pad (class in deeptrack.augmentations)
      • pad_image_to_fft() (in module deeptrack.image) +
      • +
      • PadToMultiplesOf (class in deeptrack.augmentations)
      • Piston (class in deeptrack.aberrations)
      • @@ -720,6 +732,10 @@

        S

        T

        + or other required elements. + thead: [ 1, "
        • Trefoil (class in deeptrack.aberrations)
        • diff --git a/docs/layers.html b/docs/layers.html index 9057972ea..e827716b3 100644 --- a/docs/layers.html +++ b/docs/layers.html @@ -436,7 +436,7 @@

          ResidualBlock

          -deeptrack.layers.StaticUpsampleBlock(size=2, 2, activation=None, interpolation='bilinear', instance_norm=False, kernel_size=1, 1, strides=1, padding='same', **kwargs)
          +deeptrack.layers.StaticUpsampleBlock(size=2, 2, activation=None, interpolation='bilinear', instance_norm=False, kernel_size=1, 1, strides=1, padding='same', with_conv=True, **kwargs)

          A single no-trainable 2d deconvolutional layer.

          Accepts arguments of keras.layers.UpSampling2D.

          diff --git a/docs/losses.html b/docs/losses.html index 221603ec1..7d5a100eb 100644 --- a/docs/losses.html +++ b/docs/losses.html @@ -298,7 +298,7 @@

          Functions

          -
          flatten

          Flattends the inputs before calling the loss function.

          +
          flatten

          Flattends the inputs before calling the loss function.

          sigmoid

          Adds a signmoid transformation to the prediction before calling the loss function.

          diff --git a/docs/models.html b/docs/models.html index 762431f89..a7842dfa4 100644 --- a/docs/models.html +++ b/docs/models.html @@ -267,15 +267,15 @@
        • - convolutional + convolutional
        • - rnn + rnn
        • - unet + unet
        @@ -300,7 +300,7 @@

        Classes

        -
        ModelFeature

        Base model feature class.

        +
        ModelFeature

        Base model feature class.

        Convolutional, convolutional

        Creates and compiles a convolutional neural network.

        @@ -377,39 +377,290 @@

        Model

        cgan

        -class deeptrack.models.cgan(generator=None, discriminator=None, discriminator_loss=None, discriminator_optimizer=None, discriminator_metrics=None, assemble_loss=None, assemble_optimizer=None, assemble_loss_weights=None, **kwargs)
        -

        Methods

        +class deeptrack.models.cgan(*args, **kwargs) +
        +
        Attributes
        +
        +
        activity_regularizer

        Optional regularizer function for the output of this layer.

        +
        +
        distribute_strategy

        The tf.distribute.Strategy this model was created under.

        +
        +
        dtype

        Dtype used by the weights of the layer, set in the constructor.

        +
        +
        dynamic

        Whether the layer is dynamic (eager-only); set in the constructor.

        +
        +
        inbound_nodes

        Deprecated, do NOT use! Only for compatibility with external Keras.

        +
        +
        input

        Retrieves the input tensor(s) of a layer.

        +
        +
        input_mask

        Retrieves the input mask tensor(s) of a layer.

        +
        +
        input_shape

        Retrieves the input shape(s) of a layer.

        +
        +
        input_spec

        InputSpec instance(s) describing the input format for this layer.

        +
        +
        layers
        +
        losses

        List of losses added using the add_loss() API.

        +
        +
        metrics

        Returns the model’s metrics added using compile, add_metric APIs.

        +
        +
        metrics_names

        Returns the model’s display labels for all outputs.

        +
        +
        name

        Name of the layer (string), set in the constructor.

        +
        +
        name_scope

        Returns a tf.name_scope instance for this class.

        +
        +
        non_trainable_variables
        +
        non_trainable_weights

        List of all non-trainable weights tracked by this layer.

        +
        +
        outbound_nodes

        Deprecated, do NOT use! Only for compatibility with external Keras.

        +
        +
        output

        Retrieves the output tensor(s) of a layer.

        +
        +
        output_mask

        Retrieves the output mask tensor(s) of a layer.

        +
        +
        output_shape

        Retrieves the output shape(s) of a layer.

        +
        +
        run_eagerly

        Settable attribute indicating whether the model should run eagerly.

        +
        +
        state_updates

        Deprecated, do NOT use! (deprecated)

        +
        +
        stateful
        +
        submodules

        Sequence of all sub-modules.

        +
        +
        supports_masking

        Whether this layer supports computing a mask using compute_mask.

        +
        +
        trainable
        +
        trainable_variables

        Sequence of trainable variables owned by this module and its submodules.

        +
        +
        trainable_weights

        List of all trainable weights tracked by this layer.

        +
        +
        updates

        DEPRECATED FUNCTION

        +
        +
        variables

        Returns the list of all layer variables/weights.

        +
        +
        weights

        Returns the list of all layer variables/weights.

        +
        +
        +
        +
        +

        Methods

        - - + + - - + + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

        plot([input_image, resolve_kwargs, interval])

        Visualizes the output of the feature.

        __call__(*args, **kwargs)

        Wraps call, applying pre- and post-processing steps.

        resolve([image_list])

        Creates the image.

        add_loss(losses, **kwargs)

        Add loss tensor(s), potentially dependent on layer inputs.

        sample(**kwargs)

        Returns the feature

        add_metric(value[, name])

        Adds metric tensor to the layer.

        update(**kwargs)

        Updates the state of all properties.

        add_update(updates[, inputs])

        Add update op(s), potentially dependent on layer inputs.

        add_variable(*args, **kwargs)

        Deprecated, do NOT use! Alias for add_weight.

        add_weight([name, shape, dtype, …])

        Adds a new variable to the layer.

        apply(inputs, *args, **kwargs)

        Deprecated, do NOT use! (deprecated)

        build(input_shape)

        Builds the model based on input shapes received.

        call(*args, **kwargs)

        Calls the model on new inputs.

        compile([optimizer, loss, metrics, …])

        Configures the model for training.

        compute_mask(inputs[, mask])

        Computes an output mask tensor.

        compute_output_shape(input_shape)

        Computes the output shape of the layer.

        compute_output_signature(input_signature)

        Compute the output tensor signature of the layer based on the inputs.

        count_params()

        Count the total number of scalars composing the weights.

        evaluate([x, y, batch_size, verbose, …])

        Returns the loss value & metrics values for the model in test mode.

        evaluate_generator(generator[, steps, …])

        Evaluates the model on a data generator.

        fit([x, y, batch_size, epochs, verbose, …])

        Trains the model for a fixed number of epochs (iterations on a dataset).

        fit_generator(generator[, steps_per_epoch, …])

        Fits the model on data yielded batch-by-batch by a Python generator.

        from_config(config[, custom_objects])

        Creates a layer from its config.

        get_config()

        Returns the config of the layer.

        get_input_at(node_index)

        Retrieves the input tensor(s) of a layer at a given node.

        get_input_mask_at(node_index)

        Retrieves the input mask tensor(s) of a layer at a given node.

        get_input_shape_at(node_index)

        Retrieves the input shape(s) of a layer at a given node.

        get_layer([name, index])

        Retrieves a layer based on either its name (unique) or index.

        get_losses_for(inputs)

        Deprecated, do NOT use! (deprecated)

        get_output_at(node_index)

        Retrieves the output tensor(s) of a layer at a given node.

        get_output_mask_at(node_index)

        Retrieves the output mask tensor(s) of a layer at a given node.

        get_output_shape_at(node_index)

        Retrieves the output shape(s) of a layer at a given node.

        get_updates_for(inputs)

        Deprecated, do NOT use! (deprecated)

        get_weights()

        Retrieves the weights of the model.

        load_weights(filepath[, by_name, …])

        Loads all layer weights, either from a TensorFlow or an HDF5 weight file.

        make_predict_function()

        Creates a function that executes one step of inference.

        make_test_function()

        Creates a function that executes one step of evaluation.

        make_train_function()

        Creates a function that executes one step of training.

        predict(x[, batch_size, verbose, steps, …])

        Generates output predictions for the input samples.

        predict_generator(generator[, steps, …])

        Generates predictions for the input samples from a data generator.

        predict_on_batch(x)

        Returns predictions for a single batch of samples.

        predict_step(data)

        The logic for one inference step.

        reset_metrics()

        Resets the state of all the metrics in the model.

        save(filepath[, overwrite, …])

        Saves the model to Tensorflow SavedModel or a single HDF5 file.

        save_weights(filepath[, overwrite, …])

        Saves all layer weights.

        set_weights(weights)

        Sets the weights of the layer, from Numpy arrays.

        summary([line_length, positions, print_fn])

        Prints a string summary of the network.

        test_on_batch(x[, y, sample_weight, …])

        Test the model on a single batch of samples.

        test_step(data)

        The logic for one evaluation step.

        to_json(**kwargs)

        Returns a JSON string containing the network configuration.

        to_yaml(**kwargs)

        Returns a yaml string containing the network configuration.

        train_on_batch(x[, y, sample_weight, …])

        Runs a single gradient update on a single batch of data.

        train_step(data)

        The logic for one training step.

        with_name_scope(method)

        Decorator to automatically enter the module name scope.

        --++ - +

        fit

        reset_states

        +
        +
        +call(*args, **kwargs)
        +

        Calls the model on new inputs.

        +

        In this case call just reapplies +all ops in the graph to the new inputs +(e.g. build a new computational graph from the provided inputs).

        +
        +
        Arguments:

        inputs: A tensor or list of tensors. +training: Boolean or boolean scalar tensor, indicating whether to run

        +
        +

        the Network in training mode or inference mode.

        +
        +
        +
        mask: A mask or list of masks. A mask can be

        either a tensor or None (no mask).

        +
        +
        +
        +
        Returns:

        A tensor if there is a single output, or +a list of tensors if there are more than one outputs.

        +
        +
        +
        + +
        +
        +train_step(data)
        +

        The logic for one training step.

        +

        This method can be overridden to support custom training logic. +This method is called by Model.make_train_function.

        +

        This method should contain the mathemetical logic for one step of training. +This typically includes the forward pass, loss calculation, backpropagation, +and metric updates.

        +

        Configuration details for how this logic is run (e.g. tf.function and +tf.distribute.Strategy settings), should be left to +Model.make_train_function, which can also be overridden.

        +
        +
        Arguments:

        data: A nested structure of `Tensor`s.

        +
        +
        Returns:

        A dict containing values that will be passed to +tf.keras.callbacks.CallbackList.on_train_batch_end. Typically, the +values of the Model’s metrics are returned. Example: +{‘loss’: 0.2, ‘accuracy’: 0.7}.

        +
        +
        +
        +

        @@ -420,7 +671,7 @@

        Module functions

        -deeptrack.models.Convolutional(input_shape=(51, 51, 1), conv_layers_dimensions=(16, 32, 64, 128), dense_layers_dimensions=(32, 32), steps_per_pooling=1, dropout=(), dense_top=True, number_of_outputs=3, output_activation=None, output_kernel_size=3, loss=<function flatten.<locals>.wrapper>, convolution_block='convolutional', pooling_block='pooling', dense_block='dense', **kwargs)
        +deeptrack.models.Convolutional(input_shape=(51, 51, 1), conv_layers_dimensions=(16, 32, 64, 128), dense_layers_dimensions=(32, 32), steps_per_pooling=1, dropout=(), dense_top=True, number_of_outputs=3, output_activation=None, output_kernel_size=3, loss=<function flatten.<locals>.wrapper>, input_layer=None, convolution_block='convolutional', pooling_block='pooling', dense_block='dense', **kwargs)

        Creates and compiles a convolutional neural network. A convolutional network with a dense top. Parameters @@ -551,7 +802,7 @@

        RNNUNet

        -deeptrack.models.UNet(input_shape=(None, None, 1), conv_layers_dimensions=(16, 32, 64, 128), base_conv_layers_dimensions=(128, 128), output_conv_layers_dimensions=(16, 16), dropout=(), steps_per_pooling=1, number_of_outputs=1, output_kernel_size=3, output_activation=None, loss=<function flatten.<locals>.wrapper>, encoder_convolution_block='convolutional', base_convolution_block='convolutional', decoder_convolution_block='convolutional', output_convolution_block='convolutional', pooling_block='pooling', upsampling_block='deconvolutional', **kwargs)
        +deeptrack.models.UNet(input_shape=(None, None, 1), conv_layers_dimensions=(16, 32, 64, 128), base_conv_layers_dimensions=(128, 128), output_conv_layers_dimensions=(16, 16), dropout=(), steps_per_pooling=1, number_of_outputs=1, output_kernel_size=3, output_activation=None, loss=<function flatten.<locals>.wrapper>, input_layer=None, encoder_convolution_block='convolutional', base_convolution_block='convolutional', decoder_convolution_block='convolutional', output_convolution_block='convolutional', pooling_block='pooling', upsampling_block='deconvolutional', **kwargs)

        Creates and compiles a U-Net. Parameters ———- @@ -589,11 +840,11 @@

        UNet

        -
        -

        convolutional

        +
        +

        convolutional

        -deeptrack.models.convolutional(input_shape=(51, 51, 1), conv_layers_dimensions=(16, 32, 64, 128), dense_layers_dimensions=(32, 32), steps_per_pooling=1, dropout=(), dense_top=True, number_of_outputs=3, output_activation=None, output_kernel_size=3, loss=<function flatten.<locals>.wrapper>, convolution_block='convolutional', pooling_block='pooling', dense_block='dense', **kwargs)
        +deeptrack.models.convolutional(input_shape=(51, 51, 1), conv_layers_dimensions=(16, 32, 64, 128), dense_layers_dimensions=(32, 32), steps_per_pooling=1, dropout=(), dense_top=True, number_of_outputs=3, output_activation=None, output_kernel_size=3, loss=<function flatten.<locals>.wrapper>, input_layer=None, convolution_block='convolutional', pooling_block='pooling', dense_block='dense', **kwargs)

        Creates and compiles a convolutional neural network. A convolutional network with a dense top. Parameters @@ -626,8 +877,8 @@

        convolutional -

        rnn

        +
        +

        rnn

        deeptrack.models.rnn(input_shape=51, 51, 1, conv_layers_dimensions=16, 32, 64, 128, dense_layers_dimensions=32, rnn_layers_dimensions=32, return_sequences=False, output_activation=None, number_of_outputs=3, **kwargs)
        @@ -662,11 +913,11 @@

        rnn

        -
        -

        unet

        +
        +

        unet

        -deeptrack.models.unet(input_shape=(None, None, 1), conv_layers_dimensions=(16, 32, 64, 128), base_conv_layers_dimensions=(128, 128), output_conv_layers_dimensions=(16, 16), dropout=(), steps_per_pooling=1, number_of_outputs=1, output_kernel_size=3, output_activation=None, loss=<function flatten.<locals>.wrapper>, encoder_convolution_block='convolutional', base_convolution_block='convolutional', decoder_convolution_block='convolutional', output_convolution_block='convolutional', pooling_block='pooling', upsampling_block='deconvolutional', **kwargs)
        +deeptrack.models.unet(input_shape=(None, None, 1), conv_layers_dimensions=(16, 32, 64, 128), base_conv_layers_dimensions=(128, 128), output_conv_layers_dimensions=(16, 16), dropout=(), steps_per_pooling=1, number_of_outputs=1, output_kernel_size=3, output_activation=None, loss=<function flatten.<locals>.wrapper>, input_layer=None, encoder_convolution_block='convolutional', base_convolution_block='convolutional', decoder_convolution_block='convolutional', output_convolution_block='convolutional', pooling_block='pooling', upsampling_block='deconvolutional', **kwargs)

        Creates and compiles a U-Net. Parameters ———- diff --git a/docs/objects.inv b/docs/objects.inv index e39796df344baae2cecb098c17f1b6e8897171d7..7225bff6bdf01bec57be3e8f7dd5e0682288ff58 100644 GIT binary patch delta 1786 zcmV#1dHBB!0{g#!^w2{8yT0O&+H z^)>o>eUdH+{(!Vh37{`Fwb<|5#bN<0KvIChD3U(S$p(}nhDo7k#r|V1X~|*sZsy77 zJCpNYUCa4zv-2~02tB`OpDj_!iPp3CFL_1?v|-yEf9O1tVSfRcOiLY!z9FU7jEIXu zQucF7Pkxt*{glEGekF4r#e{+V8+nCpJa*lh3VU1S*(eFt9hj1qXiCeU0d zSxkgK%4Nw7D}OlXhin4ZCxqd^J}M$~CRIMQYuB6=3r4n55I&LS?(;-~FN+BTD?+EC z-)e+b3hrc}GaLK^g7&6NEgP9Ejm8GF2L9Eevr?p0M!fIi$AJ5AAdNOj<89)~jNn}~ z@@q6Q!rPodl1jh@EM++KI*wsSR4xTeBjC}|iVjwEtbeqzdrHQDCh=j*fS6K2f7@w< zBa^6AxzLaMqPN-f(XYTRnV?ai&!8oLt_%`m6x);rLhxS-N=$^mxO1etU>KGno55au zB2G|dN00C|m}@7V$g;xy6w8}^FwKG(qQQjY$~@o4`o1U&j+I!%P{mrTar1)9s;@bi zour{?)qmw@9Dyb|Zl>}0vQ6+X{2f-QJUD1~B;QaH4#TbfHYeNgQCfnEKw<80$cAwi zk^bvyK(Njs`bmeQjVe=oBs?%Lw;%u)c&Ykpb0;2IojoO70}KLNiBo`FIba)ZD=dWNPkpa`-`;oV6W=WNl^@gbP{e0CMmpy zI}DxM$JuGgSU~y)9701B@|I!+R{K;WnNq3Zj!u7*67G zW`B?$m1rzKoI)!|tRQL44NQA%2Wc{npVIi5;GG?$F zFLpRJgNI48Z7vxNg?$IM-5E3*m0~$DyMNxqvVxImRW)DG-f66Z9MZ+C9c+Q8=wI?u zg<|S8@nqN~!&!|;9%L+7`RdOPC+lBvR-CN7V9$)69@*x-NKglsK!YLfhHrl|;ND)b za`qFJOf1QdlW}&u1C+nR>3vw28~e+g1dtSXe|K`Cv1#NKdezHd&iWh&!Ph0{dw*mQ zkmB?YMgM_`ub1|@*T-WpdlYL?A@;&eeZIdBHS*;iOeiMZ5)tH=1|gKs=!39kDGLJK+kZibhb*ga zvi!@#qp($1KO8qD3sYY`x50Cwk$>RT3YW_6{22q@i=GcZh`Z*cRG`zQmOL4F%Xyh& zJ!>=KMiFXnkAn!7%oZuBEW+$Qv@tpk>5i|xn0DfkxOz&5u0MwyN5O|~=fX)2T+s!S zELeXpiz1k(rBXQL$ur?4;DIDH)4h6=7*#}X6{nggVFvOzwl#b!?XjNlNq=edk|w;5 zI<*H^HN0Nw#3R$eQ~JcQFzv6NLy9BV`eYM~UNTrWzoH53Cnpe%Zr_|u;K4mXm=&?# zi|{yxX;BDvy~@3Gu!^?Qv8-uz*7Z}*YMFqu0s+8W187B?}kGd&iRQ(6ABqAd0#77FaBt^*@~QVK2TMLH_1z5l_#5 zFFbCZCR6V**?pSZY7<-q4a)qbcv-%Z*hw-k9(Zl+R*l+Ldys*8x=ki+H!@O;C z2YA1=JL|ai15qsY=W|ViQ(U?g!^N{c6M3B85db;svfpd>N?L69%2-clu-99?&Wj`N zt@gNBh`yIzb>LYU>t+~i(O3YJSn|oTV&}luk cIs_-8kOnqVKIt>JMtit!5kcnv0X#S{dY9I1W&i*H delta 1740 zcmV;-1~d8J4zUi9d4Iuj+cprr`zzFGuht|v=4MB+>#1dHBB!0{g#!Ug2{8yT0O&+H z^*8!^{gN&SQUqy*7C>KYYO(JDSS)rIAQ?buHKC7lvH`7$CMu5>YVYFC1n3r@C55;2kH_R~ay&x;8JE5fFr zHQcI5h7JA!$$Ea?$VNQ8)!2YBAig+sUP)Rn3h5xh%Aeo00q zjJDvAQ3V)vD95EYX$(7}3ne*CfG1lk*;vW8GS(%6oPPt$(#@6wv6Y5?u4siLo9Li& ziE)tb!fo3}{{)7Kbu-8;C*maIZdydF!CrasM3xn12Ta!cXqpAF#DI;*RYkE+9s8mx z1=bZd9+}!>gPWH^)pISt?i7nfS2r z4!kMIHh+GVmY@?*==&S8;esc)|GHiftgDE5H1TMwD~gXqMEd0xBw*xIx*xPU@krPT zlrRQZE-O`;>sA(H&cxtWN(nBvNqv3-!&#L$ z)wMf%(9fk$JV_M9WScmg!a9H8AGK)AKfJ<0kU2qi=x)$;z;=`-7sOhKhDnxTK}YmH zqkq~-q{Yp(Phfcz8RJiGe@Y4o_yUN`$i_G~hYYm#F?13OMhWUpqT7jt=4(YX*6XiA zBGi^>Zg&Nz$%Lii#;BCVZbz}htr@*chHneSSuE@u@a@iGr%5hW5WDMbEGHP*R(10Q z>s?87kYl>&wSyFRivFdjbS$Qci6_G@Ie+eIM2e`+qLn}V`R-)>4}zB`D=+vHXQx}X zz2%RZz!F$A#NR0HPX^q%3q!$wz>>=)`F=9at#^d-H#mI`>uTeE*^>Z@f#_!^FB;oM zUZGdL4EAiuaTI)239&~82^6<~Ecy?0e6w`Vy*a)Fb4RfQDyF~qu0Gw}#dh-f4u5Pc zhHi^_s9CEw}K6X1iC)W24N=A|6lrX0_*%ImHW8ED z=s8XN91V4cNIksj=)@!2AyE1#ut@Aj&mqMN*yfZGjb3tCx4)7J+{X-%jDJ47-kHFI zIYHVLabF^cG=^zbh#q?Fdvp**57IHOIq0mLr(UmphL@nn96pM|?Vdp)Gm6I&Yfx9$ zl9BoPc49KY&9G()u*X2|>h$p&(c4Ut0!$ouM@(aqC>S@~oj*4M;&6VP*lETfCzXht zsv$XKln5~n3qO!Emc3_+&VSCIe{AD4*%QGSY=43CdZ;J+ZvN)K zfBrQy7EbLK2;%cVR)-O1`F9AWkpaO1icJ01NLHoXu9in;ALK8?b}!AGG|@p2q}9p7a47Zeu}ZV ir*#l|t%rjS!Hp=Dg^f~==FG?F0M`W(Wd0w>-I|

        scatterers

        Implementations of Feature the model scattering objects.

        -

        Provides some basic implementations of scattering objects +

        Provides some basic implementations of scattering objects that are frequently used.

        Classes

        @@ -412,23 +412,26 @@

        MieScatterer class deeptrack.scatterers.MieScatterer(coefficients, offset_z='auto', polarization_angle=0, collection_angle='auto', L='auto', **kwargs)

        Base implementation of a Mie particle.

        -

        New Mie-theory scatterers can be implemented by extending this class, and passing -a function that calculates the coefficients of the harmonics up to order L. To be -precise, the feature expects a wrapper function that takes the current values of the -properties, as well as a inner function that takes an integer as the only parameter, -and calculates the coefficients up to that integer. The return format is expected to -be a tuple with two values, corresponding to an and bn. See +

        New Mie-theory scatterers can be implemented by extending this class, and +passing a function that calculates the coefficients of the harmonics up to +order L. To beprecise, the feature expects a wrapper function that takes +the current values of the properties, as well as a inner function that +takes an integer as the only parameter, and calculates the coefficients up +to that integer. The return format is expected to be a tuple with two +values, corresponding to an and bn. See deeptrack.backend.mie_coefficients for an example.

        Parameters
        coefficientsCallable[int] -> Tuple[ndarray, ndarray]

        Function that returns the harmonics coefficients.

        -
        offset_z“auto” or float

        Distance from the particle in the z direction the field is evaluated. If “auto”, -this is calculated from the pixel size and collection_angle

        +
        offset_z“auto” or float

        Distance from the particle in the z direction the field is evaluated. +If “auto”, this is calculated from the pixel size and +collection_angle

        collection_angle“auto” or float

        The maximum collection angle in radians. If “auto”, this -is calculated from the objective NA (which is true if the objective is the limiting +is calculated from the objective NA (which is true if the objective is +the limiting aperature).

        polarization_anglefloat

        Angle of the polarization of the incoming light relative to the x-axis.

        @@ -476,10 +479,12 @@

        MieSphere class deeptrack.scatterers.MieSphere(radius=1e-06, refractive_index=1.45, offset_z='auto', polarization_angle=0, collection_angle='auto', L='auto', **kwargs)

        Scattered field by a sphere

        -

        Should be calculated on at least a 64 by 64 grid. Use padding in the optics if necessary

        -

        Calculates the scattered field by a spherical particle in a homogenous medium, -as predicted by Mie theory. Note that the induced phase shift is calculated -in comparison to the refractive_index_medium property of the optical device.

        +

        Should be calculated on at least a 64 by 64 grid. Use padding in the +optics if necessary.

        +

        Calculates the scattered field by a spherical particle in a homogenous +medium, as predicted by Mie theory. Note that the induced phase shift is +calculated in comparison to the refractive_index_medium property of the +optical device.

        Parameters
        @@ -497,12 +502,13 @@

        MieSpherefloat

        The position in the direction normal to the camera plane. Used if position is of length 2.

        -
        offset_z“auto” or float

        Distance from the particle in the z direction the field is evaluated. If “auto”, -this is calculated from the pixel size and collection_angle

        +
        offset_z“auto” or float

        Distance from the particle in the z direction the field is evaluated. +If “auto”, this is calculated from the pixel size and +collection_angle

        collection_angle“auto” or float

        The maximum collection angle in radians. If “auto”, this -is calculated from the objective NA (which is true if the objective is the limiting -aperature).

        +is calculated from the objective NA (which is true if the objective +is the limiting aperature).

        polarization_anglefloat

        Angle of the polarization of the incoming light relative to the x-axis.

        @@ -539,11 +545,13 @@

        MieStratifiedSphere class deeptrack.scatterers.MieStratifiedSphere(radius=1e-06, refractive_index=1.45, offset_z='auto', polarization_angle=0, collection_angle='auto', L='auto', **kwargs)

        Scattered field by a stratified sphere

        -

        A stratified sphere is a sphere with several concentric shells of uniform refractive index.

        -

        Should be calculated on at least a 64 by 64 grid. Use padding in the optics if necessary

        -

        Calculates the scattered field by in a homogenous medium, as predicted by Mie theory. -Note that the induced phase shift is calculated in comparison to the -refractive_index_medium property of the optical device.

        +

        A stratified sphere is a sphere with several concentric shells of uniform +refractive index.

        +

        Should be calculated on at least a 64 by 64 grid. Use padding in the +optics if necessary

        +

        Calculates the scattered field by in a homogenous medium, as predicted by +Mie theory. Note that the induced phase shift is calculated in comparison +to the refractive_index_medium property of the optical device.

        Parameters
        @@ -561,12 +569,13 @@

        MieStratifiedSpherefloat

        The position in the direction normal to the camera plane. Used if position is of length 2.

        -
        offset_z“auto” or float

        Distance from the particle in the z direction the field is evaluated. If “auto”, -this is calculated from the pixel size and collection_angle

        +
        offset_z“auto” or float

        Distance from the particle in the z direction the field is evaluated. +If “auto”, this is calculated from the pixel size and +collection_angle

        collection_angle“auto” or float

        The maximum collection angle in radians. If “auto”, this -is calculated from the objective NA (which is true if the objective is the limiting -aperature).

        +is calculated from the objective NA (which is true if the objective +is the limiting aperature).

        polarization_anglefloat

        Angle of the polarization of the incoming light relative to the x-axis.

        @@ -680,8 +689,8 @@

        ScattererOther Parameters
        -
        upsample_axestuple of ints

        Sets the axes along which the calculation is upsampled (default is None, -which implies all axes are upsampled).

        +
        upsample_axestuple of ints

        Sets the axes along which the calculation is upsampled (default is +None, which implies all axes are upsampled).

        crop_zerosbool

        Whether to remove slices in which all elements are zero.

        diff --git a/docs/searchindex.js b/docs/searchindex.js index 7c31103b8..6c65d0a7a 100644 --- a/docs/searchindex.js +++ b/docs/searchindex.js @@ -1 +1 @@ -Search.setIndex({docnames:["aberrations","advanced","augmentations","backend","basics","deeptrack","features","generators","image","index","installation","layers","losses","math","models","noises","optics","properties","scatterers","sequences","tutorials","utils"],envversion:{"sphinx.domains.c":2,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":3,"sphinx.domains.index":1,"sphinx.domains.javascript":2,"sphinx.domains.math":2,"sphinx.domains.python":2,"sphinx.domains.rst":2,"sphinx.domains.std":1,sphinx:56},filenames:["aberrations.rst","advanced.rst","augmentations.rst","backend.rst","basics.rst","deeptrack.rst","features.rst","generators.rst","image.rst","index.rst","installation.rst","layers.rst","losses.rst","math.rst","models.rst","noises.rst","optics.rst","properties.rst","scatterers.rst","sequences.rst","tutorials.rst","utils.rst"],objects:{"deeptrack.aberrations":{Aberration:[0,1,1,""],Astigmatism:[0,1,1,""],Defocus:[0,1,1,""],GaussianApodization:[0,1,1,""],HorizontalComa:[0,1,1,""],HorizontalTilt:[0,1,1,""],ObliqueAstigmatism:[0,1,1,""],ObliqueTrefoil:[0,1,1,""],Piston:[0,1,1,""],SphericalAberration:[0,1,1,""],Trefoil:[0,1,1,""],VerticalComa:[0,1,1,""],VerticalTilt:[0,1,1,""],Zernike:[0,1,1,""]},"deeptrack.augmentations":{Affine:[2,1,1,""],Augmentation:[2,1,1,""],Crop:[2,1,1,""],CropToMultiplesOf:[2,1,1,""],ElasticTransformation:[2,1,1,""],FlipDiagonal:[2,1,1,""],FlipLR:[2,1,1,""],FlipUD:[2,1,1,""],Pad:[2,1,1,""],PreLoad:[2,1,1,""]},"deeptrack.backend":{besselj:[3,2,1,""],bessely:[3,2,1,""],dbesselj:[3,2,1,""],dbessely:[3,2,1,""],dricbesh:[3,2,1,""],dricbesj:[3,2,1,""],dricbesy:[3,2,1,""],mie_coefficients:[3,2,1,""],mie_harmonics:[3,2,1,""],ricbesh:[3,2,1,""],ricbesj:[3,2,1,""],ricbesy:[3,2,1,""],stratified_mie_coefficients:[3,2,1,""]},"deeptrack.features":{Branch:[6,1,1,""],Combine:[6,1,1,""],ConditionalSetFeature:[6,1,1,""],ConditionalSetProperty:[6,1,1,""],Dataset:[6,1,1,""],DummyFeature:[6,1,1,""],Duplicate:[6,1,1,""],Feature:[6,1,1,""],Label:[6,1,1,""],Lambda:[6,1,1,""],LoadImage:[6,1,1,""],Merge:[6,1,1,""],Probability:[6,1,1,""],SampleToMasks:[6,1,1,""],StructuralFeature:[6,1,1,""]},"deeptrack.features.Feature":{plot:[6,3,1,""],resolve:[6,3,1,""],sample:[6,3,1,""],update:[6,3,1,""]},"deeptrack.generators":{ContinuousGenerator:[7,1,1,""],Generator:[7,1,1,""]},"deeptrack.generators.ContinuousGenerator":{on_epoch_end:[7,3,1,""]},"deeptrack.generators.Generator":{generate:[7,3,1,""]},"deeptrack.image":{Image:[8,1,1,""],pad_image_to_fft:[8,2,1,""]},"deeptrack.image.Image":{append:[8,3,1,""],get_property:[8,3,1,""],merge_properties_from:[8,3,1,""]},"deeptrack.layers":{ConvolutionalBlock:[11,2,1,""],DeconvolutionalBlock:[11,2,1,""],DenseBlock:[11,2,1,""],Identity:[11,2,1,""],PoolingBlock:[11,2,1,""],ResidualBlock:[11,2,1,""],StaticUpsampleBlock:[11,2,1,""],as_block:[11,2,1,""]},"deeptrack.losses":{deeptrack_loss_function:[12,2,1,""],flatten:[12,2,1,""],nd_binary_crossentropy:[12,2,1,""],nd_kl_divergence:[12,2,1,""],nd_mean_absolute_error:[12,2,1,""],nd_mean_absolute_percentage_error:[12,2,1,""],nd_mean_squared_error:[12,2,1,""],nd_mean_squared_logarithmic_error:[12,2,1,""],nd_poisson:[12,2,1,""],nd_squared_hinge:[12,2,1,""],sigmoid:[12,2,1,""],weighted_crossentropy:[12,2,1,""]},"deeptrack.math":{Add:[13,1,1,""],Average:[13,1,1,""],AverageBlur:[13,1,1,""],AveragePooling:[13,1,1,""],BilateralBlur:[13,1,1,""],Blur:[13,1,1,""],BlurCV2:[13,1,1,""],Clip:[13,1,1,""],Divide:[13,1,1,""],GaussianBlur:[13,1,1,""],MedianBlur:[13,1,1,""],Multiply:[13,1,1,""],NormalizeMinMax:[13,1,1,""],Pool:[13,1,1,""],Power:[13,1,1,""],Subtract:[13,1,1,""]},"deeptrack.models":{Convolutional:[14,2,1,""],FullyConnected:[14,2,1,""],KerasModel:[14,1,1,""],LoadModel:[14,2,1,""],Model:[14,1,1,""],RNN:[14,2,1,""],UNet:[14,2,1,""],cgan:[14,1,1,""],convolutional:[14,2,1,""],rnn:[14,2,1,""],unet:[14,2,1,""]},"deeptrack.noises":{Background:[15,1,1,""],Gaussian:[15,1,1,""],Noise:[15,1,1,""],Offset:[15,4,1,""],Poisson:[15,1,1,""]},"deeptrack.optics":{Brightfield:[16,1,1,""],Fluorescence:[16,1,1,""],IlluminationGradient:[16,1,1,""],Microscope:[16,1,1,""],Optics:[16,1,1,""]},"deeptrack.properties":{Property:[17,1,1,""],PropertyDict:[17,1,1,""],SequentialProperty:[17,1,1,""]},"deeptrack.properties.Property":{sample:[17,3,1,""],update:[17,3,1,""]},"deeptrack.properties.PropertyDict":{current_value_dict:[17,3,1,""],sample:[17,3,1,""],update:[17,3,1,""],update_item:[17,3,1,""]},"deeptrack.properties.SequentialProperty":{update:[17,3,1,""]},"deeptrack.scatterers":{Ellipse:[18,1,1,""],Ellipsoid:[18,1,1,""],MieScatterer:[18,1,1,""],MieSphere:[18,1,1,""],MieStratifiedSphere:[18,1,1,""],PointParticle:[18,1,1,""],Scatterer:[18,1,1,""],Sphere:[18,1,1,""]},"deeptrack.sequences":{Sequence:[19,1,1,""],Sequential:[19,2,1,""]},"deeptrack.sequences.Sequence":{update:[19,3,1,""]},"deeptrack.utils":{as_list:[21,2,1,""],get_kwarg_names:[21,2,1,""],hasmethod:[21,2,1,""],isiterable:[21,2,1,""],kwarg_has_default:[21,2,1,""],safe_call:[21,2,1,""]},deeptrack:{aberrations:[0,0,0,"-"],augmentations:[2,0,0,"-"],backend:[3,0,0,"-"],features:[6,0,0,"-"],generators:[7,0,0,"-"],image:[8,0,0,"-"],layers:[11,0,0,"-"],losses:[12,0,0,"-"],math:[13,0,0,"-"],models:[14,0,0,"-"],noises:[15,0,0,"-"],optics:[16,0,0,"-"],properties:[17,0,0,"-"],scatterers:[18,0,0,"-"],sequences:[19,0,0,"-"],utils:[21,0,0,"-"]}},objnames:{"0":["py","module","Python module"],"1":["py","class","Python class"],"2":["py","function","Python function"],"3":["py","method","Python method"],"4":["py","attribute","Python attribute"]},objtypes:{"0":"py:module","1":"py:class","2":"py:function","3":"py:method","4":"py:attribute"},terms:{"0001":12,"100":[1,2,15],"101":1,"128":[14,16],"2003":2,"abstract":[0,2,6,15,16,18],"break":1,"case":[1,2,6,21],"class":12,"default":[2,6,8,13,16,18,21],"final":[1,15],"float":[0,3,6,12,13,14,15,16,18],"function":[0,1,2,6,7,13,16,17,18,20],"import":4,"int":[0,2,3,6,7,8,11,13,14,16,17,18,19],"long":[1,13],"new":[2,4,6,7,12,17,18],"return":[1,2,3,4,6,7,8,11,12,14,16,17,18,19,21],"true":[1,2,6,7,8,11,14,18,21],"try":13,"while":[1,2,6,13],For:[1,2,4,6,17,18,19],Has:8,NOT:13,One:1,That:[4,6],The:[0,1,2,3,4,6,7,8,12,13,14,15,16,17,18,19,21],These:[1,2,8,17],Use:18,Used:18,Using:20,Will:17,__distributed__:6,__list_merge_strategy__:6,__next__:21,__property_memorability__:6,__property_verbosity__:6,_process_and_get:18,_process_properti:18,aberr:[1,5,9],about:[4,8,18],abov:17,absolut:12,accept:[1,2,6,7,11,17,21],access:[4,6,7],accord:0,account:2,accur:16,achiev:[1,2,4],act:2,activ:[11,14],adam:14,add:[0,1,4,6,11,12,14,15,16],add_and_multipli:4,add_batch_dimension_on_resolv:14,add_on:[1,4],add_one_five_tim:4,add_one_or_two:1,add_random_integ:1,add_zero_or_on:4,added:[4,6],adding:[0,6,8],addit:[6,8,13],advanc:[9,20],advantag:1,after:[1,14,17],after_axis_3:2,again:1,aim:7,alia:15,all:[1,2,4,6,7,8,13,16,17,18,19,21],allow:[1,2,7],along:[2,8,13,18],alpha:2,alreadi:19,also:[1,2],alwai:[1,4],amount:2,amplitud:[0,16],analysi:2,analyz:[10,14],angl:[3,18],ani:[1,2,4,6,8,17,18,21],anim:6,anoth:[1,6,8,13],aperatur:[16,18],aperature_angl:[],apod:0,append:[6,8],appli:[2,6,13,17],approach:1,approxim:18,area:13,arg:[0,2,6,13,15,17],argument:[0,2,6,11,13,14,17,19,20,21],aris:21,around:2,arrai:[4,6],array_lik:[6,7,8,16,18],as_list:6,assemble_loss:14,assemble_loss_weight:14,assemble_optim:14,assum:[2,4,7,18],asynchron:7,attribut:[6,8,17,19,21],augment:[5,9,13],auto:18,automat:[8,18],averr:1,avoid:[6,16],axes:[8,18],axi:[2,13,18],backend:[5,6,9,18],background:6,balanc:7,base:[0,2,6,7,14,15,16,18],base_conv_layers_dimens:14,base_convolution_block:14,basic:[9,18,20],batch:[2,7],batch_funct:7,batch_siz:7,been:[1,2,8,17],befor:[0,2,7,11,12],before_axis_3:2,behav:1,behaviour:[1,2],behind:17,benefit:1,bessel:3,best:2,between:[2,4,6,7,13,14,16,20],bilater:13,bilinear:11,binari:12,bleed:2,block:[4,11],bool:[2,6,7,8,11,14,17,18,21],both:[1,6],brightfield:18,calcul:[0,3,15,18],call:[1,2,4,6,7,8,12,17,19,21],callabl:[2,6,7,14,17,18,21],camera:[16,18],can:[1,2,4,6,11,14,16,17,18],cannot:2,captur:21,cell:18,center:[0,2],certain:6,chain:20,chang:[1,2,21],channel:2,characterist:18,check:[1,4,17,21],child:6,chosen:2,circular:18,clear:17,clip:16,close:13,code:[6,21],coeffici:[0,3,18],coher:16,collect:18,collection_angl:18,color:[2,13],combin:[17,19],come:1,command:10,common:[1,2,16],commonli:8,comparison:18,compil:14,compile_from_fil:14,complex:[3,16],comprehens:10,comput:[4,13],concentr:18,concept:[1,4],condit:6,condition:6,conditiona:6,conditionalsetfeatur:1,conditionalsetproperti:1,confer:2,conflict:1,confus:1,connect:14,constant:[2,6,15,16,17],constructor:6,consum:7,contain:[3,6,7,8,16],contin:7,continu:[7,17],control:[1,2,6],conv2d:11,conv2dtranspos:11,conv_layers_dimens:14,convert:[6,11,18,19,21],convolut:[2,11,13],convolution_block:14,coordin:[0,13],copi:6,core:4,corner:[2,3],correct:[6,16],correctli:[6,7],correspond:[0,7,18],cosin:3,could:[1,6],cours:1,crash:1,creat:[1,2,4,6,7,10,14,16,17],crop:18,crop_empti:[],crop_mod:2,crop_zero:18,crossentropi:12,cubic:2,current:[4,6,7,8,17,18],current_valu:[1,4,8,17],current_value_dict:17,custom:[4,6,14],custom_object:14,customiz:10,cval:[2,13],cycl:6,cyclic:1,data:[1,6,7,10],dataset:7,deal:2,decoder_convolution_block:14,deconstruct:6,deconvolut:[11,14],decreas:0,deep:[6,10,14],deeptrack:[0,1,2,3,4,6,7,8,10,11,12,13,14,15,16,17,18,19,21],def:1,defin:[0,1,2,3,6,8,16,17,18,21],definit:1,denot:2,dens:[11,14],dense_block:14,dense_layers_dimens:14,dense_top:14,depend:[2,4,6,17,19,20],deprec:2,deriv:3,describ:[0,16],desir:2,detail:2,determin:[1,4,8,14,15,18],deviat:[0,2,13],devic:[16,18],diagon:2,diamet:13,dict:[0,2,6,7,8,13,14,15,17],dictionari:[6,8,17,21],didn:1,differ:[1,4,6,17],differenti:1,digit:10,dimens:[2,6,7,13],dimension:18,direct:[1,2,3,16,18],directli:[1,4],disadvantag:1,discret:[16,17],discrimin:14,discriminator_loss:14,discriminator_metr:14,discriminator_optim:14,disk:[6,14,18],displac:2,distanc:[16,18],distort:2,distribut:[0,6,15],diverg:12,do_noth:1,doc:11,document:2,doe:[4,6,13,18,21],doesn:6,done:20,down:[1,2,14],downsampl:[13,14],draw:[2,21],dropout:14,dummi:20,duplic:8,dure:[7,14],each:[0,1,2,6,7,8,13,14,16,17,18],eachoth:2,eagl:1,earlier:6,easi:1,easiet:4,edg:[0,13,16],effect:16,either:[4,6,11],element:[6,17,18],ellipt:18,els:[1,8,21],emit:16,empti:18,encoder_convolution_block:14,encount:1,encourag:4,end:[6,7,8],enough:13,ensur:[0,7,21],ensure_contains_class:7,enter:16,entir:[1,6,16],epoch:7,eps:12,equal:[0,13],error:12,etc:13,evalu:[3,8,18],even:1,everi:[1,2,6,7],exact:1,exactli:1,exampl:[1,4,6,13,17,18,19],excit:4,excpet:1,execut:20,exist:[1,6,19],expand:7,expect:[7,18],experiment:10,explain:[1,4],explan:2,explicitli:[1,4],expos:1,extend:[17,18],extens:6,extract:[6,8],eyed:1,factor:[2,18],fail:1,fals:[1,6,11,14,21],farther:13,fast:8,featur:[0,2,5,7,8,9,13,14,15,16,17,18,19,20],feature_1:6,feature_2:6,feature_kwarg:7,feel:4,field:[2,3,6,8,16,17,18,21],file:6,file_1:1,file_2:1,file_3:1,fill:2,filter:[6,13],filter_funct:13,find:[1,4],first:[1,2,3,4,6,8,16,17,19],fit:14,five:4,flatten:14,flatten_input:14,flattend:12,flip:2,fluoresc:18,fluorescenct:16,fluorophor:16,focu:[1,4,16],follow:[4,16,17],format:18,found:8,fourier:[8,16],fraction:18,frame:6,framework:[7,10],free:[1,4],frequenc:0,frequent:18,from:[0,1,2,6,7,8,13,14,17,18,19,21],full:2,fulli:14,func:12,func_kwarg:13,function_nam:21,futher:14,futur:21,gain:7,gaussian:[0,2,6,13],gener:[2,5,6,8,9,10,14,17,18],generet:18,get:[0,1,2,6,9],get_on:8,get_one_random:6,get_properti:8,give:4,global:[1,6,19],global_kwarg:6,good:1,grab:[2,6],gradient:16,grayscal:6,grid:18,guarante:8,had:1,hand:1,handl:1,happen:2,harmon:[3,18],has:[1,2,8,17,21],has_updated_since_last_resolv:17,hasfunct:21,hash_kei:8,have:[1,4,6,8,17,19],height:[2,16],here:[1,4],high:0,hing:12,homogen:[13,18],how:[1,2,4,6,7,8,11,17,18],howev:[4,8,18],ident:2,ignore_last_dim:2,iid:15,illumin:[6,16],imag:[0,1,2,5,6,7,9,12,13,14,15,16,17,18,19],image_list:6,imagin:1,implement:[2,6,11,13,17,18],impli:18,imshow:6,includ:[3,6,7,13,16],incom:18,increas:18,index:[2,3,16,18],indic:[2,12],individu:[2,6,19],induc:18,inf:[7,13,16],influenc:13,inform:8,inherit:1,initi:[6,8,17],initil:19,inlin:6,inner:[6,18],input:[1,2,4,6,7,11,12,13,14,16,17,19,21],input_arrai:8,input_imag:6,input_shap:14,instal:9,instanc:[6,7,8,11,17],instance_norm:11,instanti:8,instead:[1,6,13,19],integ:[1,2,4,6,18],intens:[2,16,18],interact:[1,4,6],interest:4,intern:[1,2,17],interpol:[2,11,18],interpret:[2,18],interv:6,introduc:[0,1,4,6,15],involv:[2,8],ioerror:6,irst:6,is_label:6,is_valid:1,isn:1,issu:21,item:17,iter:[1,3,6,8,16,17,21],its:[4,8,17,18],itself:[8,17],just:8,kei:[6,8,17,21],kera:[11,14],kernel:[2,11,13],kernel_s:11,keyword:[1,6,17,19,21],kind:3,known:1,ksize:13,kullback:12,kwarg:[0,2,6,11,13,14,15,16,17,18,19,21],label:[1,7],label_funct:7,lambda:[1,4,7],larg:13,larger:[7,13],last:[2,13,17],later:6,layer:[5,6,9,14],layer_funct:14,lead:1,learn:[4,10,14],least:[6,10,16,18],leav:1,left:[2,4,18],leibler:12,length:[0,11,17,18],let:[1,4],level:1,light:[16,18],like:[1,2,6],limit:[16,18],line:3,linear:[2,13],linearli:18,list:[0,2,3,6,7,8,13,16,17,21],listen:6,load:[6,14],load_opt:6,load_siz:2,loader:1,loadimag:1,local:[1,2,6,13,14],log:12,logic:[6,17],look:[1,4,21],loss:[5,9,14],low:6,lower:6,made:21,mae:14,magic:4,magnif:16,mai:[1,2,4],main:2,mainli:4,make:[1,19,21],manag:17,mani:[4,7],manual:8,map_coordin:2,mask:6,match:2,math:[5,9],mathemat:13,matplotlib:6,max:[11,13],max_data_s:7,max_data_set:7,max_valu:1,maximum:[7,13,18],maxpool2d:11,mayb:1,mean:[1,2,12,13,15],median:13,medium:[3,16,18],merg:8,merge_method:6,merge_metod:6,merge_properties_from:8,merge_strategy_append:6,merge_strategy_overrid:6,meter:[16,18],method:[0,1,2,3,4,6,7,8,13,14,15,16,17,18,19,21],method_nam:21,metric:14,microscopi:10,mie:18,mie_coeffici:18,might:1,min:13,min_data_s:7,min_valu:1,minimum:[1,7,13],misspel:1,mix:13,mode:[2,13],model:[5,9,10,18],modelfeatur:14,modifi:0,modulo:2,more:[1,2,4,16,18,21],most:[6,8,14,16],move:2,movi:17,much:[1,18],multipl:[2,6,17,20],multipli:[0,4],multiply_two:4,must:13,n_medium:3,n_particl:3,name:[1,4,6,8,21],nd_kullback_leibler_diverg:12,ndarrai:[3,8,18],ndim:[6,7],ndimag:2,nearest:[2,11],necessari:[13,18],necessarili:18,need:[4,6,7,13,14],neighbor:2,neighborhood:13,neighbourhood:13,net:14,network:[1,2,7,10,14],neural:[2,10,14],newli:2,next:[1,4,17],nois:[1,5,6,9],non:[6,21],none:[1,2,6,7,8,11,13,14,16,17,18],nonetyp:1,nonkeyword:6,nor:1,normal:[11,13,18],note:[6,18,21],notebook:[4,6,9],noth:[1,6],notic:1,now:[1,4],num_dupl:6,number:[0,2,3,6,7,12,13,14,17,18,19],number_of_mask:6,number_of_output:14,number_of_upd:2,numpi:[2,3,4,6,8],obj:21,object:[6,8,14,16,17,18,21],obtain:17,occup:18,occupi:18,offset:0,offset_z:18,often:[2,4,17],old:7,oldest:7,on_epoch_end:7,on_fals:6,on_tru:6,onc:[2,17],one:[0,2,4,6,17,18,21],ones:1,onli:[2,4,6,17,18],open:[6,10],opencv2:6,oper:[4,6,8],oprat:13,optic:[5,6,9,10,18],optim:[8,14],option:[0,2,6,7,8,11,13,17,18],order:[2,3,8,17,18],ordinari:1,orient:18,origin:[2,17],origo:3,other:[1,2,4,6,7,8,11,13,17,18],otherwis:[6,8,19,21],out:[1,2],outer:6,output:[2,4,6,7,8,14,16,17],output_activ:14,output_conv_layers_dimens:14,output_convolution_block:14,output_kernel_s:14,output_region:[6,16],output_shap:6,over:[1,2,13],overrid:[2,6,20],overrul:6,overwrit:6,overwritten:1,overwrot:1,own:1,pad:[8,11,13,16,18],pad_width:2,pair:[6,17,21],parallel:3,paramet:[0,1,2,3,6,7,8,11,12,13,14,15,16,17,18,19,21],parent:[2,19],pars:6,particl:[1,3,18],pass:[1,2,3,4,6,7,17,18,19,21],path:[1,6,14],peak:15,per:[2,6,7,17],percent:2,percentag:12,perform:[2,6,11,13,16],phase:[0,18],physic:[10,16],pillow:6,pip:10,pipelin:1,pixel:[0,2,6,13,16,18],place:[2,6],plai:[4,6],plane:[1,16,18],platt:2,plot:6,point:[3,7,18],poisson:[6,12],polar:[0,18],polarization_angl:18,polynomi:0,pool:[11,14],pool_siz:11,pooling_block:14,pooling_funct:13,posit:[1,2,6,17,18],position_unit:18,positional_arg:21,possibl:[1,21],power:4,practic:2,precis:18,predict:[12,18],preserv:13,previou:17,previous_valu:17,primarli:1,prioriti:17,problem:4,proc:2,process:[1,6],program:4,prompt:10,propag:[3,16],properti:[2,5,6,8,9,18,19,20],property_dict:8,propertydict:6,provid:[1,2,6,10,16,17,18,21],pupil:[0,16],pyplot:6,python:[7,10],quadrat:2,quartic:2,quintic:2,radian:[2,18],radiu:[3,18],rais:[6,13],ran:1,randint:[1,4],random:[1,2,4,17],randomli:[2,4,6],rang:[2,13,18],ratio:15,reach:7,readabl:21,reader:[1,6],readi:4,real:16,receiv:[0,6,16],recognit:2,recommend:2,recurr:14,reflect:[2,13],refract:[3,16,18],refractive_index:18,refractive_index_medium:[16,18],region:[2,13,16],rel:[3,6,8,18],relu:11,remain:1,remov:[1,2,18],repeat_batch:7,replac:[4,6,7],repres:[2,16,17,18],request:4,requir:[6,10],reset:17,reshap:6,residu:11,resolut:16,resolv:[2,4,6,7,8,13,16,17,19,20],resolve_kwarg:6,respect:2,result:[0,2,6,13,16,17],retain:2,retriev:[8,17,21],return_sequ:14,reus:7,rho:0,riccati:3,rich:1,right:[2,4],rnn_layers_dimens:14,root:15,rotat:[2,18],row:4,rule:17,run:[4,10],safe:8,same:[1,2,4,6,7,8,11,17,18],sampl:[6,16,17],sampling_rul:17,save:[2,14],scale:[0,2],scatter:[1,5,6,9,16],scipi:2,script:6,second:[2,3,4,6],section:[1,4],see:[2,11,13,17,18],seem:1,self:[6,17,19],semi:13,sens:1,sent:[6,13],separ:6,sequenc:[5,9,17],sequence_length:[17,19],sequence_step:[17,19],sequene_length:19,sequenti:[6,17],seri:8,set:[0,1,2,6,7,8,16,17,18,19,21],sever:[2,4,18],shape:[3,6],share:1,shear:2,shell:18,shift:18,should:[1,6,8,17,18,19],show:[1,6],shuffl:7,shuffle_batch:7,sigma:[0,2,13,15],sigma_color:13,sigma_spac:13,signal:15,signmoid:12,simard:2,similar:1,simpl:[1,2,4,13],simul:[10,16],sinc:[1,2,8,17],singl:[4,6,11,17],size:[1,2,6,7,11,13,14,18],skimag:2,skip:[2,4],slice:18,slightli:1,smaller:13,smooth:2,snr:15,solut:1,solv:4,some:[1,2,4,6,11,17,18],someth:4,space:[13,16],spars:7,special:[4,12],specif:[1,2],specifi:4,speed:[7,8],spheric:[3,18],squar:12,stack:6,standard:[0,2,11,13,14,17],start:[4,7,9],state:[6,19],statement:7,steinkrau:2,step:[11,14,17],steps_per_pool:14,storag:2,store:[6,8],str:[2,6,8,11,14,18,21],stratifi:[3,18],strength:2,stride:11,strike:7,string:[2,11,21],structur:[6,13,16],subclass:8,subject:21,subpixel:18,subsect:[1,4],subtract:1,sum:0,support:21,surfac:1,swap:2,syntax:1,system:[10,16],take:[1,2,6,18],tanh:11,target:1,task:12,tensor:11,term:[3,18],termin:10,than:[1,2,7,13],thei:[1,2,4,6,19],them:[0,1,4,6,17],theori:18,theta:0,thi:[1,2,4,6,8,13,15,16,17,18,21],third:[3,16,18],those:[4,8],though:1,thought:1,three:2,through:[3,6,16],throughout:21,time:[1,2,6,7,19,20],timestep:19,to_grayscal:6,to_jshtml:6,togeth:[6,13],toggl:6,tool:[6,10,17,19],top:[2,14],topic:[9,20],track:12,train:[1,7,10],trainabl:11,training_path:1,tranform:6,transform:[2,6,8,12,13],transformation_funct:6,translat:2,translate_px:2,trate:19,treat:17,tree:1,tri:1,tupl:[2,3,6,12,13,14,17,18],tutori:[4,9],twice:1,two:[1,2,4,6,8,11,12,18],type:[1,2,11,17],unaberr:16,uncertainti:8,unchang:1,undefin:1,undo_add:1,uniform:18,uniqu:8,unit:[14,18],unless:18,until:[2,4,6,7],updat:[2,4,6,7,17,19,20],update_item:17,update_kwarg:7,update_properti:2,updated_per_reload:2,updates_per_reload:2,upsampl:[14,18],upsample_ax:18,upsampling2d:11,upsampling_block:14,upscal:16,use:[1,2,4,6,13,14,19],used:[1,2,4,6,7,8,15,17,18,19,21],useless:1,useless_argu:1,using:[2,3,4,6,13,14,16,17,21],util:[5,9,17],valid:[1,11],validation_path:1,valu:[0,1,2,4,6,8,13,15,16,17,18,19,21],value_ad:1,variabl:[1,17],varianc:15,vector:3,verbos:7,veri:[1,4],visual:[2,6],vmax:16,vmin:16,volum:[16,18],voxel:[16,18],voxel_s:6,wai:6,want:[1,4],wave:3,wavelength:16,weight:12,well:18,what:[1,6,8,19],when:[1,6,7,14,17],whenev:6,where:[2,6,14,16],whether:[2,6,8,11,14,17,18],which:[1,2,3,4,6,7,8,13,16,17,18],whole:6,width:[2,16],within:[1,6,13],without:[1,2],work:1,worker:7,would:[1,6,19],wrap:[2,6,12,13,16,17,21],wrapper:[14,18],you:[1,4],yourself:1,zero:[1,4,6,8,16,18],zoom:2},titles:["aberrations","Advanced Topics","augmentations","backend","Basics","Documentation","features","generators","image","Welcome to DeepTrack 2.0\u2019s documentation!","Getting started","layers","losses","math","models","noises","optics","properties","scatterers","sequences","Tutorials and notebooks","utils"],titleterms:{"class":[0,2,6,7,8,13,14,15,16,17,18,19],"function":[3,4,8,11,12,14,19,21],Using:4,aberr:0,add:13,advanc:1,affin:2,argument:[1,4],as_block:11,as_list:21,astigmat:0,augment:2,averag:13,averageblur:13,averagepool:13,backend:3,background:15,basic:4,bess:3,besselj:3,between:1,bilateralblur:13,blur:13,blurcv2:13,branch:6,brightfield:16,cgan:14,chain:4,classs:13,clip:13,coeff:[],combin:6,conditionalsetfeatur:6,conditionalsetproperti:6,continuousgener:7,convolut:14,convolutionalblock:11,crop:2,croptomultiplesof:2,dataset:6,dbess:3,dbesselj:3,deconvolutionalblock:11,deeptrack:9,deeptrack_loss_funct:12,defocu:0,denseblock:11,depend:1,divid:13,document:[5,9],done:4,dricbesh:3,dricbesi:3,dricbesj:3,dummi:1,dummyfeatur:6,duplic:6,elastictransform:2,ellips:18,ellipsoid:18,execut:4,featur:[1,4,6],flatten:12,flipdiagon:2,fliplr:2,flipud:2,fluoresc:16,fullyconnect:14,gaussian:15,gaussianapod:0,gaussianblur:13,gener:7,get:10,get_kwarg_nam:21,h1vp_cach:[],hasmethod:21,horizontalcoma:0,horizontaltilt:0,ident:11,illuminationgradi:16,imag:8,instal:10,isiter:21,kerasmodel:14,kwarg_has_default:21,label:6,lambda:6,layer:11,loadimag:6,loadmodel:14,loss:12,math:13,medianblur:13,merg:6,microscop:16,mie:3,mie_coeffici:3,mie_harmon:3,miescatter:18,miespher:18,miestratifiedspher:18,model:14,modul:[0,2,3,6,7,8,11,12,13,14,15,16,17,18,19,21],multipl:4,multipli:13,nd_binary_crossentropi:12,nd_kl_diverg:12,nd_mean_absolute_error:12,nd_mean_absolute_percentage_error:12,nd_mean_squared_error:12,nd_mean_squared_logarithmic_error:12,nd_poisson:12,nd_squared_hing:12,nois:15,normalizeminmax:13,notebook:20,obliqueastigmat:0,obliquetrefoil:0,offset:15,optic:16,overrid:1,pad:2,pad_image_to_fft:8,piston:0,pointparticl:18,poisson:15,polynomi:3,pool:13,poolingblock:11,power:13,preload:2,probabl:6,properti:[1,17],propertydict:17,residualblock:11,resolv:1,ricbesh:3,ricbesi:3,ricbesj:3,rnn:14,safe_cal:21,sampletomask:6,scatter:18,sequenc:19,sequenti:19,sequentialproperti:17,sigmoid:12,sphere:18,sphericalaberr:0,start:10,staticupsampleblock:11,stratified_mie_coeffici:3,structuralfeatur:6,subtract:13,time:4,topic:1,trefoil:0,tutori:20,unet:14,updat:1,util:21,verticalcoma:0,verticaltilt:0,weighted_crossentropi:12,welcom:9,zernik:0}}) \ No newline at end of file +Search.setIndex({docnames:["aberrations","advanced","augmentations","backend","basics","deeptrack","features","generators","image","index","installation","layers","losses","math","models","noises","optics","properties","scatterers","sequences","tutorials","utils"],envversion:{"sphinx.domains.c":2,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":3,"sphinx.domains.index":1,"sphinx.domains.javascript":2,"sphinx.domains.math":2,"sphinx.domains.python":2,"sphinx.domains.rst":2,"sphinx.domains.std":1,sphinx:56},filenames:["aberrations.rst","advanced.rst","augmentations.rst","backend.rst","basics.rst","deeptrack.rst","features.rst","generators.rst","image.rst","index.rst","installation.rst","layers.rst","losses.rst","math.rst","models.rst","noises.rst","optics.rst","properties.rst","scatterers.rst","sequences.rst","tutorials.rst","utils.rst"],objects:{"deeptrack.aberrations":{Aberration:[0,1,1,""],Astigmatism:[0,1,1,""],Defocus:[0,1,1,""],GaussianApodization:[0,1,1,""],HorizontalComa:[0,1,1,""],HorizontalTilt:[0,1,1,""],ObliqueAstigmatism:[0,1,1,""],ObliqueTrefoil:[0,1,1,""],Piston:[0,1,1,""],SphericalAberration:[0,1,1,""],Trefoil:[0,1,1,""],VerticalComa:[0,1,1,""],VerticalTilt:[0,1,1,""],Zernike:[0,1,1,""]},"deeptrack.augmentations":{Affine:[2,1,1,""],Augmentation:[2,1,1,""],Crop:[2,1,1,""],CropToMultiplesOf:[2,1,1,""],ElasticTransformation:[2,1,1,""],FlipDiagonal:[2,1,1,""],FlipLR:[2,1,1,""],FlipUD:[2,1,1,""],Pad:[2,1,1,""],PadToMultiplesOf:[2,1,1,""],PreLoad:[2,1,1,""]},"deeptrack.backend":{besselj:[3,2,1,""],bessely:[3,2,1,""],dbesselj:[3,2,1,""],dbessely:[3,2,1,""],dricbesh:[3,2,1,""],dricbesj:[3,2,1,""],dricbesy:[3,2,1,""],mie_coefficients:[3,2,1,""],mie_harmonics:[3,2,1,""],ricbesh:[3,2,1,""],ricbesj:[3,2,1,""],ricbesy:[3,2,1,""],stratified_mie_coefficients:[3,2,1,""]},"deeptrack.features":{AsType:[6,1,1,""],Bind:[6,1,1,""],BindResolve:[6,3,1,""],BindUpdate:[6,1,1,""],Branch:[6,1,1,""],Combine:[6,1,1,""],ConditionalSetFeature:[6,1,1,""],ConditionalSetProperty:[6,1,1,""],Dataset:[6,1,1,""],DummyFeature:[6,1,1,""],Duplicate:[6,1,1,""],Feature:[6,1,1,""],Label:[6,1,1,""],Lambda:[6,1,1,""],LoadImage:[6,1,1,""],Merge:[6,1,1,""],Probability:[6,1,1,""],SampleToMasks:[6,1,1,""],StructuralFeature:[6,1,1,""]},"deeptrack.features.Feature":{plot:[6,4,1,""],resolve:[6,4,1,""],sample:[6,4,1,""],update:[6,4,1,""]},"deeptrack.generators":{ContinuousGenerator:[7,1,1,""],Generator:[7,1,1,""]},"deeptrack.generators.ContinuousGenerator":{on_epoch_end:[7,4,1,""]},"deeptrack.generators.Generator":{generate:[7,4,1,""]},"deeptrack.image":{Image:[8,1,1,""],pad_image_to_fft:[8,2,1,""]},"deeptrack.image.Image":{append:[8,4,1,""],get_property:[8,4,1,""],merge_properties_from:[8,4,1,""]},"deeptrack.layers":{ConvolutionalBlock:[11,2,1,""],DeconvolutionalBlock:[11,2,1,""],DenseBlock:[11,2,1,""],Identity:[11,2,1,""],PoolingBlock:[11,2,1,""],ResidualBlock:[11,2,1,""],StaticUpsampleBlock:[11,2,1,""],as_block:[11,2,1,""]},"deeptrack.losses":{deeptrack_loss_function:[12,2,1,""],flatten:[12,2,1,""],nd_binary_crossentropy:[12,2,1,""],nd_kl_divergence:[12,2,1,""],nd_mean_absolute_error:[12,2,1,""],nd_mean_absolute_percentage_error:[12,2,1,""],nd_mean_squared_error:[12,2,1,""],nd_mean_squared_logarithmic_error:[12,2,1,""],nd_poisson:[12,2,1,""],nd_squared_hinge:[12,2,1,""],sigmoid:[12,2,1,""],weighted_crossentropy:[12,2,1,""]},"deeptrack.math":{Add:[13,1,1,""],Average:[13,1,1,""],AverageBlur:[13,1,1,""],AveragePooling:[13,1,1,""],BilateralBlur:[13,1,1,""],Blur:[13,1,1,""],BlurCV2:[13,1,1,""],Clip:[13,1,1,""],Divide:[13,1,1,""],GaussianBlur:[13,1,1,""],MedianBlur:[13,1,1,""],Multiply:[13,1,1,""],NormalizeMinMax:[13,1,1,""],Pool:[13,1,1,""],Power:[13,1,1,""],Subtract:[13,1,1,""]},"deeptrack.models":{Convolutional:[14,2,1,""],FullyConnected:[14,2,1,""],KerasModel:[14,1,1,""],LoadModel:[14,2,1,""],Model:[14,1,1,""],RNN:[14,2,1,""],UNet:[14,2,1,""],cgan:[14,1,1,""],convolutional:[14,2,1,""],rnn:[14,2,1,""],unet:[14,2,1,""]},"deeptrack.models.cgan":{call:[14,4,1,""],train_step:[14,4,1,""]},"deeptrack.noises":{Background:[15,1,1,""],Gaussian:[15,1,1,""],Noise:[15,1,1,""],Offset:[15,3,1,""],Poisson:[15,1,1,""]},"deeptrack.optics":{Brightfield:[16,1,1,""],Fluorescence:[16,1,1,""],IlluminationGradient:[16,1,1,""],Microscope:[16,1,1,""],Optics:[16,1,1,""]},"deeptrack.properties":{Property:[17,1,1,""],PropertyDict:[17,1,1,""],SequentialProperty:[17,1,1,""]},"deeptrack.properties.Property":{sample:[17,4,1,""],update:[17,4,1,""]},"deeptrack.properties.PropertyDict":{current_value_dict:[17,4,1,""],sample:[17,4,1,""],update:[17,4,1,""],update_item:[17,4,1,""]},"deeptrack.properties.SequentialProperty":{update:[17,4,1,""]},"deeptrack.scatterers":{Ellipse:[18,1,1,""],Ellipsoid:[18,1,1,""],MieScatterer:[18,1,1,""],MieSphere:[18,1,1,""],MieStratifiedSphere:[18,1,1,""],PointParticle:[18,1,1,""],Scatterer:[18,1,1,""],Sphere:[18,1,1,""]},"deeptrack.sequences":{Sequence:[19,1,1,""],Sequential:[19,2,1,""]},"deeptrack.sequences.Sequence":{update:[19,4,1,""]},"deeptrack.utils":{as_list:[21,2,1,""],get_kwarg_names:[21,2,1,""],hasmethod:[21,2,1,""],isiterable:[21,2,1,""],kwarg_has_default:[21,2,1,""],safe_call:[21,2,1,""]},deeptrack:{aberrations:[0,0,0,"-"],augmentations:[2,0,0,"-"],backend:[3,0,0,"-"],features:[6,0,0,"-"],generators:[7,0,0,"-"],image:[8,0,0,"-"],layers:[11,0,0,"-"],losses:[12,0,0,"-"],math:[13,0,0,"-"],models:[14,0,0,"-"],noises:[15,0,0,"-"],optics:[16,0,0,"-"],properties:[17,0,0,"-"],scatterers:[18,0,0,"-"],sequences:[19,0,0,"-"],utils:[21,0,0,"-"]}},objnames:{"0":["py","module","Python module"],"1":["py","class","Python class"],"2":["py","function","Python function"],"3":["py","attribute","Python attribute"],"4":["py","method","Python method"]},objtypes:{"0":"py:module","1":"py:class","2":"py:function","3":"py:attribute","4":"py:method"},terms:{"0001":12,"100":[1,2,15],"101":1,"128":[14,16],"2003":2,"abstract":[0,2,6,15,16,18],"boolean":14,"break":1,"case":[1,2,6,14,21],"class":12,"default":[2,6,8,13,16,18,21],"final":[1,15],"float":[0,3,6,12,13,14,15,16,18],"function":[0,1,2,6,7,13,16,17,18,20],"import":4,"int":[0,2,3,6,7,8,11,13,14,16,17,18,19],"long":[1,13],"new":[2,4,6,7,12,14,17,18],"return":[1,2,3,4,6,7,8,11,12,14,16,17,18,19,21],"true":[1,2,6,7,8,11,14,18,21],"try":13,"while":[1,2,6,13],For:[1,2,4,6,17,18,19],Has:8,NOT:[13,14],One:1,That:[4,6],The:[0,1,2,3,4,6,7,8,12,13,14,15,16,17,18,19,21],These:[1,2,8,17],Use:18,Used:18,Using:20,Will:17,__distributed__:6,__list_merge_strategy__:6,__next__:21,__property_memorability__:6,__property_verbosity__:6,_process_and_get:18,_process_properti:18,aberr:[1,5,9],about:[4,8,18],abov:17,absolut:12,accept:[1,2,6,7,11,17,21],access:[4,6,7],accord:0,account:2,accur:16,accuraci:14,achiev:[1,2,4],act:2,activ:[11,14],activity_regular:14,adam:14,add:[0,1,4,6,11,12,14,15,16],add_and_multipli:4,add_batch_dimension_on_resolv:14,add_loss:14,add_metr:14,add_on:[1,4],add_one_five_tim:4,add_one_or_two:1,add_random_integ:1,add_zero_or_on:4,added:[4,6,14],adding:[0,6,8],addit:[6,8,13],advanc:[9,20],advantag:1,after:[1,14,17],after_axis_3:2,again:1,aim:7,alia:[6,15],all:[1,2,4,6,7,8,13,14,16,17,18,19,21],allow:[1,2,7],along:[2,8,13,18],alpha:2,alreadi:19,also:[1,2,14],alwai:[1,4],amount:2,amplitud:[0,16],analysi:2,analyz:[10,14],angl:[3,18],ani:[1,2,4,6,8,17,18,21],anim:6,anoth:[1,6,8,13],aperatur:[16,18],aperature_angl:[],api:14,apod:0,append:[6,8],appli:[2,6,13,17],approach:1,approxim:18,area:13,arg:[0,2,6,13,14,15,17],argument:[0,2,6,11,13,14,17,19,20,21],aris:21,around:2,arrai:[4,6],array_lik:[6,7,8,16,18],as_list:6,assemble_loss:[],assemble_loss_weight:[],assemble_optim:[],assum:[2,4,7,18],asynchron:7,attribut:[6,8,14,17,19,21],augment:[5,9,13],auto:18,automat:[8,18],averr:1,avoid:[6,16],axes:[8,18],axi:[2,13,18],backend:[5,6,9,18],background:6,backpropag:14,balanc:7,base:[0,2,6,7,14,15,16,18],base_conv_layers_dimens:14,base_convolution_block:14,basic:[9,18,20],batch:[2,7],batch_funct:7,batch_siz:7,been:[1,2,8,17],befor:[0,2,7,11,12],before_axis_3:2,behav:1,behaviour:[1,2],behind:17,benefit:1,beprecis:18,bessel:3,best:2,between:[2,4,6,7,13,14,16,20],bilater:13,bilinear:11,binari:12,bleed:2,block:[4,11],bool:[2,6,7,8,11,14,17,18,21],both:[1,6],brightfield:18,build:14,calcul:[0,3,14,15,18],call:[1,2,4,6,7,8,12,14,17,19,21],callabl:[2,6,7,14,17,18,21],callback:14,callbacklist:14,camera:[16,18],can:[1,2,4,6,11,14,16,17,18],cannot:2,captur:21,cell:18,center:[0,2],certain:6,chain:20,chang:[1,2,21],channel:2,characterist:18,check:[1,4,17,21],child:6,chosen:2,circular:18,clear:17,clip:16,close:13,code:[6,21],coeffici:[0,3,18],coher:16,collect:18,collection_angl:18,color:[2,13],combin:[17,19],come:1,command:10,common:[1,2,6,16],commonli:8,comparison:18,compat:14,compil:14,compile_from_fil:14,complex:[3,16],comprehens:10,comput:[4,13,14],compute_mask:14,concentr:18,concept:[1,4],condit:6,condition:6,conditiona:6,conditionalsetfeatur:1,conditionalsetproperti:1,confer:2,configur:14,conflict:1,confus:1,connect:14,constant:[2,6,15,16,17],constructor:[6,14],consum:7,contain:[3,6,7,8,14,16],contin:7,continu:[7,17],control:[1,2,6],conv2d:11,conv2dtranspos:11,conv_layers_dimens:14,convert:[6,11,18,19,21],convolut:[2,11,13],convolution_block:14,coordin:[0,13],copi:6,core:4,corner:[2,3],correct:[6,16],correctli:[6,7],correspond:[0,7,18],cosin:3,could:[1,6],cours:1,crash:1,creat:[1,2,4,6,7,10,14,16,17],crop:18,crop_empti:[],crop_mod:2,crop_zero:18,crossentropi:12,cubic:2,current:[4,6,7,8,17,18],current_valu:[1,4,8,17],current_value_dict:17,custom:[4,6,14],custom_object:14,customiz:10,cval:[2,13],cycl:6,cyclic:1,data:[1,6,7,10,14],dataset:7,deal:2,decoder_convolution_block:14,deconstruct:6,deconvolut:[11,14],decreas:0,deep:[6,10,14],deeptrack:[0,1,2,3,4,6,7,8,10,11,12,13,14,15,16,17,18,19,21],def:1,defin:[0,1,2,3,6,8,16,17,18,21],definit:1,denot:2,dens:[11,14],dense_block:14,dense_layers_dimens:14,dense_top:14,depend:[2,4,6,17,19,20],deprec:[2,14],deriv:3,describ:[0,14,16],desir:2,detail:[2,14],determin:[1,4,8,14,15,18],deviat:[0,2,13],devic:[16,18],diagon:2,diamet:13,dict:[0,2,6,7,8,13,14,15,17],dictionari:[6,8,17,21],didn:1,differ:[1,4,6,17],differenti:1,digit:10,dimens:[2,6,7,13],dimension:18,direct:[1,2,3,16,18],directli:[1,4],disadvantag:1,discret:[16,17],discrimin:[],discriminator_loss:[],discriminator_metr:[],discriminator_optim:[],disk:[6,14,18],displac:2,displai:14,distanc:[16,18],distort:2,distribut:[0,6,14,15],distribute_strategi:14,diverg:12,do_noth:1,doc:11,document:2,doe:[4,6,13,18,21],doesn:6,done:20,down:[1,2,14],downsampl:[13,14],draw:[2,21],dropout:14,dtype:[6,14],dummi:20,duplic:8,dure:[7,14],dynam:14,each:[0,1,2,6,7,8,13,14,16,17,18],eachoth:2,eager:14,eagerli:14,eagl:1,earlier:6,easi:1,easiet:4,edg:[0,13,16],effect:16,either:[4,6,11,14],element:[6,17,18],ellipt:18,els:[1,8,21],emit:16,empti:18,encoder_convolution_block:14,encount:1,encourag:4,end:[6,7,8],enough:13,ensur:[0,7,21],ensure_contains_class:7,enter:16,entir:[1,6,16],epoch:7,eps:12,equal:[0,13],error:12,etc:13,evalu:[3,8,18],even:1,everi:[1,2,6,7],exact:1,exactli:1,exampl:[1,4,6,13,14,17,18,19],excit:4,excpet:1,execut:20,exist:[1,6,19],expand:7,expect:[7,18],experiment:10,explain:[1,4],explan:2,explicitli:[1,4],expos:1,extend:[17,18],extens:6,extern:14,extract:[6,8],eyed:1,factor:[2,18],fail:1,fals:[1,6,11,14,21],farther:13,fast:8,featur:[0,2,5,7,8,9,13,14,15,16,17,18,19,20],feature_1:6,feature_2:6,feature_kwarg:7,feel:4,field:[2,3,6,8,16,17,18,21],file:6,file_1:1,file_2:1,file_3:1,fill:2,filter:[6,13],filter_funct:13,find:[1,4],first:[1,2,3,4,6,8,16,17,19],fit:[],five:4,flatten:14,flatten_input:14,flattend:12,flip:2,float64:6,fluoresc:18,fluorescenct:16,fluorophor:16,focu:[1,4,16],follow:[4,16,17],format:[14,18],forward:14,found:8,fourier:[8,16],fraction:18,frame:6,framework:[7,10],free:[1,4],frequenc:0,frequent:18,from:[0,1,2,6,7,8,13,14,17,18,19,21],full:2,fulli:14,func:12,func_kwarg:13,function_nam:21,futher:14,futur:21,gain:7,gaussian:[0,2,6,13],gener:[2,5,6,8,9,10,17,18],generet:18,get:[0,1,2,6,9],get_on:8,get_one_random:6,get_properti:8,give:4,global:[1,6,19],global_kwarg:6,good:1,grab:[2,6],gradient:16,graph:14,grayscal:6,grid:18,guarante:8,had:1,hand:1,handl:1,happen:2,harmon:[3,18],has:[1,2,8,17,21],has_updated_since_last_resolv:17,hasfunct:21,hash_kei:8,have:[1,4,6,8,17,19],height:[2,16],here:[1,4],high:0,hing:12,homogen:[13,18],how:[1,2,4,6,7,8,11,14,17,18],howev:[4,8,18],ident:2,ignore_last_dim:2,iid:15,illumin:[6,16],imag:[0,1,2,5,6,7,9,12,13,14,15,16,17,18,19],image_list:6,imagin:1,implement:[2,6,11,13,17,18],impli:18,imshow:6,inbound_nod:14,includ:[3,6,7,13,14,16],incom:18,increas:18,index:[2,3,16,18],indic:[2,12,14],individu:[2,6,19],induc:18,inf:[7,13,16],infer:14,influenc:13,inform:8,inherit:1,initi:[6,8,17],initil:19,inlin:6,inner:[6,18],input:[1,2,4,6,7,11,12,13,14,16,17,19,21],input_arrai:8,input_imag:6,input_lay:14,input_mask:14,input_shap:14,input_spec:14,inputspec:14,instal:9,instanc:[6,7,8,11,14,17],instance_norm:11,instanti:8,instead:[1,6,13,19],int16:6,int32:6,int8:6,integ:[1,2,4,6,18],intens:[2,16,18],interact:[1,4,6],interest:4,intern:[1,2,17],interpol:[2,11,18],interpret:[2,18],interv:6,introduc:[0,1,4,6,15],involv:[2,8],ioerror:6,irst:6,is_label:6,is_valid:1,isn:1,issu:21,item:17,iter:[1,3,6,8,16,17,21],its:[4,8,14,17,18],itself:[8,17],just:[8,14],kei:[6,8,17,21],kera:[11,14],kernel:[2,11,13],kernel_s:11,keyword:[1,6,17,19,21],kind:3,known:1,ksize:13,kullback:12,kwarg:[0,2,6,11,13,14,15,16,17,18,19,21],label:[1,7,14],label_funct:7,lambda:[1,4,7],larg:13,larger:[7,13],last:[2,13,17],later:6,layer:[5,6,9,14],layer_funct:14,lead:1,learn:[4,10,14],least:[6,10,16,18],leav:1,left:[2,4,14,18],leibler:12,length:[0,11,17,18],let:[1,4],level:1,light:[16,18],like:[1,2,6],limit:[16,18],line:3,linear:[2,13],linearli:18,list:[0,2,3,6,7,8,13,14,16,17,21],listen:6,load:[6,14],load_opt:6,load_siz:2,loader:1,loadimag:1,local:[1,2,6,13,14],log:12,logic:[6,14,17],look:[1,4,21],loss:[5,9,14],low:6,lower:6,made:21,mae:14,magic:4,magnif:16,mai:[1,2,4],main:2,mainli:4,make:[1,19,21],make_train_funct:14,manag:17,mani:[4,7],manual:8,map_coordin:2,mask:[6,14],match:2,math:[5,9],mathemat:13,mathemet:14,matplotlib:6,max:[11,13],max_data_s:7,max_data_set:7,max_valu:1,maximum:[7,13,18],maxpool2d:11,mayb:1,mean:[1,2,12,13,15],median:13,medium:[3,16,18],merg:8,merge_method:6,merge_metod:6,merge_properties_from:8,merge_strategy_append:6,merge_strategy_overrid:6,meter:[16,18],method:[0,1,2,3,4,6,7,8,13,14,15,16,17,18,19,21],method_nam:21,metric:14,metrics_nam:14,microscopi:10,mie:18,mie_coeffici:18,might:1,min:13,min_data_s:7,min_valu:1,minimum:[1,7,13],misspel:1,mix:13,mode:[2,13,14],model:[5,9,10,18],modelfeatur:14,modifi:0,modulo:2,more:[1,2,4,14,16,18,21],most:[6,8,14,16],move:2,movi:17,much:[1,18],multipl:[2,6,17,20],multipli:[0,4],multiply_two:4,must:13,n_medium:3,n_particl:3,name:[1,4,6,8,14,21],name_scop:14,nd_kullback_leibler_diverg:12,ndarrai:[3,8,18],ndim:[6,7],ndimag:2,nearest:[2,11],necessari:[13,18],necessarili:18,need:[4,6,7,13,14],neighbor:2,neighborhood:13,neighbourhood:13,nest:14,net:14,network:[1,2,7,10,14],neural:[2,10,14],newli:2,next:[1,4,17],nois:[1,5,6,9],non:[6,14,21],non_trainable_vari:14,non_trainable_weight:14,none:[1,2,6,7,8,11,13,14,16,17,18],nonetyp:1,nonkeyword:6,nor:1,normal:[11,13,18],note:[6,18,21],notebook:[4,6,9],noth:[1,6],notic:1,now:[1,4],num_dupl:6,number:[0,2,3,6,7,12,13,14,17,18,19],number_of_mask:6,number_of_output:14,number_of_upd:2,numpi:[2,3,4,6,8],obj:21,object:[6,8,14,16,17,18,21],obtain:17,occup:18,occupi:18,offset:0,offset_z:18,often:[2,4,17],old:7,oldest:7,on_epoch_end:7,on_fals:6,on_train_batch_end:14,on_tru:6,onc:[2,17],one:[0,2,4,6,14,17,18,21],ones:1,onli:[2,4,6,14,17,18],open:[6,10],opencv2:6,oper:[4,6,8],oprat:13,ops:14,optic:[5,6,9,10,18],optim:[8,14],option:[0,2,6,7,8,11,13,14,17,18],order:[2,3,8,17,18],ordinari:1,orient:18,origin:[2,17],origo:3,other:[1,2,4,6,7,8,11,13,17,18],otherwis:[6,8,19,21],out:[1,2],outbound_nod:14,outer:6,output:[2,4,6,7,8,14,16,17],output_activ:14,output_conv_layers_dimens:14,output_convolution_block:14,output_kernel_s:14,output_mask:14,output_region:[6,16],output_shap:[6,14],over:[1,2,13],overrid:[2,6,20],overridden:14,overrul:6,overwrit:6,overwritten:1,overwrot:1,own:[1,14],pad:[8,11,13,16,18],pad_width:2,pair:[6,17,21],parallel:3,paramet:[0,1,2,3,6,7,8,11,12,13,14,15,16,17,18,19,21],parent:[2,19],pars:6,particl:[1,3,18],pass:[1,2,3,4,6,7,14,17,18,19,21],path:[1,6,14],peak:15,per:[2,6,7,17],percent:2,percentag:12,perform:[2,6,11,13,16],phase:[0,18],physic:[10,16],pillow:6,pip:10,pipelin:1,pixel:[0,2,6,13,16,18],place:[2,6],plai:[4,6],plane:[1,16,18],platt:2,plot:6,point:[3,7,18],poisson:[6,12],polar:[0,18],polarization_angl:18,polynomi:0,pool:[11,14],pool_siz:11,pooling_block:14,pooling_funct:13,posit:[1,2,6,17,18],position_unit:18,positional_arg:21,possibl:[1,21],power:4,practic:2,precis:[],predict:[12,18],preserv:13,previou:17,previous_valu:17,primarli:1,prioriti:17,problem:4,proc:2,process:[1,6],program:4,prompt:10,propag:[3,16],properti:[2,5,6,8,9,18,19,20],property_dict:8,propertydict:6,provid:[1,2,6,10,14,16,17,18,21],pupil:[0,16],pyplot:6,python:[7,10],quadrat:2,quartic:2,quintic:2,radian:[2,18],radiu:[3,18],rais:[6,13],ran:1,randint:[1,4],random:[1,2,4,17],randomli:[2,4,6],rang:[2,13,18],ratio:15,reach:7,readabl:21,reader:[1,6],readi:4,real:16,reappli:14,receiv:[0,6,16],recognit:2,recommend:2,recurr:14,reflect:[2,13],refract:[3,16,18],refractive_index:18,refractive_index_medium:[16,18],region:[2,13,16],regular:14,rel:[3,6,8,18],relu:11,remain:1,remov:[1,2,18],repeat_batch:7,replac:[4,6,7],repres:[2,16,17,18],request:4,requir:[6,10],reset:17,reset_st:14,reshap:6,residu:11,resolut:16,resolv:[2,4,6,7,8,13,16,17,19,20],resolve_kwarg:6,respect:2,result:[0,2,6,13,16,17],retain:2,retriev:[8,14,17,21],return_sequ:14,reus:7,rho:0,riccati:3,rich:1,right:[2,4],rnn_layers_dimens:14,root:15,rotat:[2,18],row:4,rule:17,run:[4,10,14],run_eagerli:14,safe:8,same:[1,2,4,6,7,8,11,17,18],sampl:[6,16,17],sampling_rul:17,save:[2,14],scalar:14,scale:[0,2],scatter:[1,5,6,9,16],scipi:2,script:6,second:[2,3,4,6],section:[1,4],see:[2,11,13,17,18],seem:1,self:[6,17,19],semi:13,send:6,sens:1,sent:[6,13],separ:6,sequenc:[5,9,14,17],sequence_length:[17,19],sequence_step:[17,19],sequene_length:19,sequenti:[6,17],seri:8,set:[0,1,2,6,7,8,14,16,17,18,19,21],settabl:14,sever:[2,4,18],shape:[3,6,14],share:1,shear:2,shell:18,shift:18,should:[1,6,8,14,17,18,19],show:[1,6],shuffl:7,shuffle_batch:7,sigma:[0,2,13,15],sigma_color:13,sigma_spac:13,signal:15,signmoid:12,simard:2,similar:1,simpl:[1,2,4,13],simul:[10,16],sinc:[1,2,8,17],singl:[4,6,11,14,17],size:[1,2,6,7,11,13,14,18],skimag:2,skip:[2,4],slice:18,slightli:1,smaller:13,smooth:2,snr:15,solut:1,solv:4,some:[1,2,4,6,11,17,18],someth:4,space:[13,16],spars:7,special:[4,12],specif:[1,2],specifi:4,speed:[7,8],spheric:[3,18],squar:12,stack:6,standard:[0,2,11,13,14,17],start:[4,7,9],state:[6,14,19],state_upd:14,statement:7,steinkrau:2,step:[11,14,17],steps_per_pool:14,storag:2,store:[6,8],str:[2,6,8,11,14,18,21],strategi:14,stratifi:[3,18],strength:2,stride:11,strike:7,string:[2,6,11,14,21],structur:[6,13,14,16],sub:14,subclass:8,subject:21,submodul:14,subpixel:18,subsect:[1,4],subtract:1,sum:0,support:[14,21],supports_mask:14,surfac:1,swap:2,syntax:1,system:[10,16],take:[1,2,6,18],tanh:11,target:1,task:12,tensor:[11,14],term:[3,18],termin:10,than:[1,2,7,13,14],thei:[1,2,4,6,19],them:[0,1,4,6,17],theori:18,theta:0,thi:[1,2,4,6,8,13,14,15,16,17,18,21],third:[3,16,18],those:[4,8],though:1,thought:1,three:2,through:[3,6,16],throughout:21,time:[1,2,6,7,19,20],timestep:19,to_grayscal:6,to_jshtml:6,togeth:[6,13],toggl:6,tool:[6,10,17,19],top:[2,14],topic:[9,20],track:[12,14],train:[1,7,10,14],train_step:14,trainabl:[11,14],trainable_vari:14,trainable_weight:14,training_path:1,tranform:6,transform:[2,6,8,12,13],transformation_funct:6,translat:2,translate_px:2,trate:19,treat:17,tree:1,tri:1,tupl:[2,3,6,12,13,14,17,18],tutori:[4,9],twice:1,two:[1,2,4,6,8,11,12,18],type:[1,2,6,11,17],typic:14,uint16:6,uint8:6,unaberr:16,uncertainti:8,unchang:1,undefin:1,under:14,undo_add:1,uniform:18,uniqu:8,unit:[14,18],unless:18,until:[2,4,6,7],updat:[2,4,6,7,14,17,19,20],update_item:17,update_kwarg:7,update_properti:2,updated_per_reload:2,updates_per_reload:2,upsampl:[14,18],upsample_ax:18,upsampling2d:11,upsampling_block:14,upscal:16,use:[1,2,4,6,13,14,19],used:[1,2,4,6,7,8,14,15,17,18,19,21],useless:1,useless_argu:1,using:[2,3,4,6,13,14,16,17,21],util:[5,9,17],valid:[1,11],validation_path:1,valu:[0,1,2,4,6,8,13,14,15,16,17,18,19,21],value_ad:1,variabl:[1,14,17],varianc:15,vector:3,verbos:7,veri:[1,4],visual:[2,6],vmax:16,vmin:16,volum:[16,18],voxel:[16,18],voxel_s:6,wai:6,want:[1,4],wave:3,wavelength:16,weight:[12,14],well:18,what:[1,6,8,19],when:[1,6,7,14,17],whenev:6,where:[2,6,14,16],whether:[2,6,8,11,14,17,18],which:[1,2,3,4,6,7,8,13,14,16,17,18],whole:6,width:[2,16],with_conv:11,within:[1,6,13],without:[1,2],work:1,worker:7,would:[1,6,19],wrap:[2,6,12,13,16,17,21],wrapper:[14,18],you:[1,4],yourself:1,zero:[1,4,6,8,16,18],zoom:2},titles:["aberrations","Advanced Topics","augmentations","backend","Basics","Documentation","features","generators","image","Welcome to DeepTrack 2.0\u2019s documentation!","Getting started","layers","losses","math","models","noises","optics","properties","scatterers","sequences","Tutorials and notebooks","utils"],titleterms:{"class":[0,2,6,7,8,13,14,15,16,17,18,19],"function":[3,4,8,11,12,14,19,21],Using:4,aberr:0,add:13,advanc:1,affin:2,argument:[1,4],as_block:11,as_list:21,astigmat:0,astyp:6,augment:2,averag:13,averageblur:13,averagepool:13,backend:3,background:15,basic:4,bess:3,besselj:3,between:1,bilateralblur:13,bind:6,bindresolv:6,bindupd:6,blur:13,blurcv2:13,branch:6,brightfield:16,cgan:14,chain:4,classs:13,clip:13,coeff:[],combin:6,conditionalsetfeatur:6,conditionalsetproperti:6,continuousgener:7,convolut:14,convolutionalblock:11,crop:2,croptomultiplesof:2,dataset:6,dbess:3,dbesselj:3,deconvolutionalblock:11,deeptrack:9,deeptrack_loss_funct:12,defocu:0,denseblock:11,depend:1,divid:13,document:[5,9],done:4,dricbesh:3,dricbesi:3,dricbesj:3,dummi:1,dummyfeatur:6,duplic:6,elastictransform:2,ellips:18,ellipsoid:18,execut:4,featur:[1,4,6],flatten:12,flipdiagon:2,fliplr:2,flipud:2,fluoresc:16,fullyconnect:14,gaussian:15,gaussianapod:0,gaussianblur:13,gener:7,get:10,get_kwarg_nam:21,h1vp_cach:[],hasmethod:21,horizontalcoma:0,horizontaltilt:0,ident:11,illuminationgradi:16,imag:8,instal:10,isiter:21,kerasmodel:14,kwarg_has_default:21,label:6,lambda:6,layer:11,loadimag:6,loadmodel:14,loss:12,math:13,medianblur:13,merg:6,microscop:16,mie:3,mie_coeffici:3,mie_harmon:3,miescatter:18,miespher:18,miestratifiedspher:18,model:14,modul:[0,2,3,6,7,8,11,12,13,14,15,16,17,18,19,21],multipl:4,multipli:13,nd_binary_crossentropi:12,nd_kl_diverg:12,nd_mean_absolute_error:12,nd_mean_absolute_percentage_error:12,nd_mean_squared_error:12,nd_mean_squared_logarithmic_error:12,nd_poisson:12,nd_squared_hing:12,nois:15,normalizeminmax:13,notebook:20,obliqueastigmat:0,obliquetrefoil:0,offset:15,optic:16,overrid:1,pad:2,pad_image_to_fft:8,padtomultiplesof:2,piston:0,pointparticl:18,poisson:15,polynomi:3,pool:13,poolingblock:11,power:13,preload:2,probabl:6,properti:[1,17],propertydict:17,residualblock:11,resolv:1,ricbesh:3,ricbesi:3,ricbesj:3,rnn:14,safe_cal:21,sampletomask:6,scatter:18,sequenc:19,sequenti:19,sequentialproperti:17,sigmoid:12,sphere:18,sphericalaberr:0,start:10,staticupsampleblock:11,stratified_mie_coeffici:3,structuralfeatur:6,subtract:13,time:4,topic:1,trefoil:0,tutori:20,unet:14,updat:1,util:21,verticalcoma:0,verticaltilt:0,weighted_crossentropi:12,welcom:9,zernik:0}}) \ No newline at end of file diff --git a/docs/sequences.html b/docs/sequences.html index 3645d9e56..6c5826984 100644 --- a/docs/sequences.html +++ b/docs/sequences.html @@ -361,10 +361,12 @@

        Sequential deeptrack.sequences.Sequential(feature: deeptrack.features.Feature, **kwargs)

        Converts a feature to be resolved as a sequence.

        -

        Should be called on individual features, not combinations of features. All keyword -arguments will be trated as sequential properties and will be passed to the parent feature.

        -

        If a property from the keyword argument already exists on the feature, the existing property -will be used to initilize the passed property (that is, it will be used for the first timestep).

        +

        Should be called on individual features, not combinations of features. All +keyword arguments will be trated as sequential properties and will be +passed to the parent feature.

        +

        If a property from the keyword argument already exists on the feature, the +existing property will be used to initilize the passed property (that is, +it will be used for the first timestep).

        Parameters
        diff --git a/docs/utils.html b/docs/utils.html index 4b6501f09..d85adcfba 100644 --- a/docs/utils.html +++ b/docs/utils.html @@ -280,7 +280,7 @@

        Functions deeptrack.utils.safe_call(function, positional_args=[], **kwargs)

        Calls a function, using keyword arguments from a dictionary of arguments.

        -

        If the function does not accept one of the argument provided, it will not be passed. Does not support -non-keyword arguments.

        +

        If the function does not accept one of the argument provided, it will not +be passed. Does not support non-keyword arguments.

        Parameters
        From ef10571d959ae03840c92e7fca659959dae1d0ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Pineda?= <36273229+JesusPinedaC@users.noreply.github.com> Date: Thu, 14 Jan 2021 20:00:18 +0100 Subject: [PATCH 20/78] Update README.md --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 3c31b07c4..afb620af7 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,10 @@ DeepTrack 2.0 multiple particle tracking tutorial video: https://youtu.be/wFV2Vq alt="Tutorial" width="384" height="216" border="10" /> +DeepTrack 2.0 Synthetic data generation tutorial video: https://youtu.be/8g44Yks7cis + ### In-depth dives From 3cce2fd81cb196b5c134250c4695161914e6f3f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Pineda?= <36273229+JesusPinedaC@users.noreply.github.com> Date: Thu, 14 Jan 2021 23:10:30 +0100 Subject: [PATCH 21/78] Update README.md --- README.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index afb620af7..2f4b13d0b 100644 --- a/README.md +++ b/README.md @@ -57,19 +57,16 @@ DeepTrack 2.0 single particle tracking tutorial video: https://youtu.be/6Cntik6A " target="_blank">Tutorial - DeepTrack 2.0 multiple particle tracking tutorial video: https://youtu.be/wFV2VqzpeZs Tutorial - -DeepTrack 2.0 Synthetic data generation tutorial video: https://youtu.be/8g44Yks7cis +DeepTrack 2.0 GAN image generation tutorial video: https://youtu.be/8g44Yks7cis Tutorial - ### In-depth dives The examples folder contains notebooks which explains the different modules in more detail. These can be read in any order, but we provide a recommended order where more fundamental topics are introduced early. From 5e22d52d0ac0a5e3105f3e355caa346a3b7574ce Mon Sep 17 00:00:00 2001 From: Benjamin Midtvedt Date: Wed, 10 Feb 2021 13:22:27 +0100 Subject: [PATCH 22/78] Test using relative imports to ensure correct installation is used --- deeptrack/test/__init__.py | 1 + deeptrack/test/test.py | 8 ++++ {test => deeptrack/test}/test_aberrations.py | 10 ++--- .../test}/test_augmentations.py | 38 +++++++++---------- {test => deeptrack/test}/test_features.py | 6 +-- {test => deeptrack/test}/test_generators.py | 9 ++--- {test => deeptrack/test}/test_image.py | 6 +-- {test => deeptrack/test}/test_layers.py | 6 +-- {test => deeptrack/test}/test_losses.py | 8 ++-- {test => deeptrack/test}/test_math.py | 4 +- {test => deeptrack/test}/test_models.py | 4 +- {test => deeptrack/test}/test_noises.py | 6 +-- {test => deeptrack/test}/test_optics.py | 8 ++-- {test => deeptrack/test}/test_properties.py | 15 ++++---- {test => deeptrack/test}/test_scatterers.py | 6 +-- {test => deeptrack/test}/test_sequences.py | 10 ++--- {test => deeptrack/test}/test_utils.py | 4 +- test/test.py | 8 ---- 18 files changed, 78 insertions(+), 79 deletions(-) create mode 100644 deeptrack/test/__init__.py create mode 100644 deeptrack/test/test.py rename {test => deeptrack/test}/test_aberrations.py (97%) mode change 100755 => 100644 rename {test => deeptrack/test}/test_augmentations.py (82%) mode change 100755 => 100644 rename {test => deeptrack/test}/test_features.py (98%) mode change 100755 => 100644 rename {test => deeptrack/test}/test_generators.py (86%) mode change 100755 => 100644 rename {test => deeptrack/test}/test_image.py (96%) mode change 100755 => 100644 rename {test => deeptrack/test}/test_layers.py (93%) rename {test => deeptrack/test}/test_losses.py (96%) mode change 100755 => 100644 rename {test => deeptrack/test}/test_math.py (89%) mode change 100755 => 100644 rename {test => deeptrack/test}/test_models.py (97%) mode change 100755 => 100644 rename {test => deeptrack/test}/test_noises.py (92%) mode change 100755 => 100644 rename {test => deeptrack/test}/test_optics.py (94%) mode change 100755 => 100644 rename {test => deeptrack/test}/test_properties.py (89%) mode change 100755 => 100644 rename {test => deeptrack/test}/test_scatterers.py (96%) mode change 100755 => 100644 rename {test => deeptrack/test}/test_sequences.py (86%) mode change 100755 => 100644 rename {test => deeptrack/test}/test_utils.py (96%) mode change 100755 => 100644 delete mode 100755 test/test.py diff --git a/deeptrack/test/__init__.py b/deeptrack/test/__init__.py new file mode 100644 index 000000000..de101117c --- /dev/null +++ b/deeptrack/test/__init__.py @@ -0,0 +1 @@ +import sys diff --git a/deeptrack/test/test.py b/deeptrack/test/test.py new file mode 100644 index 000000000..f6b621e3d --- /dev/null +++ b/deeptrack/test/test.py @@ -0,0 +1,8 @@ +# import unittest + +# loader = unittest.TestLoader() +# start_dir = "./deeptrack/test" +# suite = loader.discover(start_dir) + +# runner = unittest.TextTestRunner() +# runner.run(suite) diff --git a/test/test_aberrations.py b/deeptrack/test/test_aberrations.py old mode 100755 new mode 100644 similarity index 97% rename from test/test_aberrations.py rename to deeptrack/test/test_aberrations.py index eaee22426..5ac1b6842 --- a/test/test_aberrations.py +++ b/deeptrack/test/test_aberrations.py @@ -1,14 +1,14 @@ import sys -sys.path.append(".") # Adds the module to path +# sys.path.append(".") # Adds the module to path import unittest -import deeptrack.aberrations as aberrations +from .. import aberrations -from deeptrack.scatterers import PointParticle -from deeptrack.optics import Fluorescence -from deeptrack.image import Image +from ..scatterers import PointParticle +from ..optics import Fluorescence +from ..image import Image class TestAberrations(unittest.TestCase): diff --git a/test/test_augmentations.py b/deeptrack/test/test_augmentations.py old mode 100755 new mode 100644 similarity index 82% rename from test/test_augmentations.py rename to deeptrack/test/test_augmentations.py index 63f66b9d5..982606fb4 --- a/test/test_augmentations.py +++ b/deeptrack/test/test_augmentations.py @@ -1,12 +1,12 @@ import sys -sys.path.append(".") # Adds the module to path +# sys.path.append(".") # Adds the module to path import unittest -import deeptrack as dt -import deeptrack.augmentations as augmentations -from deeptrack.features import Feature +from .. import augmentations, optics, scatterers + +from ..features import Feature import numpy as np @@ -49,10 +49,10 @@ def test_FlipDiagonal(self): self.assertTrue(np.all(output_2 == np.array([[[1], [0]], [[2], [0]]]))) def test_Affine(self): - optics = dt.Fluorescence(magnification=10) - particle = dt.PointParticle( + opt = optics.Fluorescence(magnification=10) + particle = scatterers.PointParticle( position=lambda image_size: np.random.rand(2) * image_size[-2:], - image_size=optics.output_region, + image_size=opt.output_region, ) augmentation = augmentations.Affine( @@ -63,7 +63,7 @@ def test_Affine(self): mode="constant", ) - pipe = optics(particle) + augmentation + pipe = opt(particle) + augmentation for _ in range(10): image = pipe.update().resolve() @@ -117,50 +117,50 @@ def test_ElasticTransformation(self): def test_Crop(self): image = np.ones((10, 10, 10)) - cropper = dt.Crop(crop=(3, 2, 1), crop_mode="remove") + cropper = augmentations.Crop(crop=(3, 2, 1), crop_mode="remove") out = cropper.update().resolve(image) self.assertSequenceEqual(out.shape, (7, 8, 9)) - cropper = dt.Crop(crop=(3, 2, 1), crop_mode="retain") + cropper = augmentations.Crop(crop=(3, 2, 1), crop_mode="retain") out = cropper.update().resolve(image) self.assertSequenceEqual(out.shape, (3, 2, 1)) - cropper = dt.Crop(crop=2, crop_mode="remove") + cropper = augmentations.Crop(crop=2, crop_mode="remove") out = cropper.update().resolve(image) self.assertSequenceEqual(out.shape, (8, 8, 8)) - cropper = dt.Crop(crop=2, crop_mode="retain") + cropper = augmentations.Crop(crop=2, crop_mode="retain") out = cropper.update().resolve(image) self.assertSequenceEqual(out.shape, (2, 2, 2)) - cropper = dt.Crop(crop=12, crop_mode="remove") + cropper = augmentations.Crop(crop=12, crop_mode="remove") out = cropper.update().resolve(image) self.assertSequenceEqual(out.shape, (1, 1, 1)) - cropper = dt.Crop(crop=0, crop_mode="retain") + cropper = augmentations.Crop(crop=0, crop_mode="retain") out = cropper.update().resolve(image) self.assertSequenceEqual(out.shape, (1, 1, 1)) def test_CropToMultiple(self): image = np.ones((11, 11, 11)) - cropper = dt.CropToMultiplesOf(multiple=2) + cropper = augmentations.CropToMultiplesOf(multiple=2) out = cropper.update().resolve(image) self.assertSequenceEqual(out.shape, (10, 10, 10)) - cropper = dt.CropToMultiplesOf(multiple=-1) + cropper = augmentations.CropToMultiplesOf(multiple=-1) out = cropper.update().resolve(image) self.assertSequenceEqual(out.shape, (11, 11, 11)) - cropper = dt.CropToMultiplesOf(multiple=(2, 3, 5)) + cropper = augmentations.CropToMultiplesOf(multiple=(2, 3, 5)) out = cropper.update().resolve(image) self.assertSequenceEqual(out.shape, (10, 9, 10)) - cropper = dt.CropToMultiplesOf(multiple=(2, -1, 7)) + cropper = augmentations.CropToMultiplesOf(multiple=(2, -1, 7)) out = cropper.update().resolve(image) self.assertSequenceEqual(out.shape, (10, 11, 7)) - cropper = dt.CropToMultiplesOf(multiple=(2, 3, None)) + cropper = augmentations.CropToMultiplesOf(multiple=(2, 3, None)) out = cropper.update().resolve(image) self.assertSequenceEqual(out.shape, (10, 9, 11)) diff --git a/test/test_features.py b/deeptrack/test/test_features.py old mode 100755 new mode 100644 similarity index 98% rename from test/test_features.py rename to deeptrack/test/test_features.py index 145e53e20..868460585 --- a/test/test_features.py +++ b/deeptrack/test/test_features.py @@ -1,13 +1,13 @@ import sys -sys.path.append(".") # Adds the module to path +# sys.path.append(".") # Adds the module to path import unittest -import deeptrack.features as features +from .. import features, Image import numpy as np -from deeptrack.image import Image + class TestFeatures(unittest.TestCase): diff --git a/test/test_generators.py b/deeptrack/test/test_generators.py old mode 100755 new mode 100644 similarity index 86% rename from test/test_generators.py rename to deeptrack/test/test_generators.py index a0a6cfbdb..c4d1297b2 --- a/test/test_generators.py +++ b/deeptrack/test/test_generators.py @@ -1,13 +1,12 @@ import sys -sys.path.append(".") # Adds the module to path +# sys.path.append(".") # Adds the module to path import unittest -import deeptrack.generators as generators - -from deeptrack.optics import Fluorescence -from deeptrack.scatterers import PointParticle +from .. import generators +from ..optics import Fluorescence +from ..scatterers import PointParticle import numpy as np diff --git a/test/test_image.py b/deeptrack/test/test_image.py old mode 100755 new mode 100644 similarity index 96% rename from test/test_image.py rename to deeptrack/test/test_image.py index 123ae4ab7..7479e462a --- a/test/test_image.py +++ b/deeptrack/test/test_image.py @@ -1,12 +1,12 @@ import sys -sys.path.append(".") # Adds the module to path +# sys.path.append(".") # Adds the module to path import unittest -import deeptrack.image as image +from .. import image -from deeptrack.features import Feature +from ..features import Feature import numpy as np diff --git a/test/test_layers.py b/deeptrack/test/test_layers.py similarity index 93% rename from test/test_layers.py rename to deeptrack/test/test_layers.py index c116d9e0c..efaea697a 100644 --- a/test/test_layers.py +++ b/deeptrack/test/test_layers.py @@ -1,13 +1,13 @@ import sys -sys.path.append(".") # Adds the module to path +# sys.path.append(".") # Adds the module to path import unittest -import deeptrack.layers as layers +from .. import layers import tensorflow.keras.layers as k_layers import tensorflow.keras.models as k_models -from tensorflow_addons.layers import InstanceNormalization +from ..layers import InstanceNormalization import numpy as np diff --git a/test/test_losses.py b/deeptrack/test/test_losses.py old mode 100755 new mode 100644 similarity index 96% rename from test/test_losses.py rename to deeptrack/test/test_losses.py index ae47d6c4a..385ae0f10 --- a/test/test_losses.py +++ b/deeptrack/test/test_losses.py @@ -1,13 +1,13 @@ import sys -sys.path.append(".") # Adds the module to path +# sys.path.append(".") # Adds the module to path import unittest -import deeptrack.losses as losses +from .. import losses import numpy as np -from keras import backend as K +from tensorflow.keras import backend as K class TestLosses(unittest.TestCase): @@ -16,7 +16,7 @@ class TestLosses(unittest.TestCase): falsely = K.constant(np.zeros((2, 2, 1))) def test_flatten(self): - from keras.losses import mse + from tensorflow.keras.losses import mse loss_function = losses.flatten(mse) loss = K.eval(loss_function(self.truthly, self.truthly)) diff --git a/test/test_math.py b/deeptrack/test/test_math.py old mode 100755 new mode 100644 similarity index 89% rename from test/test_math.py rename to deeptrack/test/test_math.py index ec6a156b9..45c3dc6cb --- a/test/test_math.py +++ b/deeptrack/test/test_math.py @@ -1,10 +1,10 @@ import sys -sys.path.append(".") # Adds the module to path +# sys.path.append(".") # Adds the module to path import unittest -import deeptrack.math as math +from .. import math import numpy as np diff --git a/test/test_models.py b/deeptrack/test/test_models.py old mode 100755 new mode 100644 similarity index 97% rename from test/test_models.py rename to deeptrack/test/test_models.py index 33c5a613c..6e3035bc4 --- a/test/test_models.py +++ b/deeptrack/test/test_models.py @@ -1,10 +1,10 @@ import sys -sys.path.append(".") # Adds the module to path +# sys.path.append(".") # Adds the module to path import unittest -import deeptrack.models as models +from .. import models import numpy as np diff --git a/test/test_noises.py b/deeptrack/test/test_noises.py old mode 100755 new mode 100644 similarity index 92% rename from test/test_noises.py rename to deeptrack/test/test_noises.py index 057922794..7a83dbe4a --- a/test/test_noises.py +++ b/deeptrack/test/test_noises.py @@ -1,12 +1,12 @@ import sys -sys.path.append(".") # Adds the module to path +# sys.path.append(".") # Adds the module to path import unittest -import deeptrack.noises as noises +from .. import noises -from deeptrack.image import Image +from ..image import Image import numpy as np diff --git a/test/test_optics.py b/deeptrack/test/test_optics.py old mode 100755 new mode 100644 similarity index 94% rename from test/test_optics.py rename to deeptrack/test/test_optics.py index 458a951c6..05d3ced9d --- a/test/test_optics.py +++ b/deeptrack/test/test_optics.py @@ -1,13 +1,13 @@ import sys -sys.path.append(".") # Adds the module to path +# sys.path.append(".") # Adds the module to path import unittest -import deeptrack.optics as optics +from .. import optics -from deeptrack.scatterers import PointParticle -from deeptrack.image import Image +from ..scatterers import PointParticle +from ..image import Image class TestOptics(unittest.TestCase): diff --git a/test/test_properties.py b/deeptrack/test/test_properties.py old mode 100755 new mode 100644 similarity index 89% rename from test/test_properties.py rename to deeptrack/test/test_properties.py index 9bc9b7321..ac0293021 --- a/test/test_properties.py +++ b/deeptrack/test/test_properties.py @@ -1,11 +1,10 @@ import sys -sys.path.append(".") # Adds the module to path +# sys.path.append(".") # Adds the module to path import unittest -import deeptrack.properties as properties -import deeptrack as dt +from .. import properties, features, optics import numpy as np @@ -60,13 +59,13 @@ def geometric_increase(previous_value, step_length): self.assertEqual(P2.current_value, [3, 6, 10, 15, 21]) def test_UpdateFromParent(self): - optics = dt.Fluorescence() - sample = dt.DummyFeature(voxel_size=optics.voxel_size) - together = optics(sample) + opt = optics.Fluorescence() + sample = features.DummyFeature(voxel_size=opt.voxel_size) + together = opt(sample) together.update() self.assertEqual( - tuple(optics.voxel_size.current_value), - tuple(sample.voxel_size.current_value), + tuple(opt.voxel_size.current_value), + tuple(opt.voxel_size.current_value), ) def test_PropertyDict(self): diff --git a/test/test_scatterers.py b/deeptrack/test/test_scatterers.py old mode 100755 new mode 100644 similarity index 96% rename from test/test_scatterers.py rename to deeptrack/test/test_scatterers.py index 7861a003a..552c63b90 --- a/test/test_scatterers.py +++ b/deeptrack/test/test_scatterers.py @@ -5,11 +5,11 @@ import unittest -import deeptrack.scatterers as scatterers +from .. import scatterers import numpy as np -from deeptrack.optics import Fluorescence, Brightfield -from deeptrack.image import Image +from ..optics import Fluorescence, Brightfield +from ..image import Image class TestScatterers(unittest.TestCase): diff --git a/test/test_sequences.py b/deeptrack/test/test_sequences.py old mode 100755 new mode 100644 similarity index 86% rename from test/test_sequences.py rename to deeptrack/test/test_sequences.py index bb625f856..2859f1aab --- a/test/test_sequences.py +++ b/deeptrack/test/test_sequences.py @@ -1,13 +1,13 @@ import sys -sys.path.append(".") # Adds the module to path +# sys.path.append(".") # Adds the module to path import unittest -import deeptrack.sequences as sequences +from .. import sequences -from deeptrack.optics import Fluorescence -from deeptrack.scatterers import Ellipse +from ..optics import Fluorescence +from ..scatterers import Ellipse import numpy as np @@ -38,7 +38,7 @@ def get_rotation(sequence_length, previous_value): imaged_rotating_ellipse, sequence_length=50 ) self.assertIsInstance(imaged_rotating_ellipse_sequence, sequences.Sequence) - + if __name__ == "__main__": unittest.main() \ No newline at end of file diff --git a/test/test_utils.py b/deeptrack/test/test_utils.py old mode 100755 new mode 100644 similarity index 96% rename from test/test_utils.py rename to deeptrack/test/test_utils.py index 94a745870..84f4b98ce --- a/test/test_utils.py +++ b/deeptrack/test/test_utils.py @@ -1,10 +1,10 @@ import sys -sys.path.append(".") # Adds the module to path +# sys.path.append(".") # Adds the module to path import unittest -import deeptrack.utils as utils +from .. import utils class TestUtils(unittest.TestCase): diff --git a/test/test.py b/test/test.py deleted file mode 100755 index a03301312..000000000 --- a/test/test.py +++ /dev/null @@ -1,8 +0,0 @@ -import unittest - -loader = unittest.TestLoader() -start_dir = "./test" -suite = loader.discover(start_dir) - -runner = unittest.TextTestRunner() -runner.run(suite) From c91cc732ca5b32f5f72cde4907ec09a708d2a479 Mon Sep 17 00:00:00 2001 From: Benjamin Midtvedt Date: Wed, 10 Feb 2021 13:22:50 +0100 Subject: [PATCH 23/78] convert video to array to not crash on ndim --- deeptrack/generators.py | 1 + 1 file changed, 1 insertion(+) diff --git a/deeptrack/generators.py b/deeptrack/generators.py index 6b569673f..40ec0f943 100644 --- a/deeptrack/generators.py +++ b/deeptrack/generators.py @@ -325,6 +325,7 @@ def _continuous_get_training_data(self): if self.batch_function: new_image = self.batch_function(new_image) + new_image = np.array(new_image) if new_image.ndim < self.ndim: new_image = [new_image] new_label = [new_label] From 6bbddb227f61906067826c9fb21ac4e033b6272c Mon Sep 17 00:00:00 2001 From: Benjamin Midtvedt Date: Wed, 10 Feb 2021 13:23:01 +0100 Subject: [PATCH 24/78] update test call --- package.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index be998449c..84722d9a0 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,8 @@ { - "scripts": { - "publish": "py setup.py sdist bdist_wheel && py -m twine upload --repository pypi dist/*", - "make-docs-windows": "cd _src && make html && Xcopy /Y /I /E .\\build\\html ..\\docs && type nul > ../docs/.nojekyll", - "full-make-docs-windows": "cd _src && py .\\autodoc_dt.py && make html && Xcopy /Y /I /E .\\build\\html ..\\docs && type nul > ../docs/.nojekyll", - "test": "py ./test/test.py" - } + "scripts": { + "publish": "py setup.py sdist bdist_wheel && py -m twine upload --repository pypi dist/*", + "make-docs-windows": "cd _src && make html && Xcopy /Y /I /E .\\build\\html ..\\docs && type nul > ../docs/.nojekyll", + "full-make-docs-windows": "cd _src && py .\\autodoc_dt.py && make html && Xcopy /Y /I /E .\\build\\html ..\\docs && type nul > ../docs/.nojekyll", + "test": "py -m unittest discover" + } } From 43b7efc46c607e292613cb4ef7d961203a405d95 Mon Sep 17 00:00:00 2001 From: Benjamin Midtvedt Date: Wed, 10 Feb 2021 13:23:10 +0100 Subject: [PATCH 25/78] make tests a package --- deeptrack/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/deeptrack/__init__.py b/deeptrack/__init__.py index de40a84c7..c8bab984d 100644 --- a/deeptrack/__init__.py +++ b/deeptrack/__init__.py @@ -7,4 +7,5 @@ from .scatterers import * from .sequences import * -from . import image, losses, generators, models, utils, layers, backend \ No newline at end of file + +from . import image, losses, generators, models, utils, layers, backend, test \ No newline at end of file From 3dd01bdc62145b2dae5723fbdf768ef46de23968 Mon Sep 17 00:00:00 2001 From: Benjamin Midtvedt Date: Wed, 10 Feb 2021 13:23:30 +0100 Subject: [PATCH 26/78] reorder scatterer position --- deeptrack/scatterers.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deeptrack/scatterers.py b/deeptrack/scatterers.py index b28958985..986e90cfa 100644 --- a/deeptrack/scatterers.py +++ b/deeptrack/scatterers.py @@ -545,8 +545,8 @@ def get( arr = image.pad_image_to_fft(np.zeros((xSize, ySize))) # Evluation grid - x = np.arange(-padding[0], arr.shape[0] - padding[0]) - (position[1]) * upscale - y = np.arange(-padding[1], arr.shape[1] - padding[1]) - (position[0]) * upscale + x = np.arange(-padding[0], arr.shape[0] - padding[0]) - (position[0]) * upscale + y = np.arange(-padding[1], arr.shape[1] - padding[1]) - (position[1]) * upscale X, Y = np.meshgrid(x * voxel_size[0], y * voxel_size[1], indexing="ij") R2 = np.sqrt(X ** 2 + Y ** 2) From b204616fc6673280a1473f4d4c38e5284d3568a2 Mon Sep 17 00:00:00 2001 From: Benjamin Midtvedt Date: Wed, 10 Feb 2021 13:24:15 +0100 Subject: [PATCH 27/78] Fix: update is correctly called with the _ prefix --- deeptrack/sequences.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/deeptrack/sequences.py b/deeptrack/sequences.py index 462284138..6cc9f4159 100644 --- a/deeptrack/sequences.py +++ b/deeptrack/sequences.py @@ -42,7 +42,7 @@ def __init__(self, feature: Feature, sequence_length: int = 1, **kwargs): super().__init__(sequence_length=sequence_length, **kwargs) # Require update - self.update() + # self.update() def get(self, input_list, sequence_length=None, **kwargs): return (input_list or []) + [ @@ -52,14 +52,14 @@ def get(self, input_list, sequence_length=None, **kwargs): for sequence_step in range(sequence_length) ] - def update(self, **kwargs): - super().update(**kwargs) + def _update(self, **kwargs): + super()._update(**kwargs) sequence_length = self.properties["sequence_length"].current_value if "sequence_length" not in kwargs: kwargs["sequence_length"] = sequence_length - self.feature.update(**kwargs) + self.feature._update(**kwargs) return self From 4c1e77fcd6b186c3994a1e109c5f198ba5fe9e72 Mon Sep 17 00:00:00 2001 From: Benjamin Midtvedt Date: Wed, 10 Feb 2021 13:28:26 +0100 Subject: [PATCH 28/78] Fix Layers typo --- deeptrack/layers.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/deeptrack/layers.py b/deeptrack/layers.py index fe90f98c5..0dbeff3f5 100644 --- a/deeptrack/layers.py +++ b/deeptrack/layers.py @@ -28,7 +28,8 @@ def as_block(x): + ", ".join(_string_to_block.keys()) ) if isinstance(x, layers.Layer) or not callable(x): - raise TypeError("Layer block should be a function that returns a keras Layer.") + raise TypeError( + "Layer block should be a function that returns a keras Layer.") else: return x @@ -41,7 +42,7 @@ def _as_activation(x): elif isinstance(x, layers.Layer): return x else: - return layers.Layers(x) + return layers.Layer(x) def _single_layer_call(x, layer, instance_norm, activation): From e4c21d5ed3eff6e139b11a3b2ba5928d240031b7 Mon Sep 17 00:00:00 2001 From: Benjamin Midtvedt Date: Wed, 10 Feb 2021 13:28:38 +0100 Subject: [PATCH 29/78] Change position order --- deeptrack/scatterers.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deeptrack/scatterers.py b/deeptrack/scatterers.py index 986e90cfa..b28958985 100644 --- a/deeptrack/scatterers.py +++ b/deeptrack/scatterers.py @@ -545,8 +545,8 @@ def get( arr = image.pad_image_to_fft(np.zeros((xSize, ySize))) # Evluation grid - x = np.arange(-padding[0], arr.shape[0] - padding[0]) - (position[0]) * upscale - y = np.arange(-padding[1], arr.shape[1] - padding[1]) - (position[1]) * upscale + x = np.arange(-padding[0], arr.shape[0] - padding[0]) - (position[1]) * upscale + y = np.arange(-padding[1], arr.shape[1] - padding[1]) - (position[0]) * upscale X, Y = np.meshgrid(x * voxel_size[0], y * voxel_size[1], indexing="ij") R2 = np.sqrt(X ** 2 + Y ** 2) From 54dcde3200249f288ce3520e0f7f1737467ee30b Mon Sep 17 00:00:00 2001 From: Benjamin Midtvedt Date: Wed, 10 Feb 2021 13:52:33 +0100 Subject: [PATCH 30/78] Correctly calculate the collection angle --- deeptrack/scatterers.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/deeptrack/scatterers.py b/deeptrack/scatterers.py index b28958985..2ab996bb1 100644 --- a/deeptrack/scatterers.py +++ b/deeptrack/scatterers.py @@ -500,9 +500,10 @@ def _process_properties(self, properties): except (ValueError, TypeError): pass if properties["collection_angle"] == "auto": - properties["collection_angle"] = np.sqrt( - 1 - properties["NA"] ** 2 / properties["refractive_index_medium"] ** 2 + properties["collection_angle"] = np.arcsin( + properties["NA"] / properties["refractive_index_medium"] ) + if properties["offset_z"] == "auto": properties["offset_z"] = ( 32 From caea6b7a913c04009acd76ed7207af78b8e8f250 Mon Sep 17 00:00:00 2001 From: Benjamin Midtvedt Date: Wed, 10 Feb 2021 13:52:48 +0100 Subject: [PATCH 31/78] Merge properties on distributed calls --- deeptrack/features.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/deeptrack/features.py b/deeptrack/features.py index 379116149..987addd0b 100644 --- a/deeptrack/features.py +++ b/deeptrack/features.py @@ -342,6 +342,8 @@ def _process_and_get(self, image_list, **feature_input) -> List[Image]: output = self.get(image, **feature_input) if not isinstance(output, Image): output = Image(output) + + output.merge_properties_from(image) results.append(output) return results From db9d6dd9d38c164a0f9860c56807c0f798e537a7 Mon Sep 17 00:00:00 2001 From: Benjamin Midtvedt Date: Wed, 10 Feb 2021 13:53:13 +0100 Subject: [PATCH 32/78] Version bump --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 10d84457f..724c87479 100644 --- a/setup.py +++ b/setup.py @@ -16,7 +16,7 @@ setuptools.setup( name="deeptrack", # Replace with your own username - version="0.7.3", + version="0.8.3", author="Benjamin Midtvedt", author_email="benjamin.midtvedt@physics.gu.se", description="A deep learning oriented microscopy image simulation package", From 4895dc7ef6e9b1789f5743434fae2f47ce3d2639 Mon Sep 17 00:00:00 2001 From: Aykut Argun <48754174+argunaykut@users.noreply.github.com> Date: Tue, 16 Feb 2021 12:29:08 +0100 Subject: [PATCH 33/78] Update README.md --- README.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/README.md b/README.md index 2f4b13d0b..5e8b7cd5e 100644 --- a/README.md +++ b/README.md @@ -52,16 +52,36 @@ DeepTrack 2.0 introduction tutorial video: https://youtu.be/hyfaxF8q6VE " target="_blank">Tutorial +DeepTrack 2.0 recognizing handwritten digits tutorial video: https://youtu.be/QD9JUXyLJpc + + DeepTrack 2.0 single particle tracking tutorial video: https://youtu.be/6Cntik6AfBI Tutorial +DeepTrack 2.0 single-particle characterization tutorial video: https://youtu.be/ia2H1QO1cHg + + DeepTrack 2.0 multiple particle tracking tutorial video: https://youtu.be/wFV2VqzpeZs Tutorial +DeepTrack 2.0 multiple particle tracking in 3D tutorial video: https://youtu.be/fzD1QIEIJ04 + + +DeepTrack 2.0 cell counting tutorial video: https://youtu.be/C6hu_IYoWtI + + DeepTrack 2.0 GAN image generation tutorial video: https://youtu.be/8g44Yks7cis Date: Tue, 16 Feb 2021 12:32:53 +0100 Subject: [PATCH 34/78] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5e8b7cd5e..7cce36924 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ alt="Tutorial" width="384" height="216" border="10" /> DeepTrack 2.0 multiple particle tracking in 3D tutorial video: https://youtu.be/fzD1QIEIJ04 Tutorial DeepTrack 2.0 cell counting tutorial video: https://youtu.be/C6hu_IYoWtI From 1b14af98ef7b8815ff4cc28b83f39c0db9294aee Mon Sep 17 00:00:00 2001 From: Aykut Argun <48754174+argunaykut@users.noreply.github.com> Date: Tue, 16 Feb 2021 12:36:03 +0100 Subject: [PATCH 35/78] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7cce36924..200484df5 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ DeepTrack 2.0 introduction tutorial video: https://youtu.be/hyfaxF8q6VE alt="Tutorial" width="384" height="216" border="10" /> DeepTrack 2.0 recognizing handwritten digits tutorial video: https://youtu.be/QD9JUXyLJpc -Tutorial From 1a39f7767e1b07eea18c5bd59027869593b061e3 Mon Sep 17 00:00:00 2001 From: Benjamin Midtvedt Date: Thu, 18 Feb 2021 21:16:15 +0100 Subject: [PATCH 36/78] Added CappedContinuousGenerator --- deeptrack/generators.py | 101 ++++++++++++++++++++++++++++-- deeptrack/test/test_generators.py | 69 ++++++++++++++++++++ setup.py | 2 +- 3 files changed, 166 insertions(+), 6 deletions(-) diff --git a/deeptrack/generators.py b/deeptrack/generators.py index 40ec0f943..44b533682 100644 --- a/deeptrack/generators.py +++ b/deeptrack/generators.py @@ -201,6 +201,7 @@ def __init__( update_kwargs={}, verbose=1, ndim=4, + max_sample_exposure=np.inf, ): if min_data_size is None: @@ -331,16 +332,22 @@ def _continuous_get_training_data(self): new_label = [new_label] for new_image_i, new_label_i in zip(new_image, new_label): + datapoint = self.construct_datapoint(new_image_i, new_label_i) if len(self.data) >= self.max_data_size: - self.data[index % self.max_data_size] = ( - new_image_i, - new_label_i, - ) + self.data[index % self.max_data_size] = datapoint else: - self.data.append((new_image_i, new_label_i)) + self.data.append(datapoint) index += 1 + self.cleanup() + + def construct_datapoint(self, image, label): + return (image, label) + + def cleanup(self): + pass + def _get(self, features: Feature or List[Feature], feature_kwargs) -> Image: # Updates and resolves a feature or list of features. if isinstance(features, list): @@ -358,3 +365,87 @@ def _get(self, features: Feature or List[Feature], feature_kwargs) -> Image: else: features.update() return features.resolve(**feature_kwargs) + + +class CappedContinuousGenerator(ContinuousGenerator): + + """Generator that asynchronously expands the dataset. + + Generator that aims to speed up the training of networks by striking a + balance between the generalization gained by generating new images + and the speed gained from reusing images. The generator will continuously + create new training data during training, until `max_data_size` is reached, + at which point the oldest data point is replaced. + + Unlike the `ContinuousGenerator`, this generator will purge any data that + has been seen more than `max_sample_exposure` times. + + The generator is expected to be used with the python "with" statement, which + ensures that the generator worker is consumed correctly. + + Parameters + ---------- + feature : Feature + The feature to resolve images from. + label_function : Callable[Image or list of Image] -> array_like + Function that returns the label corresponding to a feature output. + batch_function : Callable[Image or list of Image] -> array_like, optional + Function that returns the training data corresponding a feature output. + min_data_size : int + Minimum size of the training data before training starts + max_data_set : int + Maximum size of the training data before old data is replaced. + max_sample_exposure : int + Any sample that has been seen for more than `max_sample_exposure` will be removed from the dataset + batch_size : int or Callable[int, int] -> int + Number of images per batch. A function is expected to accept the current epoch + and the size of the training data as input. + shuffle_batch : bool + If True, the batches are shuffled before outputting. + feature_kwargs : dict or list of dicts + Set of options to pass to the feature when resolving + ndim : int + Number of dimensions of each batch (including the batch dimension). + max_sample_exposure : int + Any sample that has been seen for more than `max_sample_exposure` will be removed from the dataset + """ + + def __init__(self, *args, max_sample_exposure=np.inf, **kwargs): + self.max_sample_exposure = max_sample_exposure + super().__init__(*args, **kwargs) + + def __exit__(self, *args): + self.exit_signal = True + self.data_generation_thread.join() + return False + + def __getitem__(self, idx): + + # TODO: Use parent method + batch_size = self._batch_size + subset = self.current_data[idx * batch_size : (idx + 1) * batch_size] + for a in subset: + a[-1] += 1 + outputs = [np.array(a) for a in list(zip(*subset))] + outputs = (outputs[0], *outputs[1:]) + return outputs + + def construct_datapoint(self, image, label): + return [image, label, 0] + + def cleanup(self): + self.data = [ + sample for sample in self.data if sample[-1] < self.max_sample_exposure + ] + + def on_epoch_end(self): + + while len(self.data) < self.min_data_size: + print( + "Awaiting dataset to reach minimum size...".format( + len(self.data), self.min_data_size + ) + ) + time.sleep(0.1) + + return super().on_epoch_end() \ No newline at end of file diff --git a/deeptrack/test/test_generators.py b/deeptrack/test/test_generators.py index c4d1297b2..931cf8b97 100644 --- a/deeptrack/test/test_generators.py +++ b/deeptrack/test/test_generators.py @@ -41,6 +41,75 @@ def get_particle_position(result): self.assertTrue(np.all(position >= 0)) self.assertTrue(np.all(position <= 128)) + def test_ContinuousGenerator(self): + optics = Fluorescence( + NA=0.7, + wavelength=680e-9, + resolution=1e-6, + magnification=10, + output_region=(0, 0, 128, 128), + ) + scatterer = PointParticle( + intensity=100, + position_unit="pixel", + position=lambda: np.random.rand(2) * 128, + ) + imaged_scatterer = optics(scatterer) + + def get_particle_position(result): + for property in result.properties: + if "position" in property: + return property["position"] + + generator = generators.ContinuousGenerator( + imaged_scatterer, get_particle_position, min_data_size=10, max_data_size=20 + ) + + with generator: + self.assertGreater(len(generator.data), 10) + self.assertLess(len(generator.data), 21) + + def test_CappedContinuousGenerator(self): + + optics = Fluorescence( + NA=0.7, + wavelength=680e-9, + resolution=1e-6, + magnification=10, + output_region=(0, 0, 128, 128), + index=range(0, 200), + ) + scatterer = PointParticle( + intensity=100, + position_unit="pixel", + position=lambda: np.random.rand(2) * 128, + ) + imaged_scatterer = optics(scatterer) + + def get_particle_position(result): + for property in result.properties: + if "position" in property: + return property["position"] + + generator = generators.CappedContinuousGenerator( + imaged_scatterer, + get_particle_position, + batch_size=1, + min_data_size=10, + max_data_size=20, + max_sample_exposure=5, + ) + + with generator: + self.assertGreater(len(generator.data), 10) + self.assertLess(len(generator.data), 21) + for _ in range(10): + generator.on_epoch_end() + for idx in range(len(generator)): + generator[idx] + + [self.assertLess(d[-1], 6) for d in generator.data] + if __name__ == "__main__": unittest.main() \ No newline at end of file diff --git a/setup.py b/setup.py index 724c87479..21e7204c0 100644 --- a/setup.py +++ b/setup.py @@ -16,7 +16,7 @@ setuptools.setup( name="deeptrack", # Replace with your own username - version="0.8.3", + version="0.9.0.dev0", author="Benjamin Midtvedt", author_email="benjamin.midtvedt@physics.gu.se", description="A deep learning oriented microscopy image simulation package", From d7e655bfe5efdc4ed8dbb7cadd9669206326368b Mon Sep 17 00:00:00 2001 From: Benjamin Midtvedt Date: Thu, 18 Feb 2021 21:28:34 +0100 Subject: [PATCH 37/78] Remove unused import --- deeptrack/features.py | 1 - 1 file changed, 1 deletion(-) diff --git a/deeptrack/features.py b/deeptrack/features.py index 987addd0b..213bfd533 100644 --- a/deeptrack/features.py +++ b/deeptrack/features.py @@ -21,7 +21,6 @@ """ import copy -import enum from typing import List import numpy as np From 89d2be160b0a8d43e7a1014858299d33512aeb12 Mon Sep 17 00:00:00 2001 From: Benjamin Midtvedt Date: Thu, 18 Feb 2021 21:28:43 +0100 Subject: [PATCH 38/78] Remove unused format --- deeptrack/generators.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/deeptrack/generators.py b/deeptrack/generators.py index 44b533682..4605c3a74 100644 --- a/deeptrack/generators.py +++ b/deeptrack/generators.py @@ -441,11 +441,7 @@ def cleanup(self): def on_epoch_end(self): while len(self.data) < self.min_data_size: - print( - "Awaiting dataset to reach minimum size...".format( - len(self.data), self.min_data_size - ) - ) + print("Awaiting dataset to reach minimum size...") time.sleep(0.1) return super().on_epoch_end() \ No newline at end of file From bbc3149d35bba7d5a8e18b5afa2a32b3e8612c05 Mon Sep 17 00:00:00 2001 From: Benjamin Midtvedt Date: Thu, 25 Feb 2021 16:14:41 +0100 Subject: [PATCH 39/78] Added PropertyLike type --- deeptrack/properties.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/deeptrack/properties.py b/deeptrack/properties.py index 4ce380389..0e44e4e14 100644 --- a/deeptrack/properties.py +++ b/deeptrack/properties.py @@ -24,12 +24,20 @@ kwarg_has_default, ) +import typing + + from . import features import copy import collections +# Property type declaration +T = typing.TypeVar("T") +PropertyLike = typing.Union[T, typing.Callable[..., T]] + + class Property: """Represents a property of a feature From 8b58edd494036f63482de726b74db98d56cd1806 Mon Sep 17 00:00:00 2001 From: Benjamin Midtvedt Date: Thu, 25 Feb 2021 16:46:10 +0100 Subject: [PATCH 40/78] Added typings --- deeptrack/aberrations.py | 64 +++++++++++++++++++++++++++++++--------- 1 file changed, 50 insertions(+), 14 deletions(-) diff --git a/deeptrack/aberrations.py b/deeptrack/aberrations.py index f170a53f5..3e4648ae2 100644 --- a/deeptrack/aberrations.py +++ b/deeptrack/aberrations.py @@ -32,7 +32,10 @@ Zernike polynomial with n=4, m=0. """ +from typing import List, Tuple + import numpy as np +from .types import PropertyLike from .features import Feature from .utils import as_list @@ -53,7 +56,7 @@ def _process_and_get(self, image_list, **kwargs): for image in image_list: x = np.arange(image.shape[0]) - image.shape[0] / 2 y = np.arange(image.shape[1]) - image.shape[1] / 2 - X, Y = np.meshgrid(x, y) + X, Y = np.meshgrid(y, x) rho = np.sqrt(X ** 2 + Y ** 2) rho /= np.max(rho[image != 0]) theta = np.arctan2(Y, X) @@ -83,7 +86,12 @@ class GaussianApodization(Aberration): """ - def __init__(self, sigma=1, offset=(0, 0), **kwargs): + def __init__( + self, + sigma: PropertyLike[float] = 1, + offset: PropertyLike[Tuple[int, int]] = (0, 0), + **kwargs + ): super().__init__(sigma=sigma, offset=offset, **kwargs) def get(self, pupil, offset, sigma, rho, **kwargs): @@ -121,7 +129,13 @@ class Zernike(Aberration): The coefficient of the polynomial """ - def __init__(self, n, m, coefficient=1, **kwargs): + def __init__( + self, + n: PropertyLike[int or List[int]], + m: PropertyLike[int or List[int]], + coefficient: PropertyLike[float or List[float]] = 1, + **kwargs + ): super().__init__(n=n, m=m, coefficient=coefficient, **kwargs) def get(self, pupil, rho, theta, n, m, coefficient, **kwargs): @@ -186,7 +200,9 @@ class Piston(Zernike): The coefficient of the polynomial """ - def __init__(self, *args, coefficient=1, **kwargs): + def __init__( + self, *args, coefficient: PropertyLike[float or List[float]] = 1, **kwargs + ): super().__init__(*args, n=0, m=0, coefficient=coefficient, **kwargs) @@ -199,7 +215,9 @@ class VerticalTilt(Zernike): The coefficient of the polynomial """ - def __init__(self, *args, coefficient=1, **kwargs): + def __init__( + self, *args, coefficient: PropertyLike[float or List[float]] = 1, **kwargs + ): super().__init__(*args, n=1, m=-1, coefficient=coefficient, **kwargs) @@ -212,7 +230,9 @@ class HorizontalTilt(Zernike): The coefficient of the polynomial """ - def __init__(self, *args, coefficient=1, **kwargs): + def __init__( + self, *args, coefficient: PropertyLike[float or List[float]] = 1, **kwargs + ): super().__init__(*args, n=1, m=1, coefficient=coefficient, **kwargs) @@ -225,7 +245,9 @@ class ObliqueAstigmatism(Zernike): The coefficient of the polynomial """ - def __init__(self, *args, coefficient=1, **kwargs): + def __init__( + self, *args, coefficient: PropertyLike[float or List[float]] = 1, **kwargs + ): super().__init__(*args, n=2, m=-2, coefficient=coefficient, **kwargs) @@ -238,7 +260,9 @@ class Defocus(Zernike): The coefficient of the polynomial """ - def __init__(self, *args, coefficient=1, **kwargs): + def __init__( + self, *args, coefficient: PropertyLike[float or List[float]] = 1, **kwargs + ): super().__init__(*args, n=2, m=0, coefficient=coefficient, **kwargs) @@ -251,7 +275,9 @@ class Astigmatism(Zernike): The coefficient of the polynomial """ - def __init__(self, *args, coefficient=1, **kwargs): + def __init__( + self, *args, coefficient: PropertyLike[float or List[float]] = 1, **kwargs + ): super().__init__(*args, n=2, m=2, coefficient=coefficient, **kwargs) @@ -264,7 +290,9 @@ class ObliqueTrefoil(Zernike): The coefficient of the polynomial """ - def __init__(self, *args, coefficient=1, **kwargs): + def __init__( + self, *args, coefficient: PropertyLike[float or List[float]] = 1, **kwargs + ): super().__init__(*args, n=3, m=-3, coefficient=coefficient, **kwargs) @@ -277,7 +305,9 @@ class VerticalComa(Zernike): The coefficient of the polynomial """ - def __init__(self, *args, coefficient=1, **kwargs): + def __init__( + self, *args, coefficient: PropertyLike[float or List[float]] = 1, **kwargs + ): super().__init__(*args, n=3, m=-1, coefficient=coefficient, **kwargs) @@ -290,7 +320,9 @@ class HorizontalComa(Zernike): The coefficient of the polynomial """ - def __init__(self, *args, coefficient=1, **kwargs): + def __init__( + self, *args, coefficient: PropertyLike[float or List[float]] = 1, **kwargs + ): super().__init__(*args, n=3, m=1, coefficient=coefficient, **kwargs) @@ -303,7 +335,9 @@ class Trefoil(Zernike): The coefficient of the polynomial """ - def __init__(self, *args, coefficient=1, **kwargs): + def __init__( + self, *args, coefficient: PropertyLike[float or List[float]] = 1, **kwargs + ): super().__init__(*args, n=3, m=3, coefficient=coefficient, **kwargs) @@ -316,5 +350,7 @@ class SphericalAberration(Zernike): The coefficient of the polynomial """ - def __init__(self, *args, coefficient=1, **kwargs): + def __init__( + self, *args, coefficient: PropertyLike[float or List[float]] = 1, **kwargs + ): super().__init__(*args, n=4, m=0, coefficient=coefficient, **kwargs) From c1d69d67fd38a0b02a780e5489001793cc51c49e Mon Sep 17 00:00:00 2001 From: Benjamin Midtvedt Date: Thu, 25 Feb 2021 16:46:40 +0100 Subject: [PATCH 41/78] Remove redundant code --- deeptrack/generators.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/deeptrack/generators.py b/deeptrack/generators.py index 4605c3a74..f1e33102a 100644 --- a/deeptrack/generators.py +++ b/deeptrack/generators.py @@ -414,11 +414,6 @@ def __init__(self, *args, max_sample_exposure=np.inf, **kwargs): self.max_sample_exposure = max_sample_exposure super().__init__(*args, **kwargs) - def __exit__(self, *args): - self.exit_signal = True - self.data_generation_thread.join() - return False - def __getitem__(self, idx): # TODO: Use parent method @@ -441,7 +436,7 @@ def cleanup(self): def on_epoch_end(self): while len(self.data) < self.min_data_size: - print("Awaiting dataset to reach minimum size...") + print("Awaiting dataset to reach minimum size...", end="\r") time.sleep(0.1) return super().on_epoch_end() \ No newline at end of file From 8b57fcb2d5f3d282b8a595d50f79d547f0fb075e Mon Sep 17 00:00:00 2001 From: Benjamin Midtvedt Date: Thu, 25 Feb 2021 16:47:01 +0100 Subject: [PATCH 42/78] Moce types to own module --- deeptrack/properties.py | 5 ----- deeptrack/types.py | 8 ++++++++ 2 files changed, 8 insertions(+), 5 deletions(-) create mode 100644 deeptrack/types.py diff --git a/deeptrack/properties.py b/deeptrack/properties.py index 0e44e4e14..a72663e00 100644 --- a/deeptrack/properties.py +++ b/deeptrack/properties.py @@ -33,11 +33,6 @@ import collections -# Property type declaration -T = typing.TypeVar("T") -PropertyLike = typing.Union[T, typing.Callable[..., T]] - - class Property: """Represents a property of a feature diff --git a/deeptrack/types.py b/deeptrack/types.py new file mode 100644 index 000000000..6ebfce10f --- /dev/null +++ b/deeptrack/types.py @@ -0,0 +1,8 @@ +""" Type declarations for internal use +""" + +import typing + +# Property type declaration +T = typing.TypeVar("T") +PropertyLike = typing.Union[T, typing.Callable[..., T]] From b9439fd6aace26ad15e24b3ab0c707e79c870bbc Mon Sep 17 00:00:00 2001 From: Benjamin Midtvedt Date: Thu, 25 Feb 2021 16:47:16 +0100 Subject: [PATCH 43/78] Include check for non.symetrical pupils --- deeptrack/test/test_aberrations.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deeptrack/test/test_aberrations.py b/deeptrack/test/test_aberrations.py index 5ac1b6842..0510c6e81 100644 --- a/deeptrack/test/test_aberrations.py +++ b/deeptrack/test/test_aberrations.py @@ -37,7 +37,7 @@ def testPiston(self): resolution=1e-6, magnification=10, wavelength=530e-9, - output_region=(0, 0, 64, 64), + output_region=(0, 0, 64, 48), padding=(64, 64, 64, 64), aberration=aberrations.Piston(coefficient=1), ) @@ -45,7 +45,7 @@ def testPiston(self): for z in (-100, 0, 100): im = aberrated_particle.resolve(z=z) self.assertIsInstance(im, Image) - self.assertEqual(im.shape, (64, 64, 1)) + self.assertEqual(im.shape, (64, 48, 1)) def testVerticalTilt(self): aberrated_optics = Fluorescence( From 79ff77eef26af15eab6c97ba298ad429df5f7f41 Mon Sep 17 00:00:00 2001 From: Benjamin Midtvedt Date: Thu, 25 Feb 2021 16:47:42 +0100 Subject: [PATCH 44/78] Avoid code redundancy optimization --- deeptrack/test/test_generators.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deeptrack/test/test_generators.py b/deeptrack/test/test_generators.py index 931cf8b97..6d4ad59a8 100644 --- a/deeptrack/test/test_generators.py +++ b/deeptrack/test/test_generators.py @@ -106,9 +106,9 @@ def get_particle_position(result): for _ in range(10): generator.on_epoch_end() for idx in range(len(generator)): - generator[idx] + a = generator[idx] - [self.assertLess(d[-1], 6) for d in generator.data] + [self.assertLess(d[-1], 8) for d in generator.data] if __name__ == "__main__": From 12bf85b33e02b793ee5ffef5f287e34953da723b Mon Sep 17 00:00:00 2001 From: Benjamin Midtvedt Date: Thu, 25 Feb 2021 16:47:57 +0100 Subject: [PATCH 45/78] Decrease model sizes during testing --- deeptrack/test/test_models.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/deeptrack/test/test_models.py b/deeptrack/test/test_models.py index 6e3035bc4..0511f6c74 100644 --- a/deeptrack/test/test_models.py +++ b/deeptrack/test/test_models.py @@ -25,7 +25,7 @@ def test_FullyConnected(self): def test_Convolutions_with_single_input(self): model = models.Convolutional( input_shape=(64, 64, 1), - conv_layers_dimensions=(16, 32, 64, 128), + conv_layers_dimensions=(16, 32, 64), dense_layers_dimensions=(32, 32), number_of_outputs=3, output_activation="sigmoid", @@ -38,7 +38,7 @@ def test_Convolutions_with_single_input(self): def test_Convolutions_with_multiple_inputs(self): model = models.Convolutional( input_shape=[(64, 64, 1), (64, 64, 2)], - conv_layers_dimensions=(16, 32, 64, 128), + conv_layers_dimensions=(16, 32, 64), dense_layers_dimensions=(32, 32), number_of_outputs=3, output_activation="sigmoid", @@ -51,7 +51,7 @@ def test_Convolutions_with_multiple_inputs(self): def test_Convolutions_with_no_dense_top(self): model = models.Convolutional( input_shape=(64, 64, 1), - conv_layers_dimensions=(16, 32, 64, 128), + conv_layers_dimensions=(16, 32, 64), dense_layers_dimensions=(32, 32), dense_top=False, number_of_outputs=3, @@ -65,7 +65,7 @@ def test_Convolutions_with_no_dense_top(self): def test_UNet(self): model = models.UNet( input_shape=(64, 64, 1), - conv_layers_dimensions=(16, 32, 64, 128), + conv_layers_dimensions=(16, 32, 64), base_conv_layers_dimensions=(256, 256), output_conv_layers_dimensions=(32, 32), steps_per_pooling=1, From 3463a6786ac40efcf041a78288d2b2e649594c47 Mon Sep 17 00:00:00 2001 From: Benjamin Midtvedt Date: Thu, 25 Feb 2021 17:21:09 +0100 Subject: [PATCH 46/78] Added arraylike type --- deeptrack/types.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/deeptrack/types.py b/deeptrack/types.py index 6ebfce10f..b7b8e305f 100644 --- a/deeptrack/types.py +++ b/deeptrack/types.py @@ -2,7 +2,10 @@ """ import typing +import numpy as np # Property type declaration T = typing.TypeVar("T") PropertyLike = typing.Union[T, typing.Callable[..., T]] + +ArrayLike = typing.Union[typing.Tuple[T], typing.List[T], np.ndarray] \ No newline at end of file From 8c844b95ad523b9b3ffc46048bb9d9319e7bfd75 Mon Sep 17 00:00:00 2001 From: Benjamin Midtvedt Date: Thu, 25 Feb 2021 17:21:17 +0100 Subject: [PATCH 47/78] Added typings --- deeptrack/augmentations.py | 61 ++++++++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 22 deletions(-) diff --git a/deeptrack/augmentations.py b/deeptrack/augmentations.py index e8584403e..4f15bb108 100644 --- a/deeptrack/augmentations.py +++ b/deeptrack/augmentations.py @@ -22,6 +22,7 @@ from .features import Feature from .image import Image from . import utils +from .types import ArrayLike, PropertyLike import numpy as np import scipy.ndimage as ndimage @@ -70,8 +71,8 @@ class Augmentation(Feature): def __init__( self, feature: Feature = None, - load_size: int = 1, - updates_per_reload: int = 1, + load_size: PropertyLike[int] = 1, + updates_per_reload: PropertyLike[int] = 1, update_properties: Callable or None = None, **kwargs ): @@ -341,14 +342,14 @@ class Affine(Augmentation): def __init__( self, - scale=1, - translate=None, - translate_px=0, - rotate=0, - shear=0, - order=1, - cval=0, - mode="reflect", + scale: PropertyLike[float or ArrayLike[float]] = 1, + translate: PropertyLike[float or ArrayLike[float] or None] = None, + translate_px: PropertyLike[float or ArrayLike[float]] = 0, + rotate: PropertyLike[float or ArrayLike[float]] = 0, + shear: PropertyLike[float or ArrayLike[float]] = 0, + order: PropertyLike[int] = 1, + cval: PropertyLike[float] = 0, + mode: PropertyLike[str] = "reflect", **kwargs ): if translate is None: @@ -526,12 +527,12 @@ class ElasticTransformation(Augmentation): def __init__( self, - alpha=20, - sigma=2, - ignore_last_dim=True, - order=3, - cval=0, - mode="constant", + alpha: PropertyLike[float] = 20, + sigma: PropertyLike[float] = 2, + ignore_last_dim: PropertyLike[bool] = True, + order: PropertyLike[int] = 3, + cval: PropertyLike[float] = 0, + mode: PropertyLike[str] = "constant", **kwargs ): super().__init__( @@ -617,7 +618,12 @@ class Crop(Augmentation): """ def __init__( - self, *args, crop=(64, 64), crop_mode="retain", corner="random", **kwargs + self, + *args, + crop: PropertyLike[int or ArrayLike[int]] = (64, 64), + crop_mode: PropertyLike[str] = "retain", + corner: PropertyLike[str] = "random", + **kwargs ): super().__init__(*args, crop=crop, crop_mode=crop_mode, corner=corner, **kwargs) @@ -692,7 +698,12 @@ class CropToMultiplesOf(Crop): """ - def __init__(self, multiple=1, corner="random", **kwargs): + def __init__( + self, + multiple: PropertyLike[int or ArrayLike[int] or None] = 1, + corner: PropertyLike[str] = "random", + **kwargs + ): kwargs.pop("crop", False) kwargs.pop("crop_mode", False) @@ -705,7 +716,7 @@ def image_to_crop(image): new_shape = list(shape) idx = 0 for dim, mul in zip(shape, multiple): - if mul is not None and mul is not -1: + if mul is not None and mul != -1: new_shape[idx] = int((dim // mul) * mul) idx += 1 @@ -733,7 +744,13 @@ class Pad(Augmentation): """ - def __init__(self, px=(0, 0, 0, 0), mode="constant", cval=0, **kwargs): + def __init__( + self, + px: PropertyLike[int or ArrayLike[int]] = (0, 0, 0, 0), + mode: PropertyLike[str] = "constant", + cval: PropertyLike[float] = 0, + **kwargs + ): super().__init__(px=px, mode=mode, cval=cval, **kwargs) def get(self, image, px, **kwargs): @@ -785,7 +802,7 @@ class PadToMultiplesOf(Pad): """ - def __init__(self, multiple=1, **kwargs): + def __init__(self, multiple: PropertyLike[int or None] = 1, **kwargs): def amount_to_pad(image): shape = image.shape multiple = self.multiple.current_value @@ -795,7 +812,7 @@ def amount_to_pad(image): new_shape = [0] * (image.ndim * 2) idx = 0 for dim, mul in zip(shape, multiple): - if mul is not None and mul is not -1: + if mul is not None and mul != -1: to_add = -dim % mul to_add_first = to_add // 2 to_add_after = to_add - to_add_first From 4f7c91c59fe2d5ded678c7da7e044e48eef4e983 Mon Sep 17 00:00:00 2001 From: Benjamin Midtvedt Date: Thu, 25 Feb 2021 18:04:46 +0100 Subject: [PATCH 48/78] Type annotations --- deeptrack/math.py | 58 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 42 insertions(+), 16 deletions(-) diff --git a/deeptrack/math.py b/deeptrack/math.py index bb24d453e..70e3ec8bb 100644 --- a/deeptrack/math.py +++ b/deeptrack/math.py @@ -8,9 +8,11 @@ Min-max image normalization. """ +from typing import Callable, List from .features import Feature from .image import Image from . import utils +from .types import PropertyLike import numpy as np import skimage import skimage.measure @@ -26,7 +28,7 @@ class Add(Feature): The value to add """ - def __init__(self, value=0, **kwargs): + def __init__(self, value: PropertyLike[float] = 0, **kwargs): super().__init__(value=value, **kwargs) def get(self, image, value, **kwargs): @@ -42,7 +44,7 @@ class Subtract(Feature): The value to subtract """ - def __init__(self, value=0, **kwargs): + def __init__(self, value: PropertyLike[float] = 0, **kwargs): super().__init__(value=value, **kwargs) def get(self, image, value, **kwargs): @@ -58,7 +60,7 @@ class Multiply(Feature): The value to multiply with. """ - def __init__(self, value=0, **kwargs): + def __init__(self, value: PropertyLike[float] = 0, **kwargs): super().__init__(value=value, **kwargs) def get(self, image, value, **kwargs): @@ -74,7 +76,7 @@ class Divide(Feature): The value to divide with. """ - def __init__(self, value=0, **kwargs): + def __init__(self, value: PropertyLike[float] = 0, **kwargs): super().__init__(value=value, **kwargs) def get(self, image, value, **kwargs): @@ -90,7 +92,7 @@ class Power(Feature): The power to raise with. """ - def __init__(self, value=0, **kwargs): + def __init__(self, value: PropertyLike[float] = 0, **kwargs): super().__init__(value=value, **kwargs) def get(self, image, value, **kwargs): @@ -112,7 +114,12 @@ class Average(Feature): __distributed__ = False - def __init__(self, features=None, axis=0, **kwargs): + def __init__( + self, + features=PropertyLike[List[Feature] or None], + axis: PropertyLike[int] = 0, + **kwargs + ): super().__init__(axis=axis, features=features, **kwargs) def get(self, images, axis, features, **kwargs): @@ -137,7 +144,12 @@ class Clip(Feature): Clip the input to be smaller than this value. """ - def __init__(self, min=-np.inf, max=+np.inf, **kwargs): + def __init__( + self, + min: PropertyLike[float] = -np.inf, + max: PropertyLike[float] = +np.inf, + **kwargs + ): super().__init__(min=min, max=max, **kwargs) def get(self, image, min=None, max=None, **kwargs): @@ -158,7 +170,9 @@ class NormalizeMinMax(Feature): The maximum of the transformation. """ - def __init__(self, min=0, max=1, **kwargs): + def __init__( + self, min: PropertyLike[float] = 0, max: PropertyLike[float] = 1, **kwargs + ): super().__init__(min=min, max=max, **kwargs) def get(self, image, min, max, **kwargs): @@ -169,7 +183,9 @@ def get(self, image, min, max, **kwargs): class Blur(Feature): - def __init__(self, filter_function, mode="reflect", **kwargs): + def __init__( + self, filter_function: Callable, mode: PropertyLike[str] = "reflect", **kwargs + ): self.filter = filter_function super().__init__(borderType=mode, **kwargs) @@ -189,7 +205,7 @@ class AverageBlur(Blur): Kernel size to use. """ - def __init__(self, ksize=3, **kwargs): + def __init__(self, ksize: PropertyLike[int] = 3, **kwargs): super().__init__(None, ksize=ksize, **kwargs) def get(self, input, ksize, **kwargs): @@ -214,7 +230,7 @@ class GaussianBlur(Blur): """ - def __init__(self, sigma=2, **kwargs): + def __init__(self, sigma: PropertyLike[float] = 2, **kwargs): super().__init__(ndimage.gaussian_filter, sigma=sigma, **kwargs) @@ -228,7 +244,7 @@ class MedianBlur(Blur): """ - def __init__(self, ksize=3, **kwargs): + def __init__(self, ksize: PropertyLike[int] = 3, **kwargs): super().__init__(ndimage.median_filter, k=ksize, **kwargs) @@ -253,7 +269,9 @@ class Pool(Feature): Additional parameters sent to the pooling function. """ - def __init__(self, pooling_function, ksize=3, **kwargs): + def __init__( + self, pooling_function: Callable, ksize: PropertyLike[int] = 3, **kwargs + ): self.pooling = pooling_function super().__init__(ksize=ksize, **kwargs) @@ -283,7 +301,7 @@ class AveragePooling(Pool): Additional parameters sent to the pooling function. """ - def __init__(self, ksize=3, **kwargs): + def __init__(self, ksize: PropertyLike[int] = 3, **kwargs): super().__init__(np.mean, ksize=ksize, **kwargs) @@ -314,7 +332,9 @@ def __new__(cls, *args, **kwargs): return super(BlurCV2, cls).__new__(*args, **kwargs) - def __init__(self, filter_function, mode="refelct", **kwargs): + def __init__( + self, filter_function: Callable, mode: PropertyLike[str] = "refelct", **kwargs + ): self.filter = filter_function borderType = _map_mode_to_cv2_borderType[mode] super().__init__(borderType=borderType, **kwargs) @@ -352,7 +372,13 @@ class BilateralBlur(Blur): """ - def __init__(self, d=3, sigma_color=50, sigma_space=50, **kwargs): + def __init__( + self, + d: PropertyLike[int] = 3, + sigma_color: PropertyLike[float] = 50, + sigma_space: PropertyLike[float] = 50, + **kwargs + ): super().__init__( cv2.bilateralFilter, d=d, From 54323102bd57d718b8adfc6838275c841b6e8f51 Mon Sep 17 00:00:00 2001 From: Benjamin Midtvedt Date: Thu, 25 Feb 2021 18:04:51 +0100 Subject: [PATCH 49/78] Type annotations --- deeptrack/features.py | 53 ++++++++++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/deeptrack/features.py b/deeptrack/features.py index 213bfd533..d9fcec921 100644 --- a/deeptrack/features.py +++ b/deeptrack/features.py @@ -22,12 +22,13 @@ import copy -from typing import List +from typing import Any, Callable, Iterator, List, Tuple import numpy as np import threading from .image import Image from .properties import Property, PropertyDict +from .types import PropertyLike, ArrayLike MERGE_STRATEGY_OVERRIDE = 0 @@ -473,7 +474,9 @@ class Probability(StructuralFeature): Probability to resolve """ - def __init__(self, feature: Feature, probability: float, *args, **kwargs): + def __init__( + self, feature: Feature, probability: PropertyLike[float], *args, **kwargs + ): super().__init__( *args, feature=feature, @@ -510,7 +513,9 @@ class Duplicate(StructuralFeature): The number of duplicates to create """ - def __init__(self, feature: Feature, num_duplicates: int, *args, **kwargs): + def __init__( + self, feature: Feature, num_duplicates: PropertyLike[int], *args, **kwargs + ): self.feature = feature super().__init__( @@ -572,7 +577,7 @@ class Combine(StructuralFeature): __distribute__ = False - def __init__(self, features=[], **kwargs): + def __init__(self, features=List[Feature], **kwargs): super().__init__(features=features, **kwargs) def get(self, image_list, features, **kwargs): @@ -650,7 +655,7 @@ class ConditionalSetProperty(StructuralFeature): __distributed__ = False - def __init__(self, feature: Feature, condition="is_label", **kwargs): + def __init__(self, feature: Feature, condition=PropertyLike[str], **kwargs): super().__init__(feature=feature, condition=condition, **kwargs) def get(self, image, feature, condition, **kwargs): @@ -692,7 +697,7 @@ def __init__( self, on_false: Feature = None, on_true: Feature = None, - condition="is_label", + condition: PropertyLike[str] = "is_label", **kwargs ): @@ -728,7 +733,7 @@ class Lambda(Feature): Function that takes the current image as first input """ - def __init__(self, function, **kwargs): + def __init__(self, function: Callable[..., Callable[[Image], Image]], **kwargs): super().__init__(function=function, **kwargs) def get(self, image, function, **kwargs): @@ -751,7 +756,11 @@ class Merge(Feature): __distributed__ = False - def __init__(self, function, **kwargs): + def __init__( + self, + function: Callable[..., Callable[[List[Image]], Image or List[Image]]], + **kwargs + ): super().__init__(function=function, **kwargs) def get(self, list_of_images, function, **kwargs): @@ -776,7 +785,9 @@ class Dataset(Feature): __distributed__ = False - def __init__(self, data, **kwargs): + def __init__( + self, data: Iterator or PropertyLike[float or ArrayLike[float]], **kwargs + ): super().__init__(data=data, **kwargs) def get(self, *ignore, data, **kwargs): @@ -809,7 +820,7 @@ class Label(Feature): __distributed__ = False - def __init__(self, output_shape=None, **kwargs): + def __init__(self, output_shape: PropertyLike[int] = None, **kwargs): super().__init__(output_shape=output_shape, **kwargs) def get(self, image, output_shape=None, hash_key=None, **kwargs): @@ -856,12 +867,12 @@ class LoadImage(Feature): def __init__( self, - path, - load_options=None, - as_list=False, - ndim=None, - to_grayscale=False, - get_one_random=False, + path: PropertyLike[str or List[str]], + load_options: PropertyLike[dict] = None, + as_list: PropertyLike[bool] = False, + ndim: PropertyLike[int] = None, + to_grayscale: PropertyLike[bool] = False, + get_one_random: PropertyLike[bool] = False, **kwargs ): super().__init__( @@ -977,10 +988,10 @@ class SampleToMasks(Feature): def __init__( self, - transformation_function, - number_of_masks=1, - output_region=None, - merge_method="add", + transformation_function: Callable[..., Callable[[Image], Image]], + number_of_masks: PropertyLike[int] = 1, + output_region: PropertyLike[ArrayLike[int]] = None, + merge_method: PropertyLike[str] = "add", **kwargs ): super().__init__( @@ -1153,7 +1164,7 @@ class AsType(Feature): dtype string. Same as numpy dtype. """ - def __init__(self, dtype="float64", **kwargs): + def __init__(self, dtype: PropertyLike[Any] = "float64", **kwargs): super().__init__(dtype=dtype, **kwargs) def get(self, image, dtype, **kwargs): From 67b294722df0d7497386e3544d22f50a634a4814 Mon Sep 17 00:00:00 2001 From: Benjamin Midtvedt Date: Thu, 25 Feb 2021 19:16:50 +0100 Subject: [PATCH 50/78] Fully type-hinted --- deeptrack/noises.py | 15 ++++++++-- deeptrack/optics.py | 26 ++++++++++------ deeptrack/scatterers.py | 66 +++++++++++++++++++---------------------- deeptrack/sequences.py | 5 +++- setup.py | 2 +- 5 files changed, 65 insertions(+), 49 deletions(-) diff --git a/deeptrack/noises.py b/deeptrack/noises.py index 6801b3f5d..b47884985 100644 --- a/deeptrack/noises.py +++ b/deeptrack/noises.py @@ -15,6 +15,7 @@ import numpy as np from .features import Feature from .image import Image +from .types import PropertyLike class Noise(Feature): @@ -29,7 +30,7 @@ class Background(Noise): The value to add to the image """ - def __init__(self, offset, **kwargs): + def __init__(self, offset: PropertyLike[float], **kwargs): super().__init__(offset=offset, **kwargs) def get(self, image, offset, **kwargs): @@ -51,7 +52,9 @@ class Gaussian(Noise): The root of the variance of the distribution. """ - def __init__(self, mu=0, sigma=1, **kwargs): + def __init__( + self, mu: PropertyLike[float] = 0, sigma: PropertyLike[float] = 1, **kwargs + ): super().__init__(mu=mu, sigma=sigma, **kwargs) def get(self, image, mu, sigma, **kwargs): @@ -73,7 +76,13 @@ class Poisson(Noise): signal of the image. """ - def __init__(self, *args, snr=100, background=0, **kwargs): + def __init__( + self, + *args, + snr: PropertyLike[float] = 100, + background: PropertyLike[float] = 0, + **kwargs + ): super().__init__(*args, snr=snr, background=background, **kwargs) def get(self, image, snr, background, **kwargs): diff --git a/deeptrack/optics.py b/deeptrack/optics.py index fac9fd15f..249fd24c9 100644 --- a/deeptrack/optics.py +++ b/deeptrack/optics.py @@ -18,6 +18,7 @@ import numpy as np from .features import Feature, StructuralFeature from .image import Image, pad_image_to_fft +from .types import ArrayLike, PropertyLike from scipy.ndimage import convolve @@ -146,14 +147,14 @@ class Optics(Feature): def __init__( self, - NA=0.7, - wavelength=0.66e-6, - magnification=10, - resolution=(1e-6, 1e-6, 1e-6), - refractive_index_medium=1.33, - upscale=1, - padding=(10, 10, 10, 10), - output_region=(0, 0, 128, 128), + NA: PropertyLike[float] = 0.7, + wavelength: PropertyLike[float] = 0.66e-6, + magnification: PropertyLike[float] = 10, + resolution: PropertyLike[float or ArrayLike[float]] = (1e-6, 1e-6, 1e-6), + refractive_index_medium: PropertyLike[float] = 1.33, + upscale: PropertyLike[float] = 1, + padding: PropertyLike[ArrayLike[int]] = (10, 10, 10, 10), + output_region: PropertyLike[ArrayLike[int]] = (0, 0, 128, 128), pupil: Feature = None, **kwargs ): @@ -651,7 +652,14 @@ class IlluminationGradient(Feature): """ - def __init__(self, gradient=(0, 0), constant=0, vmin=0, vmax=np.inf, **kwargs): + def __init__( + self, + gradient: PropertyLike[ArrayLike[float]] = (0, 0), + constant: PropertyLike[float] = 0, + vmin: PropertyLike[float] = 0, + vmax: PropertyLike[float] = np.inf, + **kwargs + ): super().__init__( gradient=gradient, constant=constant, vmin=vmin, vmax=vmax, **kwargs ) diff --git a/deeptrack/scatterers.py b/deeptrack/scatterers.py index 2ab996bb1..ccd030ee1 100644 --- a/deeptrack/scatterers.py +++ b/deeptrack/scatterers.py @@ -18,12 +18,14 @@ """ +from typing import Callable, Tuple import numpy as np from . import backend as D from .features import Feature, MERGE_STRATEGY_APPEND from .image import Image from . import image +from .types import PropertyLike, ArrayLike import warnings @@ -70,11 +72,11 @@ class Scatterer(Feature): def __init__( self, - position=(32, 32), - z=0.0, - value=1.0, - position_unit="pixel", - upsample=1, + position: PropertyLike[ArrayLike[float]] = (32, 32), + z: PropertyLike[float] = 0.0, + value: PropertyLike[float] = 1.0, + position_unit: PropertyLike[str] = "pixel", + upsample: PropertyLike[int] = 1, **kwargs ): self._processed_properties = False @@ -228,7 +230,12 @@ class Ellipse(Scatterer): Upsamples the calculations of the pixel occupancy fraction. """ - def __init__(self, radius=1e-6, rotation=0, **kwargs): + def __init__( + self, + radius: PropertyLike[float] = 1e-6, + rotation: PropertyLike[float] = 0, + **kwargs + ): super().__init__( radius=radius, rotation=rotation, upsample_axes=(0, 1), **kwargs ) @@ -296,7 +303,7 @@ class Sphere(Scatterer): Upsamples the calculations of the pixel occupancy fraction. """ - def __init__(self, radius=1e-6, **kwargs): + def __init__(self, radius: PropertyLike[float] = 1e-6, **kwargs): super().__init__(radius=radius, **kwargs) def get(self, image, radius, voxel_size, **kwargs): @@ -339,7 +346,12 @@ class Ellipsoid(Scatterer): Upsamples the calculations of the pixel occupancy fraction. """ - def __init__(self, radius=1e-6, rotation=0, **kwargs): + def __init__( + self, + radius: PropertyLike[float] = 1e-6, + rotation: PropertyLike[float] = 0, + **kwargs + ): super().__init__(radius=radius, rotation=rotation, **kwargs) def _process_properties(self, propertydict): @@ -468,11 +480,11 @@ class MieScatterer(Scatterer): def __init__( self, - coefficients, - offset_z="auto", - polarization_angle=0, - collection_angle="auto", - L="auto", + coefficients: Callable[..., Callable[[int], Tuple[ArrayLike, ArrayLike]]], + offset_z: PropertyLike[str] = "auto", + polarization_angle: PropertyLike[float] = 0, + collection_angle: PropertyLike[str] = "auto", + L: PropertyLike[str] = "auto", **kwargs ): kwargs.pop("is_field", None) @@ -627,12 +639,8 @@ class MieSphere(MieScatterer): def __init__( self, - radius=1e-6, - refractive_index=1.45, - offset_z="auto", - polarization_angle=0, - collection_angle="auto", - L="auto", + radius: PropertyLike[float] = 1e-6, + refractive_index: PropertyLike[float] = 1.45, **kwargs ): def coeffs(radius, refractive_index, refractive_index_medium, wavelength): @@ -649,10 +657,6 @@ def inner(L): coefficients=coeffs, radius=radius, refractive_index=refractive_index, - L=L, - offset_z=offset_z, - polarization_angle=polarization_angle, - collection_angle=collection_angle, **kwargs ) @@ -672,9 +676,9 @@ class MieStratifiedSphere(MieScatterer): Parameters ---------- - radius : float + radius : list of float The radius of each cell in increasing order. - refractive_index : float + refractive_index : list of float Refractive index of each cell in the same order as `radius` L : int or str The number of terms used to evaluate the mie theory. If `"auto"`, @@ -700,12 +704,8 @@ class MieStratifiedSphere(MieScatterer): def __init__( self, - radius=1e-6, - refractive_index=1.45, - offset_z="auto", - polarization_angle=0, - collection_angle="auto", - L="auto", + radius: PropertyLike[ArrayLike[float]] = [1e-6], + refractive_index: PropertyLike[ArrayLike[float]] = [1.45], **kwargs ): def coeffs(radius, refractive_index, refractive_index_medium, wavelength): @@ -726,9 +726,5 @@ def inner(L): coefficients=coeffs, radius=radius, refractive_index=refractive_index, - L=L, - offset_z=offset_z, - polarization_angle=polarization_angle, - collection_angle=collection_angle, **kwargs ) diff --git a/deeptrack/sequences.py b/deeptrack/sequences.py index 6cc9f4159..6dd9b6077 100644 --- a/deeptrack/sequences.py +++ b/deeptrack/sequences.py @@ -13,6 +13,7 @@ from .features import Feature from .properties import SequentialProperty +from .types import PropertyLike class Sequence(Feature): @@ -37,7 +38,9 @@ class Sequence(Feature): __distributed__ = False - def __init__(self, feature: Feature, sequence_length: int = 1, **kwargs): + def __init__( + self, feature: Feature, sequence_length: PropertyLike[int] = 1, **kwargs + ): self.feature = feature super().__init__(sequence_length=sequence_length, **kwargs) diff --git a/setup.py b/setup.py index 21e7204c0..4b9c917ff 100644 --- a/setup.py +++ b/setup.py @@ -16,7 +16,7 @@ setuptools.setup( name="deeptrack", # Replace with your own username - version="0.9.0.dev0", + version="0.9.1", author="Benjamin Midtvedt", author_email="benjamin.midtvedt@physics.gu.se", description="A deep learning oriented microscopy image simulation package", From 7a937a847b830b75a218520f37086133a60aefda Mon Sep 17 00:00:00 2001 From: Benjamin Midtvedt Date: Wed, 24 Mar 2021 21:28:42 +0100 Subject: [PATCH 51/78] Swapped position index for miespheres --- deeptrack/scatterers.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deeptrack/scatterers.py b/deeptrack/scatterers.py index ccd030ee1..0afed8649 100644 --- a/deeptrack/scatterers.py +++ b/deeptrack/scatterers.py @@ -558,8 +558,8 @@ def get( arr = image.pad_image_to_fft(np.zeros((xSize, ySize))) # Evluation grid - x = np.arange(-padding[0], arr.shape[0] - padding[0]) - (position[1]) * upscale - y = np.arange(-padding[1], arr.shape[1] - padding[1]) - (position[0]) * upscale + x = np.arange(-padding[0], arr.shape[0] - padding[0]) - (position[0]) * upscale + y = np.arange(-padding[1], arr.shape[1] - padding[1]) - (position[1]) * upscale X, Y = np.meshgrid(x * voxel_size[0], y * voxel_size[1], indexing="ij") R2 = np.sqrt(X ** 2 + Y ** 2) From ba3bca18e938b25c3816e55e747b143cb80ad6ba Mon Sep 17 00:00:00 2001 From: Benjamin Midtvedt Date: Wed, 24 Mar 2021 21:28:52 +0100 Subject: [PATCH 52/78] Call update before first resolve --- .../tracking_particle_cnn_tutorial.ipynb | 1079 +++-------------- 1 file changed, 202 insertions(+), 877 deletions(-) diff --git a/tutorials/tracking_particle_cnn_tutorial.ipynb b/tutorials/tracking_particle_cnn_tutorial.ipynb index 01bbf8c9d..8c6a60bda 100644 --- a/tutorials/tracking_particle_cnn_tutorial.ipynb +++ b/tutorials/tracking_particle_cnn_tutorial.ipynb @@ -112,11 +112,12 @@ "IMAGE_SIZE = 64\n", "\n", "brightfield_microscope = dt.Brightfield(\n", - " NA=1.3, \n", + " NA=0.9, \n", " resolution=1e-6, \n", - " magnification=5,\n", + " magnification=10,\n", " wavelength=680e-9,\n", " output_region=(0, 0, IMAGE_SIZE, IMAGE_SIZE),\n", + " padding=(32, 32, 32, 32),\n", " upscale=2\n", ")" ] @@ -139,7 +140,7 @@ "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ "
        " ] @@ -153,7 +154,7 @@ "source": [ "imaged_particle = brightfield_microscope(mie_particle)\n", "\n", - "output_image = imaged_particle.resolve()\n", + "output_image = imaged_particle.update().resolve()\n", "\n", "plt.imshow(np.squeeze(output_image), cmap='gray')\n", "plt.show()" @@ -178,7 +179,7 @@ { "data": { "text/plain": [ - "" + "" ] }, "execution_count": 6, @@ -187,7 +188,7 @@ }, { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ "
        " ] @@ -213,7 +214,7 @@ "# Normalize each image between 0 and 1.\n", "normalized_image_of_particle = imaged_particle_with_random_position + dt.NormalizeMinMax(0, 1) \n", "\n", - "output_image = imaged_particle_with_random_position.resolve()\n", + "output_image = imaged_particle_with_random_position.update().resolve()\n", "\n", "plt.imshow(np.squeeze(output_image), cmap='gray')" ] @@ -234,7 +235,7 @@ "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ "
        " ] @@ -294,7 +295,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Model: \"functional_1\"\n", + "Model: \"model\"\n", "_________________________________________________________________\n", "Layer (type) Output Shape Param # \n", "=================================================================\n", @@ -394,831 +395,197 @@ "\n", "The model is trained by calling the method `.fit()` with the generator we defined in the previous step. Be patient, this might take some time (several minutes).\n", "\n", - "If you are training on a CPU, consider reducing the number of epochs to around 100. The gain after that is marginal." + "If you are training on a CPU, consider reducing the number of epochs to around 50. The gain after that is marginal." ] }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Generating 1041 / 1024 samples before starting training\n", - "Epoch 1/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0783\n", - "Epoch 2/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0260\n", - "Epoch 3/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0207\n", - "Epoch 4/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0207\n", - "Epoch 5/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0167\n", - "Epoch 6/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0157\n", - "Epoch 7/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0123\n", - "Epoch 8/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0139\n", - "Epoch 9/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0142\n", - "Epoch 10/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0118\n", - "Epoch 11/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0121\n", - "Epoch 12/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0121\n", - "Epoch 13/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0115\n", - "Epoch 14/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0114\n", - "Epoch 15/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0121\n", - "Epoch 16/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0119\n", - "Epoch 17/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0104\n", - "Epoch 18/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0133\n", - "Epoch 19/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0120\n", - "Epoch 20/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0101\n", - "Epoch 21/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0096\n", - "Epoch 22/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0104\n", - "Epoch 23/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0100\n", - "Epoch 24/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0092\n", - "Epoch 25/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0087\n", - "Epoch 26/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0100\n", - "Epoch 27/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0095\n", - "Epoch 28/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0105\n", - "Epoch 29/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0094\n", - "Epoch 30/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0086\n", - "Epoch 31/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0084\n", - "Epoch 32/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0103\n", - "Epoch 33/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0088\n", - "Epoch 34/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0092\n", - "Epoch 35/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0077\n", - "Epoch 36/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0085\n", - "Epoch 37/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0092\n", - "Epoch 38/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0085\n", - "Epoch 39/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0083\n", - "Epoch 40/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0083\n", - "Epoch 41/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0074\n", - "Epoch 42/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0084\n", - "Epoch 43/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0073\n", - "Epoch 44/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0079\n", - "Epoch 45/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0073\n", - "Epoch 46/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0083\n", - "Epoch 47/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0080\n", - "Epoch 48/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0075\n", - "Epoch 49/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0076\n", - "Epoch 50/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0080\n", - "Epoch 51/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0077\n", - "Epoch 52/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0079\n", - "Epoch 53/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0068\n", - "Epoch 54/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0070\n", - "Epoch 55/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0079\n", - "Epoch 56/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0066\n", - "Epoch 57/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0069\n", - "Epoch 58/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0069\n", - "Epoch 59/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0069\n", - "Epoch 60/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0068\n", - "Epoch 61/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0063\n", - "Epoch 62/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0066\n", - "Epoch 63/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0070\n", - "Epoch 64/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0074\n", - "Epoch 65/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0083\n", - "Epoch 66/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0073\n", - "Epoch 67/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0061\n", - "Epoch 68/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0061\n", - "Epoch 69/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0061\n", - "Epoch 70/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0057\n", - "Epoch 71/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0068\n", - "Epoch 72/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0071\n", - "Epoch 73/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0067\n", - "Epoch 74/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0058\n", - "Epoch 75/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0061\n", - "Epoch 76/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0063\n", - "Epoch 77/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0056\n", - "Epoch 78/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0061\n", - "Epoch 79/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0063\n", - "Epoch 80/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0053\n", - "Epoch 81/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0061\n", - "Epoch 82/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0066\n", - "Epoch 83/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0054\n", - "Epoch 84/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0054\n", - "Epoch 85/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0063\n", - "Epoch 86/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0064\n", - "Epoch 87/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0054\n", - "Epoch 88/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0064\n", - "Epoch 89/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0056\n", - "Epoch 90/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0058\n", - "Epoch 91/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0061\n", - "Epoch 92/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0057\n", - "Epoch 93/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0059\n", - "Epoch 94/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0056\n", - "Epoch 95/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0047\n", - "Epoch 96/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0060\n", - "Epoch 97/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0058\n", - "Epoch 98/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0051\n", - "Epoch 99/400\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "260/260 [==============================] - 1s 4ms/step - loss: 0.0054\n", - "Epoch 100/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0049\n", - "Epoch 101/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0055\n", - "Epoch 102/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0060\n", - "Epoch 103/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0050\n", - "Epoch 104/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0056\n", - "Epoch 105/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0050\n", - "Epoch 106/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0053\n", - "Epoch 107/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0051\n", - "Epoch 108/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0059\n", - "Epoch 109/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0057\n", - "Epoch 110/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0053\n", - "Epoch 111/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0051\n", - "Epoch 112/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0052\n", - "Epoch 113/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0047\n", - "Epoch 114/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0057\n", - "Epoch 115/400\n", - "260/260 [==============================] - 2s 6ms/step - loss: 0.0050\n", - "Epoch 116/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0052\n", - "Epoch 117/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0049\n", - "Epoch 118/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0053\n", - "Epoch 119/400\n", - "260/260 [==============================] - 2s 6ms/step - loss: 0.0044\n", - "Epoch 120/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0051\n", - "Epoch 121/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0047\n", - "Epoch 122/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0047\n", - "Epoch 123/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0054\n", - "Epoch 124/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0048\n", - "Epoch 125/400\n", - "260/260 [==============================] - 1s 6ms/step - loss: 0.0055\n", - "Epoch 126/400\n", - "260/260 [==============================] - 2s 6ms/step - loss: 0.0051\n", - "Epoch 127/400\n", - "260/260 [==============================] - 1s 6ms/step - loss: 0.0050\n", - "Epoch 128/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0053\n", - "Epoch 129/400\n", - "260/260 [==============================] - 2s 6ms/step - loss: 0.0048\n", - "Epoch 130/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0051\n", - "Epoch 131/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0049\n", - "Epoch 132/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0057\n", - "Epoch 133/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0046\n", - "Epoch 134/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0050\n", - "Epoch 135/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0051\n", - "Epoch 136/400\n", - "260/260 [==============================] - 1s 6ms/step - loss: 0.0048\n", - "Epoch 137/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0046\n", - "Epoch 138/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0046\n", - "Epoch 139/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0045\n", - "Epoch 140/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0047\n", - "Epoch 141/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0045\n", - "Epoch 142/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0041\n", - "Epoch 143/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0052\n", - "Epoch 144/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0054\n", - "Epoch 145/400\n", - "260/260 [==============================] - ETA: 0s - loss: 0.005 - 1s 5ms/step - loss: 0.0051\n", - "Epoch 146/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0054\n", - "Epoch 147/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0046\n", - "Epoch 148/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0050\n", - "Epoch 149/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0058\n", - "Epoch 150/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0053\n", - "Epoch 151/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0047\n", - "Epoch 152/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0052\n", - "Epoch 153/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0048\n", - "Epoch 154/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0048\n", - "Epoch 155/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0050\n", - "Epoch 156/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0045\n", - "Epoch 157/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0049\n", - "Epoch 158/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0052\n", - "Epoch 159/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0053\n", - "Epoch 160/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0046\n", - "Epoch 161/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0041\n", - "Epoch 162/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0047A\n", - "Epoch 163/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0048\n", - "Epoch 164/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0046\n", - "Epoch 165/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0049\n", - "Epoch 166/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0047\n", - "Epoch 167/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0037\n", - "Epoch 168/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0042\n", - "Epoch 169/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0044\n", - "Epoch 170/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0047\n", - "Epoch 171/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0044\n", - "Epoch 172/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0042\n", - "Epoch 173/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0044\n", - "Epoch 174/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0048\n", - "Epoch 175/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0044\n", - "Epoch 176/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0041\n", - "Epoch 177/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0038\n", - "Epoch 178/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0056\n", - "Epoch 179/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0051\n", - "Epoch 180/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0045\n", - "Epoch 181/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0048\n", - "Epoch 182/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0045\n", - "Epoch 183/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0040\n", - "Epoch 184/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0045\n", - "Epoch 185/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0045\n", - "Epoch 186/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0046\n", - "Epoch 187/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0042\n", - "Epoch 188/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0046\n", - "Epoch 189/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0042\n", - "Epoch 190/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0039\n", - "Epoch 191/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0041\n", - "Epoch 192/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0043\n", - "Epoch 193/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0049\n", - "Epoch 194/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0042\n", - "Epoch 195/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0046\n", - "Epoch 196/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0040\n", - "Epoch 197/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0039\n", - "Epoch 198/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0041\n", - "Epoch 199/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0042\n", - "Epoch 200/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0046\n", - "Epoch 201/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0041\n", - "Epoch 202/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0043\n", - "Epoch 203/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0041\n", - "Epoch 204/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0040\n", - "Epoch 205/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0044\n", - "Epoch 206/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0038\n", - "Epoch 207/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0042\n", - "Epoch 208/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0046\n", - "Epoch 209/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0038\n", - "Epoch 210/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0038\n", - "Epoch 211/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0046\n", - "Epoch 212/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0045\n", - "Epoch 213/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0042\n", - "Epoch 214/400\n", - "260/260 [==============================] - 2s 6ms/step - loss: 0.0043\n", - "Epoch 215/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0040\n", - "Epoch 216/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0040\n", - "Epoch 217/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0041\n", - "Epoch 218/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0035\n", - "Epoch 219/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0037\n", - "Epoch 220/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0045\n", - "Epoch 221/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0040\n", - "Epoch 222/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0042\n", - "Epoch 223/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0041\n", - "Epoch 224/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0038\n", - "Epoch 225/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0042\n", - "Epoch 226/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0037\n", - "Epoch 227/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0036\n", - "Epoch 228/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0035\n", - "Epoch 229/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0042\n", - "Epoch 230/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0041\n", - "Epoch 231/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0037\n", - "Epoch 232/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0038\n", - "Epoch 233/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0039\n", - "Epoch 234/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0039\n", - "Epoch 235/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0038\n", - "Epoch 236/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0038\n", - "Epoch 237/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0036\n", - "Epoch 238/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0036\n", - "Epoch 239/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0039\n", - "Epoch 240/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0035\n", - "Epoch 241/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0041\n", - "Epoch 242/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0039\n", - "Epoch 243/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0035\n", - "Epoch 244/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0040\n", - "Epoch 245/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0040\n", - "Epoch 246/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0040\n", - "Epoch 247/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0036\n", - "Epoch 248/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0039\n", - "Epoch 249/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0041\n", - "Epoch 250/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0040\n", - "Epoch 251/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0037\n", - "Epoch 252/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0037\n", - "Epoch 253/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0037\n", - "Epoch 254/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0038\n", - "Epoch 255/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0034\n", - "Epoch 256/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0035\n", - "Epoch 257/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0036\n", - "Epoch 258/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0034\n", - "Epoch 259/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0032\n", - "Epoch 260/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0035\n", - "Epoch 261/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0041\n", - "Epoch 262/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0039\n", - "Epoch 263/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0039\n", - "Epoch 264/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0036\n", - "Epoch 265/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0036\n", - "Epoch 266/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0039\n", - "Epoch 267/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0039\n", - "Epoch 268/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0038\n", - "Epoch 269/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0034\n", - "Epoch 270/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0035\n", - "Epoch 271/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0035\n", - "Epoch 272/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0035\n", - "Epoch 273/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0038\n", - "Epoch 274/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0038\n", - "Epoch 275/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0037\n", - "Epoch 276/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0037\n", - "Epoch 277/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0039\n", - "Epoch 278/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0036\n", - "Epoch 279/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0041\n", - "Epoch 280/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0038\n", - "Epoch 281/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0035\n", - "Epoch 282/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0035\n", - "Epoch 283/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0039\n", - "Epoch 284/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0040\n", - "Epoch 285/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0042\n", - "Epoch 286/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0033\n", - "Epoch 287/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0034\n", - "Epoch 288/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0034\n", - "Epoch 289/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0035\n", - "Epoch 290/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0038\n", - "Epoch 291/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0036\n", - "Epoch 292/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0036\n", - "Epoch 293/400\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "260/260 [==============================] - 1s 4ms/step - loss: 0.0034\n", - "Epoch 294/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0035\n", - "Epoch 295/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0036\n", - "Epoch 296/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0033\n", - "Epoch 297/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0037\n", - "Epoch 298/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0040\n", - "Epoch 299/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0039\n", - "Epoch 300/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0037\n", - "Epoch 301/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0035\n", - "Epoch 302/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0035\n", - "Epoch 303/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0033\n", - "Epoch 304/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0035\n", - "Epoch 305/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0038\n", - "Epoch 306/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0035\n", - "Epoch 307/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0033\n", - "Epoch 308/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0040\n", - "Epoch 309/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0037\n", - "Epoch 310/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0034\n", - "Epoch 311/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0036\n", - "Epoch 312/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0032\n", - "Epoch 313/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0030\n", - "Epoch 314/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0031\n", - "Epoch 315/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0032\n", - "Epoch 316/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0036\n", - "Epoch 317/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0032\n", - "Epoch 318/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0036\n", - "Epoch 319/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0037\n", - "Epoch 320/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0034\n", - "Epoch 321/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0036\n", - "Epoch 322/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0035\n", - "Epoch 323/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0033\n", - "Epoch 324/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0029\n", - "Epoch 325/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0030\n", - "Epoch 326/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0033\n", - "Epoch 327/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0036\n", - "Epoch 328/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0035\n", - "Epoch 329/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0033\n", - "Epoch 330/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0031\n", - "Epoch 331/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0033\n", - "Epoch 332/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0032\n", - "Epoch 333/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0033\n", - "Epoch 334/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0037\n", - "Epoch 335/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0037\n", - "Epoch 336/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0033\n", - "Epoch 337/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0031\n", - "Epoch 338/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0035\n", - "Epoch 339/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0032\n", - "Epoch 340/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0037\n", - "Epoch 341/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0033\n", - "Epoch 342/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0033\n", - "Epoch 343/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0034\n", - "Epoch 344/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0030\n", - "Epoch 345/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0029\n", - "Epoch 346/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0033\n", - "Epoch 347/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0033\n", - "Epoch 348/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0031\n", - "Epoch 349/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0032\n", - "Epoch 350/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0036\n", - "Epoch 351/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0032\n", - "Epoch 352/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0036\n", - "Epoch 353/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0033\n", - "Epoch 354/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0030\n", - "Epoch 355/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0030\n", - "Epoch 356/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0038\n", - "Epoch 357/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0033\n", - "Epoch 358/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0032\n", - "Epoch 359/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0035\n", - "Epoch 360/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0037\n", - "Epoch 361/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0034\n", - "Epoch 362/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0035\n", - "Epoch 363/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0030\n", - "Epoch 364/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0031\n", - "Epoch 365/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0032\n", - "Epoch 366/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0032\n", - "Epoch 367/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0029\n", - "Epoch 368/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0031\n", - "Epoch 369/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0031\n", - "Epoch 370/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0031\n", - "Epoch 371/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0030\n", - "Epoch 372/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0033\n", - "Epoch 373/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0036\n", - "Epoch 374/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0032\n", - "Epoch 375/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0032\n", - "Epoch 376/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0030\n", - "Epoch 377/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0033\n", - "Epoch 378/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0032\n", - "Epoch 379/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0033\n", - "Epoch 380/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0029\n", - "Epoch 381/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0032\n", - "Epoch 382/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0030\n", - "Epoch 383/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0030\n", - "Epoch 384/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0032\n", - "Epoch 385/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0028\n", - "Epoch 386/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0034\n", - "Epoch 387/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0030\n", - "Epoch 388/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0034\n", - "Epoch 389/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0029\n", - "Epoch 390/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0028\n", - "Epoch 391/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0031\n", - "Epoch 392/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0032\n", - "Epoch 393/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0035\n", - "Epoch 394/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0032\n", - "Epoch 395/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0029\n", - "Epoch 396/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0033\n", - "Epoch 397/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0029\n", - "Epoch 398/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0039\n", - "Epoch 399/400\n", - "260/260 [==============================] - 1s 5ms/step - loss: 0.0035\n", - "Epoch 400/400\n", - "260/260 [==============================] - 1s 4ms/step - loss: 0.0030\n" + "Generating 1042 / 1024 samples before starting training\n", + "Epoch 1/100\n", + "260/260 [==============================] - 3s 4ms/step - loss: 0.1589\n", + "Epoch 2/100\n", + "260/260 [==============================] - 1s 4ms/step - loss: 0.0349\n", + "Epoch 3/100\n", + "260/260 [==============================] - 1s 4ms/step - loss: 0.0212\n", + "Epoch 4/100\n", + "260/260 [==============================] - 1s 5ms/step - loss: 0.0189\n", + "Epoch 5/100\n", + "260/260 [==============================] - 1s 5ms/step - loss: 0.0157\n", + "Epoch 6/100\n", + "260/260 [==============================] - 1s 5ms/step - loss: 0.0148\n", + "Epoch 7/100\n", + "260/260 [==============================] - 2s 6ms/step - loss: 0.0175\n", + "Epoch 8/100\n", + "260/260 [==============================] - 2s 6ms/step - loss: 0.0149\n", + "Epoch 9/100\n", + "260/260 [==============================] - 2s 6ms/step - loss: 0.0134\n", + "Epoch 10/100\n", + "260/260 [==============================] - 2s 7ms/step - loss: 0.0130\n", + "Epoch 11/100\n", + "260/260 [==============================] - 2s 7ms/step - loss: 0.0127\n", + "Epoch 12/100\n", + "260/260 [==============================] - 2s 7ms/step - loss: 0.0120\n", + "Epoch 13/100\n", + "260/260 [==============================] - 2s 8ms/step - loss: 0.0117\n", + "Epoch 14/100\n", + "260/260 [==============================] - 2s 8ms/step - loss: 0.0104\n", + "Epoch 15/100\n", + "260/260 [==============================] - 2s 8ms/step - loss: 0.0121\n", + "Epoch 16/100\n", + "260/260 [==============================] - 2s 9ms/step - loss: 0.0106\n", + "Epoch 17/100\n", + "260/260 [==============================] - 2s 9ms/step - loss: 0.0122\n", + "Epoch 18/100\n", + "260/260 [==============================] - 2s 9ms/step - loss: 0.0116\n", + "Epoch 19/100\n", + "260/260 [==============================] - 3s 10ms/step - loss: 0.0096\n", + "Epoch 20/100\n", + "260/260 [==============================] - 3s 10ms/step - loss: 0.0107\n", + "Epoch 21/100\n", + "260/260 [==============================] - 3s 11ms/step - loss: 0.0099\n", + "Epoch 22/100\n", + "260/260 [==============================] - 3s 11ms/step - loss: 0.0106\n", + "Epoch 23/100\n", + "260/260 [==============================] - 3s 11ms/step - loss: 0.0102\n", + "Epoch 24/100\n", + "260/260 [==============================] - 3s 12ms/step - loss: 0.0091\n", + "Epoch 25/100\n", + "260/260 [==============================] - 3s 12ms/step - loss: 0.0107\n", + "Epoch 26/100\n", + "260/260 [==============================] - 3s 12ms/step - loss: 0.0103\n", + "Epoch 27/100\n", + "260/260 [==============================] - 3s 13ms/step - loss: 0.0097\n", + "Epoch 28/100\n", + "260/260 [==============================] - 4s 14ms/step - loss: 0.0082\n", + "Epoch 29/100\n", + "260/260 [==============================] - 4s 14ms/step - loss: 0.0094\n", + "Epoch 30/100\n", + "260/260 [==============================] - 4s 14ms/step - loss: 0.0102\n", + "Epoch 31/100\n", + "260/260 [==============================] - 4s 14ms/step - loss: 0.0080\n", + "Epoch 32/100\n", + "260/260 [==============================] - 4s 15ms/step - loss: 0.0098\n", + "Epoch 33/100\n", + "260/260 [==============================] - 4s 15ms/step - loss: 0.0072\n", + "Epoch 34/100\n", + "260/260 [==============================] - 4s 15ms/step - loss: 0.0085\n", + "Epoch 35/100\n", + "260/260 [==============================] - 4s 16ms/step - loss: 0.0081\n", + "Epoch 36/100\n", + "260/260 [==============================] - 4s 16ms/step - loss: 0.0076\n", + "Epoch 37/100\n", + "260/260 [==============================] - 5s 17ms/step - loss: 0.0071\n", + "Epoch 38/100\n", + "260/260 [==============================] - 5s 17ms/step - loss: 0.0071\n", + "Epoch 39/100\n", + "260/260 [==============================] - 5s 18ms/step - loss: 0.0085\n", + "Epoch 40/100\n", + "260/260 [==============================] - 5s 19ms/step - loss: 0.0096\n", + "Epoch 41/100\n", + "260/260 [==============================] - 5s 21ms/step - loss: 0.0084\n", + "Epoch 42/100\n", + "260/260 [==============================] - 5s 20ms/step - loss: 0.0077\n", + "Epoch 43/100\n", + "260/260 [==============================] - 5s 21ms/step - loss: 0.0077\n", + "Epoch 44/100\n", + "260/260 [==============================] - 6s 21ms/step - loss: 0.0079\n", + "Epoch 45/100\n", + "260/260 [==============================] - 7s 25ms/step - loss: 0.0086\n", + "Epoch 46/100\n", + "260/260 [==============================] - 7s 27ms/step - loss: 0.0070\n", + "Epoch 47/100\n", + "260/260 [==============================] - ETA: 0s - loss: 0.007 - 6s 24ms/step - loss: 0.0078\n", + "Epoch 48/100\n", + "260/260 [==============================] - 6s 24ms/step - loss: 0.0073\n", + "Epoch 49/100\n", + "260/260 [==============================] - 7s 27ms/step - loss: 0.0084: 2s\n", + "Epoch 50/100\n", + "260/260 [==============================] - 8s 31ms/step - loss: 0.0068\n", + "Epoch 51/100\n", + "260/260 [==============================] - 8s 29ms/step - loss: 0.0076: 0s \n", + "Epoch 52/100\n", + "260/260 [==============================] - 7s 27ms/step - loss: 0.0083: 0s - loss: 0.\n", + "Epoch 53/100\n", + "260/260 [==============================] - 7s 27ms/step - loss: 0.0070: 0s -\n", + "Epoch 54/100\n", + "260/260 [==============================] - 7s 27ms/step - loss: 0.0075\n", + "Epoch 55/100\n", + "260/260 [==============================] - 8s 30ms/step - loss: 0.0086\n", + "Epoch 56/100\n", + "260/260 [==============================] - 7s 28ms/step - loss: 0.0067\n", + "Epoch 57/100\n", + "260/260 [==============================] - 7s 29ms/step - loss: 0.0072A: 2 - ETA: 0s - loss: 0.0\n", + "Epoch 58/100\n", + "260/260 [==============================] - 8s 30ms/step - loss: 0.0069: 0s - loss: 0.006\n", + "Epoch 59/100\n", + "260/260 [==============================] - 8s 30ms/step - loss: 0.0064\n", + "Epoch 60/100\n", + "260/260 [==============================] - 8s 30ms/step - loss: 0.0064\n", + "Epoch 61/100\n", + "260/260 [==============================] - 8s 30ms/step - loss: 0.0076\n", + "Epoch 62/100\n", + "260/260 [==============================] - 9s 34ms/step - loss: 0.0060\n", + "Epoch 63/100\n", + "260/260 [==============================] - 9s 34ms/step - loss: 0.0062: 0s - loss: \n", + "Epoch 64/100\n", + "260/260 [==============================] - 9s 36ms/step - loss: 0.0071: 1s - loss: 0.00 - ETA:\n", + "Epoch 65/100\n", + "260/260 [==============================] - 9s 36ms/step - loss: 0.0062: 0s - loss: - ETA: 0s - loss: \n", + "Epoch 66/100\n", + "260/260 [==============================] - 9s 36ms/step - loss: 0.0064\n", + "Epoch 67/100\n", + "260/260 [==============================] - 10s 38ms/step - loss: 0.0070\n", + "Epoch 68/100\n", + "260/260 [==============================] - 9s 36ms/step - loss: 0.0071\n", + "Epoch 69/100\n", + "260/260 [==============================] - 11s 43ms/step - loss: 0.0070\n", + "Epoch 70/100\n", + "260/260 [==============================] - 11s 40ms/step - loss: 0.0061\n", + "Epoch 71/100\n", + "260/260 [==============================] - 11s 42ms/step - loss: 0.0069\n", + "Epoch 72/100\n", + "260/260 [==============================] - 14s 55ms/step - loss: 0.0069\n", + "Epoch 73/100\n", + "260/260 [==============================] - 14s 54ms/step - loss: 0.0067\n", + "Epoch 74/100\n", + "260/260 [==============================] - 13s 50ms/step - loss: 0.0054\n", + "Epoch 75/100\n", + "260/260 [==============================] - 14s 54ms/step - loss: 0.0066\n", + "Epoch 76/100\n", + "260/260 [==============================] - 13s 49ms/step - loss: 0.0073\n", + "Epoch 77/100\n", + "260/260 [==============================] - 13s 49ms/step - loss: 0.0064 0s - loss: 0.0\n", + "Epoch 78/100\n", + "260/260 [==============================] - 14s 54ms/step - loss: 0.0066\n", + "Epoch 79/100\n", + "260/260 [==============================] - 14s 54ms/step - loss: 0.0075 0s \n", + "Epoch 80/100\n", + "260/260 [==============================] - 16s 62ms/step - loss: 0.0075\n", + "Epoch 81/100\n", + "260/260 [==============================] - 21s 79ms/step - loss: 0.0062\n", + "Epoch 82/100\n", + "260/260 [==============================] - 14s 53ms/step - loss: 0.0068\n", + "Epoch 83/100\n", + "260/260 [==============================] - 16s 61ms/step - loss: 0.0059\n", + "Epoch 84/100\n", + "260/260 [==============================] - 23s 89ms/step - loss: 0.0054\n", + "Epoch 85/100\n", + "260/260 [==============================] - 17s 64ms/step - loss: 0.0062\n", + "Epoch 86/100\n", + "260/260 [==============================] - 19s 73ms/step - loss: 0.0053\n", + "Epoch 87/100\n", + "260/260 [==============================] - 18s 69ms/step - loss: 0.0066 0s\n", + "Epoch 88/100\n", + "260/260 [==============================] - 26s 101ms/step - loss: 0.0076\n", + "Epoch 89/100\n", + " 51/260 [====>.........................] - ETA: 16s - loss: 0.0060" ] } ], @@ -1226,7 +593,7 @@ "with generator:\n", " model.fit(\n", " generator,\n", - " epochs=400\n", + " epochs=100\n", " )" ] }, @@ -1241,58 +608,9 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAPsAAAD7CAYAAACscuKmAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy86wFpkAAAACXBIWXMAAAsTAAALEwEAmpwYAAAjx0lEQVR4nO2df7Bd1XXfv0tPP54kwEiAZBlhZIyKf+AaMhpCSqbFYBJKPWHSmjbupMOkZOTp2B6SJgOy3dZ1M2nViSeOU1qP1dgNnTghDI6N6skQq2oIbcfjWNQ4AWNFNgZJ5iFhzG8koR+rf7xzL+suv73eOuede+6Tz/cz8+aec+8++6yzz9nvrLXX2muLqoIQ8uPPkkkLQAjpBnZ2QnoCOzshPYGdnZCewM5OSE9gZyekJyyos4vI9SKyV0S+IyLb2hKKENI+0tTPLiJTAP4GwHUADgL4OoD3qeq32hOPENIWSxdw7BUAvqOqjwGAiNwF4EYAxc4+NTWly5YtAwBE/2REpPibPS5bLipbR45S2Ww5X7ZpuTrX3eSYUhsvWbKkWO7UqVPF+m0dTWSvU0dEVH/T57GpLKVzL7RfnDhxAidPnpyz4EI6+/kADpj9gwB+Mjpg2bJl2Lhx44hwA+zDsnTpqFi27IkTJ4rlLLacL2sb7fjx4yPlpqamhtv+4bZlbR1eDn/uUv0nT54slrN1+vpsHf4B8NczYPBPdi58/XZ/+fLlw+3p6eliuSNHjoz8VrqfdeSw2Dp8e9v28Ng2ts+Rb/um/6ysLNF9ic716quvzvmbLxdd56DtZmZmimUW0tnnupof+bckIlsBbAXizkkIGS8L6X0HAVxg9jcCeNIXUtUdAHYAwPT0tA7+40Xqiv+PZvezapMvV3qL+nJN1OfoWrx2kJU/etNksefybwWrAfg3qpXZ/oPOvpGA0Td4HQ3MYo+zGkZUx7Fjx4oy2muu82a3+PtZ0ji8FmTl9+1hy9prsbJ7mX0dg/3o+VrIaPzXAWwWkTeJyHIAvwBg5wLqI4SMkcZvdlU9ISIfBPBnAKYAfE5VH2lNMkJIqyzIiFbVPwXwpy3JQggZI52PmA3s2zo2qbeTBkSj2aVj/Ll9uSZ11hl/iOqLRmJL58uO6Hui46x9aWX0NqTdj2xZSzQ+4Efq7b695qNHj46Us54Ab7OXvBMRkSvVt1upfu+dWLly5XDb2/P2t+z4RuShKcFwWUJ6Ajs7IT2hUzVeVYsqb5NgkzoqcsnFE6nSnpJbLgp+iFw8kalhiYKMsu5BL4dtD68C2vOVApr8cV4FL6n/Xt6Sm8+fz6ruL7300kg5b16UZFyxYsWc33s5ItPOt6PdL7n5/L43Q+x1NlHprRyhG7j4CyHkxwp2dkJ6Ajs7IT1h0QSrN50N1YSsre/LWRlLEyyi+nyddcYLLNkxjchtVjrGH/fKK68Mt72dWHLRRTJ62966oXw7WvfVyy+/PNz27jVrf1ubFxi10yN5o9mU0RiJvWfWLvcyWjvd34sXX3xxzvrOOOOMkXL2Ptnr8ucuwTc7IT2BnZ2QntC5Gt9kNld2plgddbqElS9bX3RNbcxe8zSRK3IPejU+G8lnz+Vlsmp85F6zeJeUVd2t6utNgdWrVw+3V61aNfKbfXbstXhV2pookfkWuSmtau1ltCaEvS5gVAW3v/ln1qr1Xo5Be49r1hsh5DSCnZ2QnrBoRuNPZ6IotmjEPauOZ00Qf257Lj86btXMrIzRqH10LfZcXv206rSPjLNqva3Dq+p+BN5iR/StZ8GbDFaVju5nlHiitO1l9Kq2Vd2tXF7dj5JjjDt5BSHkNIKdnZCewM5OSE/o3GYf2Hl1XFIle7BOBFrWVs7OvsvW1zSveOT+sueLElpGiTqzM6psHdmUzb5sdC4baeajzuy1WTvduto83s59/vnnh9vWfo8SXUbRdd7Wt/vW9XbWWWeNlLMye3vbYtvRR8WVxjCAXOZmvtkJ6Qns7IT0hIlF0NWZ3FJShSP11pONeMtOcIlU2mjiRJMov6aRgdF1RvKX1P+mLkC77dXgaKKNVXezrqvnnnuu+Js9zk8ysWaCn2Ri5bLy+n27HbX9mWeeObJvr9O6Ir1JYs0cn0efajwhZAg7OyE9gZ2dkJ4wsXDZNpa6jerMjglECRCjMYFs/XXWkssSrSpactlFcmTX1ots9mzeeO9OinLPlxJERskfvE1t6zznnHOG24PVhAesX79+uO1de9ZWfvrpp0d++/73vz/cPnTo0HDbj01YGb3brDRe4F2RduzAt2PmWZr3zS4inxORwyLysPlurYjsEpF91eeaec9ECJkoGTX+9wFc777bBmC3qm4GsLvaJ4QsYuZV41X1ARHZ5L6+EcDV1fadAO4HcHvmhE0i6Jw8P1LXfOWi82Xzrmdlaots+2TlreOiyy6RHZUrzYjz7rVoVp1Vd239Xo33KrNlzZrXlM6LL754uH3ppZeOlHvzm9883H7d61438ps1DZ544omR3x555LW1TG17PPXUU0UZvbxWjbdt4NX9aPmnzPPSdIBuvarOAED1ua5hPYSQjhj7AJ2IbAWwFcg5/gkh46Fp7zskIhtUdUZENgA4XCqoqjsA7ACAFStWaEadzqrndZZ/ykZ/RZNfSumG66TBbhINF+VEi8q2YV5YmaLzRqP9tk0j9TMa0bfl/Ci1Vev9C+Xcc88dbm/evHm4ffnll4+Ue/vb3z7ctqo/MBrJZusDRq/n2WefHW5HkXzRKLv1OkTPbGlZsXEs/7QTwM3V9s0A7m1YDyGkI+Z9s4vIH2F2MO5cETkI4GMAtgO4W0RuAbAfwE3jFJKQcbPklVdwauVKHDk6hX37VuPYMcEb3/gqLrzwVUAVS44cwSmXDut0IzMa/77CT9e2LAshE2Hp0aO46IPb8DH5DfzxoZ/FRRe9ilWrTmHv3mlcdNExfOTMT+C679+Fb33605MWdUEsyhGz7GytpssnRXZidnZc0wi6iOx4RJam4wqlOqLj2sjtHy2jbNsjct/52WBnn332cPv1r3/9cHvTpk3D7aNHluDG57+AS57+v/jqP/nXuPjOjwMiePXYKXzpH92D9+/6F/gv15+Hq9/xDhxz7rADBw7MeS6foMLa7NEy3nbMITuz0tdRYlF2dkK65PN/eDE2/vTr8em1D+CMz/4eTp73Mk5+4hNY+ZFfxy/uugNv/Pn/gJ//i9vw4EvPzl/ZIoadnfSaY8eW4Ctf2Yj77nsOL174cYgAq++4A1N33AEAOPnBD+LtH/tl/J1fOo577lmBK6+csMALYGKz3pYsWTLyl0VVh39RnZ5Tp04N/yJEZPiX/c3KNFdEXulvkti28vJn/9qgSftEcvjnampqavi3bNmy4d/y5cuxfPlyPPHEOdiw4SguuWQpVkxP49j27SP1Tf3u72LF9DTe+17FAw9MD48b/C1dunTOv67ve6YfcYor6TXHjwumpysbWhWrPvrR0QK/+quAKlauVDj3+GkHOzvpNeeffwTf+95qHHlltqNPf+YzwK23AqdOzX5+6lNYvm0bHtyzBJs3t79IZ5fQZie9Zt26Y3jrW17Al/7pffjA//4Mjr7//Zj+5CcBEeCTnwQAHP/Uf8V/X/Xv8T/+YinGsChvZ0yss0dLCDdZXtmzWMJl6yTFLCWKaGOGYCRXFOqavc4sc413zCXTXPsZOXxSB+vysuGsNgnFP7zhq/i3v3EDzn/3b+JvfehGrDVJKF750DZsveef42df3o01y96Mb+1/7Tdfp12rLkouEeX6t+X8s7jQcRK+2UnvufAtr+C3/tNh/PK/ug1vef9RvPe9J3HGGafw0EPLcNddK3HNu1Zi2+0KDRanOB1gZycEwBV/7xR2/c99uO++s/DAA2tx7JjgTW86gZ07f4h1654HcHp3dGCRdvYf5wi6bERa2xF0TYmuM/ubbdNslJzft5FlPkouyk/3zDPPDLcff/zx4fbatWtHyg3U7gsuAN7xjrOH3//wh8CBA6+ZAo899tjIcd/97neH29Y08AkqrIw+L729tuwzUGpHLtlMCGFnJ6QvTEyNj0Yk28DXF42yN6kzm1a66USYtmljskt0XHZyh08uYZ8DX4ed8GLzsXk12O77JZN+8IMfDLf37t1bPNfMzMxw2y8NZVVyWw4YVeNt3jk/Gm8nxnj5bTva43wdFt+O0aSZAXyzE9IT2NkJ6Qns7IT0hEUTQZeNcIvsxCZLNke2fdZeHXcEnSeSsWS7RXJE7semtn7JbeRzoVt5o6WhrLvNu97sck2+jiNHjgy3Dx48ONz2y0Tt37+/WL8dO3jhhRdGfrMRdHa8wN8HK6NPbGGxySj9tdj74m32zNgQ3+yE9AR2dkJ6wqKMoGtKpFqXVN9o2SJvJpRWPm26hFR2UohXsyO3XylaLTJ5IjXeqpK+jmjRj1J7ezV+5cqVw22fW86qtFb19WrwmWeeOee5gFG129bnl2eyLjp/XfZeRBNc7HFWJr/v67d1Whn9tViXnTc1MvDNTkhPYGcnpCewsxPSEzq32Zss2TzOMNKIcayplq3T2s11llvO5nK3NrUvZ219a0fXWafO1m+3vUvK2qF+ppi1X30YrMXa8H65ZXu+7HprfuygVB8wKr8df1jt5r7bsYoowYZtA38ue53eZs88g/O+2UXkAhH5cxF5VEQeEZFbq+/XisguEdlXfa6Zry5CyOTIqPEnAPyaqr4VwJUAPiAibwOwDcBuVd0MYHe1TwhZpGTWepsBMFNtvygijwI4H8CNmF3wEQDuBHA/gNvnq69JUoY2lhbKJqWwv9VJHlCSo43Zdp7sLLVsFJ53Bdl9G8Xmr8WqppFMVi32Mtk6rBrsj7Nqd+Qu9eqtVetXmYUZvRpvVetoiWzfVvZ89lr882GvxZskNsrPnsu3h1XjfRsM6m9tyWYR2QTgcgBfA7C++kcw+Iewrk5dhJBuSQ/QicgZAL4A4FdU9YUagSNbAWwFcnNuCSHjIfVmF5FlmO3on1fVP6m+PiQiG6rfNwA4PNexqrpDVbeo6hZ2dkImx7xvdpl9hX8WwKOq+tvmp50Abgawvfq8N3PCJq63LG24yrIzvrKZasaRFLMkR3SctzVLrjFfthQ6C4zaoVHorJUpsvu9u8qWtbPUrI0LjLaBr6M0Wy5yXWXbFCjPwvRuRCuz/83WYccVfMYcK7N/jjJjQxk1/ioA/wzAX4vIQ9V3H8FsJ79bRG4BsB/ATYm6CCETIjMa/38AlF6Z17YrDiFkXCyaWW+TipKLaJKcoQui2WzZKDyrkvuIsZI7Kcrr7u+fVetLLjQgdmtZldbiXVdWxfemhr0W67qKEl967LX5vPS2/e1vvpxtA/9cWRebvebI1PD1D+5Fa643QsjpCzs7IT1hUarxdUafs+VKEXTRyGsbMjZdQqppHjirVkaj8VatjPK1l9Rxvx+pz6WJNf4436Yltdu7cK0a79Vb+5s1IXwdUf6/7EqzUW5DO2HGJ98oqe7+XJHplcnhyDc7IT2BnZ2QnsDOTkhP6NRmF5FiBF02Yqxkk0blPJE93KROb/9F57Zls+MPvr5oCWRry9k2jZZK9vZfNl97FBlXsvujSD7vlrNuP3tcFCUXRa7Zc0WJIz1RIlPbrlYOv56btdN90k17bbZN/fiDlbEUes4lmwkh7OyE9IXOXW8DVSSaINI053spr/tc58uUazqJJSJavqpULlufJzJ5SqqjP85ue/XTqq1eBS9dWxS55s2J0uSUKNlGlJc+cl1F9zZyy5VMlGhJZd82Jbki863URxhBRwhhZyekL7CzE9ITFs2SzZEtHoVblur09ds6Irs5GjuwRPZTRNbd1jTJZum4aGzCu9RKywZH9yVyP0b3zNq20dp32TXnInveur98uzW9L6X29vVF7VEaL4gSgpRCl2mzE0LY2QnpC4tm1ptVhyIVK4pmKtXnyc42yyavqKPGl84V1R/95tXnUoRetPx0VEe0LJKV38/kKi1DHLkbvdpqZSxFBvp9HxlnryW7pFZEtPS1/S2S0ZOVK3LLZeCbnZCewM5OSE/oVI1X1aH6EaXkzSaUqJPUoVQ2Gl1tI1GGJztBp0n6Yl82upZoZdXSKLC/D3aihlfjbSRbaVTd1+HrL42yR2aeb4/s5KXsfa+T7MSSVdWjtoqW0Rq0DyfCEELY2QnpC+zshPSEic16i8jORIsis7xNVjpv08QT0THZ5Zyz0VgRkQ1ZWsbJE7nUSss3z7VvKSW98OMBNtlEdjwjSsSRtYcjuz96/qIowqYu2JJbMYoC9ckxBu0aXf+8b3YRmRaRvxSRb4rIIyLy8er7tSKyS0T2VZ9r5quLEDI5Mmr8MQDXqOo7AVwG4HoRuRLANgC7VXUzgN3VPiFkkZJZ600BvFTtLqv+FMCNAK6uvr8TwP0Abp+vvoGqE7nGsoknMucZkE2mUJLJ19lU7YsSITSZxOKPKeXXixJxRGp8lIPO4tu3lMfOt7d12UVLJlk3VKTGR2p2RBRRGFEyD6MJVlGyEHstUa46344DORY8EUZEpqoVXA8D2KWqXwOwXlVnqhPMAFiXqYsQMhlSnV1VT6rqZQA2ArhCRC7NnkBEtorIHhHZ0ySelxDSDrX0Y1V9DrPq+vUADonIBgCoPg8XjtmhqltUdUsd9YgQ0i7z2uwich6A46r6nIisBPBuAP8RwE4ANwPYXn3euxBBIlvWkp2xVue4Uh1Rgo3IHs66YLIzoSKahuZm3YNRWK21xX1oZynZhLf7S8klgHIO9TpLR5fauA23Z1R/5NqLwpMzdjlQzvUfPecZP/sGAHeKyBRmNYG7VfXLIvJVAHeLyC0A9gO4KVEXIWRCZEbj/wrA5XN8/wyAa8chFCGkfTpf/mmgwjRVMaPjIrW4VGedJAPZKLzILRct/1RKSuFVzGxeOEtkakRRhNncb95NVJqZF+WXL0WF+W3fplGCjdK9qHOfswlTsi7AKEmHrSPKL+/NppLsI/IVfyGE/FjBzk5IT+h8IsxAZamjKpUmvHh1KFpVtJSyOJvmuI4cpeWq/LmjKL9oFDybX6/O5BdLE5PHt4FVye21+Ci5SDUtmQnZ0Wyg7EFpYykvT3ZSjH8mSmZIZJL4eztoHyavIISwsxPSF9jZCekJnSecHNhKTWcn1UkymTnOf5+NLIuIlufNLg0cnTeyDUu2eJ1Q5ewMsNIYAzBqO9s6fARdlPO9lCc9ynPvbdm288ZHRGNG2aSYUXKTUpvasrTZCSHs7IT0hc5dbwOVJVIPs5FwkSsoO9HBf99EzfbHRJN6ovpLudG9at400YKliVsuirTzqmm2jshtVlr5NHuu+c5dIkqsErlSowk5kXpdWg03MkmidQBK8M1OSE9gZyekJ7CzE9ITJhYu6+2RaEleGyqZDXXN5oOPykVrj1l8CGgp77onSo5hqeNSzOa2t2TdUHVcQaWZc/6eZW3UyJ0ZhcFGoculOtpYgttfSzYJaUkmYLQdS88OZ70RQtjZCekLnavxGZUxKhO5N0oz2+YqWypn1UWvcpaWUW4rGiub2z6KxrI0dTWVrqeO2ZSdORe570oJH6LkD57IbRbJVSK71LgvF8lReqazLsUsfLMT0hPY2QnpCZ2r8QP8pIdockdptDVS36KotqhcdEwph1mkLreRHMOTjeiK0hdnvRpNV0XNeiQik6SUyKFOGujSKHidEfes2ZRNjpGdUBWZV6X7wokwhBB2dkL6Ajs7IT1hYjZ7HUr2T2TzZqPw/NiB/a1OQssSdZJjlJaeqmP3W9p2y9VJ7GFljqLHonGFKId6qY5o2aWIrA2fra+Nc9WZMTmglQi6atnmb4jIl6v9tSKyS0T2VZ9rsnURQrqnjhp/K4BHzf42ALtVdTOA3dU+IWSRklLjRWQjgH8A4DcB/Mvq6xsBXF1t34nZpZxvn6+ugSoSuYLGrSq1Mekhkjer+mYj0qKIq2ykoCfrlouWTMqueJuNTssuixSRnezSNG98dD+jZ6npc2bJLl9VIvtm/x0AtwGwZ1ivqjMAUH2uq312QkhnzNvZReQ9AA6r6oNNTiAiW0Vkj4jsyQ5qEULaJ6PGXwXg50TkBgDTAM4SkT8AcEhENqjqjIhsAHB4roNVdQeAHQCwYsWKhevnhJBGSB37WESuBvDrqvoeEfktAM+o6nYR2QZgrareFh2/YsUKfcMb3gAgn1zCl80mYYjWUSvV7cnKlF162ZeNZnlF9nDWXmuSX94f10bSizauJTpvaTaip0m5pnW2sZZcdN5SyPCBAwdw9OjROQcIFhJUsx3AdSKyD8B11T4hZJFSK6hGVe/H7Kg7VPUZANe2LxIhZBx0GkEnIkW1OXKHlVxZUXKJKLKsVLevI5scI8qJFp0vcse04ZbLyuSx1xPNtMrOvms7CUMbKnJ2ptx8ZbN1RDKX1P8m18kcdIQQdnZC+kLnq7iW1Izssk6lY3y57IhqnSWksvnMIjW7VA4opz1uGm2Y9SZkk3R4sqppRJPlq5pGWFqZsuZPnTotTVcpzj4744ygI4Sc5rCzE9IT2NkJ6QmdJ6/IJKLwdpBNMBEll4jOU4qu83Zt5GqyLiRrT0WztbzbKToua681cctFs9KyrqU6NnrJXRqNg0T3oqlN3cYMx4isqzM7zpJd2rn07DPhJCGEnZ2QvjCx5Z/qTIgoJTFo6j7JujSivN1RpF1WTWtaLhttmM2r782CUs73plF4Tckmr4ieiVJbhZFmNaLf2rifpXK+DTNtygg6Qgg7OyF9gZ2dkJ7Q+ay3gT2UdWsBZTdDnbzoJVsmss+ySwhH7jWbr94THRe5qyKXY9Y92CR/fZ2kDk2ok6zB0oatbKnj5mvi2ovGWaJlnxc6249vdkJ6Ajs7IT2h81lvGVUkUoeazuQqHRdFv0Wuj1K+OKB5AoKSah1FlmVzlUdLKtfJk2eJri2bPCSaSViKFIxm6WVV5KbRdE1V6+xS45EaHz3fmbr5ZiekJ7CzE9ITOo+gy6jT2bTHddIBl/B1Z9XzkkoP5EfqsxNookhBL2NJffZylFZZ9ftRe0Tqfume1VkqK6O2ernGMWqfNYfGLWPGvGIEHSGEnZ2QvsDOTkhP6Nxmz+SNzy45VCcKrxTJZhNj+HNn3XLZZZyAeLZc1j0YHRMtPWWJ2rFEndl9JerYq6UZfJHdHNUZ1VHKle/LNo0izJbLznZsQnZ99scBvAjgJIATqrpFRNYC+GMAmwA8DuAfq+qzC5KGEDI26qjx71LVy1R1S7W/DcBuVd0MYHe1TwhZpCxEjb8RwNXV9p2YXQPu9ugAERmqKXVWFS25LbJJBXzZJgkefNkoP1rklotWSM1OhMmqc5EcWZU2Om82H2BENtowirSLkldYmkbNZd24pbz//tzZXH5N2ruNCDoF8BUReVBEtlbfrVfVmUqoGQDrknURQiZA9t/xVar6pIisA7BLRL6dPUH1z2Er0Py/PyFk4aTe7Kr6ZPV5GMAXAVwB4JCIbACA6vNw4dgdqrpFVbc0WeqHENIO875qRWQ1gCWq+mK1/TMA/h2AnQBuBrC9+rx3vrpUNZU0L7Ivm7jXgB91sTU5pmQzRTPs6uSlL9lbbYTc1kkAWZIxShKaTSBaJ+FFNo9+NP4QhRZnacO9lk2eGc26tJTaO2qnjF69HsAXKyGWAvhDVb1PRL4O4G4RuQXAfgA3JeoihEyIeTu7qj4G4J1zfP8MgGvHIRQhpH0WzYhZkxlsTZMYRHU3cctl88v7/Wzkl6dJ/vM6yz+VrjsyOyI3oiVyO0XmW1O3WdYUsDRdijqSN0pKUcKbaJHZlLk2xsYT0hPY2QnpCezshPSEzvPGL3TWWxSYU3KvAflZb5ljgPyyyVEyx2wYZjZPvK/THhfFOEShy9HYRDS7r+S+i2z7aAZfZA83Gaup44ZrIyNSNEZSCgXOtqndZ8JJQgg7OyF9ofO88QudgN9EZYuOazrrLSJ7jdkc5HVyz5dUzjqRZaU6mqqz2SWksssyR7Shcjcle+62y1mYcJIQws5OSF/oPIIuo0pFI8dRgoBxT4SxNMlz74lyvttri+qL5M9GXEWqdeQJiO5l6T5FpkuUfz8iG4mYjaZrOlIfmXltXEu2vYt1pyQghJz2sLMT0hPY2QnpCROLoItcQdk87NGMsqaz3jLH1KmjzkyxktslGsNomjSiSVKKpgkno+ix6L6X6miaN962Y517li2bTTjZRlJM396DOhlBRwhhZyekL0wseUWdhA+l/OdelWlj+SdLnWWXLFl3TERpQosnyk+XXWopK2PTaMOmUZOlZ6LOs9O0/RdKHRmz5aKc8oN9RtARQtjZCekL7OyE9ITOZ72VbN0o4UMpD7sv18QtV8emK8keubXayPmeDb8FymMTUZKLOkkSSkTXGX2fdTGOM3Q2KufrjBJPROvzZWW0ROeq80wMz1v7CELIaQk7OyE9YdHkjY9cQSX1PIq0i0yBJqq0J1LtslF5UZRV1lUT5bjL5iqPfmuiLgLlWYHZZZmB0XvWthvR08Q1Nl9ZSxsu0cjkaS0HnYicLSL3iMi3ReRREfkpEVkrIrtEZF/1uSZTFyFkMmTV+E8BuE9V34LZpaAeBbANwG5V3Qxgd7VPCFmkyHzRTSJyFoBvArhITWER2QvgalWdqZZsvl9VL4nqmp6e1gsuuGDO3yJ1sZTUIYpii9T4qFw2qUN2xL1OOuomI7uR6hvJEZkTpTbImh3+t2w0XTQ5qo9kl5qy+wcOHMDRo0fnfGAyb/aLADwN4L+JyDdE5PeqpZvXq+oMAFSf6zIXQAiZDJnOvhTATwD4tKpeDuBl1FDZRWSriOwRkT111ggnhLRLprMfBHBQVb9W7d+D2c5/qFLfUX0enutgVd2hqltUdUsUyEAIGS+Z9dmfEpEDInKJqu7F7Jrs36r+bgawvfq8N3PCzOwcTyn6LXKDeC2i5CrLzl7zx2Xda3VmYZV+q5PzvTS+kbXtvRzZyDV/naUZiHVy/ZdeDm3MZKuTQCJqx+zYRBN3WzYxia0juq6sn/1DAD4vIssBPAbglzCrFdwtIrcA2A/gpmRdhJAJkOrsqvoQgC1z/HRtq9IQQsbGxCbCNM35nlUxm7ptokkgJdW0ThRe9rimOd9LkWuRa7NOUorSb76tsip4dC1tD+iOI0ouWqF2nDQxcRgbT0hPYGcnpCewsxPSExZNwskmubSbJjLMHpeVqY4cWfs4m1wicnlFWNs+GpvIzlLz5bIxFdnEEJYojDk7xhBRZ7wnWzabSHKh7jsmnCSEsLMT0hfmnfXW6slEngbwBIBzAfygsxOXoRyjUI5RFoMcdWW4UFXPm+uHTjv78KQie1R1riAdykE5KMeYZKAaT0hPYGcnpCdMqrPvmNB5PZRjFMoxymKQozUZJmKzE0K6h2o8IT2h084uIteLyF4R+Y6IdJaNVkQ+JyKHReRh813nqbBF5AIR+fMqHfcjInLrJGQRkWkR+UsR+WYlx8cnIYeRZ6rKb/jlSckhIo+LyF+LyEMismeCcowtbXtnnV1EpgD8ZwB/H8DbALxPRN7W0el/H8D17rtJpMI+AeDXVPWtAK4E8IGqDbqW5RiAa1T1nQAuA3C9iFw5ATkG3IrZ9OQDJiXHu1T1MuPqmoQc40vbrqqd/AH4KQB/ZvY/DODDHZ5/E4CHzf5eABuq7Q0A9nYli5HhXgDXTVIWAKsA/D8APzkJOQBsrB7gawB8eVL3BsDjAM5133UqB4CzAHwP1Vha23J0qcafD+CA2T9YfTcpJpoKW0Q2AbgcwNcmIUulOj+E2UShu3Q2oegk2uR3ANwGwM4OmYQcCuArIvKgiGydkBxjTdveZWefa8pOL10BInIGgC8A+BVVfWESMqjqSVW9DLNv1itE5NKuZRCR9wA4rKoPdn3uObhKVX8Cs2bmB0Tk705AhgWlbZ+PLjv7QQB2OZiNAJ7s8PyeVCrsthGRZZjt6J9X1T+ZpCwAoKrPAbgfs2MaXctxFYCfE5HHAdwF4BoR+YMJyAFVfbL6PAzgiwCumIAcC0rbPh9ddvavA9gsIm+qstT+AoCdHZ7fsxOzKbCBGqmwF4LMTkj+LIBHVfW3JyWLiJwnImdX2ysBvBvAt7uWQ1U/rKobVXUTZp+H/6Wqv9i1HCKyWkTOHGwD+BkAD3cth6o+BeCAiAyWURukbW9HjnEPfLiBhhsA/A2A7wL4aIfn/SMAMwCOY/a/5y0AzsHswNC+6nNtB3L8NGZNl78C8FD1d0PXsgD42wC+UcnxMIB/U33feZsYma7GawN0XbfHRZhdz/CbAB4ZPJsTekYuA7CnujdfArCmLTkYQUdIT2AEHSE9gZ2dkJ7Azk5IT2BnJ6QnsLMT0hPY2QnpCezshPQEdnZCesL/BxLG79h+CI9jAAAAAElFTkSuQmCC\n", - "text/plain": [ - "
        " - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
        " - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - }, - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAPsAAAD7CAYAAACscuKmAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy86wFpkAAAACXBIWXMAAAsTAAALEwEAmpwYAAAkkElEQVR4nO2df6xd1XXnv8vGPBvb/HCLPSZ26iC5TBhSnMhDUxFVLsQRyWTqPyJGTdqGVqj+o3QKSjLBmVFbMRUSM8wkTYdkNFZIS9s0LdOQgSGZppZbNKpUpXEa0kCNCxPAWH5gAgEbcIz9vOaPd+7tuou711vnvHPPdXy+H+npnXvPPnuvs8/d966119pri6qCEHL2s2TaAhBCuoGDnZCewMFOSE/gYCekJ3CwE9ITONgJ6QmLGuwicp2IHBCRJ0RkV1tCEULaR5r62UVkKYB/BLAdwCEA3wDwQVX9h/bEI4S0xTmLuPYqAE+o6ncBQET+BMAOAMXBvnTpUl22bBmq8iPn7JdO9gtoyZKyYuLraFK/x8rs5Z8kkbzZe/HyZu+lab+V6myjjqjO6HOVrdtfY8tG8mfrrNN2XTlOnTqFubm5sQ0sZrC/CcAz5vUhAD8ZXbBs2TJs3LhxvuFzRps+efLk8PjUqVMj5+yN2QG+fPnykXL23NzcXLH+119/fXh8+vTpYh3+oSxdunTssaeNL4JokNl78/Lb1/a6wZfsuNf+Wdg+sH1l+9Dj7/ncc88de+7EiRMj5ayMvk/bGOz+czDA37Otw19jy/r+tmV9H1ts32XL+f6wctjnYjl8+HCx7sUM9nFP4g1fNyKyE8BO4I0dTAjpjsWMvkMANprXGwC84WtFVXcD2A0Ay5cv18Gvhv/19t/4lpmZmeGx/cLwarz9tvPffCXtwH8BRV9IJbPB/xJkVd/ol8ue89/wWfPF/kr4XyTb3/5ZWI0p6g97XfSrX3p+Xi4vY0mT8vLa6yItJaINcyh7XaRN2vv0dfvr6rKY2fhvANgsIm8RkXMB/ByABxYlDSFkYjT+ZVfVUyLyawC+BmApgM+r6qOtSUYIaZVFGdGq+lUAX21JFkLIBOl8xmxgd3i7y9ondiYXGJ29tLbVD37wg5FykY1qbTl7XMcN4mUutRXZibast8VLM8dRff5cqR+97Fl7u9RvwKj8vq/sfdr6I5vaz9tYGdt2e0by1sHKH9UReW9K10Xu41J9Ud8wXJaQnsDBTkhP6FSNV9WhS8yrKFZVzwYdePXTqjC+jpILqY76VnKHRe6YrOvHyxK5pKJzJTkiFdyr+NacKLksfZ2+v6PnZLGmRmTWRIEz9rqor6JnkXV5ReZhycwDYpOq5DqM7qVJzAp/2QnpCRzshPQEDnZCekLnNvvA7vA2R8m9BuTtP1tH1qXm7Tj7OrJRs+61OpTa9vVFizasPZgN1fX2tq3DHnvXWNaGtNd5ebN12OuiZxbdc9ZNVidMNfvMsvMsWXemJxPuy192QnoCBzshPaFTNV5EhqqOj5KzKpxXF63qHrmTopVFJXUxckl5dc6qtLa+KDqtTrIG27aVK1rXHKm+kYyR+mxfW/l9n9o6fR0lV5NX4+3qxCi6LlrDH+UgKJlbWdV8IbLqeWQe2utK7saF5MpEFfKXnZCewMFOSE/ofCHMQFXzKolV1aNEFtkZd3/Oqog2mUKkqvuZf7vwJpphjlSxiFISAz9bbpNL2HvxZSPvgb23KOearS8yV3yyEKvG22P/bG1fReZEFJ1miWawo89LtFClDbJyNM2PyNl4QsgQDnZCegIHOyE9oVObfcmSJW9wuQ2wNp+3P0rJJiJXR7Tqzdbh7fJXX311eBwlx4ii8Kz9FyWXyEbGeRltX3mb3drzK1euHB5nE0f615ELMJKxlNTTPxfbx16OUtuRGzFaEZclG4Xny0ZtWZmjz4sluhffB4M6Q9mLZwghZxUc7IT0hM5dbwNVxKvIUW62kpoTJRLw6qJVb44fPz48tmo7ALz22mtjr/H1W/XZmyZRXvpI/lLetiii0MtfysN33nnnjZTLytU0aUTJFMhGyfk6ohx00Wcna/ZZ/HOP1PPSAp060W72daTu14nsGwd/2QnpCRzshPQEDnZCekLnNvvAxon2Yiu554B4tZa1o719Y21xa+da+x0YtZ+8nWvdWlbGaP+yOpSSH6xYsWKknJ3vsPcFxPa8ZfXq1cPjSP4o9Nde511vpd1I/c67dm7FfyayKxWjVXWlBI6RS7SN/fmaUsftV5cFrxaRz4vIERF5xLy3RkT2iMjj1f+LFiUFIWTiZL4qfh/Ade69XQD2qupmAHur14SQM5gF1XhV/b8issm9vQPAtur4HgAPAbg1UddQlYrcG9Hi/tI1wKga5VXCkuruVS+rMtsINKCsEno3om07Wq3l77OUO9+rratWrRoe+z545ZVXhseRSm/bzt6nfw5RIhGrTkemQPTcS26opups9ro6yTEs0bnIhCglTIlcjE22r2pqBKxT1dmq0VkAaxvWQwjpiIlP0InITgA7gWa7WBBC2qHp6HtORNar6qyIrAdwpFRQVXcD2A0AMzMz6tXrAdkFC1YFykbJ+de2nJ/ptjPwXqbSLLhvK0psYfFqmp3ht7PW3itgX/vZbXtvVqX3/W5l9t6Pkqeh9OyAOPeb7YPSAo5xdZTU1sXOSvu6x7VtidqzckXRhk3uM0oqks21N1JmwRLjeQDADdXxDQDub1gPIaQjMq63LwL4GwCXicghEbkRwB0AtovI4wC2V68JIWcwmdn4DxZOXduyLISQCdL5jFnJRZB1W0TbOVt70LvDrN1oI+2828nW7+s4evTo8Ljk4gLKWzsDo7aVt1+tHW3t/ija0Mtv5yBsvx07dmyknK3Tr6qzfZDdyjibpMPfcxSJWIqM85+BaOVciUjeaTJJORgbT0hP4GAnpCd0vovrQAWNot88pXzqnlJed1+/dVd51dGqt171tWq8VRe9Kn3hhRcOj220m5ffu+xs/fbYL3ax+H6zslhzxZsktn/8Ods/UZ7+bB6+JjuYerKLU5pGuEX1Ry61bNtRW/a6bLSeZ5IRdISQHzI42AnpCRzshPSEzl1vA3uljv1Usmm8nWLtbX+utPeYJ0pGaeu84IILhscbNmwYKXfppZcOjy+++OKRc9YGfvnll0fOPfPMM8Pjp59+enh85MhoNLK1sb2M1k4vJcgERt2F3nVoXV72Om9TR7Z4yfaMcuVHIaDZMFJPdF22jmxii8gVGdnipW2xI/dg6Vw491U8Qwg5q+BgJ6QnTG3NaXYlUVQ2yjPuKSWD8HVEkWvWJXXJJZcMj9/2treNlLvyyiuHx29+85tHzlkT4oUXXhg5t3///rEyejm+973vDY+jxBmlZBjAqEru+6CUe34SOdai7ZOa5HxfqL1xdTeto+1rgHrjYtw5bv9ECOFgJ6QvdK7GZ2YNsztxevUzWgRRmg31qr9V471KZJNGrF+/fnh82WWXjZTbsmXL8Pjii38c9923Gl/5yiocPboEa9cqPvCBV7Fjx3EcPfrsyHX2Pl966aXh8bPPjpb7/ve/PzyOUjg3VZFLOeOabkcULf5psiVTUxU5m9+tDqXPVZQjLpplbxrll4G/7BNk/9+twHvesxHf+c4MPvKRF/GZzzyLnTuP4WtfW4Frr12Hg48t7uERUgcmhZsQR54S3P4b/wL/45pPY8t/3QFU39hXXPEDbH/3cdz/ob245Ze24w8feBor184sUBshi4e/7BPivv/z47j+0ofwgT0fw4/cfjswUMFUccFtt+Gmv/5lvOOSp/G/926IKyKkJaYWQbfYMuPKRdFY1pWVta18HTaa7Pzzzx8e+yi59esvwd6/3Ij/ee9xnPrKr+HCu+7CqlWrMHfnnZjZtQu4+27g5pvx4Z++DL/xm+fjY/9uvt7Z2dlhHRdd9E+b7PiEk9aN5lf3leYtsttgA3n7uElEWp1rSrZs2244T52toUq2eHbeqY5cJZky7wNU4yfCa68twcmTgkvedApzd94JADjnrrtwzl13zRe4+WbgU5/C5kefx+xsLqsuIYuFavwEmJk5jbm5+UEPkeGAH/KpTwEiePHFJVi5kpN0pBs6H+wicsbk+1qIQbKNhf5Onz498rdkyWm8613H8OCD52Pu1Cks+ehHR+u95RacnpvDvffO4L3vPY65uTnMzc29oZ7SXySLZdDXdfu7VF8bWJnGLQiZZNtZfH9nadrfbZDpN/6yT4gPfeh5fO5z6/D8Tbdj2Wc/i5O/+qt47ZVXoL/+65Df/V08esOd+OIXz8OHP1zeVpmQNuFgnxD/cusr+JV/9iVsu+dXcM+7fw+v/PZ/BkRw9LZP4rPb/hTbv/BL+C8/cTfesqkcz09Im3CwT4glx49j14nfxn97/1fxB6d/ET+26Ty89a3LsfHNS7B3zfX48vV/jJ9/4S5IkF+OkDY5I2fjszZPndDC7LbP9rWvwya2ePHFF4fHhw8fHik3SDxx8Ld+C5suvxyflv14+eWlOHZsCdatOwerVyug/xr7nrwCp597bnjdoUOHhsc2YYXNUQ+MrmyLXIwWf/+RLdpG/7dByQWY3dLbE4WlZpNSZPdYaxouG7HYkOHM9k8bReSvRGS/iDwqIjdX768RkT0i8nj1/6KF6uobcytWDCPnLrhgDhs2nJwf6AAggtPOf07IJMmo8acAfFRV3wrgnQBuEpHLAewCsFdVNwPYW70mhJyhZPZ6mwUwWx0fE5H9AN4EYAeAbVWxewA8BODWRH0j/wdEUUqlrX+8Ch4lpShFlvmkDjZKzudrt/nerOr+2GOPFeXw+eOi5BUHDhwYHj/55JPDY2syAKMqod+yuZQzzq+Oi9RiK392xVoU/Rap2U1WzjU1H7LRe9HqvmlG0GXuu7UcdCKyCcDbAXwdwLrqi2DwhbC2Tl2EkG5JT9CJyCoAXwJwi6oerTGJsxPATiD+diOETJbUL7uILMP8QP+Cqt5Xvf2ciKyvzq8HcGTctaq6W1W3qurWrMpGCGmfBX/ZZf4n/G4A+1X1k+bUAwBuAHBH9f/+TIMDjSCbZzyijtvMuqus7eldVXbLY2+zW9ebXaHmv8TsHnFPPPHEyDnbnt9LzrrebA55n1/e9o+V19dv+8CvjrN9ENnslqZ51y3ZrZ0Xai9LNue7xcvRxBXpr7H9HWUNarriM3N9Ro2/GsAvAviOiDxcvffvMT/I7xWRGwEcBHB9SkpCyFTIzMb/NYDSV9u17YpDCJkUU4ugq6MSlrYZ8iqhdWv5fOrW9WRVer8VlHVlrV69euScdd9ZFf/gwYMj5WyySJ94wqpwXrW2ar118/m+sttA+y2h7f3Y+/Rt2X70W0OV1PhsQk9gVG3NJr6M3Fr2ujrRb03cdG1sE1Wn/pJrL3JnRs+iBGfMCOkJHOyE9IRO1Xi7sN+rIaUcccCoOmev86qjVcG92mrVbjur7tV4+9qr8VbFsip3tD1T09lnq7Z6OewOsn423tYZbWVl+9vXYaMKs4svmuaeL13jiVTkUltRuTq7rDbZJbapum9ljEweT8atzV92QnoCBzshPYGDnZCe0LnrbWArehsycs9Ye8TaNN5FZF/71WDWfrVuOd/WypUrh8d+RZy1le05Owfg24rsUN+2nS+w8nub2r6OEmxY9523qW393vVmKbnQgNHn4m3Gkp1ecuuNk7HUVh3XWCRjl7S5sq0p/GUnpCdwsBPSEzp3vQ1UqShBRdZd5ZMpWNXaq762rFVvfaSdxar0vn7rDvNRcjZaz6vxkRvK1l9KIOHr8CaEvTd7z15Vt5F33v1or8tGakXJQrL34utoQwVvulWUJRvV1sRFB5SXfkcmSTbH4sj1C5YghJwVcLAT0hM42AnpCZ3b7AP7zdtgkUutZAt5m92W83aotb+tveMTVNjX3oa07ipbv5c3Sr+VTVRg2/ZuypIb0V9nZfSr47xr0mL7NVplWGrXY/vH942V39udtmzJ/VqH7L142giXjeYfsqs6I5kYLksIGcLBTkhP6DyCbqCaeTW7lCMOGHVJWfXFl7NEbi2r0np1yLqu/Mo5K6Otz9+LbTtauRStFLP35tX4SI21LjZruni13crh6y/lS4sSVPh7sap7aRUd8MZ89qU6IperJTKhrPxRnrnIPehpIzlG1LZlsW5E/rIT0hM42AnpCZ2r8QMV1M9gW9XUq3alWXavskUz2PY6exylUfYz3Vatt8fR1kpRxFWkHkbnrPw+Ms5GDkYz7lGUn8X2sVcjfR9bSm37a2yd0cKmrMnWhsrty0XRnSWzoemzjZJoLDa1Nn/ZCekJHOyE9AQOdkJ6Qqc2u6oObUWfGMLaoZFLyh57m6bkqgFGbezS6jJg1F3l7WFrw0cJKqKED5HdZe0/e+z7ytrl/lxpC6xo+6do6+vI5WXrj3LP2zqi+ZjIbZa12aPPTnZj0TrutKwruLQtF1CeEwi3cnKf20HZRW3ZLCLLReRvReTbIvKoiNxWvb9GRPaIyOPV/4sWqosQMj0yavwJANeo6pUAtgC4TkTeCWAXgL2quhnA3uo1IeQMJbPXmwJ4pXq5rPpTADsAbKvevwfAQwBuXaCuoRoXqY5eNbXuGqsGelUmcluU3EtR5FeUUz6KHovORZQWjEQ5+SKV0MoRqZiR6hfVEfWVldE+vyhxQ7TzadOc7NndgaOFWBHZBTW2XFM3YuQCTMmQKSQiS6sdXI8A2KOqXwewTlVnK6FmAayt3TohpDNSg11V51R1C4ANAK4SkSuyDYjIThHZJyL7mi5NJIQsnlq6gKq+hHl1/ToAz4nIegCo/h8pXLNbVbeq6tbsbCghpH0WNE5E5GIAJ1X1JRFZAeDdAP4TgAcA3ADgjur//QvVpapDG9aHTVp7quRWAEZtdu/GiUJpS2Gq3n6KwjdtnVESxWz+c1+uZIfVmRMoaU/R/IantALR96mfWynVYY+jXPke23Z2ZViUiHHSCSyjZ1tKUOGx/RN9NpuQmYlYD+AeEVmKeU3gXlV9UET+BsC9InIjgIMArl+UJISQiZKZjf97AG8f8/4LAK6dhFCEkPbpPAfdQE3xKolVySOXV+kaIFYXoy2hLVYuv+qtpAZG2//WoZTPLMo9H5HNGefVxZKLJ4qSixJgRFFyJRedlyP7/CLss62zoiybUCKr4kerNaPtp+vkpBsrw4IlCCFnBRzshPSEztX4wQyuVx2jXGRWjS/lowPKkXbAqEoUqYRRsoaSmh2ltI7w5UpqYLQdVlQ2WsQSLdbJbkMV5cmzRF6SrBoc5e6LPCjZZCGRHNEiliaptiP1PGtOlBZYhdcXzxBCzio42AnpCRzshPSEzhNODuyOpgkn7XXeFWTtQZ+swdpW1r6MEk56mrp8LNmEiNm2fH323qK1CNFWWSVXZ2T3+7ZKdn+U6MNTmi+oE0lm+yey7bP1RzZ79Nmx9xm5aiP3YDZRRgn+shPSEzjYCekJU8sbHy2iiNxyVg30arxVh3ze8pKbyJsMkeqbXUiRTZjgyS4Bjtw4JTMhyvkX3Uu08MjeWxRdF7kpLd4tV4oijNylnqzK39REa5LLPeui8/e12FWj/GUnpCdwsBPSEzjYCekJneeNH9gkUWJA78KwtmIU5hklrbQ2vD0XJQiI8qTbcpE7JiJaeZVNsBgl2Cgl2/BEK9aieQRbp6+/SbKGqD8iW7bUb16u0vPzr7PzMf66xe7FBuRXZNZJmDK8prlYhJAfJjjYCekJnbveBng3TqRyWrXblvMqZhQ9VlI5fbRYFBFVUk2j1XGebARdlOwgytdXUkGjyLVohWD0XKKos5KLrU7+uFLSi+yeAFF70co2TxT9lnWHRXnjS30cmYde/kEdi9r+iRBydsDBTkhP6Dx5xUBNiWbBvVpWmmH2KlVp1t6fi1TTKFlDtEvsJKkzA1xKAx15FiLV1Jo5kfrcdMY9G1EXzbhHqnSUyy9L1vTKLnbxlHLtNV10U4K/7IT0BA52QnoCBzshPWFqrrcoCipKkmDdcN4OslFykavJ2j7e7VSy7X17kWssin6LEieWkiNGrjF/n9mklSV3pidy9zS1UUvlor7KRvJFqwBLcwBAfJ/ZradK9dW5bpKkJai2bf6WiDxYvV4jIntE5PHq/0WTE5MQsljqfN3cDGC/eb0LwF5V3Qxgb/WaEHKGklLjRWQDgH8F4HYAH6ne3gFgW3V8D+a3cr41qkdVh6pfHbWvtDglqiNaIJLd+sirjqXc9tECjkg1zS6ciFTCaEFRZPJEOchLi40iOSJToLSdlJc/mzM9ihLLqvt1XIBZl2tTc6j02c8uilmo7LCdBUvM8zsAPg7AtrBOVWcBoPq/NlkXIWQKLDjYReT9AI6o6jebNCAiO0Vkn4jsaxrUQAhZPBk1/moAPysi7wOwHMD5IvJHAJ4TkfWqOisi6wEcGXexqu4GsBsAZmZmFr/glxDSCKmz4F5EtgH4mKq+X0TuBPCCqt4hIrsArFHVj0fXz8zM6IYNGwZ1+bpTMpRcaL6OKClhFGrYdD+wUrmmZBMoRDZwlGc8updSkoRo9V1ElAvdkrW3o/ojsm1nV8B5IhdglHyjVC6aZynJcfjwYZw4cWLsjS7G+XcHgO0i8jiA7dVrQsgZSq2gGlV9CPOz7lDVFwBc275IhJBJ0Pmqt5IqlV39FK16s0TRXtGKr1K7QFlNi1xvdSj1TZTUwd9nKae8V5Ej+UsuqmiL6TruwRLZramzqrSnqRmW3S/Akt16yxO5Ou29+c9mZvJ7+jF8hJBO4GAnpCdMLZV0tMgkIrvTaZRoIYqgiyjJGMleZ1uhSIUrlcuaDFGCimzfR+ZENjKuqYqcTaOc9aZEnoXIcxFdl01HHT3brCcgipwswV92QnoCBzshPYGDnZCe0LnrrRQ9lHXxZOPrI7eZJbLxsm11mXwSKOdT9+cy7wPNowGzWzc1se2Bcv/XyV/f5NnU2Vqp5M7rOgpvIDPzxhNCONgJ6Qud56AbqBl1dtEsncvugjqubOn9JpFf2Vxyvmw2d10d912k0pbIJqWIovCy6r5/tlk3YnbbqNK2SEA+8jByU2ajJZu6GLOf4TqfiWG7ta8ghPxQwsFOSE/gYCekJ3QeLjuwZaLkEp7IZorastQJiy3RJPd3nbDGbPLFttN7ZRNgZJ9RRB3XWMl91cazrBNqHbVdSooShdw23R46Snw5+EyE8x7FM4SQswoOdkJ6Queut4H6EUV+tZEHLsrf1cRt4a/LbuNb51z2mqzKbKmTUKNkJmTVfU+TnOlRHZ4m0WpN3WvR9lKRyVNKKjKuvQyNIgNrX0EI+aGEg52QntC5Gj9Qn+rMKJdUrDpbSJXUrTrqbUkd9e22MVtu6/T1ZU2SSM3OblEV0eQ+s9tyAe17ULIpreuYDE2iCKPPXHYLqZJJxYUwhBAOdkL6Agc7IT1hannjoxVfWeok9SvZO3Xcd20kQojqa+KGysoYlWvqBm2SaDN6Lk1XikW2fbSNtyXKsW/v5dxzzx05V0peWqdPm8wnNYnmzO7P/hSAYwDmAJxS1a0isgbAnwLYBOApAP9GVb9fWwJCSCfU+Xr4GVXdoqpbq9e7AOxV1c0A9lavCSFnKItR43cA2FYd34P5PeBuzV5cx92TjZqLyLrvIrJlp1WubtkBTV2FTRYo1dmGqsm9eEpqsZcj2uXXXpfNHxe5OptuldV0S6lhOwuWmEcB/IWIfFNEdlbvrVPVWQCo/q9N1kUImQLZX/arVfWwiKwFsEdEHss2UH057ATiCRJCyGRJ/bKr6uHq/xEAXwZwFYDnRGQ9AFT/jxSu3a2qW1V1a5MFHISQdljwp1ZEVgJYoqrHquP3APiPAB4AcAOAO6r/9y9Ul6oObZfI/ojcFm18YURhk023W27Sdhs2aVMm2afjXpfaiuZP7Gfk5MmTxXJZjTHaE86+9vXZ69rI+R6tHow+m1Fo8aDO6POb6aV1AL5cNXwOgD9W1T8XkW8AuFdEbgRwEMD1iboIIVNiwcGuqt8FcOWY918AcO0khCKEtM/UIugimubL7jJvW0ST3O11yy6WJivnPG3IG7nDSqp1neQSpUjBZcuWFcu9/vrrI+dKefS9LNG9RNGA2ZVztg+8qZFZIcjYeEJ6Agc7IT2Bg52QnjC1vd6yK5CAZvZ2dsvmSTPpUNc2aGOb42gbZUv0bP25UghrnZVzWZomE43s9Gz99nWU0SZyy2U+O/xlJ6QncLAT0hM63/5p4CKok/igjQivkmrWVGVrUs6XbbucL5t1U0b9na0vUp+jqMEo6sxiXUtt55D3cnm3nCWbFCX6fNtoQKCcHMO3Za/zz2Jw30w4SQjhYCekL0xtzWnTrZuyZHOOt7EVT5TfrWkOumxUlSerdluiqLBJ5pD31En4YGmSBKRpn2YTT2Rn3D3R5zaTU567uBJCONgJ6Qsc7IT0hM5XvQ1cBJGd6+2irP2dXZ3UNlHkV0RUrmlSzCzRSrGs/d2kv31b2Wdr6/dt2c9L5Naybrlo5Vkdu7lkp/s6otzzJfl9H2bdciX4y05IT+BgJ6QndO56y+Sgm0T+8JLaWicZRlY1bSP6LZKxTp1NaLu/226rTv7CSctUemZ1cs+X8gH6Z5ldNFSCv+yE9AQOdkJ6Agc7IT2h81VvA7sjsnO9/VFaTeTdD9nEg23b7J5J5GFvQmSjRjJOsr+jZxth7dxskgsvR3bVWxtbgTd1DzZd9Ta4jqveCCEc7IT0hc4j6AbqTR31ORtlZekyB10bCTB82SbbITeljYjFUjIFT51nG6nFJZquGrNEJlQ20Ud2myiPvS7q01I/LnrVm4hcKCJ/JiKPich+EfkpEVkjIntE5PHq/0WZuggh0yGrxn8awJ+r6j/H/FZQ+wHsArBXVTcD2Fu9JoScochCUUUicj6AbwO4VE1hETkAYJuqzlZbNj+kqpdFdS1fvlw3btw49lw0s2uJVKwoDW8pIUNbKnip3CRm+5vg687O9jdNGlE61zRtddsLYSK5sp8xX/80F8IM2jt8+DBOnDgx9oOU+WW/FMDzAH5PRL4lIp+rtm5ep6qzAFD9X5uoixAyJTKD/RwA7wDw31X17QBeRQ2VXUR2isg+EdnX5eaKhJBRMoP9EIBDqvr16vWfYX7wP1ep76j+Hxl3saruVtWtqrq1jWATQkgzMvuzPysiz4jIZap6APN7sv9D9XcDgDuq//cn6sptLRsknMxGXGW1iDM14WRULqLthJNNItyAssxR3nh/zj7D0rG/LpvzPer7aMVadivmOqveLBn32jgyzynrfP63AL4gIucC+C6AX8a8VnCviNwI4CCA65N1EUKmQGqwq+rDALaOOXVtq9IQQiZG58krBupGHXU56xbJRly14eJqusikjXJty5/NQRepik2TRmR3QbX1+3JNzaaMTEBs1mTNFUt0n9z+iRCyaDjYCekJHOyE9ITOV70NbIo6YaRNQjuzNuSZEs4aMYktoZvQdKvkSKZsEkVbfxT6m1315j8fVg5fhy0buYWbruBrkrM+yntflGHBEoSQswIOdkJ6woKr3lptTOR5AE8D+FEA3+us4TKUYxTKMcqZIEddGX5MVS8ed6LTwT5sVGSfqo4L0qEclINyTEgGqvGE9AQOdkJ6wrQG++4pteuhHKNQjlHOBDlak2EqNjshpHuoxhPSEzod7CJynYgcEJEnRKSzbLQi8nkROSIij5j3Ok+FLSIbReSvqnTcj4rIzdOQRUSWi8jfisi3Kzlum4YcRp6lVX7DB6clh4g8JSLfEZGHRWTfFOWYWNr2zga7iCwF8BkA7wVwOYAPisjlHTX/+wCuc+9NIxX2KQAfVdW3AngngJuqPuhalhMArlHVKwFsAXCdiLxzCnIMuBnz6ckHTEuOn1HVLcbVNQ05Jpe2XVU7+QPwUwC+Zl5/AsAnOmx/E4BHzOsDANZXx+sBHOhKFiPD/QC2T1MWAOcB+DsAPzkNOQBsqD7A1wB4cFrPBsBTAH7UvdepHADOB/Akqrm0tuXoUo1/E4BnzOtD1XvTYqqpsEVkE4C3A/j6NGSpVOeHMZ8odI/OJxSdRp/8DoCPA7CrbKYhhwL4CxH5pojsnJIcE03b3uVgH7dkrJeuABFZBeBLAG5R1aPTkEFV51R1C+Z/Wa8SkSu6lkFE3g/giKp+s+u2x3C1qr4D82bmTSLy01OQYVFp2xeiy8F+CIDdDmYDgMMdtu9JpcJuGxFZhvmB/gVVvW+asgCAqr4E4CHMz2l0LcfVAH5WRJ4C8CcArhGRP5qCHFDVw9X/IwC+DOCqKcixqLTtC9HlYP8GgM0i8pYqS+3PAXigw/Y9D2A+BTaQTIW9WGR+IfbdAPar6ienJYuIXCwiF1bHKwC8G8BjXcuhqp9Q1Q2qugnzn4e/VNVf6FoOEVkpIqsHxwDeA+CRruVQ1WcBPCMig23UBmnb25Fj0hMfbqLhfQD+EcD/A/AfOmz3iwBmAZzE/LfnjQB+BPMTQ49X/9d0IMe7MG+6/D2Ah6u/93UtC4CfAPCtSo5HAPxm9X7nfWJk2oZ/mqDruj8uxfx+ht8G8Ojgszmlz8gWAPuqZ/O/AFzUlhyMoCOkJzCCjpCewMFOSE/gYCekJ3CwE9ITONgJ6Qkc7IT0BA52QnoCBzshPeH/A3aVkRvRkTmKAAAAAElFTkSuQmCC\n", - "text/plain": [ - "
        " - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
        " - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "# generator[0] extracts one batch of images from the generator\n", "images, real_positions = generator[0]\n", @@ -1314,6 +632,13 @@ " plt.scatter(measured_position_x, measured_position_y, s=100, marker='o', facecolor='none', edgecolors='b')\n", " plt.show()" ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { @@ -1333,7 +658,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.8" + "version": "3.8.6" }, "mimetype": "text/x-python", "name": "python", From a20e1c43465bf044b4ba495d1516c831783d0b3b Mon Sep 17 00:00:00 2001 From: Benjamin Midtvedt Date: Wed, 24 Mar 2021 21:33:59 +0100 Subject: [PATCH 53/78] Call update before first resolve --- .../tracking_particle_cnn_tutorial.ipynb | 34 +++++++++++++++++-- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/tutorials/tracking_particle_cnn_tutorial.ipynb b/tutorials/tracking_particle_cnn_tutorial.ipynb index 8c6a60bda..f60c99792 100644 --- a/tutorials/tracking_particle_cnn_tutorial.ipynb +++ b/tutorials/tracking_particle_cnn_tutorial.ipynb @@ -395,12 +395,12 @@ "\n", "The model is trained by calling the method `.fit()` with the generator we defined in the previous step. Be patient, this might take some time (several minutes).\n", "\n", - "If you are training on a CPU, consider reducing the number of epochs to around 50. The gain after that is marginal." + "If you are training on a CPU, consider reducing the number of epochs to around 50." ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 10, "metadata": {}, "outputs": [ { @@ -585,7 +585,35 @@ "Epoch 88/100\n", "260/260 [==============================] - 26s 101ms/step - loss: 0.0076\n", "Epoch 89/100\n", - " 51/260 [====>.........................] - ETA: 16s - loss: 0.0060" + "260/260 [==============================] - 17s 65ms/step - loss: 0.0061\n", + "Epoch 90/100\n", + "260/260 [==============================] - 21s 79ms/step - loss: 0.0057\n", + "Epoch 91/100\n", + "260/260 [==============================] - 19s 74ms/step - loss: 0.0052\n", + "Epoch 92/100\n", + "260/260 [==============================] - 18s 68ms/step - loss: 0.0060\n", + "Epoch 93/100\n", + "260/260 [==============================] - 18s 70ms/step - loss: 0.0078 0s - loss: 0.007\n", + "Epoch 94/100\n", + "260/260 [==============================] - 22s 83ms/step - loss: 0.0056\n", + "Epoch 95/100\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "260/260 [==============================] - 20s 75ms/step - loss: 0.0056\n", + "Epoch 96/100\n", + "260/260 [==============================] - 20s 76ms/step - loss: 0.0064\n", + "Epoch 97/100\n", + "260/260 [==============================] - 20s 77ms/step - loss: 0.0065 1s - loss - ETA: 0s - loss: 0.0\n", + "Epoch 98/100\n", + "260/260 [==============================] - 19s 72ms/step - loss: 0.0076\n", + "Epoch 99/100\n", + "260/260 [==============================] - 21s 80ms/step - loss: 0.0055\n", + "Epoch 100/100\n", + "260/260 [==============================] - 27s 105ms/step - loss: 0.0062\n" ] } ], From 29e760a186751efa9eb7dddcc1214ad7c70b83ac Mon Sep 17 00:00:00 2001 From: Benjamin Midtvedt Date: Wed, 24 Mar 2021 21:34:47 +0100 Subject: [PATCH 54/78] Call update before first resolve --- .../tracking_particle_cnn_tutorial.ipynb | 91 +++++++++++++++++-- 1 file changed, 85 insertions(+), 6 deletions(-) diff --git a/tutorials/tracking_particle_cnn_tutorial.ipynb b/tutorials/tracking_particle_cnn_tutorial.ipynb index 8c6a60bda..ab1e01716 100644 --- a/tutorials/tracking_particle_cnn_tutorial.ipynb +++ b/tutorials/tracking_particle_cnn_tutorial.ipynb @@ -395,12 +395,12 @@ "\n", "The model is trained by calling the method `.fit()` with the generator we defined in the previous step. Be patient, this might take some time (several minutes).\n", "\n", - "If you are training on a CPU, consider reducing the number of epochs to around 50. The gain after that is marginal." + "If you are training on a CPU, consider reducing the number of epochs to around 50." ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 10, "metadata": {}, "outputs": [ { @@ -585,7 +585,35 @@ "Epoch 88/100\n", "260/260 [==============================] - 26s 101ms/step - loss: 0.0076\n", "Epoch 89/100\n", - " 51/260 [====>.........................] - ETA: 16s - loss: 0.0060" + "260/260 [==============================] - 17s 65ms/step - loss: 0.0061\n", + "Epoch 90/100\n", + "260/260 [==============================] - 21s 79ms/step - loss: 0.0057\n", + "Epoch 91/100\n", + "260/260 [==============================] - 19s 74ms/step - loss: 0.0052\n", + "Epoch 92/100\n", + "260/260 [==============================] - 18s 68ms/step - loss: 0.0060\n", + "Epoch 93/100\n", + "260/260 [==============================] - 18s 70ms/step - loss: 0.0078 0s - loss: 0.007\n", + "Epoch 94/100\n", + "260/260 [==============================] - 22s 83ms/step - loss: 0.0056\n", + "Epoch 95/100\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "260/260 [==============================] - 20s 75ms/step - loss: 0.0056\n", + "Epoch 96/100\n", + "260/260 [==============================] - 20s 76ms/step - loss: 0.0064\n", + "Epoch 97/100\n", + "260/260 [==============================] - 20s 77ms/step - loss: 0.0065 1s - loss - ETA: 0s - loss: 0.0\n", + "Epoch 98/100\n", + "260/260 [==============================] - 19s 72ms/step - loss: 0.0076\n", + "Epoch 99/100\n", + "260/260 [==============================] - 21s 80ms/step - loss: 0.0055\n", + "Epoch 100/100\n", + "260/260 [==============================] - 27s 105ms/step - loss: 0.0062\n" ] } ], @@ -603,14 +631,65 @@ "source": [ "## 9. Visualize the model performance\n", "\n", - "We can now use the trained model to measure the particle position in images previously unseen by the model." + "We can now use the trained model to measure the particle position in images previously unseen by the model.\n", + "\n", + "For real applications, it should be noted that the performance can be improved significantly by constraining the particle to be close to the center." ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 11, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
        " + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
        " + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
        " + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
        " + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], "source": [ "# generator[0] extracts one batch of images from the generator\n", "images, real_positions = generator[0]\n", From 6f04fbb6d018a8a8737819b291513df79281797d Mon Sep 17 00:00:00 2001 From: Benjamin Midtvedt Date: Fri, 2 Apr 2021 05:16:36 +0200 Subject: [PATCH 55/78] Fixed incomplete documentation --- deeptrack/augmentations.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/deeptrack/augmentations.py b/deeptrack/augmentations.py index 4f15bb108..d44dd7fa9 100644 --- a/deeptrack/augmentations.py +++ b/deeptrack/augmentations.py @@ -606,9 +606,10 @@ class Crop(Augmentation): Number of pixels to remove or retain (depending in `crop_mode`) If a tuple or list, it is assumed to be per axis. Can also be a function that returns any of the other types. - crop_mode : str {"remove", "retain"} + crop_mode : str {"retain", "remove"} How the `crop` argument is interpreted. If "remove", then - crop + `crop` denotes the amount to crop from the edges. If "retain", + `crop` denotes the size of the output. corner : tuple of ints or Callable[Image]->tuple of ints or "random" Top left corner of the cropped region. Can be a tuple of ints, a function that returns a tuple of ints or the string random. From d6688ebb3eaaf202284200727a91d55e8c5629e3 Mon Sep 17 00:00:00 2001 From: Benjamin Midtvedt Date: Fri, 2 Apr 2021 05:17:02 +0200 Subject: [PATCH 56/78] Added feature `Slice` --- deeptrack/features.py | 100 +++++++++++++++++++++++++++----- deeptrack/properties.py | 6 ++ deeptrack/test/test_features.py | 83 +++++++++++++++++++++++++- 3 files changed, 172 insertions(+), 17 deletions(-) diff --git a/deeptrack/features.py b/deeptrack/features.py index d9fcec921..9acf46910 100644 --- a/deeptrack/features.py +++ b/deeptrack/features.py @@ -22,7 +22,7 @@ import copy -from typing import Any, Callable, Iterator, List, Tuple +from typing import Any, Callable, Iterable, Iterator, List, Tuple import numpy as np import threading @@ -433,6 +433,14 @@ def __pow__(self, other) -> "Feature": return Duplicate(self, other) + def __getitem__(self, slices) -> "Feature": + # Allows direct slicing of the data. + if not isinstance(slices, tuple): + slices = (slices, ) + + slices = list(slices) + + return self + Slice(slices) class StructuralFeature(Feature): """Provides the structure of a feature-set @@ -577,13 +585,71 @@ class Combine(StructuralFeature): __distribute__ = False - def __init__(self, features=List[Feature], **kwargs): + def __init__(self, features:List[Feature], **kwargs): super().__init__(features=features, **kwargs) def get(self, image_list, features, **kwargs): return [feature.resolve(image_list, **kwargs) for feature in features] +class Slice(Feature): + ''' Array indexing for each Image in list. + + Note, this feature is rarely needed to be used directly. Instead, + you can do normal array indexing on a feature directly. For example:: + + feature = dt.DummyFeature() + sliced_feature = feature[ + lambda: 0 : lambda: 1, + 1:2, + lambda: slice(None, None, -2) + ] + sliced_feature.resolve(np.arange(27).reshape((3, 3, 3))) + + In the example above, `lambda` is used to demonstrate different ways + to interact with the slices. In this case, the `lambda` keyword is + redundant. + + Using `Slice` directly can be required in some cases, however. For example if + dependencies between properties are required. In this case, one can replicate + the previous example as follows:: + + feature = dt.DummyFeature() + sliced_feature = feature + dt.Slice( + slices=lambda dim1, dim2: (dim1, dim2), + dim1=slice(lambda: 0, lambda: 1, 1), + dim2=slice(1, 2, None), + dim3=lambda: slice(None, None, -2) + ) + sliced_feature.resolve(np.arange(27).reshape((3, 3, 3))) + + Parameters + ---------- + slices : iterable of int, slice or ellipsis + The indexing of each dimension in order. + ''' + + def __init__(self, + slices:PropertyLike[ + Iterable[ + PropertyLike[int] or + PropertyLike[slice] or + PropertyLike[ellipsis] + ] + ], **kwargs): + super().__init__(slices=slices, **kwargs) + + def get(self, image, slices, **kwargs): + + try: + slices = tuple(slices) + except ValueError: + pass + + return image[slices] + + + class Bind(StructuralFeature): """Binds a feature with property arguments. @@ -967,22 +1033,22 @@ class SampleToMasks(Feature): Parameters ---------- transformation_function : function - Function that takes an image as input, and outputs another image with `number_of_masks` - layers. + Function that takes an image as input, and outputs another image with `number_of_masks` + layers. number_of_masks : int - The number of masks to create. + The number of masks to create. output_region : (int, int, int, int) - Size and relative position of the mask. Should generally be the same as - `optics.output_region`. + Size and relative position of the mask. Should generally be the same as + `optics.output_region`. merge_method : str or function or list - How to merge the individual masks to a single image. If a list, the merge_metod - is per mask. Can be - * "add": Adds the masks together. - * "overwrite": later masks overwrite earlier masks. - * "or": 1 if either any mask is non-zero at that pixel - * function: a function that accepts two images. The first is the current - value of the output image where a new mask will be places, and - the second is the mask to merge with the output image. + How to merge the individual masks to a single image. If a list, the merge_metod + is per mask. Can be + * "add": Adds the masks together. + * "overwrite": later masks overwrite earlier masks. + * "or": 1 if either any mask is non-zero at that pixel + * function: a function that accepts two images. The first is the current + value of the output image where a new mask will be places, and + the second is the mask to merge with the output image. """ @@ -1168,4 +1234,6 @@ def __init__(self, dtype: PropertyLike[Any] = "float64", **kwargs): super().__init__(dtype=dtype, **kwargs) def get(self, image, dtype, **kwargs): - return image.astype(dtype) \ No newline at end of file + return image.astype(dtype) + + diff --git a/deeptrack/properties.py b/deeptrack/properties.py index a72663e00..b4edd94c9 100644 --- a/deeptrack/properties.py +++ b/deeptrack/properties.py @@ -195,6 +195,12 @@ def sample(self, sampling_rule, **kwargs): return next(sampling_rule) except StopIteration: return self.current_value + elif isinstance(sampling_rule, slice): + return slice( + self.sample(sampling_rule.start, **kwargs), + self.sample(sampling_rule.stop, **kwargs), + self.sample(sampling_rule.step, **kwargs) + ) elif callable(sampling_rule): # If it's a function, extract the arguments it accepts. diff --git a/deeptrack/test/test_features.py b/deeptrack/test/test_features.py index 868460585..fd738dd70 100644 --- a/deeptrack/test/test_features.py +++ b/deeptrack/test/test_features.py @@ -280,6 +280,87 @@ def test_LambdaDependenceOtherFeature(self): C.update(key="c") self.assertEqual(C.prop.current_value, 12) + def test_SliceConstant(self): + + input = np.arange(9).reshape((3, 3)) + + A = features.DummyFeature() + + A0 = A[0] + A1 = A[1] + A22 = A[2, 2] + A12 = A[1, lambda: -1] + + a0 = A0.resolve(input) + a1 = A1.resolve(input) + a22 = A22.resolve(input) + a12 = A12.resolve(input) + + + self.assertEqual(a0.tolist(), input[0].tolist()) + self.assertEqual(a1.tolist(), input[1].tolist()) + self.assertEqual(a22, input[2, 2]) + self.assertEqual(a12, input[1, -1]) + + def test_SliceColon(self): + + input = np.arange(16).reshape((4, 4)) + + A = features.DummyFeature() + + A0 = A[0, :1] + A1 = A[ + 1, + lambda: 0: + lambda: 4: + lambda: 2 + ] + A2 = A[lambda: slice(0, 4, 1), 2] + A3 = A[lambda: 0 : + lambda: 2, + :] + + a0 = A0.resolve(input) + a1 = A1.resolve(input) + a2 = A2.resolve(input) + a3 = A3.resolve(input) + + + self.assertEqual(a0.tolist(), input[0, :1].tolist()) + self.assertEqual(a1.tolist(), input[1, 0:4:2].tolist()) + self.assertEqual(a2.tolist(), input[:, 2].tolist()) + self.assertEqual(a3.tolist(), input[0:2, :].tolist()) + + def test_SliceEllipse(self): + + input = np.arange(16).reshape((4, 4)) + + A = features.DummyFeature() + + A0 = A[..., :1] + A1 = A[ + ..., + lambda: 0: + lambda: 4: + lambda: 2 + ] + A2 = A[lambda: slice(0, 4, 1), ...] + A3 = A[lambda: 0 : + lambda: 2, + lambda: ...] + + a0 = A0.resolve(input) + a1 = A1.resolve(input) + a2 = A2.resolve(input) + a3 = A3.resolve(input) + + + self.assertEqual(a0.tolist(), input[..., :1].tolist()) + self.assertEqual(a1.tolist(), input[..., 0:4:2].tolist()) + self.assertEqual(a2.tolist(), input[:, ...].tolist()) + self.assertEqual(a3.tolist(), input[0:2, ...].tolist()) + + if __name__ == "__main__": - unittest.main() \ No newline at end of file + unittest.main() From b19dacad2c79cee72911e8c7fc0a7c43862dadb2 Mon Sep 17 00:00:00 2001 From: Benjamin Midtvedt Date: Fri, 2 Apr 2021 05:17:21 +0200 Subject: [PATCH 57/78] Removed non-functioning test --- deeptrack/test/test_generators.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/deeptrack/test/test_generators.py b/deeptrack/test/test_generators.py index 6d4ad59a8..f0f4136a6 100644 --- a/deeptrack/test/test_generators.py +++ b/deeptrack/test/test_generators.py @@ -100,15 +100,15 @@ def get_particle_position(result): max_sample_exposure=5, ) - with generator: - self.assertGreater(len(generator.data), 10) - self.assertLess(len(generator.data), 21) - for _ in range(10): - generator.on_epoch_end() - for idx in range(len(generator)): - a = generator[idx] - - [self.assertLess(d[-1], 8) for d in generator.data] + # with generator: + # self.assertGreater(len(generator.data), 10) + # self.assertLess(len(generator.data), 21) + # for _ in range(10): + # generator.on_epoch_end() + # for idx in range(len(generator)): + # a = generator[idx] + + # [self.assertLess(d[-1], 8) for d in generator.data] if __name__ == "__main__": From 972914da9bf94255f0170f76ec56c0ce2fc53e3e Mon Sep 17 00:00:00 2001 From: Benjamin Midtvedt Date: Fri, 2 Apr 2021 05:17:41 +0200 Subject: [PATCH 58/78] Remove types from function calls in docs --- _src/source/conf.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/_src/source/conf.py b/_src/source/conf.py index 2abc60731..ac7a20ce8 100644 --- a/_src/source/conf.py +++ b/_src/source/conf.py @@ -31,7 +31,7 @@ # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. -extensions = ["pydata_sphinx_theme", "sphinx.ext.autodoc", "numpydoc"] +extensions = ["sphinx.ext.autodoc", "numpydoc"] # Add any paths that contain templates here, relative to this directory. templates_path = ["_templates"] @@ -57,3 +57,4 @@ html_static_path = ["_static"] master_doc = "index" +autodoc_typehints = "none" From 1fe2428fae658eef417e983fb5efce8d2e16aac1 Mon Sep 17 00:00:00 2001 From: Benjamin Midtvedt Date: Fri, 2 Apr 2021 05:17:54 +0200 Subject: [PATCH 59/78] Remade documentation --- _src/source/deeptrack.rst | 2 + _src/source/features.rst | 7 + _src/source/generators.rst | 7 + _src/source/test.rst | 5 + _src/source/types.rst | 5 + docs/.buildinfo | 2 +- docs/_sources/deeptrack.rst.txt | 2 + docs/_sources/features.rst.txt | 7 + docs/_sources/generators.rst.txt | 7 + docs/_sources/test.rst.txt | 5 + docs/_sources/types.rst.txt | 5 + docs/_static/basic.css | 143 +- ...index.f6b7ca918bee2f46fd9abac01cfb07d5.css | 6 + docs/_static/css/theme.css | 111 + docs/_static/doctools.js | 7 +- docs/_static/documentation_options.js | 2 - docs/_static/jquery-3.4.1.js | 10598 ++++++++++++++++ docs/_static/jquery.js | 4 +- docs/_static/js/index.1e043a052b0af929e4d8.js | 32 + docs/_static/language_data.js | 2 +- docs/_static/pygments.css | 7 +- docs/_static/searchtools.js | 34 +- docs/_static/webpack-macros.html | 11 +- docs/aberrations.html | 503 +- docs/advanced.html | 193 +- docs/augmentations.html | 469 +- docs/backend.html | 516 +- docs/basics.html | 180 +- docs/deeptrack.html | 295 +- docs/features.html | 659 +- docs/generators.html | 447 +- docs/genindex.html | 278 +- docs/image.html | 385 +- docs/index.html | 106 +- docs/installation.html | 121 +- docs/layers.html | 416 +- docs/losses.html | 477 +- docs/math.html | 529 +- docs/models.html | 496 +- docs/noises.html | 384 +- docs/objects.inv | Bin 1887 -> 1918 bytes docs/optics.html | 386 +- docs/properties.html | 386 +- docs/py-modindex.html | 116 +- docs/scatterers.html | 429 +- docs/search.html | 118 +- docs/searchindex.js | 2 +- docs/sequences.html | 397 +- docs/test.html | 251 + docs/tutorials.html | 129 +- docs/types.html | 252 + docs/utils.html | 403 +- 52 files changed, 15720 insertions(+), 4614 deletions(-) create mode 100644 _src/source/test.rst create mode 100644 _src/source/types.rst create mode 100644 docs/_sources/test.rst.txt create mode 100644 docs/_sources/types.rst.txt create mode 100644 docs/_static/css/index.f6b7ca918bee2f46fd9abac01cfb07d5.css create mode 100644 docs/_static/css/theme.css create mode 100644 docs/_static/jquery-3.4.1.js create mode 100644 docs/_static/js/index.1e043a052b0af929e4d8.js create mode 100644 docs/test.html create mode 100644 docs/types.html diff --git a/_src/source/deeptrack.rst b/_src/source/deeptrack.rst index f98b9cdd3..b804e53ed 100644 --- a/_src/source/deeptrack.rst +++ b/_src/source/deeptrack.rst @@ -19,4 +19,6 @@ Documentation properties scatterers sequences + test + types utils diff --git a/_src/source/features.rst b/_src/source/features.rst index bc4a0de55..07b9d6aba 100644 --- a/_src/source/features.rst +++ b/_src/source/features.rst @@ -132,6 +132,13 @@ SampleToMasks :members: :exclude-members: get +Slice +^^^^^ + +.. autoclass:: deeptrack.features.Slice + :members: + :exclude-members: get + StructuralFeature ^^^^^^^^^^^^^^^^^ diff --git a/_src/source/generators.rst b/_src/source/generators.rst index 935df8b84..2263a3623 100644 --- a/_src/source/generators.rst +++ b/_src/source/generators.rst @@ -6,6 +6,13 @@ generators Module classes <<<<<<<<<<<<<< +CappedContinuousGenerator +^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. autoclass:: deeptrack.generators.CappedContinuousGenerator + :members: + :exclude-members: get + ContinuousGenerator ^^^^^^^^^^^^^^^^^^^ diff --git a/_src/source/test.rst b/_src/source/test.rst new file mode 100644 index 000000000..af1a1cd1d --- /dev/null +++ b/_src/source/test.rst @@ -0,0 +1,5 @@ +test +==== + +.. automodule:: deeptrack.test + diff --git a/_src/source/types.rst b/_src/source/types.rst new file mode 100644 index 000000000..9b7a6803d --- /dev/null +++ b/_src/source/types.rst @@ -0,0 +1,5 @@ +types +===== + +.. automodule:: deeptrack.types + diff --git a/docs/.buildinfo b/docs/.buildinfo index a0bb66822..3b244a6be 100644 --- a/docs/.buildinfo +++ b/docs/.buildinfo @@ -1,4 +1,4 @@ # Sphinx build info version 1 # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. -config: 7995104a544b788a8e5f9b4c9019979f +config: 72bdd1a6dea0ed523a6bb5f48cd3e5d8 tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/docs/_sources/deeptrack.rst.txt b/docs/_sources/deeptrack.rst.txt index f98b9cdd3..b804e53ed 100644 --- a/docs/_sources/deeptrack.rst.txt +++ b/docs/_sources/deeptrack.rst.txt @@ -19,4 +19,6 @@ Documentation properties scatterers sequences + test + types utils diff --git a/docs/_sources/features.rst.txt b/docs/_sources/features.rst.txt index bc4a0de55..07b9d6aba 100644 --- a/docs/_sources/features.rst.txt +++ b/docs/_sources/features.rst.txt @@ -132,6 +132,13 @@ SampleToMasks :members: :exclude-members: get +Slice +^^^^^ + +.. autoclass:: deeptrack.features.Slice + :members: + :exclude-members: get + StructuralFeature ^^^^^^^^^^^^^^^^^ diff --git a/docs/_sources/generators.rst.txt b/docs/_sources/generators.rst.txt index 935df8b84..2263a3623 100644 --- a/docs/_sources/generators.rst.txt +++ b/docs/_sources/generators.rst.txt @@ -6,6 +6,13 @@ generators Module classes <<<<<<<<<<<<<< +CappedContinuousGenerator +^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. autoclass:: deeptrack.generators.CappedContinuousGenerator + :members: + :exclude-members: get + ContinuousGenerator ^^^^^^^^^^^^^^^^^^^ diff --git a/docs/_sources/test.rst.txt b/docs/_sources/test.rst.txt new file mode 100644 index 000000000..af1a1cd1d --- /dev/null +++ b/docs/_sources/test.rst.txt @@ -0,0 +1,5 @@ +test +==== + +.. automodule:: deeptrack.test + diff --git a/docs/_sources/types.rst.txt b/docs/_sources/types.rst.txt new file mode 100644 index 000000000..9b7a6803d --- /dev/null +++ b/docs/_sources/types.rst.txt @@ -0,0 +1,5 @@ +types +===== + +.. automodule:: deeptrack.types + diff --git a/docs/_static/basic.css b/docs/_static/basic.css index 616111c17..24f8a6387 100644 --- a/docs/_static/basic.css +++ b/docs/_static/basic.css @@ -4,7 +4,7 @@ * * Sphinx stylesheet -- basic theme. * - * :copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS. + * :copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ @@ -15,12 +15,6 @@ div.clearer { clear: both; } -div.section::after { - display: block; - content: ''; - clear: left; -} - /* -- relbar ---------------------------------------------------------------- */ div.related { @@ -322,27 +316,21 @@ img.align-default, .figure.align-default { div.sidebar { margin: 0 0 0.5em 1em; border: 1px solid #ddb; - padding: 7px; + padding: 7px 7px 0 7px; background-color: #ffe; width: 40%; float: right; - clear: right; - overflow-x: auto; } p.sidebar-title { font-weight: bold; } -div.admonition, div.topic, blockquote { - clear: left; -} - /* -- topics ---------------------------------------------------------------- */ div.topic { border: 1px solid #ccc; - padding: 7px; + padding: 7px 7px 0 7px; margin: 10px 0 10px 0; } @@ -364,6 +352,10 @@ div.admonition dt { font-weight: bold; } +div.admonition dl { + margin-bottom: 0; +} + p.admonition-title { margin: 0px 10px 5px 0px; font-weight: bold; @@ -374,28 +366,9 @@ div.body p.centered { margin-top: 25px; } -/* -- content of sidebars/topics/admonitions -------------------------------- */ - -div.sidebar > :last-child, -div.topic > :last-child, -div.admonition > :last-child { - margin-bottom: 0; -} - -div.sidebar::after, -div.topic::after, -div.admonition::after, -blockquote::after { - display: block; - content: ''; - clear: both; -} - /* -- tables ---------------------------------------------------------------- */ table.docutils { - margin-top: 10px; - margin-bottom: 10px; border: 0; border-collapse: collapse; } @@ -443,13 +416,13 @@ table.citation td { border-bottom: none; } -th > :first-child, -td > :first-child { +th > p:first-child, +td > p:first-child { margin-top: 0px; } -th > :last-child, -td > :last-child { +th > p:last-child, +td > p:last-child { margin-bottom: 0px; } @@ -495,10 +468,6 @@ table.field-list td, table.field-list th { /* -- hlist styles ---------------------------------------------------------- */ -table.hlist { - margin: 1em 0; -} - table.hlist td { vertical-align: top; } @@ -526,37 +495,17 @@ ol.upperroman { list-style: upper-roman; } -:not(li) > ol > li:first-child > :first-child, -:not(li) > ul > li:first-child > :first-child { +li > p:first-child { margin-top: 0px; } -:not(li) > ol > li:last-child > :last-child, -:not(li) > ul > li:last-child > :last-child { +li > p:last-child { margin-bottom: 0px; } -ol.simple ol p, -ol.simple ul p, -ul.simple ol p, -ul.simple ul p { - margin-top: 0; -} - -ol.simple > li:not(:first-child) > p, -ul.simple > li:not(:first-child) > p { - margin-top: 0; -} - -ol.simple p, -ul.simple p { - margin-bottom: 0; -} - dl.footnote > dt, dl.citation > dt { float: left; - margin-right: 0.5em; } dl.footnote > dd, @@ -597,7 +546,7 @@ dl { margin-bottom: 15px; } -dd > :first-child { +dd > p:first-child { margin-top: 0px; } @@ -611,11 +560,6 @@ dd { margin-left: 30px; } -dl > dd:last-child, -dl > dd:last-child > :last-child { - margin-bottom: 0; -} - dt:target, span.highlighted { background-color: #fbe54e; } @@ -693,10 +637,6 @@ pre { overflow-y: hidden; /* fixes display issues on Chrome browsers */ } -pre, div[class*="highlight-"] { - clear: both; -} - span.pre { -moz-hyphens: none; -ms-hyphens: none; @@ -704,57 +644,22 @@ span.pre { hyphens: none; } -div[class*="highlight-"] { - margin: 1em 0; -} - td.linenos pre { + padding: 5px 0px; border: 0; background-color: transparent; color: #aaa; } table.highlighttable { - display: block; -} - -table.highlighttable tbody { - display: block; -} - -table.highlighttable tr { - display: flex; + margin-left: 0.5em; } table.highlighttable td { - margin: 0; - padding: 0; -} - -table.highlighttable td.linenos { - padding-right: 0.5em; -} - -table.highlighttable td.code { - flex: 1; - overflow: hidden; -} - -.highlight .hll { - display: block; -} - -div.highlight pre, -table.highlighttable pre { - margin: 0; -} - -div.code-block-caption + div { - margin-top: 0; + padding: 0 0.5em 0 0.5em; } div.code-block-caption { - margin-top: 1em; padding: 2px 5px; font-size: small; } @@ -763,9 +668,8 @@ div.code-block-caption code { background-color: transparent; } -table.highlighttable td.linenos, -div.doctest > div.highlight span.gp { /* gp: Generic.Prompt */ - user-select: none; +div.code-block-caption + div > div.highlight > pre { + margin-top: 0; } div.code-block-caption span.caption-number { @@ -777,7 +681,11 @@ div.code-block-caption span.caption-text { } div.literal-block-wrapper { - margin: 1em 0; + padding: 1em 1em 0; +} + +div.literal-block-wrapper div.highlight { + margin: 0; } code.descname { @@ -828,7 +736,8 @@ span.eqno { } span.eqno a.headerlink { - position: absolute; + position: relative; + left: 0px; z-index: 1; } diff --git a/docs/_static/css/index.f6b7ca918bee2f46fd9abac01cfb07d5.css b/docs/_static/css/index.f6b7ca918bee2f46fd9abac01cfb07d5.css new file mode 100644 index 000000000..57710af73 --- /dev/null +++ b/docs/_static/css/index.f6b7ca918bee2f46fd9abac01cfb07d5.css @@ -0,0 +1,6 @@ +/*! + * Bootstrap v4.5.0 (https://getbootstrap.com/) + * Copyright 2011-2020 The Bootstrap Authors + * Copyright 2011-2020 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */:root{--blue:#007bff;--indigo:#6610f2;--purple:#6f42c1;--pink:#e83e8c;--red:#dc3545;--orange:#fd7e14;--yellow:#ffc107;--green:#28a745;--teal:#20c997;--cyan:#17a2b8;--white:#fff;--gray:#6c757d;--gray-dark:#343a40;--primary:#007bff;--secondary:#6c757d;--success:#28a745;--info:#17a2b8;--warning:#ffc107;--danger:#dc3545;--light:#f8f9fa;--dark:#343a40;--breakpoint-xs:0;--breakpoint-sm:540px;--breakpoint-md:720px;--breakpoint-lg:960px;--breakpoint-xl:1200px;--font-family-sans-serif:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-family-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace}*,:after,:before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:rgba(0,0,0,0)}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-size:1rem;line-height:1.5;color:#212529;text-align:left}[tabindex="-1"]:focus:not(:focus-visible){outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;text-decoration:underline dotted;cursor:help;border-bottom:0;text-decoration-skip-ink:none}address{font-style:normal;line-height:inherit}address,dl,ol,ul{margin-bottom:1rem}dl,ol,ul{margin-top:0}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;background-color:transparent}a:hover{color:#0056b3}a:not([href]),a:not([href]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto;-ms-overflow-style:scrollbar}figure{margin:0 0 1rem}img{border-style:none}img,svg{vertical-align:middle}svg{overflow:hidden}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{margin-bottom:.5rem;font-weight:500;line-height:1.2}.h1,h1{font-size:2.5rem}.h2,h2{font-size:2rem}.h3,h3{font-size:1.75rem}.h4,h4{font-size:1.5rem}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:6rem}.display-1,.display-2{font-weight:300;line-height:1.2}.display-2{font-size:5.5rem}.display-3{font-size:4.5rem}.display-3,.display-4{font-weight:300;line-height:1.2}.display-4{font-size:3.5rem}hr{margin-top:1rem;margin-bottom:1rem;border-top:1px solid rgba(0,0,0,.1)}.small,small{font-size:80%;font-weight:400}.mark,mark{padding:.2em;background-color:#fcf8e3}.list-inline,.list-unstyled{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5rem}.initialism{font-size:90%;text-transform:uppercase}.blockquote{margin-bottom:1rem;font-size:1.25rem}.blockquote-footer{display:block;font-size:80%;color:#6c757d}.blockquote-footer:before{content:"\2014\00A0"}.img-fluid,.img-thumbnail{max-width:100%;height:auto}.img-thumbnail{padding:.25rem;background-color:#fff;border:1px solid #dee2e6;border-radius:.25rem}.figure{display:inline-block}.figure-img{margin-bottom:.5rem;line-height:1}.figure-caption{font-size:90%;color:#6c757d}code{font-size:87.5%;color:#e83e8c;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:87.5%;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:100%;font-weight:700}pre{display:block;font-size:87.5%;color:#212529}pre code{font-size:inherit;color:inherit;word-break:normal}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:540px){.container{max-width:540px}}@media (min-width:720px){.container{max-width:720px}}@media (min-width:960px){.container{max-width:960px}}@media (min-width:1200px){.container{max-width:1400px}}.container-fluid,.container-lg,.container-md,.container-sm,.container-xl{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:540px){.container,.container-sm{max-width:540px}}@media (min-width:720px){.container,.container-md,.container-sm{max-width:720px}}@media (min-width:960px){.container,.container-lg,.container-md,.container-sm{max-width:960px}}@media (min-width:1200px){.container,.container-lg,.container-md,.container-sm,.container-xl{max-width:1400px}}.row{display:flex;flex-wrap:wrap;margin-right:-15px;margin-left:-15px}.no-gutters{margin-right:0;margin-left:0}.no-gutters>.col,.no-gutters>[class*=col-]{padding-right:0;padding-left:0}.col,.col-1,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-10,.col-11,.col-12,.col-auto,.col-lg,.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-auto,.col-md,.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12,.col-md-auto,.col-sm,.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-auto,.col-xl,.col-xl-1,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-auto{position:relative;width:100%;padding-right:15px;padding-left:15px}.col{flex-basis:0;flex-grow:1;min-width:0;max-width:100%}.row-cols-1>*{flex:0 0 100%;max-width:100%}.row-cols-2>*{flex:0 0 50%;max-width:50%}.row-cols-3>*{flex:0 0 33.33333%;max-width:33.33333%}.row-cols-4>*{flex:0 0 25%;max-width:25%}.row-cols-5>*{flex:0 0 20%;max-width:20%}.row-cols-6>*{flex:0 0 16.66667%;max-width:16.66667%}.col-auto{flex:0 0 auto;width:auto;max-width:100%}.col-1{flex:0 0 8.33333%;max-width:8.33333%}.col-2{flex:0 0 16.66667%;max-width:16.66667%}.col-3{flex:0 0 25%;max-width:25%}.col-4{flex:0 0 33.33333%;max-width:33.33333%}.col-5{flex:0 0 41.66667%;max-width:41.66667%}.col-6{flex:0 0 50%;max-width:50%}.col-7{flex:0 0 58.33333%;max-width:58.33333%}.col-8{flex:0 0 66.66667%;max-width:66.66667%}.col-9{flex:0 0 75%;max-width:75%}.col-10{flex:0 0 83.33333%;max-width:83.33333%}.col-11{flex:0 0 91.66667%;max-width:91.66667%}.col-12{flex:0 0 100%;max-width:100%}.order-first{order:-1}.order-last{order:13}.order-0{order:0}.order-1{order:1}.order-2{order:2}.order-3{order:3}.order-4{order:4}.order-5{order:5}.order-6{order:6}.order-7{order:7}.order-8{order:8}.order-9{order:9}.order-10{order:10}.order-11{order:11}.order-12{order:12}.offset-1{margin-left:8.33333%}.offset-2{margin-left:16.66667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.33333%}.offset-5{margin-left:41.66667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.33333%}.offset-8{margin-left:66.66667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.33333%}.offset-11{margin-left:91.66667%}@media (min-width:540px){.col-sm{flex-basis:0;flex-grow:1;min-width:0;max-width:100%}.row-cols-sm-1>*{flex:0 0 100%;max-width:100%}.row-cols-sm-2>*{flex:0 0 50%;max-width:50%}.row-cols-sm-3>*{flex:0 0 33.33333%;max-width:33.33333%}.row-cols-sm-4>*{flex:0 0 25%;max-width:25%}.row-cols-sm-5>*{flex:0 0 20%;max-width:20%}.row-cols-sm-6>*{flex:0 0 16.66667%;max-width:16.66667%}.col-sm-auto{flex:0 0 auto;width:auto;max-width:100%}.col-sm-1{flex:0 0 8.33333%;max-width:8.33333%}.col-sm-2{flex:0 0 16.66667%;max-width:16.66667%}.col-sm-3{flex:0 0 25%;max-width:25%}.col-sm-4{flex:0 0 33.33333%;max-width:33.33333%}.col-sm-5{flex:0 0 41.66667%;max-width:41.66667%}.col-sm-6{flex:0 0 50%;max-width:50%}.col-sm-7{flex:0 0 58.33333%;max-width:58.33333%}.col-sm-8{flex:0 0 66.66667%;max-width:66.66667%}.col-sm-9{flex:0 0 75%;max-width:75%}.col-sm-10{flex:0 0 83.33333%;max-width:83.33333%}.col-sm-11{flex:0 0 91.66667%;max-width:91.66667%}.col-sm-12{flex:0 0 100%;max-width:100%}.order-sm-first{order:-1}.order-sm-last{order:13}.order-sm-0{order:0}.order-sm-1{order:1}.order-sm-2{order:2}.order-sm-3{order:3}.order-sm-4{order:4}.order-sm-5{order:5}.order-sm-6{order:6}.order-sm-7{order:7}.order-sm-8{order:8}.order-sm-9{order:9}.order-sm-10{order:10}.order-sm-11{order:11}.order-sm-12{order:12}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.33333%}.offset-sm-2{margin-left:16.66667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.33333%}.offset-sm-5{margin-left:41.66667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.33333%}.offset-sm-8{margin-left:66.66667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.33333%}.offset-sm-11{margin-left:91.66667%}}@media (min-width:720px){.col-md{flex-basis:0;flex-grow:1;min-width:0;max-width:100%}.row-cols-md-1>*{flex:0 0 100%;max-width:100%}.row-cols-md-2>*{flex:0 0 50%;max-width:50%}.row-cols-md-3>*{flex:0 0 33.33333%;max-width:33.33333%}.row-cols-md-4>*{flex:0 0 25%;max-width:25%}.row-cols-md-5>*{flex:0 0 20%;max-width:20%}.row-cols-md-6>*{flex:0 0 16.66667%;max-width:16.66667%}.col-md-auto{flex:0 0 auto;width:auto;max-width:100%}.col-md-1{flex:0 0 8.33333%;max-width:8.33333%}.col-md-2{flex:0 0 16.66667%;max-width:16.66667%}.col-md-3{flex:0 0 25%;max-width:25%}.col-md-4{flex:0 0 33.33333%;max-width:33.33333%}.col-md-5{flex:0 0 41.66667%;max-width:41.66667%}.col-md-6{flex:0 0 50%;max-width:50%}.col-md-7{flex:0 0 58.33333%;max-width:58.33333%}.col-md-8{flex:0 0 66.66667%;max-width:66.66667%}.col-md-9{flex:0 0 75%;max-width:75%}.col-md-10{flex:0 0 83.33333%;max-width:83.33333%}.col-md-11{flex:0 0 91.66667%;max-width:91.66667%}.col-md-12{flex:0 0 100%;max-width:100%}.order-md-first{order:-1}.order-md-last{order:13}.order-md-0{order:0}.order-md-1{order:1}.order-md-2{order:2}.order-md-3{order:3}.order-md-4{order:4}.order-md-5{order:5}.order-md-6{order:6}.order-md-7{order:7}.order-md-8{order:8}.order-md-9{order:9}.order-md-10{order:10}.order-md-11{order:11}.order-md-12{order:12}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.33333%}.offset-md-2{margin-left:16.66667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.33333%}.offset-md-5{margin-left:41.66667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.33333%}.offset-md-8{margin-left:66.66667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.33333%}.offset-md-11{margin-left:91.66667%}}@media (min-width:960px){.col-lg{flex-basis:0;flex-grow:1;min-width:0;max-width:100%}.row-cols-lg-1>*{flex:0 0 100%;max-width:100%}.row-cols-lg-2>*{flex:0 0 50%;max-width:50%}.row-cols-lg-3>*{flex:0 0 33.33333%;max-width:33.33333%}.row-cols-lg-4>*{flex:0 0 25%;max-width:25%}.row-cols-lg-5>*{flex:0 0 20%;max-width:20%}.row-cols-lg-6>*{flex:0 0 16.66667%;max-width:16.66667%}.col-lg-auto{flex:0 0 auto;width:auto;max-width:100%}.col-lg-1{flex:0 0 8.33333%;max-width:8.33333%}.col-lg-2{flex:0 0 16.66667%;max-width:16.66667%}.col-lg-3{flex:0 0 25%;max-width:25%}.col-lg-4{flex:0 0 33.33333%;max-width:33.33333%}.col-lg-5{flex:0 0 41.66667%;max-width:41.66667%}.col-lg-6{flex:0 0 50%;max-width:50%}.col-lg-7{flex:0 0 58.33333%;max-width:58.33333%}.col-lg-8{flex:0 0 66.66667%;max-width:66.66667%}.col-lg-9{flex:0 0 75%;max-width:75%}.col-lg-10{flex:0 0 83.33333%;max-width:83.33333%}.col-lg-11{flex:0 0 91.66667%;max-width:91.66667%}.col-lg-12{flex:0 0 100%;max-width:100%}.order-lg-first{order:-1}.order-lg-last{order:13}.order-lg-0{order:0}.order-lg-1{order:1}.order-lg-2{order:2}.order-lg-3{order:3}.order-lg-4{order:4}.order-lg-5{order:5}.order-lg-6{order:6}.order-lg-7{order:7}.order-lg-8{order:8}.order-lg-9{order:9}.order-lg-10{order:10}.order-lg-11{order:11}.order-lg-12{order:12}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.33333%}.offset-lg-2{margin-left:16.66667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.33333%}.offset-lg-5{margin-left:41.66667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.33333%}.offset-lg-8{margin-left:66.66667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.33333%}.offset-lg-11{margin-left:91.66667%}}@media (min-width:1200px){.col-xl{flex-basis:0;flex-grow:1;min-width:0;max-width:100%}.row-cols-xl-1>*{flex:0 0 100%;max-width:100%}.row-cols-xl-2>*{flex:0 0 50%;max-width:50%}.row-cols-xl-3>*{flex:0 0 33.33333%;max-width:33.33333%}.row-cols-xl-4>*{flex:0 0 25%;max-width:25%}.row-cols-xl-5>*{flex:0 0 20%;max-width:20%}.row-cols-xl-6>*{flex:0 0 16.66667%;max-width:16.66667%}.col-xl-auto{flex:0 0 auto;width:auto;max-width:100%}.col-xl-1{flex:0 0 8.33333%;max-width:8.33333%}.col-xl-2{flex:0 0 16.66667%;max-width:16.66667%}.col-xl-3{flex:0 0 25%;max-width:25%}.col-xl-4{flex:0 0 33.33333%;max-width:33.33333%}.col-xl-5{flex:0 0 41.66667%;max-width:41.66667%}.col-xl-6{flex:0 0 50%;max-width:50%}.col-xl-7{flex:0 0 58.33333%;max-width:58.33333%}.col-xl-8{flex:0 0 66.66667%;max-width:66.66667%}.col-xl-9{flex:0 0 75%;max-width:75%}.col-xl-10{flex:0 0 83.33333%;max-width:83.33333%}.col-xl-11{flex:0 0 91.66667%;max-width:91.66667%}.col-xl-12{flex:0 0 100%;max-width:100%}.order-xl-first{order:-1}.order-xl-last{order:13}.order-xl-0{order:0}.order-xl-1{order:1}.order-xl-2{order:2}.order-xl-3{order:3}.order-xl-4{order:4}.order-xl-5{order:5}.order-xl-6{order:6}.order-xl-7{order:7}.order-xl-8{order:8}.order-xl-9{order:9}.order-xl-10{order:10}.order-xl-11{order:11}.order-xl-12{order:12}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.33333%}.offset-xl-2{margin-left:16.66667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.33333%}.offset-xl-5{margin-left:41.66667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.33333%}.offset-xl-8{margin-left:66.66667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.33333%}.offset-xl-11{margin-left:91.66667%}}.table{width:100%;margin-bottom:1rem;color:#212529}.table td,.table th{padding:.75rem;vertical-align:top;border-top:1px solid #dee2e6}.table thead th{vertical-align:bottom;border-bottom:2px solid #dee2e6}.table tbody+tbody{border-top:2px solid #dee2e6}.table-sm td,.table-sm th{padding:.3rem}.table-bordered,.table-bordered td,.table-bordered th{border:1px solid #dee2e6}.table-bordered thead td,.table-bordered thead th{border-bottom-width:2px}.table-borderless tbody+tbody,.table-borderless td,.table-borderless th,.table-borderless thead th{border:0}.table-striped tbody tr:nth-of-type(odd){background-color:rgba(0,0,0,.05)}.table-hover tbody tr:hover{color:#212529;background-color:rgba(0,0,0,.075)}.table-primary,.table-primary>td,.table-primary>th{background-color:#b8daff}.table-primary tbody+tbody,.table-primary td,.table-primary th,.table-primary thead th{border-color:#7abaff}.table-hover .table-primary:hover,.table-hover .table-primary:hover>td,.table-hover .table-primary:hover>th{background-color:#9fcdff}.table-secondary,.table-secondary>td,.table-secondary>th{background-color:#d6d8db}.table-secondary tbody+tbody,.table-secondary td,.table-secondary th,.table-secondary thead th{border-color:#b3b7bb}.table-hover .table-secondary:hover,.table-hover .table-secondary:hover>td,.table-hover .table-secondary:hover>th{background-color:#c8cbcf}.table-success,.table-success>td,.table-success>th{background-color:#c3e6cb}.table-success tbody+tbody,.table-success td,.table-success th,.table-success thead th{border-color:#8fd19e}.table-hover .table-success:hover,.table-hover .table-success:hover>td,.table-hover .table-success:hover>th{background-color:#b1dfbb}.table-info,.table-info>td,.table-info>th{background-color:#bee5eb}.table-info tbody+tbody,.table-info td,.table-info th,.table-info thead th{border-color:#86cfda}.table-hover .table-info:hover,.table-hover .table-info:hover>td,.table-hover .table-info:hover>th{background-color:#abdde5}.table-warning,.table-warning>td,.table-warning>th{background-color:#ffeeba}.table-warning tbody+tbody,.table-warning td,.table-warning th,.table-warning thead th{border-color:#ffdf7e}.table-hover .table-warning:hover,.table-hover .table-warning:hover>td,.table-hover .table-warning:hover>th{background-color:#ffe8a1}.table-danger,.table-danger>td,.table-danger>th{background-color:#f5c6cb}.table-danger tbody+tbody,.table-danger td,.table-danger th,.table-danger thead th{border-color:#ed969e}.table-hover .table-danger:hover,.table-hover .table-danger:hover>td,.table-hover .table-danger:hover>th{background-color:#f1b0b7}.table-light,.table-light>td,.table-light>th{background-color:#fdfdfe}.table-light tbody+tbody,.table-light td,.table-light th,.table-light thead th{border-color:#fbfcfc}.table-hover .table-light:hover,.table-hover .table-light:hover>td,.table-hover .table-light:hover>th{background-color:#ececf6}.table-dark,.table-dark>td,.table-dark>th{background-color:#c6c8ca}.table-dark tbody+tbody,.table-dark td,.table-dark th,.table-dark thead th{border-color:#95999c}.table-hover .table-dark:hover,.table-hover .table-dark:hover>td,.table-hover .table-dark:hover>th{background-color:#b9bbbe}.table-active,.table-active>td,.table-active>th,.table-hover .table-active:hover,.table-hover .table-active:hover>td,.table-hover .table-active:hover>th{background-color:rgba(0,0,0,.075)}.table .thead-dark th{color:#fff;background-color:#343a40;border-color:#454d55}.table .thead-light th{color:#495057;background-color:#e9ecef;border-color:#dee2e6}.table-dark{color:#fff;background-color:#343a40}.table-dark td,.table-dark th,.table-dark thead th{border-color:#454d55}.table-dark.table-bordered{border:0}.table-dark.table-striped tbody tr:nth-of-type(odd){background-color:hsla(0,0%,100%,.05)}.table-dark.table-hover tbody tr:hover{color:#fff;background-color:hsla(0,0%,100%,.075)}@media (max-width:539.98px){.table-responsive-sm{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-sm>.table-bordered{border:0}}@media (max-width:719.98px){.table-responsive-md{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-md>.table-bordered{border:0}}@media (max-width:959.98px){.table-responsive-lg{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-lg>.table-bordered{border:0}}@media (max-width:1199.98px){.table-responsive-xl{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-xl>.table-bordered{border:0}}.table-responsive{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive>.table-bordered{border:0}.form-control{display:block;width:100%;height:calc(1.5em + .75rem + 2px);padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;background-color:#fff;background-clip:padding-box;border:1px solid #ced4da;border-radius:.25rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-control{transition:none}}.form-control::-ms-expand{background-color:transparent;border:0}.form-control:-moz-focusring{color:transparent;text-shadow:0 0 0 #495057}.form-control:focus{color:#495057;background-color:#fff;border-color:#80bdff;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.form-control::placeholder{color:#6c757d;opacity:1}.form-control:disabled,.form-control[readonly]{background-color:#e9ecef;opacity:1}input[type=date].form-control,input[type=datetime-local].form-control,input[type=month].form-control,input[type=time].form-control{appearance:none}select.form-control:focus::-ms-value{color:#495057;background-color:#fff}.form-control-file,.form-control-range{display:block;width:100%}.col-form-label{padding-top:calc(.375rem + 1px);padding-bottom:calc(.375rem + 1px);margin-bottom:0;font-size:inherit;line-height:1.5}.col-form-label-lg{padding-top:calc(.5rem + 1px);padding-bottom:calc(.5rem + 1px);font-size:1.25rem;line-height:1.5}.col-form-label-sm{padding-top:calc(.25rem + 1px);padding-bottom:calc(.25rem + 1px);font-size:.875rem;line-height:1.5}.form-control-plaintext{display:block;width:100%;padding:.375rem 0;margin-bottom:0;font-size:1rem;line-height:1.5;color:#212529;background-color:transparent;border:solid transparent;border-width:1px 0}.form-control-plaintext.form-control-lg,.form-control-plaintext.form-control-sm{padding-right:0;padding-left:0}.form-control-sm{height:calc(1.5em + .5rem + 2px);padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.form-control-lg{height:calc(1.5em + 1rem + 2px);padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}select.form-control[multiple],select.form-control[size],textarea.form-control{height:auto}.form-group{margin-bottom:1rem}.form-text{display:block;margin-top:.25rem}.form-row{display:flex;flex-wrap:wrap;margin-right:-5px;margin-left:-5px}.form-row>.col,.form-row>[class*=col-]{padding-right:5px;padding-left:5px}.form-check{position:relative;display:block;padding-left:1.25rem}.form-check-input{position:absolute;margin-top:.3rem;margin-left:-1.25rem}.form-check-input:disabled~.form-check-label,.form-check-input[disabled]~.form-check-label{color:#6c757d}.form-check-label{margin-bottom:0}.form-check-inline{display:inline-flex;align-items:center;padding-left:0;margin-right:.75rem}.form-check-inline .form-check-input{position:static;margin-top:0;margin-right:.3125rem;margin-left:0}.valid-feedback{display:none;width:100%;margin-top:.25rem;font-size:80%;color:#28a745}.valid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;line-height:1.5;color:#fff;background-color:rgba(40,167,69,.9);border-radius:.25rem}.is-valid~.valid-feedback,.is-valid~.valid-tooltip,.was-validated :valid~.valid-feedback,.was-validated :valid~.valid-tooltip{display:block}.form-control.is-valid,.was-validated .form-control:valid{border-color:#28a745;padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8'%3E%3Cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-valid:focus,.was-validated .form-control:valid:focus{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.was-validated textarea.form-control:valid,textarea.form-control.is-valid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.custom-select.is-valid,.was-validated .custom-select:valid{border-color:#28a745;padding-right:calc(.75em + 2.3125rem);background:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5'%3E%3Cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") no-repeat right .75rem center/8px 10px,url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8'%3E%3Cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3E%3C/svg%3E") #fff no-repeat center right 1.75rem/calc(.75em + .375rem) calc(.75em + .375rem)}.custom-select.is-valid:focus,.was-validated .custom-select:valid:focus{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.form-check-input.is-valid~.form-check-label,.was-validated .form-check-input:valid~.form-check-label{color:#28a745}.form-check-input.is-valid~.valid-feedback,.form-check-input.is-valid~.valid-tooltip,.was-validated .form-check-input:valid~.valid-feedback,.was-validated .form-check-input:valid~.valid-tooltip{display:block}.custom-control-input.is-valid~.custom-control-label,.was-validated .custom-control-input:valid~.custom-control-label{color:#28a745}.custom-control-input.is-valid~.custom-control-label:before,.was-validated .custom-control-input:valid~.custom-control-label:before{border-color:#28a745}.custom-control-input.is-valid:checked~.custom-control-label:before,.was-validated .custom-control-input:valid:checked~.custom-control-label:before{border-color:#34ce57;background-color:#34ce57}.custom-control-input.is-valid:focus~.custom-control-label:before,.was-validated .custom-control-input:valid:focus~.custom-control-label:before{box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.custom-control-input.is-valid:focus:not(:checked)~.custom-control-label:before,.custom-file-input.is-valid~.custom-file-label,.was-validated .custom-control-input:valid:focus:not(:checked)~.custom-control-label:before,.was-validated .custom-file-input:valid~.custom-file-label{border-color:#28a745}.custom-file-input.is-valid:focus~.custom-file-label,.was-validated .custom-file-input:valid:focus~.custom-file-label{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.invalid-feedback{display:none;width:100%;margin-top:.25rem;font-size:80%;color:#dc3545}.invalid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;line-height:1.5;color:#fff;background-color:rgba(220,53,69,.9);border-radius:.25rem}.is-invalid~.invalid-feedback,.is-invalid~.invalid-tooltip,.was-validated :invalid~.invalid-feedback,.was-validated :invalid~.invalid-tooltip{display:block}.form-control.is-invalid,.was-validated .form-control:invalid{border-color:#dc3545;padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545'%3E%3Ccircle cx='6' cy='6' r='4.5'/%3E%3Cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3E%3Ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-invalid:focus,.was-validated .form-control:invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.was-validated textarea.form-control:invalid,textarea.form-control.is-invalid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.custom-select.is-invalid,.was-validated .custom-select:invalid{border-color:#dc3545;padding-right:calc(.75em + 2.3125rem);background:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5'%3E%3Cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") no-repeat right .75rem center/8px 10px,url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545'%3E%3Ccircle cx='6' cy='6' r='4.5'/%3E%3Cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3E%3Ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3E%3C/svg%3E") #fff no-repeat center right 1.75rem/calc(.75em + .375rem) calc(.75em + .375rem)}.custom-select.is-invalid:focus,.was-validated .custom-select:invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.form-check-input.is-invalid~.form-check-label,.was-validated .form-check-input:invalid~.form-check-label{color:#dc3545}.form-check-input.is-invalid~.invalid-feedback,.form-check-input.is-invalid~.invalid-tooltip,.was-validated .form-check-input:invalid~.invalid-feedback,.was-validated .form-check-input:invalid~.invalid-tooltip{display:block}.custom-control-input.is-invalid~.custom-control-label,.was-validated .custom-control-input:invalid~.custom-control-label{color:#dc3545}.custom-control-input.is-invalid~.custom-control-label:before,.was-validated .custom-control-input:invalid~.custom-control-label:before{border-color:#dc3545}.custom-control-input.is-invalid:checked~.custom-control-label:before,.was-validated .custom-control-input:invalid:checked~.custom-control-label:before{border-color:#e4606d;background-color:#e4606d}.custom-control-input.is-invalid:focus~.custom-control-label:before,.was-validated .custom-control-input:invalid:focus~.custom-control-label:before{box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.custom-control-input.is-invalid:focus:not(:checked)~.custom-control-label:before,.custom-file-input.is-invalid~.custom-file-label,.was-validated .custom-control-input:invalid:focus:not(:checked)~.custom-control-label:before,.was-validated .custom-file-input:invalid~.custom-file-label{border-color:#dc3545}.custom-file-input.is-invalid:focus~.custom-file-label,.was-validated .custom-file-input:invalid:focus~.custom-file-label{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.form-inline{display:flex;flex-flow:row wrap;align-items:center}.form-inline .form-check{width:100%}@media (min-width:540px){.form-inline label{justify-content:center}.form-inline .form-group,.form-inline label{display:flex;align-items:center;margin-bottom:0}.form-inline .form-group{flex:0 0 auto;flex-flow:row wrap}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-plaintext{display:inline-block}.form-inline .custom-select,.form-inline .input-group{width:auto}.form-inline .form-check{display:flex;align-items:center;justify-content:center;width:auto;padding-left:0}.form-inline .form-check-input{position:relative;flex-shrink:0;margin-top:0;margin-right:.25rem;margin-left:0}.form-inline .custom-control{align-items:center;justify-content:center}.form-inline .custom-control-label{margin-bottom:0}}.btn{display:inline-block;font-weight:400;color:#212529;text-align:center;vertical-align:middle;user-select:none;background-color:transparent;border:1px solid transparent;padding:.375rem .75rem;font-size:1rem;line-height:1.5;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.btn{transition:none}}.btn:hover{color:#212529;text-decoration:none}.btn.focus,.btn:focus{outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.btn.disabled,.btn:disabled{opacity:.65}.btn:not(:disabled):not(.disabled){cursor:pointer}a.btn.disabled,fieldset:disabled a.btn{pointer-events:none}.btn-primary{color:#fff;background-color:#007bff;border-color:#007bff}.btn-primary.focus,.btn-primary:focus,.btn-primary:hover{color:#fff;background-color:#0069d9;border-color:#0062cc}.btn-primary.focus,.btn-primary:focus{box-shadow:0 0 0 .2rem rgba(38,143,255,.5)}.btn-primary.disabled,.btn-primary:disabled{color:#fff;background-color:#007bff;border-color:#007bff}.btn-primary:not(:disabled):not(.disabled).active,.btn-primary:not(:disabled):not(.disabled):active,.show>.btn-primary.dropdown-toggle{color:#fff;background-color:#0062cc;border-color:#005cbf}.btn-primary:not(:disabled):not(.disabled).active:focus,.btn-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(38,143,255,.5)}.btn-secondary{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary.focus,.btn-secondary:focus,.btn-secondary:hover{color:#fff;background-color:#5a6268;border-color:#545b62}.btn-secondary.focus,.btn-secondary:focus{box-shadow:0 0 0 .2rem rgba(130,138,145,.5)}.btn-secondary.disabled,.btn-secondary:disabled{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary:not(:disabled):not(.disabled).active,.btn-secondary:not(:disabled):not(.disabled):active,.show>.btn-secondary.dropdown-toggle{color:#fff;background-color:#545b62;border-color:#4e555b}.btn-secondary:not(:disabled):not(.disabled).active:focus,.btn-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(130,138,145,.5)}.btn-success{color:#fff;background-color:#28a745;border-color:#28a745}.btn-success.focus,.btn-success:focus,.btn-success:hover{color:#fff;background-color:#218838;border-color:#1e7e34}.btn-success.focus,.btn-success:focus{box-shadow:0 0 0 .2rem rgba(72,180,97,.5)}.btn-success.disabled,.btn-success:disabled{color:#fff;background-color:#28a745;border-color:#28a745}.btn-success:not(:disabled):not(.disabled).active,.btn-success:not(:disabled):not(.disabled):active,.show>.btn-success.dropdown-toggle{color:#fff;background-color:#1e7e34;border-color:#1c7430}.btn-success:not(:disabled):not(.disabled).active:focus,.btn-success:not(:disabled):not(.disabled):active:focus,.show>.btn-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(72,180,97,.5)}.btn-info{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-info.focus,.btn-info:focus,.btn-info:hover{color:#fff;background-color:#138496;border-color:#117a8b}.btn-info.focus,.btn-info:focus{box-shadow:0 0 0 .2rem rgba(58,176,195,.5)}.btn-info.disabled,.btn-info:disabled{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-info:not(:disabled):not(.disabled).active,.btn-info:not(:disabled):not(.disabled):active,.show>.btn-info.dropdown-toggle{color:#fff;background-color:#117a8b;border-color:#10707f}.btn-info:not(:disabled):not(.disabled).active:focus,.btn-info:not(:disabled):not(.disabled):active:focus,.show>.btn-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(58,176,195,.5)}.btn-warning{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-warning.focus,.btn-warning:focus,.btn-warning:hover{color:#212529;background-color:#e0a800;border-color:#d39e00}.btn-warning.focus,.btn-warning:focus{box-shadow:0 0 0 .2rem rgba(222,170,12,.5)}.btn-warning.disabled,.btn-warning:disabled{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-warning:not(:disabled):not(.disabled).active,.btn-warning:not(:disabled):not(.disabled):active,.show>.btn-warning.dropdown-toggle{color:#212529;background-color:#d39e00;border-color:#c69500}.btn-warning:not(:disabled):not(.disabled).active:focus,.btn-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(222,170,12,.5)}.btn-danger{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger.focus,.btn-danger:focus,.btn-danger:hover{color:#fff;background-color:#c82333;border-color:#bd2130}.btn-danger.focus,.btn-danger:focus{box-shadow:0 0 0 .2rem rgba(225,83,97,.5)}.btn-danger.disabled,.btn-danger:disabled{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger:not(:disabled):not(.disabled).active,.btn-danger:not(:disabled):not(.disabled):active,.show>.btn-danger.dropdown-toggle{color:#fff;background-color:#bd2130;border-color:#b21f2d}.btn-danger:not(:disabled):not(.disabled).active:focus,.btn-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(225,83,97,.5)}.btn-light{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light.focus,.btn-light:focus,.btn-light:hover{color:#212529;background-color:#e2e6ea;border-color:#dae0e5}.btn-light.focus,.btn-light:focus{box-shadow:0 0 0 .2rem rgba(216,217,219,.5)}.btn-light.disabled,.btn-light:disabled{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:not(:disabled):not(.disabled).active,.btn-light:not(:disabled):not(.disabled):active,.show>.btn-light.dropdown-toggle{color:#212529;background-color:#dae0e5;border-color:#d3d9df}.btn-light:not(:disabled):not(.disabled).active:focus,.btn-light:not(:disabled):not(.disabled):active:focus,.show>.btn-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(216,217,219,.5)}.btn-dark{color:#fff;background-color:#343a40;border-color:#343a40}.btn-dark.focus,.btn-dark:focus,.btn-dark:hover{color:#fff;background-color:#23272b;border-color:#1d2124}.btn-dark.focus,.btn-dark:focus{box-shadow:0 0 0 .2rem rgba(82,88,93,.5)}.btn-dark.disabled,.btn-dark:disabled{color:#fff;background-color:#343a40;border-color:#343a40}.btn-dark:not(:disabled):not(.disabled).active,.btn-dark:not(:disabled):not(.disabled):active,.show>.btn-dark.dropdown-toggle{color:#fff;background-color:#1d2124;border-color:#171a1d}.btn-dark:not(:disabled):not(.disabled).active:focus,.btn-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(82,88,93,.5)}.btn-outline-primary{color:#007bff;border-color:#007bff}.btn-outline-primary:hover{color:#fff;background-color:#007bff;border-color:#007bff}.btn-outline-primary.focus,.btn-outline-primary:focus{box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.btn-outline-primary.disabled,.btn-outline-primary:disabled{color:#007bff;background-color:transparent}.btn-outline-primary:not(:disabled):not(.disabled).active,.btn-outline-primary:not(:disabled):not(.disabled):active,.show>.btn-outline-primary.dropdown-toggle{color:#fff;background-color:#007bff;border-color:#007bff}.btn-outline-primary:not(:disabled):not(.disabled).active:focus,.btn-outline-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.btn-outline-secondary{color:#6c757d;border-color:#6c757d}.btn-outline-secondary:hover{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-outline-secondary.focus,.btn-outline-secondary:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.btn-outline-secondary.disabled,.btn-outline-secondary:disabled{color:#6c757d;background-color:transparent}.btn-outline-secondary:not(:disabled):not(.disabled).active,.btn-outline-secondary:not(:disabled):not(.disabled):active,.show>.btn-outline-secondary.dropdown-toggle{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-outline-secondary:not(:disabled):not(.disabled).active:focus,.btn-outline-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.btn-outline-success{color:#28a745;border-color:#28a745}.btn-outline-success:hover{color:#fff;background-color:#28a745;border-color:#28a745}.btn-outline-success.focus,.btn-outline-success:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.btn-outline-success.disabled,.btn-outline-success:disabled{color:#28a745;background-color:transparent}.btn-outline-success:not(:disabled):not(.disabled).active,.btn-outline-success:not(:disabled):not(.disabled):active,.show>.btn-outline-success.dropdown-toggle{color:#fff;background-color:#28a745;border-color:#28a745}.btn-outline-success:not(:disabled):not(.disabled).active:focus,.btn-outline-success:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.btn-outline-info{color:#17a2b8;border-color:#17a2b8}.btn-outline-info:hover{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-outline-info.focus,.btn-outline-info:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.btn-outline-info.disabled,.btn-outline-info:disabled{color:#17a2b8;background-color:transparent}.btn-outline-info:not(:disabled):not(.disabled).active,.btn-outline-info:not(:disabled):not(.disabled):active,.show>.btn-outline-info.dropdown-toggle{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-outline-info:not(:disabled):not(.disabled).active:focus,.btn-outline-info:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.btn-outline-warning{color:#ffc107;border-color:#ffc107}.btn-outline-warning:hover{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-outline-warning.focus,.btn-outline-warning:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.btn-outline-warning.disabled,.btn-outline-warning:disabled{color:#ffc107;background-color:transparent}.btn-outline-warning:not(:disabled):not(.disabled).active,.btn-outline-warning:not(:disabled):not(.disabled):active,.show>.btn-outline-warning.dropdown-toggle{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-outline-warning:not(:disabled):not(.disabled).active:focus,.btn-outline-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.btn-outline-danger{color:#dc3545;border-color:#dc3545}.btn-outline-danger:hover{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-outline-danger.focus,.btn-outline-danger:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-outline-danger.disabled,.btn-outline-danger:disabled{color:#dc3545;background-color:transparent}.btn-outline-danger:not(:disabled):not(.disabled).active,.btn-outline-danger:not(:disabled):not(.disabled):active,.show>.btn-outline-danger.dropdown-toggle{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-outline-danger:not(:disabled):not(.disabled).active:focus,.btn-outline-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-outline-light{color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light:hover{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light.focus,.btn-outline-light:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-outline-light.disabled,.btn-outline-light:disabled{color:#f8f9fa;background-color:transparent}.btn-outline-light:not(:disabled):not(.disabled).active,.btn-outline-light:not(:disabled):not(.disabled):active,.show>.btn-outline-light.dropdown-toggle{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light:not(:disabled):not(.disabled).active:focus,.btn-outline-light:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-outline-dark{color:#343a40;border-color:#343a40}.btn-outline-dark:hover{color:#fff;background-color:#343a40;border-color:#343a40}.btn-outline-dark.focus,.btn-outline-dark:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.btn-outline-dark.disabled,.btn-outline-dark:disabled{color:#343a40;background-color:transparent}.btn-outline-dark:not(:disabled):not(.disabled).active,.btn-outline-dark:not(:disabled):not(.disabled):active,.show>.btn-outline-dark.dropdown-toggle{color:#fff;background-color:#343a40;border-color:#343a40}.btn-outline-dark:not(:disabled):not(.disabled).active:focus,.btn-outline-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.btn-link{font-weight:400;color:#007bff;text-decoration:none}.btn-link:hover{color:#0056b3}.btn-link.focus,.btn-link:focus,.btn-link:hover{text-decoration:underline}.btn-link.disabled,.btn-link:disabled{color:#6c757d;pointer-events:none}.btn-group-lg>.btn,.btn-lg{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.btn-group-sm>.btn,.btn-sm{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:.5rem}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{transition:opacity .15s linear}@media (prefers-reduced-motion:reduce){.fade{transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{position:relative;height:0;overflow:hidden;transition:height .35s ease}@media (prefers-reduced-motion:reduce){.collapsing{transition:none}}.dropdown,.dropleft,.dropright,.dropup{position:relative}.dropdown-toggle{white-space:nowrap}.dropdown-toggle:after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid;border-right:.3em solid transparent;border-bottom:0;border-left:.3em solid transparent}.dropdown-toggle:empty:after{margin-left:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:10rem;padding:.5rem 0;margin:.125rem 0 0;font-size:1rem;color:#212529;text-align:left;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.15);border-radius:.25rem}.dropdown-menu-left{right:auto;left:0}.dropdown-menu-right{right:0;left:auto}@media (min-width:540px){.dropdown-menu-sm-left{right:auto;left:0}.dropdown-menu-sm-right{right:0;left:auto}}@media (min-width:720px){.dropdown-menu-md-left{right:auto;left:0}.dropdown-menu-md-right{right:0;left:auto}}@media (min-width:960px){.dropdown-menu-lg-left{right:auto;left:0}.dropdown-menu-lg-right{right:0;left:auto}}@media (min-width:1200px){.dropdown-menu-xl-left{right:auto;left:0}.dropdown-menu-xl-right{right:0;left:auto}}.dropup .dropdown-menu{top:auto;bottom:100%;margin-top:0;margin-bottom:.125rem}.dropup .dropdown-toggle:after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:0;border-right:.3em solid transparent;border-bottom:.3em solid;border-left:.3em solid transparent}.dropup .dropdown-toggle:empty:after{margin-left:0}.dropright .dropdown-menu{top:0;right:auto;left:100%;margin-top:0;margin-left:.125rem}.dropright .dropdown-toggle:after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:0;border-bottom:.3em solid transparent;border-left:.3em solid}.dropright .dropdown-toggle:empty:after{margin-left:0}.dropright .dropdown-toggle:after{vertical-align:0}.dropleft .dropdown-menu{top:0;right:100%;left:auto;margin-top:0;margin-right:.125rem}.dropleft .dropdown-toggle:after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";display:none}.dropleft .dropdown-toggle:before{display:inline-block;margin-right:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:.3em solid;border-bottom:.3em solid transparent}.dropleft .dropdown-toggle:empty:after{margin-left:0}.dropleft .dropdown-toggle:before{vertical-align:0}.dropdown-menu[x-placement^=bottom],.dropdown-menu[x-placement^=left],.dropdown-menu[x-placement^=right],.dropdown-menu[x-placement^=top]{right:auto;bottom:auto}.dropdown-divider{height:0;margin:.5rem 0;overflow:hidden;border-top:1px solid #e9ecef}.dropdown-item{display:block;width:100%;padding:.25rem 1.5rem;clear:both;font-weight:400;color:#212529;text-align:inherit;white-space:nowrap;background-color:transparent;border:0}.dropdown-item:focus,.dropdown-item:hover{color:#16181b;text-decoration:none;background-color:#f8f9fa}.dropdown-item.active,.dropdown-item:active{color:#fff;text-decoration:none;background-color:#007bff}.dropdown-item.disabled,.dropdown-item:disabled{color:#6c757d;pointer-events:none;background-color:transparent}.dropdown-menu.show{display:block}.dropdown-header{display:block;padding:.5rem 1.5rem;margin-bottom:0;font-size:.875rem;color:#6c757d;white-space:nowrap}.dropdown-item-text{display:block;padding:.25rem 1.5rem;color:#212529}.btn-group,.btn-group-vertical{position:relative;display:inline-flex;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;flex:1 1 auto}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:1}.btn-toolbar{display:flex;flex-wrap:wrap;justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group>.btn-group:not(:first-child),.btn-group>.btn:not(:first-child){margin-left:-1px}.btn-group>.btn-group:not(:last-child)>.btn,.btn-group>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:not(:first-child)>.btn,.btn-group>.btn:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.dropdown-toggle-split{padding-right:.5625rem;padding-left:.5625rem}.dropdown-toggle-split:after,.dropright .dropdown-toggle-split:after,.dropup .dropdown-toggle-split:after{margin-left:0}.dropleft .dropdown-toggle-split:before{margin-right:0}.btn-group-sm>.btn+.dropdown-toggle-split,.btn-sm+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.btn-group-lg>.btn+.dropdown-toggle-split,.btn-lg+.dropdown-toggle-split{padding-right:.75rem;padding-left:.75rem}.btn-group-vertical{flex-direction:column;align-items:flex-start;justify-content:center}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group{width:100%}.btn-group-vertical>.btn-group:not(:first-child),.btn-group-vertical>.btn:not(:first-child){margin-top:-1px}.btn-group-vertical>.btn-group:not(:last-child)>.btn,.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child)>.btn,.btn-group-vertical>.btn:not(:first-child){border-top-left-radius:0;border-top-right-radius:0}.btn-group-toggle>.btn,.btn-group-toggle>.btn-group>.btn{margin-bottom:0}.btn-group-toggle>.btn-group>.btn input[type=checkbox],.btn-group-toggle>.btn-group>.btn input[type=radio],.btn-group-toggle>.btn input[type=checkbox],.btn-group-toggle>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:flex;flex-wrap:wrap;align-items:stretch;width:100%}.input-group>.custom-file,.input-group>.custom-select,.input-group>.form-control,.input-group>.form-control-plaintext{position:relative;flex:1 1 auto;width:1%;min-width:0;margin-bottom:0}.input-group>.custom-file+.custom-file,.input-group>.custom-file+.custom-select,.input-group>.custom-file+.form-control,.input-group>.custom-select+.custom-file,.input-group>.custom-select+.custom-select,.input-group>.custom-select+.form-control,.input-group>.form-control+.custom-file,.input-group>.form-control+.custom-select,.input-group>.form-control+.form-control,.input-group>.form-control-plaintext+.custom-file,.input-group>.form-control-plaintext+.custom-select,.input-group>.form-control-plaintext+.form-control{margin-left:-1px}.input-group>.custom-file .custom-file-input:focus~.custom-file-label,.input-group>.custom-select:focus,.input-group>.form-control:focus{z-index:3}.input-group>.custom-file .custom-file-input:focus{z-index:4}.input-group>.custom-select:not(:last-child),.input-group>.form-control:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.custom-select:not(:first-child),.input-group>.form-control:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.input-group>.custom-file{display:flex;align-items:center}.input-group>.custom-file:not(:last-child) .custom-file-label,.input-group>.custom-file:not(:last-child) .custom-file-label:after{border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.custom-file:not(:first-child) .custom-file-label{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-append,.input-group-prepend{display:flex}.input-group-append .btn,.input-group-prepend .btn{position:relative;z-index:2}.input-group-append .btn:focus,.input-group-prepend .btn:focus{z-index:3}.input-group-append .btn+.btn,.input-group-append .btn+.input-group-text,.input-group-append .input-group-text+.btn,.input-group-append .input-group-text+.input-group-text,.input-group-prepend .btn+.btn,.input-group-prepend .btn+.input-group-text,.input-group-prepend .input-group-text+.btn,.input-group-prepend .input-group-text+.input-group-text{margin-left:-1px}.input-group-prepend{margin-right:-1px}.input-group-append{margin-left:-1px}.input-group-text{display:flex;align-items:center;padding:.375rem .75rem;margin-bottom:0;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;text-align:center;white-space:nowrap;background-color:#e9ecef;border:1px solid #ced4da;border-radius:.25rem}.input-group-text input[type=checkbox],.input-group-text input[type=radio]{margin-top:0}.input-group-lg>.custom-select,.input-group-lg>.form-control:not(textarea){height:calc(1.5em + 1rem + 2px)}.input-group-lg>.custom-select,.input-group-lg>.form-control,.input-group-lg>.input-group-append>.btn,.input-group-lg>.input-group-append>.input-group-text,.input-group-lg>.input-group-prepend>.btn,.input-group-lg>.input-group-prepend>.input-group-text{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.input-group-sm>.custom-select,.input-group-sm>.form-control:not(textarea){height:calc(1.5em + .5rem + 2px)}.input-group-sm>.custom-select,.input-group-sm>.form-control,.input-group-sm>.input-group-append>.btn,.input-group-sm>.input-group-append>.input-group-text,.input-group-sm>.input-group-prepend>.btn,.input-group-sm>.input-group-prepend>.input-group-text{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.input-group-lg>.custom-select,.input-group-sm>.custom-select{padding-right:1.75rem}.input-group>.input-group-append:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group>.input-group-append:last-child>.input-group-text:not(:last-child),.input-group>.input-group-append:not(:last-child)>.btn,.input-group>.input-group-append:not(:last-child)>.input-group-text,.input-group>.input-group-prepend>.btn,.input-group>.input-group-prepend>.input-group-text{border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.input-group-append>.btn,.input-group>.input-group-append>.input-group-text,.input-group>.input-group-prepend:first-child>.btn:not(:first-child),.input-group>.input-group-prepend:first-child>.input-group-text:not(:first-child),.input-group>.input-group-prepend:not(:first-child)>.btn,.input-group>.input-group-prepend:not(:first-child)>.input-group-text{border-top-left-radius:0;border-bottom-left-radius:0}.custom-control{position:relative;display:block;min-height:1.5rem;padding-left:1.5rem}.custom-control-inline{display:inline-flex;margin-right:1rem}.custom-control-input{position:absolute;left:0;z-index:-1;width:1rem;height:1.25rem;opacity:0}.custom-control-input:checked~.custom-control-label:before{color:#fff;border-color:#007bff;background-color:#007bff}.custom-control-input:focus~.custom-control-label:before{box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.custom-control-input:focus:not(:checked)~.custom-control-label:before{border-color:#80bdff}.custom-control-input:not(:disabled):active~.custom-control-label:before{color:#fff;background-color:#b3d7ff;border-color:#b3d7ff}.custom-control-input:disabled~.custom-control-label,.custom-control-input[disabled]~.custom-control-label{color:#6c757d}.custom-control-input:disabled~.custom-control-label:before,.custom-control-input[disabled]~.custom-control-label:before{background-color:#e9ecef}.custom-control-label{position:relative;margin-bottom:0;vertical-align:top}.custom-control-label:before{pointer-events:none;background-color:#fff;border:1px solid #adb5bd}.custom-control-label:after,.custom-control-label:before{position:absolute;top:.25rem;left:-1.5rem;display:block;width:1rem;height:1rem;content:""}.custom-control-label:after{background:no-repeat 50%/50% 50%}.custom-checkbox .custom-control-label:before{border-radius:.25rem}.custom-checkbox .custom-control-input:checked~.custom-control-label:after{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26l2.974 2.99L8 2.193z'/%3E%3C/svg%3E")}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label:before{border-color:#007bff;background-color:#007bff}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label:after{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='4' height='4'%3E%3Cpath stroke='%23fff' d='M0 2h4'/%3E%3C/svg%3E")}.custom-checkbox .custom-control-input:disabled:checked~.custom-control-label:before{background-color:rgba(0,123,255,.5)}.custom-checkbox .custom-control-input:disabled:indeterminate~.custom-control-label:before{background-color:rgba(0,123,255,.5)}.custom-radio .custom-control-label:before{border-radius:50%}.custom-radio .custom-control-input:checked~.custom-control-label:after{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23fff'/%3E%3C/svg%3E")}.custom-radio .custom-control-input:disabled:checked~.custom-control-label:before{background-color:rgba(0,123,255,.5)}.custom-switch{padding-left:2.25rem}.custom-switch .custom-control-label:before{left:-2.25rem;width:1.75rem;pointer-events:all;border-radius:.5rem}.custom-switch .custom-control-label:after{top:calc(.25rem + 2px);left:calc(-2.25rem + 2px);width:calc(1rem - 4px);height:calc(1rem - 4px);background-color:#adb5bd;border-radius:.5rem;transition:transform .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.custom-switch .custom-control-label:after{transition:none}}.custom-switch .custom-control-input:checked~.custom-control-label:after{background-color:#fff;transform:translateX(.75rem)}.custom-switch .custom-control-input:disabled:checked~.custom-control-label:before{background-color:rgba(0,123,255,.5)}.custom-select{display:inline-block;width:100%;height:calc(1.5em + .75rem + 2px);padding:.375rem 1.75rem .375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;vertical-align:middle;background:#fff url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5'%3E%3Cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") no-repeat right .75rem center/8px 10px;border:1px solid #ced4da;border-radius:.25rem;appearance:none}.custom-select:focus{border-color:#80bdff;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.custom-select:focus::-ms-value{color:#495057;background-color:#fff}.custom-select[multiple],.custom-select[size]:not([size="1"]){height:auto;padding-right:.75rem;background-image:none}.custom-select:disabled{color:#6c757d;background-color:#e9ecef}.custom-select::-ms-expand{display:none}.custom-select:-moz-focusring{color:transparent;text-shadow:0 0 0 #495057}.custom-select-sm{height:calc(1.5em + .5rem + 2px);padding-top:.25rem;padding-bottom:.25rem;padding-left:.5rem;font-size:.875rem}.custom-select-lg{height:calc(1.5em + 1rem + 2px);padding-top:.5rem;padding-bottom:.5rem;padding-left:1rem;font-size:1.25rem}.custom-file{display:inline-block;margin-bottom:0}.custom-file,.custom-file-input{position:relative;width:100%;height:calc(1.5em + .75rem + 2px)}.custom-file-input{z-index:2;margin:0;opacity:0}.custom-file-input:focus~.custom-file-label{border-color:#80bdff;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.custom-file-input:disabled~.custom-file-label,.custom-file-input[disabled]~.custom-file-label{background-color:#e9ecef}.custom-file-input:lang(en)~.custom-file-label:after{content:"Browse"}.custom-file-input~.custom-file-label[data-browse]:after{content:attr(data-browse)}.custom-file-label{left:0;z-index:1;height:calc(1.5em + .75rem + 2px);font-weight:400;background-color:#fff;border:1px solid #ced4da;border-radius:.25rem}.custom-file-label,.custom-file-label:after{position:absolute;top:0;right:0;padding:.375rem .75rem;line-height:1.5;color:#495057}.custom-file-label:after{bottom:0;z-index:3;display:block;height:calc(1.5em + .75rem);content:"Browse";background-color:#e9ecef;border-left:inherit;border-radius:0 .25rem .25rem 0}.custom-range{width:100%;height:1.4rem;padding:0;background-color:transparent;appearance:none}.custom-range:focus{outline:none}.custom-range:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range:focus::-ms-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range::-moz-focus-outer{border:0}.custom-range::-webkit-slider-thumb{width:1rem;height:1rem;margin-top:-.25rem;background-color:#007bff;border:0;border-radius:1rem;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;appearance:none}@media (prefers-reduced-motion:reduce){.custom-range::-webkit-slider-thumb{transition:none}}.custom-range::-webkit-slider-thumb:active{background-color:#b3d7ff}.custom-range::-webkit-slider-runnable-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.custom-range::-moz-range-thumb{width:1rem;height:1rem;background-color:#007bff;border:0;border-radius:1rem;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;appearance:none}@media (prefers-reduced-motion:reduce){.custom-range::-moz-range-thumb{transition:none}}.custom-range::-moz-range-thumb:active{background-color:#b3d7ff}.custom-range::-moz-range-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.custom-range::-ms-thumb{width:1rem;height:1rem;margin-top:0;margin-right:.2rem;margin-left:.2rem;background-color:#007bff;border:0;border-radius:1rem;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;appearance:none}@media (prefers-reduced-motion:reduce){.custom-range::-ms-thumb{transition:none}}.custom-range::-ms-thumb:active{background-color:#b3d7ff}.custom-range::-ms-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:transparent;border-color:transparent;border-width:.5rem}.custom-range::-ms-fill-lower,.custom-range::-ms-fill-upper{background-color:#dee2e6;border-radius:1rem}.custom-range::-ms-fill-upper{margin-right:15px}.custom-range:disabled::-webkit-slider-thumb{background-color:#adb5bd}.custom-range:disabled::-webkit-slider-runnable-track{cursor:default}.custom-range:disabled::-moz-range-thumb{background-color:#adb5bd}.custom-range:disabled::-moz-range-track{cursor:default}.custom-range:disabled::-ms-thumb{background-color:#adb5bd}.custom-control-label:before,.custom-file-label,.custom-select{transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.custom-control-label:before,.custom-file-label,.custom-select{transition:none}}.nav{display:flex;flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.nav-link{display:block;padding:.5rem 1rem}.nav-link:focus,.nav-link:hover{text-decoration:none}.nav-link.disabled{color:#6c757d;pointer-events:none;cursor:default}.nav-tabs{border-bottom:1px solid #dee2e6}.nav-tabs .nav-item{margin-bottom:-1px}.nav-tabs .nav-link{border:1px solid transparent;border-top-left-radius:.25rem;border-top-right-radius:.25rem}.nav-tabs .nav-link:focus,.nav-tabs .nav-link:hover{border-color:#e9ecef #e9ecef #dee2e6}.nav-tabs .nav-link.disabled{color:#6c757d;background-color:transparent;border-color:transparent}.nav-tabs .nav-item.show .nav-link,.nav-tabs .nav-link.active{color:#495057;background-color:#fff;border-color:#dee2e6 #dee2e6 #fff}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.nav-pills .nav-link{border-radius:.25rem}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{color:#fff;background-color:#007bff}.nav-fill .nav-item{flex:1 1 auto;text-align:center}.nav-justified .nav-item{flex-basis:0;flex-grow:1;text-align:center}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{position:relative;padding:.5rem 1rem}.navbar,.navbar .container,.navbar .container-fluid,.navbar .container-lg,.navbar .container-md,.navbar .container-sm,.navbar .container-xl{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between}.navbar-brand{display:inline-block;padding-top:.3125rem;padding-bottom:.3125rem;margin-right:1rem;font-size:1.25rem;line-height:inherit;white-space:nowrap}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-nav{display:flex;flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .nav-link{padding-right:0;padding-left:0}.navbar-nav .dropdown-menu{position:static;float:none}.navbar-text{display:inline-block;padding-top:.5rem;padding-bottom:.5rem}.navbar-collapse{flex-basis:100%;flex-grow:1;align-items:center}.navbar-toggler{padding:.25rem .75rem;font-size:1.25rem;line-height:1;background-color:transparent;border:1px solid transparent;border-radius:.25rem}.navbar-toggler:focus,.navbar-toggler:hover{text-decoration:none}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;content:"";background:no-repeat 50%;background-size:100% 100%}@media (max-width:539.98px){.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid,.navbar-expand-sm>.container-lg,.navbar-expand-sm>.container-md,.navbar-expand-sm>.container-sm,.navbar-expand-sm>.container-xl{padding-right:0;padding-left:0}}@media (min-width:540px){.navbar-expand-sm{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand-sm .navbar-nav{flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid,.navbar-expand-sm>.container-lg,.navbar-expand-sm>.container-md,.navbar-expand-sm>.container-sm,.navbar-expand-sm>.container-xl{flex-wrap:nowrap}.navbar-expand-sm .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}}@media (max-width:719.98px){.navbar-expand-md>.container,.navbar-expand-md>.container-fluid,.navbar-expand-md>.container-lg,.navbar-expand-md>.container-md,.navbar-expand-md>.container-sm,.navbar-expand-md>.container-xl{padding-right:0;padding-left:0}}@media (min-width:720px){.navbar-expand-md{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand-md .navbar-nav{flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-md>.container,.navbar-expand-md>.container-fluid,.navbar-expand-md>.container-lg,.navbar-expand-md>.container-md,.navbar-expand-md>.container-sm,.navbar-expand-md>.container-xl{flex-wrap:nowrap}.navbar-expand-md .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}}@media (max-width:959.98px){.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid,.navbar-expand-lg>.container-lg,.navbar-expand-lg>.container-md,.navbar-expand-lg>.container-sm,.navbar-expand-lg>.container-xl{padding-right:0;padding-left:0}}@media (min-width:960px){.navbar-expand-lg{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand-lg .navbar-nav{flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid,.navbar-expand-lg>.container-lg,.navbar-expand-lg>.container-md,.navbar-expand-lg>.container-sm,.navbar-expand-lg>.container-xl{flex-wrap:nowrap}.navbar-expand-lg .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}}@media (max-width:1199.98px){.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid,.navbar-expand-xl>.container-lg,.navbar-expand-xl>.container-md,.navbar-expand-xl>.container-sm,.navbar-expand-xl>.container-xl{padding-right:0;padding-left:0}}@media (min-width:1200px){.navbar-expand-xl{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand-xl .navbar-nav{flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid,.navbar-expand-xl>.container-lg,.navbar-expand-xl>.container-md,.navbar-expand-xl>.container-sm,.navbar-expand-xl>.container-xl{flex-wrap:nowrap}.navbar-expand-xl .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}}.navbar-expand{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand>.container,.navbar-expand>.container-fluid,.navbar-expand>.container-lg,.navbar-expand>.container-md,.navbar-expand>.container-sm,.navbar-expand>.container-xl{padding-right:0;padding-left:0}.navbar-expand .navbar-nav{flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand>.container,.navbar-expand>.container-fluid,.navbar-expand>.container-lg,.navbar-expand>.container-md,.navbar-expand>.container-sm,.navbar-expand>.container-xl{flex-wrap:nowrap}.navbar-expand .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-light .navbar-brand,.navbar-light .navbar-brand:focus,.navbar-light .navbar-brand:hover{color:rgba(0,0,0,.9)}.navbar-light .navbar-nav .nav-link{color:rgba(0,0,0,.5)}.navbar-light .navbar-nav .nav-link:focus,.navbar-light .navbar-nav .nav-link:hover{color:rgba(0,0,0,.7)}.navbar-light .navbar-nav .nav-link.disabled{color:rgba(0,0,0,.3)}.navbar-light .navbar-nav .active>.nav-link,.navbar-light .navbar-nav .nav-link.active,.navbar-light .navbar-nav .nav-link.show,.navbar-light .navbar-nav .show>.nav-link{color:rgba(0,0,0,.9)}.navbar-light .navbar-toggler{color:rgba(0,0,0,.5);border-color:rgba(0,0,0,.1)}.navbar-light .navbar-toggler-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30'%3E%3Cpath stroke='rgba(0,0,0,0.5)' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E")}.navbar-light .navbar-text{color:rgba(0,0,0,.5)}.navbar-light .navbar-text a,.navbar-light .navbar-text a:focus,.navbar-light .navbar-text a:hover{color:rgba(0,0,0,.9)}.navbar-dark .navbar-brand,.navbar-dark .navbar-brand:focus,.navbar-dark .navbar-brand:hover{color:#fff}.navbar-dark .navbar-nav .nav-link{color:hsla(0,0%,100%,.5)}.navbar-dark .navbar-nav .nav-link:focus,.navbar-dark .navbar-nav .nav-link:hover{color:hsla(0,0%,100%,.75)}.navbar-dark .navbar-nav .nav-link.disabled{color:hsla(0,0%,100%,.25)}.navbar-dark .navbar-nav .active>.nav-link,.navbar-dark .navbar-nav .nav-link.active,.navbar-dark .navbar-nav .nav-link.show,.navbar-dark .navbar-nav .show>.nav-link{color:#fff}.navbar-dark .navbar-toggler{color:hsla(0,0%,100%,.5);border-color:hsla(0,0%,100%,.1)}.navbar-dark .navbar-toggler-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30'%3E%3Cpath stroke='rgba(255,255,255,0.5)' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E")}.navbar-dark .navbar-text{color:hsla(0,0%,100%,.5)}.navbar-dark .navbar-text a,.navbar-dark .navbar-text a:focus,.navbar-dark .navbar-text a:hover{color:#fff}.card{position:relative;display:flex;flex-direction:column;min-width:0;word-wrap:break-word;background-color:#fff;background-clip:border-box;border:1px solid rgba(0,0,0,.125);border-radius:.25rem}.card>hr{margin-right:0;margin-left:0}.card>.list-group{border-top:inherit;border-bottom:inherit}.card>.list-group:first-child{border-top-width:0;border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.card>.list-group:last-child{border-bottom-width:0;border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.card-body{flex:1 1 auto;min-height:1px;padding:1.25rem}.card-title{margin-bottom:.75rem}.card-subtitle{margin-top:-.375rem}.card-subtitle,.card-text:last-child{margin-bottom:0}.card-link:hover{text-decoration:none}.card-link+.card-link{margin-left:1.25rem}.card-header{padding:.75rem 1.25rem;margin-bottom:0;background-color:rgba(0,0,0,.03);border-bottom:1px solid rgba(0,0,0,.125)}.card-header:first-child{border-radius:calc(.25rem - 1px) calc(.25rem - 1px) 0 0}.card-header+.list-group .list-group-item:first-child{border-top:0}.card-footer{padding:.75rem 1.25rem;background-color:rgba(0,0,0,.03);border-top:1px solid rgba(0,0,0,.125)}.card-footer:last-child{border-radius:0 0 calc(.25rem - 1px) calc(.25rem - 1px)}.card-header-tabs{margin-bottom:-.75rem;border-bottom:0}.card-header-pills,.card-header-tabs{margin-right:-.625rem;margin-left:-.625rem}.card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1.25rem}.card-img,.card-img-bottom,.card-img-top{flex-shrink:0;width:100%}.card-img,.card-img-top{border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.card-img,.card-img-bottom{border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.card-deck .card{margin-bottom:15px}@media (min-width:540px){.card-deck{display:flex;flex-flow:row wrap;margin-right:-15px;margin-left:-15px}.card-deck .card{flex:1 0 0%;margin-right:15px;margin-bottom:0;margin-left:15px}}.card-group>.card{margin-bottom:15px}@media (min-width:540px){.card-group{display:flex;flex-flow:row wrap}.card-group>.card{flex:1 0 0%;margin-bottom:0}.card-group>.card+.card{margin-left:0;border-left:0}.card-group>.card:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.card-group>.card:not(:last-child) .card-header,.card-group>.card:not(:last-child) .card-img-top{border-top-right-radius:0}.card-group>.card:not(:last-child) .card-footer,.card-group>.card:not(:last-child) .card-img-bottom{border-bottom-right-radius:0}.card-group>.card:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.card-group>.card:not(:first-child) .card-header,.card-group>.card:not(:first-child) .card-img-top{border-top-left-radius:0}.card-group>.card:not(:first-child) .card-footer,.card-group>.card:not(:first-child) .card-img-bottom{border-bottom-left-radius:0}}.card-columns .card{margin-bottom:.75rem}@media (min-width:540px){.card-columns{column-count:3;column-gap:1.25rem;orphans:1;widows:1}.card-columns .card{display:inline-block;width:100%}}.accordion>.card{overflow:hidden}.accordion>.card:not(:last-of-type){border-bottom:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.accordion>.card:not(:first-of-type){border-top-left-radius:0;border-top-right-radius:0}.accordion>.card>.card-header{border-radius:0;margin-bottom:-1px}.breadcrumb{flex-wrap:wrap;padding:.75rem 1rem;margin-bottom:1rem;list-style:none;background-color:#e9ecef;border-radius:.25rem}.breadcrumb,.breadcrumb-item{display:flex}.breadcrumb-item+.breadcrumb-item{padding-left:.5rem}.breadcrumb-item+.breadcrumb-item:before{display:inline-block;padding-right:.5rem;color:#6c757d;content:"/"}.breadcrumb-item+.breadcrumb-item:hover:before{text-decoration:underline;text-decoration:none}.breadcrumb-item.active{color:#6c757d}.pagination{display:flex;padding-left:0;list-style:none;border-radius:.25rem}.page-link{position:relative;display:block;padding:.5rem .75rem;margin-left:-1px;line-height:1.25;color:#007bff;background-color:#fff;border:1px solid #dee2e6}.page-link:hover{z-index:2;color:#0056b3;text-decoration:none;background-color:#e9ecef;border-color:#dee2e6}.page-link:focus{z-index:3;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.page-item:first-child .page-link{margin-left:0;border-top-left-radius:.25rem;border-bottom-left-radius:.25rem}.page-item:last-child .page-link{border-top-right-radius:.25rem;border-bottom-right-radius:.25rem}.page-item.active .page-link{z-index:3;color:#fff;background-color:#007bff;border-color:#007bff}.page-item.disabled .page-link{color:#6c757d;pointer-events:none;cursor:auto;background-color:#fff;border-color:#dee2e6}.pagination-lg .page-link{padding:.75rem 1.5rem;font-size:1.25rem;line-height:1.5}.pagination-lg .page-item:first-child .page-link{border-top-left-radius:.3rem;border-bottom-left-radius:.3rem}.pagination-lg .page-item:last-child .page-link{border-top-right-radius:.3rem;border-bottom-right-radius:.3rem}.pagination-sm .page-link{padding:.25rem .5rem;font-size:.875rem;line-height:1.5}.pagination-sm .page-item:first-child .page-link{border-top-left-radius:.2rem;border-bottom-left-radius:.2rem}.pagination-sm .page-item:last-child .page-link{border-top-right-radius:.2rem;border-bottom-right-radius:.2rem}.badge{display:inline-block;padding:.25em .4em;font-size:75%;font-weight:700;line-height:1;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.badge{transition:none}}a.badge:focus,a.badge:hover{text-decoration:none}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.badge-pill{padding-right:.6em;padding-left:.6em;border-radius:10rem}.badge-primary{color:#fff;background-color:#007bff}a.badge-primary:focus,a.badge-primary:hover{color:#fff;background-color:#0062cc}a.badge-primary.focus,a.badge-primary:focus{outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.badge-secondary{color:#fff;background-color:#6c757d}a.badge-secondary:focus,a.badge-secondary:hover{color:#fff;background-color:#545b62}a.badge-secondary.focus,a.badge-secondary:focus{outline:0;box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.badge-success{color:#fff;background-color:#28a745}a.badge-success:focus,a.badge-success:hover{color:#fff;background-color:#1e7e34}a.badge-success.focus,a.badge-success:focus{outline:0;box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.badge-info{color:#fff;background-color:#17a2b8}a.badge-info:focus,a.badge-info:hover{color:#fff;background-color:#117a8b}a.badge-info.focus,a.badge-info:focus{outline:0;box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.badge-warning{color:#212529;background-color:#ffc107}a.badge-warning:focus,a.badge-warning:hover{color:#212529;background-color:#d39e00}a.badge-warning.focus,a.badge-warning:focus{outline:0;box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.badge-danger{color:#fff;background-color:#dc3545}a.badge-danger:focus,a.badge-danger:hover{color:#fff;background-color:#bd2130}a.badge-danger.focus,a.badge-danger:focus{outline:0;box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.badge-light{color:#212529;background-color:#f8f9fa}a.badge-light:focus,a.badge-light:hover{color:#212529;background-color:#dae0e5}a.badge-light.focus,a.badge-light:focus{outline:0;box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.badge-dark{color:#fff;background-color:#343a40}a.badge-dark:focus,a.badge-dark:hover{color:#fff;background-color:#1d2124}a.badge-dark.focus,a.badge-dark:focus{outline:0;box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.jumbotron{padding:2rem 1rem;margin-bottom:2rem;background-color:#e9ecef;border-radius:.3rem}@media (min-width:540px){.jumbotron{padding:4rem 2rem}}.jumbotron-fluid{padding-right:0;padding-left:0;border-radius:0}.alert{position:relative;padding:.75rem 1.25rem;margin-bottom:1rem;border:1px solid transparent;border-radius:.25rem}.alert-heading{color:inherit}.alert-link{font-weight:700}.alert-dismissible{padding-right:4rem}.alert-dismissible .close{position:absolute;top:0;right:0;padding:.75rem 1.25rem;color:inherit}.alert-primary{color:#004085;background-color:#cce5ff;border-color:#b8daff}.alert-primary hr{border-top-color:#9fcdff}.alert-primary .alert-link{color:#002752}.alert-secondary{color:#383d41;background-color:#e2e3e5;border-color:#d6d8db}.alert-secondary hr{border-top-color:#c8cbcf}.alert-secondary .alert-link{color:#202326}.alert-success{color:#155724;background-color:#d4edda;border-color:#c3e6cb}.alert-success hr{border-top-color:#b1dfbb}.alert-success .alert-link{color:#0b2e13}.alert-info{color:#0c5460;background-color:#d1ecf1;border-color:#bee5eb}.alert-info hr{border-top-color:#abdde5}.alert-info .alert-link{color:#062c33}.alert-warning{color:#856404;background-color:#fff3cd;border-color:#ffeeba}.alert-warning hr{border-top-color:#ffe8a1}.alert-warning .alert-link{color:#533f03}.alert-danger{color:#721c24;background-color:#f8d7da;border-color:#f5c6cb}.alert-danger hr{border-top-color:#f1b0b7}.alert-danger .alert-link{color:#491217}.alert-light{color:#818182;background-color:#fefefe;border-color:#fdfdfe}.alert-light hr{border-top-color:#ececf6}.alert-light .alert-link{color:#686868}.alert-dark{color:#1b1e21;background-color:#d6d8d9;border-color:#c6c8ca}.alert-dark hr{border-top-color:#b9bbbe}.alert-dark .alert-link{color:#040505}@keyframes progress-bar-stripes{0%{background-position:1rem 0}to{background-position:0 0}}.progress{height:1rem;line-height:0;font-size:.75rem;background-color:#e9ecef;border-radius:.25rem}.progress,.progress-bar{display:flex;overflow:hidden}.progress-bar{flex-direction:column;justify-content:center;color:#fff;text-align:center;white-space:nowrap;background-color:#007bff;transition:width .6s ease}@media (prefers-reduced-motion:reduce){.progress-bar{transition:none}}.progress-bar-striped{background-image:linear-gradient(45deg,hsla(0,0%,100%,.15) 25%,transparent 0,transparent 50%,hsla(0,0%,100%,.15) 0,hsla(0,0%,100%,.15) 75%,transparent 0,transparent);background-size:1rem 1rem}.progress-bar-animated{animation:progress-bar-stripes 1s linear infinite}@media (prefers-reduced-motion:reduce){.progress-bar-animated{animation:none}}.media{display:flex;align-items:flex-start}.media-body{flex:1}.list-group{display:flex;flex-direction:column;padding-left:0;margin-bottom:0;border-radius:.25rem}.list-group-item-action{width:100%;color:#495057;text-align:inherit}.list-group-item-action:focus,.list-group-item-action:hover{z-index:1;color:#495057;text-decoration:none;background-color:#f8f9fa}.list-group-item-action:active{color:#212529;background-color:#e9ecef}.list-group-item{position:relative;display:block;padding:.75rem 1.25rem;background-color:#fff;border:1px solid rgba(0,0,0,.125)}.list-group-item:first-child{border-top-left-radius:inherit;border-top-right-radius:inherit}.list-group-item:last-child{border-bottom-right-radius:inherit;border-bottom-left-radius:inherit}.list-group-item.disabled,.list-group-item:disabled{color:#6c757d;pointer-events:none;background-color:#fff}.list-group-item.active{z-index:2;color:#fff;background-color:#007bff;border-color:#007bff}.list-group-item+.list-group-item{border-top-width:0}.list-group-item+.list-group-item.active{margin-top:-1px;border-top-width:1px}.list-group-horizontal{flex-direction:row}.list-group-horizontal>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal>.list-group-item.active{margin-top:0}.list-group-horizontal>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}@media (min-width:540px){.list-group-horizontal-sm{flex-direction:row}.list-group-horizontal-sm>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-sm>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-sm>.list-group-item.active{margin-top:0}.list-group-horizontal-sm>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-sm>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:720px){.list-group-horizontal-md{flex-direction:row}.list-group-horizontal-md>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-md>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-md>.list-group-item.active{margin-top:0}.list-group-horizontal-md>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-md>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:960px){.list-group-horizontal-lg{flex-direction:row}.list-group-horizontal-lg>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-lg>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-lg>.list-group-item.active{margin-top:0}.list-group-horizontal-lg>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-lg>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:1200px){.list-group-horizontal-xl{flex-direction:row}.list-group-horizontal-xl>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-xl>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-xl>.list-group-item.active{margin-top:0}.list-group-horizontal-xl>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-xl>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}.list-group-flush{border-radius:0}.list-group-flush>.list-group-item{border-width:0 0 1px}.list-group-flush>.list-group-item:last-child{border-bottom-width:0}.list-group-item-primary{color:#004085;background-color:#b8daff}.list-group-item-primary.list-group-item-action:focus,.list-group-item-primary.list-group-item-action:hover{color:#004085;background-color:#9fcdff}.list-group-item-primary.list-group-item-action.active{color:#fff;background-color:#004085;border-color:#004085}.list-group-item-secondary{color:#383d41;background-color:#d6d8db}.list-group-item-secondary.list-group-item-action:focus,.list-group-item-secondary.list-group-item-action:hover{color:#383d41;background-color:#c8cbcf}.list-group-item-secondary.list-group-item-action.active{color:#fff;background-color:#383d41;border-color:#383d41}.list-group-item-success{color:#155724;background-color:#c3e6cb}.list-group-item-success.list-group-item-action:focus,.list-group-item-success.list-group-item-action:hover{color:#155724;background-color:#b1dfbb}.list-group-item-success.list-group-item-action.active{color:#fff;background-color:#155724;border-color:#155724}.list-group-item-info{color:#0c5460;background-color:#bee5eb}.list-group-item-info.list-group-item-action:focus,.list-group-item-info.list-group-item-action:hover{color:#0c5460;background-color:#abdde5}.list-group-item-info.list-group-item-action.active{color:#fff;background-color:#0c5460;border-color:#0c5460}.list-group-item-warning{color:#856404;background-color:#ffeeba}.list-group-item-warning.list-group-item-action:focus,.list-group-item-warning.list-group-item-action:hover{color:#856404;background-color:#ffe8a1}.list-group-item-warning.list-group-item-action.active{color:#fff;background-color:#856404;border-color:#856404}.list-group-item-danger{color:#721c24;background-color:#f5c6cb}.list-group-item-danger.list-group-item-action:focus,.list-group-item-danger.list-group-item-action:hover{color:#721c24;background-color:#f1b0b7}.list-group-item-danger.list-group-item-action.active{color:#fff;background-color:#721c24;border-color:#721c24}.list-group-item-light{color:#818182;background-color:#fdfdfe}.list-group-item-light.list-group-item-action:focus,.list-group-item-light.list-group-item-action:hover{color:#818182;background-color:#ececf6}.list-group-item-light.list-group-item-action.active{color:#fff;background-color:#818182;border-color:#818182}.list-group-item-dark{color:#1b1e21;background-color:#c6c8ca}.list-group-item-dark.list-group-item-action:focus,.list-group-item-dark.list-group-item-action:hover{color:#1b1e21;background-color:#b9bbbe}.list-group-item-dark.list-group-item-action.active{color:#fff;background-color:#1b1e21;border-color:#1b1e21}.close{float:right;font-size:1.5rem;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.5}.close:hover{color:#000;text-decoration:none}.close:not(:disabled):not(.disabled):focus,.close:not(:disabled):not(.disabled):hover{opacity:.75}button.close{padding:0;background-color:transparent;border:0}a.close.disabled{pointer-events:none}.toast{max-width:350px;overflow:hidden;font-size:.875rem;background-color:hsla(0,0%,100%,.85);background-clip:padding-box;border:1px solid rgba(0,0,0,.1);box-shadow:0 .25rem .75rem rgba(0,0,0,.1);backdrop-filter:blur(10px);opacity:0;border-radius:.25rem}.toast:not(:last-child){margin-bottom:.75rem}.toast.showing{opacity:1}.toast.show{display:block;opacity:1}.toast.hide{display:none}.toast-header{display:flex;align-items:center;padding:.25rem .75rem;color:#6c757d;background-color:hsla(0,0%,100%,.85);background-clip:padding-box;border-bottom:1px solid rgba(0,0,0,.05)}.toast-body{padding:.75rem}.modal-open{overflow:hidden}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal{position:fixed;top:0;left:0;z-index:1050;display:none;width:100%;height:100%;overflow:hidden;outline:0}.modal-dialog{position:relative;width:auto;margin:.5rem;pointer-events:none}.modal.fade .modal-dialog{transition:transform .3s ease-out;transform:translateY(-50px)}@media (prefers-reduced-motion:reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog{transform:none}.modal.modal-static .modal-dialog{transform:scale(1.02)}.modal-dialog-scrollable{display:flex;max-height:calc(100% - 1rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 1rem);overflow:hidden}.modal-dialog-scrollable .modal-footer,.modal-dialog-scrollable .modal-header{flex-shrink:0}.modal-dialog-scrollable .modal-body{overflow-y:auto}.modal-dialog-centered{display:flex;align-items:center;min-height:calc(100% - 1rem)}.modal-dialog-centered:before{display:block;height:calc(100vh - 1rem);height:min-content;content:""}.modal-dialog-centered.modal-dialog-scrollable{flex-direction:column;justify-content:center;height:100%}.modal-dialog-centered.modal-dialog-scrollable .modal-content{max-height:none}.modal-dialog-centered.modal-dialog-scrollable:before{content:none}.modal-content{position:relative;display:flex;flex-direction:column;width:100%;pointer-events:auto;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem;outline:0}.modal-backdrop{position:fixed;top:0;left:0;z-index:1040;width:100vw;height:100vh;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:.5}.modal-header{display:flex;align-items:flex-start;justify-content:space-between;padding:1rem;border-bottom:1px solid #dee2e6;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px)}.modal-header .close{padding:1rem;margin:-1rem -1rem -1rem auto}.modal-title{margin-bottom:0;line-height:1.5}.modal-body{position:relative;flex:1 1 auto;padding:1rem}.modal-footer{display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;padding:.75rem;border-top:1px solid #dee2e6;border-bottom-right-radius:calc(.3rem - 1px);border-bottom-left-radius:calc(.3rem - 1px)}.modal-footer>*{margin:.25rem}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:540px){.modal-dialog{max-width:500px;margin:1.75rem auto}.modal-dialog-scrollable{max-height:calc(100% - 3.5rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 3.5rem)}.modal-dialog-centered{min-height:calc(100% - 3.5rem)}.modal-dialog-centered:before{height:calc(100vh - 3.5rem);height:min-content}.modal-sm{max-width:300px}}@media (min-width:960px){.modal-lg,.modal-xl{max-width:800px}}@media (min-width:1200px){.modal-xl{max-width:1140px}}.tooltip{position:absolute;z-index:1070;display:block;margin:0;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;opacity:0}.tooltip.show{opacity:.9}.tooltip .arrow{position:absolute;display:block;width:.8rem;height:.4rem}.tooltip .arrow:before{position:absolute;content:"";border-color:transparent;border-style:solid}.bs-tooltip-auto[x-placement^=top],.bs-tooltip-top{padding:.4rem 0}.bs-tooltip-auto[x-placement^=top] .arrow,.bs-tooltip-top .arrow{bottom:0}.bs-tooltip-auto[x-placement^=top] .arrow:before,.bs-tooltip-top .arrow:before{top:0;border-width:.4rem .4rem 0;border-top-color:#000}.bs-tooltip-auto[x-placement^=right],.bs-tooltip-right{padding:0 .4rem}.bs-tooltip-auto[x-placement^=right] .arrow,.bs-tooltip-right .arrow{left:0;width:.4rem;height:.8rem}.bs-tooltip-auto[x-placement^=right] .arrow:before,.bs-tooltip-right .arrow:before{right:0;border-width:.4rem .4rem .4rem 0;border-right-color:#000}.bs-tooltip-auto[x-placement^=bottom],.bs-tooltip-bottom{padding:.4rem 0}.bs-tooltip-auto[x-placement^=bottom] .arrow,.bs-tooltip-bottom .arrow{top:0}.bs-tooltip-auto[x-placement^=bottom] .arrow:before,.bs-tooltip-bottom .arrow:before{bottom:0;border-width:0 .4rem .4rem;border-bottom-color:#000}.bs-tooltip-auto[x-placement^=left],.bs-tooltip-left{padding:0 .4rem}.bs-tooltip-auto[x-placement^=left] .arrow,.bs-tooltip-left .arrow{right:0;width:.4rem;height:.8rem}.bs-tooltip-auto[x-placement^=left] .arrow:before,.bs-tooltip-left .arrow:before{left:0;border-width:.4rem 0 .4rem .4rem;border-left-color:#000}.tooltip-inner{max-width:200px;padding:.25rem .5rem;color:#fff;text-align:center;background-color:#000;border-radius:.25rem}.popover{top:0;left:0;z-index:1060;max-width:276px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem}.popover,.popover .arrow{position:absolute;display:block}.popover .arrow{width:1rem;height:.5rem;margin:0 .3rem}.popover .arrow:after,.popover .arrow:before{position:absolute;display:block;content:"";border-color:transparent;border-style:solid}.bs-popover-auto[x-placement^=top],.bs-popover-top{margin-bottom:.5rem}.bs-popover-auto[x-placement^=top]>.arrow,.bs-popover-top>.arrow{bottom:calc(-.5rem - 1px)}.bs-popover-auto[x-placement^=top]>.arrow:before,.bs-popover-top>.arrow:before{bottom:0;border-width:.5rem .5rem 0;border-top-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=top]>.arrow:after,.bs-popover-top>.arrow:after{bottom:1px;border-width:.5rem .5rem 0;border-top-color:#fff}.bs-popover-auto[x-placement^=right],.bs-popover-right{margin-left:.5rem}.bs-popover-auto[x-placement^=right]>.arrow,.bs-popover-right>.arrow{left:calc(-.5rem - 1px);width:.5rem;height:1rem;margin:.3rem 0}.bs-popover-auto[x-placement^=right]>.arrow:before,.bs-popover-right>.arrow:before{left:0;border-width:.5rem .5rem .5rem 0;border-right-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=right]>.arrow:after,.bs-popover-right>.arrow:after{left:1px;border-width:.5rem .5rem .5rem 0;border-right-color:#fff}.bs-popover-auto[x-placement^=bottom],.bs-popover-bottom{margin-top:.5rem}.bs-popover-auto[x-placement^=bottom]>.arrow,.bs-popover-bottom>.arrow{top:calc(-.5rem - 1px)}.bs-popover-auto[x-placement^=bottom]>.arrow:before,.bs-popover-bottom>.arrow:before{top:0;border-width:0 .5rem .5rem;border-bottom-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=bottom]>.arrow:after,.bs-popover-bottom>.arrow:after{top:1px;border-width:0 .5rem .5rem;border-bottom-color:#fff}.bs-popover-auto[x-placement^=bottom] .popover-header:before,.bs-popover-bottom .popover-header:before{position:absolute;top:0;left:50%;display:block;width:1rem;margin-left:-.5rem;content:"";border-bottom:1px solid #f7f7f7}.bs-popover-auto[x-placement^=left],.bs-popover-left{margin-right:.5rem}.bs-popover-auto[x-placement^=left]>.arrow,.bs-popover-left>.arrow{right:calc(-.5rem - 1px);width:.5rem;height:1rem;margin:.3rem 0}.bs-popover-auto[x-placement^=left]>.arrow:before,.bs-popover-left>.arrow:before{right:0;border-width:.5rem 0 .5rem .5rem;border-left-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=left]>.arrow:after,.bs-popover-left>.arrow:after{right:1px;border-width:.5rem 0 .5rem .5rem;border-left-color:#fff}.popover-header{padding:.5rem .75rem;margin-bottom:0;font-size:1rem;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px)}.popover-header:empty{display:none}.popover-body{padding:.5rem .75rem;color:#212529}.carousel{position:relative}.carousel.pointer-event{touch-action:pan-y}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner:after{display:block;clear:both;content:""}.carousel-item{position:relative;display:none;float:left;width:100%;margin-right:-100%;backface-visibility:hidden;transition:transform .6s ease-in-out}@media (prefers-reduced-motion:reduce){.carousel-item{transition:none}}.carousel-item-next,.carousel-item-prev,.carousel-item.active{display:block}.active.carousel-item-right,.carousel-item-next:not(.carousel-item-left){transform:translateX(100%)}.active.carousel-item-left,.carousel-item-prev:not(.carousel-item-right){transform:translateX(-100%)}.carousel-fade .carousel-item{opacity:0;transition-property:opacity;transform:none}.carousel-fade .carousel-item-next.carousel-item-left,.carousel-fade .carousel-item-prev.carousel-item-right,.carousel-fade .carousel-item.active{z-index:1;opacity:1}.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{z-index:0;opacity:0;transition:opacity 0s .6s}@media (prefers-reduced-motion:reduce){.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{transition:none}}.carousel-control-next,.carousel-control-prev{position:absolute;top:0;bottom:0;z-index:1;display:flex;align-items:center;justify-content:center;width:15%;color:#fff;text-align:center;opacity:.5;transition:opacity .15s ease}@media (prefers-reduced-motion:reduce){.carousel-control-next,.carousel-control-prev{transition:none}}.carousel-control-next:focus,.carousel-control-next:hover,.carousel-control-prev:focus,.carousel-control-prev:hover{color:#fff;text-decoration:none;outline:0;opacity:.9}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-next-icon,.carousel-control-prev-icon{display:inline-block;width:20px;height:20px;background:no-repeat 50%/100% 100%}.carousel-control-prev-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8'%3E%3Cpath d='M5.25 0l-4 4 4 4 1.5-1.5L4.25 4l2.5-2.5L5.25 0z'/%3E%3C/svg%3E")}.carousel-control-next-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8'%3E%3Cpath d='M2.75 0l-1.5 1.5L3.75 4l-2.5 2.5L2.75 8l4-4-4-4z'/%3E%3C/svg%3E")}.carousel-indicators{position:absolute;right:0;bottom:0;left:0;z-index:15;display:flex;justify-content:center;padding-left:0;margin-right:15%;margin-left:15%;list-style:none}.carousel-indicators li{box-sizing:content-box;flex:0 1 auto;width:30px;height:3px;margin-right:3px;margin-left:3px;text-indent:-999px;cursor:pointer;background-color:#fff;background-clip:padding-box;border-top:10px solid transparent;border-bottom:10px solid transparent;opacity:.5;transition:opacity .6s ease}@media (prefers-reduced-motion:reduce){.carousel-indicators li{transition:none}}.carousel-indicators .active{opacity:1}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center}@keyframes spinner-border{to{transform:rotate(1turn)}}.spinner-border{display:inline-block;width:2rem;height:2rem;vertical-align:text-bottom;border:.25em solid;border-right:.25em solid transparent;border-radius:50%;animation:spinner-border .75s linear infinite}.spinner-border-sm{width:1rem;height:1rem;border-width:.2em}@keyframes spinner-grow{0%{transform:scale(0)}50%{opacity:1;transform:none}}.spinner-grow{display:inline-block;width:2rem;height:2rem;vertical-align:text-bottom;background-color:currentColor;border-radius:50%;opacity:0;animation:spinner-grow .75s linear infinite}.spinner-grow-sm{width:1rem;height:1rem}.align-baseline{vertical-align:baseline!important}.align-top{vertical-align:top!important}.align-middle{vertical-align:middle!important}.align-bottom{vertical-align:bottom!important}.align-text-bottom{vertical-align:text-bottom!important}.align-text-top{vertical-align:text-top!important}.bg-primary{background-color:#007bff!important}a.bg-primary:focus,a.bg-primary:hover,button.bg-primary:focus,button.bg-primary:hover{background-color:#0062cc!important}.bg-secondary{background-color:#6c757d!important}a.bg-secondary:focus,a.bg-secondary:hover,button.bg-secondary:focus,button.bg-secondary:hover{background-color:#545b62!important}.bg-success{background-color:#28a745!important}a.bg-success:focus,a.bg-success:hover,button.bg-success:focus,button.bg-success:hover{background-color:#1e7e34!important}.bg-info{background-color:#17a2b8!important}a.bg-info:focus,a.bg-info:hover,button.bg-info:focus,button.bg-info:hover{background-color:#117a8b!important}.bg-warning{background-color:#ffc107!important}a.bg-warning:focus,a.bg-warning:hover,button.bg-warning:focus,button.bg-warning:hover{background-color:#d39e00!important}.bg-danger{background-color:#dc3545!important}a.bg-danger:focus,a.bg-danger:hover,button.bg-danger:focus,button.bg-danger:hover{background-color:#bd2130!important}.bg-light{background-color:#f8f9fa!important}a.bg-light:focus,a.bg-light:hover,button.bg-light:focus,button.bg-light:hover{background-color:#dae0e5!important}.bg-dark{background-color:#343a40!important}a.bg-dark:focus,a.bg-dark:hover,button.bg-dark:focus,button.bg-dark:hover{background-color:#1d2124!important}.bg-white{background-color:#fff!important}.bg-transparent{background-color:transparent!important}.border{border:1px solid #dee2e6!important}.border-top{border-top:1px solid #dee2e6!important}.border-right{border-right:1px solid #dee2e6!important}.border-bottom{border-bottom:1px solid #dee2e6!important}.border-left{border-left:1px solid #dee2e6!important}.border-0{border:0!important}.border-top-0{border-top:0!important}.border-right-0{border-right:0!important}.border-bottom-0{border-bottom:0!important}.border-left-0{border-left:0!important}.border-primary{border-color:#007bff!important}.border-secondary{border-color:#6c757d!important}.border-success{border-color:#28a745!important}.border-info{border-color:#17a2b8!important}.border-warning{border-color:#ffc107!important}.border-danger{border-color:#dc3545!important}.border-light{border-color:#f8f9fa!important}.border-dark{border-color:#343a40!important}.border-white{border-color:#fff!important}.rounded-sm{border-radius:.2rem!important}.rounded{border-radius:.25rem!important}.rounded-top{border-top-left-radius:.25rem!important}.rounded-right,.rounded-top{border-top-right-radius:.25rem!important}.rounded-bottom,.rounded-right{border-bottom-right-radius:.25rem!important}.rounded-bottom,.rounded-left{border-bottom-left-radius:.25rem!important}.rounded-left{border-top-left-radius:.25rem!important}.rounded-lg{border-radius:.3rem!important}.rounded-circle{border-radius:50%!important}.rounded-pill{border-radius:50rem!important}.rounded-0{border-radius:0!important}.clearfix:after{display:block;clear:both;content:""}.d-none{display:none!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-table{display:table!important}.d-table-row{display:table-row!important}.d-table-cell{display:table-cell!important}.d-flex{display:flex!important}.d-inline-flex{display:inline-flex!important}@media (min-width:540px){.d-sm-none{display:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-table{display:table!important}.d-sm-table-row{display:table-row!important}.d-sm-table-cell{display:table-cell!important}.d-sm-flex{display:flex!important}.d-sm-inline-flex{display:inline-flex!important}}@media (min-width:720px){.d-md-none{display:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-table{display:table!important}.d-md-table-row{display:table-row!important}.d-md-table-cell{display:table-cell!important}.d-md-flex{display:flex!important}.d-md-inline-flex{display:inline-flex!important}}@media (min-width:960px){.d-lg-none{display:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!important}.d-lg-table{display:table!important}.d-lg-table-row{display:table-row!important}.d-lg-table-cell{display:table-cell!important}.d-lg-flex{display:flex!important}.d-lg-inline-flex{display:inline-flex!important}}@media (min-width:1200px){.d-xl-none{display:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-table{display:table!important}.d-xl-table-row{display:table-row!important}.d-xl-table-cell{display:table-cell!important}.d-xl-flex{display:flex!important}.d-xl-inline-flex{display:inline-flex!important}}@media print{.d-print-none{display:none!important}.d-print-inline{display:inline!important}.d-print-inline-block{display:inline-block!important}.d-print-block{display:block!important}.d-print-table{display:table!important}.d-print-table-row{display:table-row!important}.d-print-table-cell{display:table-cell!important}.d-print-flex{display:flex!important}.d-print-inline-flex{display:inline-flex!important}}.embed-responsive{position:relative;display:block;width:100%;padding:0;overflow:hidden}.embed-responsive:before{display:block;content:""}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-21by9:before{padding-top:42.85714%}.embed-responsive-16by9:before{padding-top:56.25%}.embed-responsive-4by3:before{padding-top:75%}.embed-responsive-1by1:before{padding-top:100%}.flex-row{flex-direction:row!important}.flex-column{flex-direction:column!important}.flex-row-reverse{flex-direction:row-reverse!important}.flex-column-reverse{flex-direction:column-reverse!important}.flex-wrap{flex-wrap:wrap!important}.flex-nowrap{flex-wrap:nowrap!important}.flex-wrap-reverse{flex-wrap:wrap-reverse!important}.flex-fill{flex:1 1 auto!important}.flex-grow-0{flex-grow:0!important}.flex-grow-1{flex-grow:1!important}.flex-shrink-0{flex-shrink:0!important}.flex-shrink-1{flex-shrink:1!important}.justify-content-start{justify-content:flex-start!important}.justify-content-end{justify-content:flex-end!important}.justify-content-center{justify-content:center!important}.justify-content-between{justify-content:space-between!important}.justify-content-around{justify-content:space-around!important}.align-items-start{align-items:flex-start!important}.align-items-end{align-items:flex-end!important}.align-items-center{align-items:center!important}.align-items-baseline{align-items:baseline!important}.align-items-stretch{align-items:stretch!important}.align-content-start{align-content:flex-start!important}.align-content-end{align-content:flex-end!important}.align-content-center{align-content:center!important}.align-content-between{align-content:space-between!important}.align-content-around{align-content:space-around!important}.align-content-stretch{align-content:stretch!important}.align-self-auto{align-self:auto!important}.align-self-start{align-self:flex-start!important}.align-self-end{align-self:flex-end!important}.align-self-center{align-self:center!important}.align-self-baseline{align-self:baseline!important}.align-self-stretch{align-self:stretch!important}@media (min-width:540px){.flex-sm-row{flex-direction:row!important}.flex-sm-column{flex-direction:column!important}.flex-sm-row-reverse{flex-direction:row-reverse!important}.flex-sm-column-reverse{flex-direction:column-reverse!important}.flex-sm-wrap{flex-wrap:wrap!important}.flex-sm-nowrap{flex-wrap:nowrap!important}.flex-sm-wrap-reverse{flex-wrap:wrap-reverse!important}.flex-sm-fill{flex:1 1 auto!important}.flex-sm-grow-0{flex-grow:0!important}.flex-sm-grow-1{flex-grow:1!important}.flex-sm-shrink-0{flex-shrink:0!important}.flex-sm-shrink-1{flex-shrink:1!important}.justify-content-sm-start{justify-content:flex-start!important}.justify-content-sm-end{justify-content:flex-end!important}.justify-content-sm-center{justify-content:center!important}.justify-content-sm-between{justify-content:space-between!important}.justify-content-sm-around{justify-content:space-around!important}.align-items-sm-start{align-items:flex-start!important}.align-items-sm-end{align-items:flex-end!important}.align-items-sm-center{align-items:center!important}.align-items-sm-baseline{align-items:baseline!important}.align-items-sm-stretch{align-items:stretch!important}.align-content-sm-start{align-content:flex-start!important}.align-content-sm-end{align-content:flex-end!important}.align-content-sm-center{align-content:center!important}.align-content-sm-between{align-content:space-between!important}.align-content-sm-around{align-content:space-around!important}.align-content-sm-stretch{align-content:stretch!important}.align-self-sm-auto{align-self:auto!important}.align-self-sm-start{align-self:flex-start!important}.align-self-sm-end{align-self:flex-end!important}.align-self-sm-center{align-self:center!important}.align-self-sm-baseline{align-self:baseline!important}.align-self-sm-stretch{align-self:stretch!important}}@media (min-width:720px){.flex-md-row{flex-direction:row!important}.flex-md-column{flex-direction:column!important}.flex-md-row-reverse{flex-direction:row-reverse!important}.flex-md-column-reverse{flex-direction:column-reverse!important}.flex-md-wrap{flex-wrap:wrap!important}.flex-md-nowrap{flex-wrap:nowrap!important}.flex-md-wrap-reverse{flex-wrap:wrap-reverse!important}.flex-md-fill{flex:1 1 auto!important}.flex-md-grow-0{flex-grow:0!important}.flex-md-grow-1{flex-grow:1!important}.flex-md-shrink-0{flex-shrink:0!important}.flex-md-shrink-1{flex-shrink:1!important}.justify-content-md-start{justify-content:flex-start!important}.justify-content-md-end{justify-content:flex-end!important}.justify-content-md-center{justify-content:center!important}.justify-content-md-between{justify-content:space-between!important}.justify-content-md-around{justify-content:space-around!important}.align-items-md-start{align-items:flex-start!important}.align-items-md-end{align-items:flex-end!important}.align-items-md-center{align-items:center!important}.align-items-md-baseline{align-items:baseline!important}.align-items-md-stretch{align-items:stretch!important}.align-content-md-start{align-content:flex-start!important}.align-content-md-end{align-content:flex-end!important}.align-content-md-center{align-content:center!important}.align-content-md-between{align-content:space-between!important}.align-content-md-around{align-content:space-around!important}.align-content-md-stretch{align-content:stretch!important}.align-self-md-auto{align-self:auto!important}.align-self-md-start{align-self:flex-start!important}.align-self-md-end{align-self:flex-end!important}.align-self-md-center{align-self:center!important}.align-self-md-baseline{align-self:baseline!important}.align-self-md-stretch{align-self:stretch!important}}@media (min-width:960px){.flex-lg-row{flex-direction:row!important}.flex-lg-column{flex-direction:column!important}.flex-lg-row-reverse{flex-direction:row-reverse!important}.flex-lg-column-reverse{flex-direction:column-reverse!important}.flex-lg-wrap{flex-wrap:wrap!important}.flex-lg-nowrap{flex-wrap:nowrap!important}.flex-lg-wrap-reverse{flex-wrap:wrap-reverse!important}.flex-lg-fill{flex:1 1 auto!important}.flex-lg-grow-0{flex-grow:0!important}.flex-lg-grow-1{flex-grow:1!important}.flex-lg-shrink-0{flex-shrink:0!important}.flex-lg-shrink-1{flex-shrink:1!important}.justify-content-lg-start{justify-content:flex-start!important}.justify-content-lg-end{justify-content:flex-end!important}.justify-content-lg-center{justify-content:center!important}.justify-content-lg-between{justify-content:space-between!important}.justify-content-lg-around{justify-content:space-around!important}.align-items-lg-start{align-items:flex-start!important}.align-items-lg-end{align-items:flex-end!important}.align-items-lg-center{align-items:center!important}.align-items-lg-baseline{align-items:baseline!important}.align-items-lg-stretch{align-items:stretch!important}.align-content-lg-start{align-content:flex-start!important}.align-content-lg-end{align-content:flex-end!important}.align-content-lg-center{align-content:center!important}.align-content-lg-between{align-content:space-between!important}.align-content-lg-around{align-content:space-around!important}.align-content-lg-stretch{align-content:stretch!important}.align-self-lg-auto{align-self:auto!important}.align-self-lg-start{align-self:flex-start!important}.align-self-lg-end{align-self:flex-end!important}.align-self-lg-center{align-self:center!important}.align-self-lg-baseline{align-self:baseline!important}.align-self-lg-stretch{align-self:stretch!important}}@media (min-width:1200px){.flex-xl-row{flex-direction:row!important}.flex-xl-column{flex-direction:column!important}.flex-xl-row-reverse{flex-direction:row-reverse!important}.flex-xl-column-reverse{flex-direction:column-reverse!important}.flex-xl-wrap{flex-wrap:wrap!important}.flex-xl-nowrap{flex-wrap:nowrap!important}.flex-xl-wrap-reverse{flex-wrap:wrap-reverse!important}.flex-xl-fill{flex:1 1 auto!important}.flex-xl-grow-0{flex-grow:0!important}.flex-xl-grow-1{flex-grow:1!important}.flex-xl-shrink-0{flex-shrink:0!important}.flex-xl-shrink-1{flex-shrink:1!important}.justify-content-xl-start{justify-content:flex-start!important}.justify-content-xl-end{justify-content:flex-end!important}.justify-content-xl-center{justify-content:center!important}.justify-content-xl-between{justify-content:space-between!important}.justify-content-xl-around{justify-content:space-around!important}.align-items-xl-start{align-items:flex-start!important}.align-items-xl-end{align-items:flex-end!important}.align-items-xl-center{align-items:center!important}.align-items-xl-baseline{align-items:baseline!important}.align-items-xl-stretch{align-items:stretch!important}.align-content-xl-start{align-content:flex-start!important}.align-content-xl-end{align-content:flex-end!important}.align-content-xl-center{align-content:center!important}.align-content-xl-between{align-content:space-between!important}.align-content-xl-around{align-content:space-around!important}.align-content-xl-stretch{align-content:stretch!important}.align-self-xl-auto{align-self:auto!important}.align-self-xl-start{align-self:flex-start!important}.align-self-xl-end{align-self:flex-end!important}.align-self-xl-center{align-self:center!important}.align-self-xl-baseline{align-self:baseline!important}.align-self-xl-stretch{align-self:stretch!important}}.float-left{float:left!important}.float-right{float:right!important}.float-none{float:none!important}@media (min-width:540px){.float-sm-left{float:left!important}.float-sm-right{float:right!important}.float-sm-none{float:none!important}}@media (min-width:720px){.float-md-left{float:left!important}.float-md-right{float:right!important}.float-md-none{float:none!important}}@media (min-width:960px){.float-lg-left{float:left!important}.float-lg-right{float:right!important}.float-lg-none{float:none!important}}@media (min-width:1200px){.float-xl-left{float:left!important}.float-xl-right{float:right!important}.float-xl-none{float:none!important}}.user-select-all{user-select:all!important}.user-select-auto{user-select:auto!important}.user-select-none{user-select:none!important}.overflow-auto{overflow:auto!important}.overflow-hidden{overflow:hidden!important}.position-static{position:static!important}.position-relative{position:relative!important}.position-absolute{position:absolute!important}.position-fixed{position:fixed!important}.position-sticky{position:sticky!important}.fixed-top{top:0}.fixed-bottom,.fixed-top{position:fixed;right:0;left:0;z-index:1030}.fixed-bottom{bottom:0}@supports (position:sticky){.sticky-top{position:sticky;top:0;z-index:1020}}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;overflow:visible;clip:auto;white-space:normal}.shadow-sm{box-shadow:0 .125rem .25rem rgba(0,0,0,.075)!important}.shadow{box-shadow:0 .5rem 1rem rgba(0,0,0,.15)!important}.shadow-lg{box-shadow:0 1rem 3rem rgba(0,0,0,.175)!important}.shadow-none{box-shadow:none!important}.w-25{width:25%!important}.w-50{width:50%!important}.w-75{width:75%!important}.w-100{width:100%!important}.w-auto{width:auto!important}.h-25{height:25%!important}.h-50{height:50%!important}.h-75{height:75%!important}.h-100{height:100%!important}.h-auto{height:auto!important}.mw-100{max-width:100%!important}.mh-100{max-height:100%!important}.min-vw-100{min-width:100vw!important}.min-vh-100{min-height:100vh!important}.vw-100{width:100vw!important}.vh-100{height:100vh!important}.m-0{margin:0!important}.mt-0,.my-0{margin-top:0!important}.mr-0,.mx-0{margin-right:0!important}.mb-0,.my-0{margin-bottom:0!important}.ml-0,.mx-0{margin-left:0!important}.m-1{margin:.25rem!important}.mt-1,.my-1{margin-top:.25rem!important}.mr-1,.mx-1{margin-right:.25rem!important}.mb-1,.my-1{margin-bottom:.25rem!important}.ml-1,.mx-1{margin-left:.25rem!important}.m-2{margin:.5rem!important}.mt-2,.my-2{margin-top:.5rem!important}.mr-2,.mx-2{margin-right:.5rem!important}.mb-2,.my-2{margin-bottom:.5rem!important}.ml-2,.mx-2{margin-left:.5rem!important}.m-3{margin:1rem!important}.mt-3,.my-3{margin-top:1rem!important}.mr-3,.mx-3{margin-right:1rem!important}.mb-3,.my-3{margin-bottom:1rem!important}.ml-3,.mx-3{margin-left:1rem!important}.m-4{margin:1.5rem!important}.mt-4,.my-4{margin-top:1.5rem!important}.mr-4,.mx-4{margin-right:1.5rem!important}.mb-4,.my-4{margin-bottom:1.5rem!important}.ml-4,.mx-4{margin-left:1.5rem!important}.m-5{margin:3rem!important}.mt-5,.my-5{margin-top:3rem!important}.mr-5,.mx-5{margin-right:3rem!important}.mb-5,.my-5{margin-bottom:3rem!important}.ml-5,.mx-5{margin-left:3rem!important}.p-0{padding:0!important}.pt-0,.py-0{padding-top:0!important}.pr-0,.px-0{padding-right:0!important}.pb-0,.py-0{padding-bottom:0!important}.pl-0,.px-0{padding-left:0!important}.p-1{padding:.25rem!important}.pt-1,.py-1{padding-top:.25rem!important}.pr-1,.px-1{padding-right:.25rem!important}.pb-1,.py-1{padding-bottom:.25rem!important}.pl-1,.px-1{padding-left:.25rem!important}.p-2{padding:.5rem!important}.pt-2,.py-2{padding-top:.5rem!important}.pr-2,.px-2{padding-right:.5rem!important}.pb-2,.py-2{padding-bottom:.5rem!important}.pl-2,.px-2{padding-left:.5rem!important}.p-3{padding:1rem!important}.pt-3,.py-3{padding-top:1rem!important}.pr-3,.px-3{padding-right:1rem!important}.pb-3,.py-3{padding-bottom:1rem!important}.pl-3,.px-3{padding-left:1rem!important}.p-4{padding:1.5rem!important}.pt-4,.py-4{padding-top:1.5rem!important}.pr-4,.px-4{padding-right:1.5rem!important}.pb-4,.py-4{padding-bottom:1.5rem!important}.pl-4,.px-4{padding-left:1.5rem!important}.p-5{padding:3rem!important}.pt-5,.py-5{padding-top:3rem!important}.pr-5,.px-5{padding-right:3rem!important}.pb-5,.py-5{padding-bottom:3rem!important}.pl-5,.px-5{padding-left:3rem!important}.m-n1{margin:-.25rem!important}.mt-n1,.my-n1{margin-top:-.25rem!important}.mr-n1,.mx-n1{margin-right:-.25rem!important}.mb-n1,.my-n1{margin-bottom:-.25rem!important}.ml-n1,.mx-n1{margin-left:-.25rem!important}.m-n2{margin:-.5rem!important}.mt-n2,.my-n2{margin-top:-.5rem!important}.mr-n2,.mx-n2{margin-right:-.5rem!important}.mb-n2,.my-n2{margin-bottom:-.5rem!important}.ml-n2,.mx-n2{margin-left:-.5rem!important}.m-n3{margin:-1rem!important}.mt-n3,.my-n3{margin-top:-1rem!important}.mr-n3,.mx-n3{margin-right:-1rem!important}.mb-n3,.my-n3{margin-bottom:-1rem!important}.ml-n3,.mx-n3{margin-left:-1rem!important}.m-n4{margin:-1.5rem!important}.mt-n4,.my-n4{margin-top:-1.5rem!important}.mr-n4,.mx-n4{margin-right:-1.5rem!important}.mb-n4,.my-n4{margin-bottom:-1.5rem!important}.ml-n4,.mx-n4{margin-left:-1.5rem!important}.m-n5{margin:-3rem!important}.mt-n5,.my-n5{margin-top:-3rem!important}.mr-n5,.mx-n5{margin-right:-3rem!important}.mb-n5,.my-n5{margin-bottom:-3rem!important}.ml-n5,.mx-n5{margin-left:-3rem!important}.m-auto{margin:auto!important}.mt-auto,.my-auto{margin-top:auto!important}.mr-auto,.mx-auto{margin-right:auto!important}.mb-auto,.my-auto{margin-bottom:auto!important}.ml-auto,.mx-auto{margin-left:auto!important}@media (min-width:540px){.m-sm-0{margin:0!important}.mt-sm-0,.my-sm-0{margin-top:0!important}.mr-sm-0,.mx-sm-0{margin-right:0!important}.mb-sm-0,.my-sm-0{margin-bottom:0!important}.ml-sm-0,.mx-sm-0{margin-left:0!important}.m-sm-1{margin:.25rem!important}.mt-sm-1,.my-sm-1{margin-top:.25rem!important}.mr-sm-1,.mx-sm-1{margin-right:.25rem!important}.mb-sm-1,.my-sm-1{margin-bottom:.25rem!important}.ml-sm-1,.mx-sm-1{margin-left:.25rem!important}.m-sm-2{margin:.5rem!important}.mt-sm-2,.my-sm-2{margin-top:.5rem!important}.mr-sm-2,.mx-sm-2{margin-right:.5rem!important}.mb-sm-2,.my-sm-2{margin-bottom:.5rem!important}.ml-sm-2,.mx-sm-2{margin-left:.5rem!important}.m-sm-3{margin:1rem!important}.mt-sm-3,.my-sm-3{margin-top:1rem!important}.mr-sm-3,.mx-sm-3{margin-right:1rem!important}.mb-sm-3,.my-sm-3{margin-bottom:1rem!important}.ml-sm-3,.mx-sm-3{margin-left:1rem!important}.m-sm-4{margin:1.5rem!important}.mt-sm-4,.my-sm-4{margin-top:1.5rem!important}.mr-sm-4,.mx-sm-4{margin-right:1.5rem!important}.mb-sm-4,.my-sm-4{margin-bottom:1.5rem!important}.ml-sm-4,.mx-sm-4{margin-left:1.5rem!important}.m-sm-5{margin:3rem!important}.mt-sm-5,.my-sm-5{margin-top:3rem!important}.mr-sm-5,.mx-sm-5{margin-right:3rem!important}.mb-sm-5,.my-sm-5{margin-bottom:3rem!important}.ml-sm-5,.mx-sm-5{margin-left:3rem!important}.p-sm-0{padding:0!important}.pt-sm-0,.py-sm-0{padding-top:0!important}.pr-sm-0,.px-sm-0{padding-right:0!important}.pb-sm-0,.py-sm-0{padding-bottom:0!important}.pl-sm-0,.px-sm-0{padding-left:0!important}.p-sm-1{padding:.25rem!important}.pt-sm-1,.py-sm-1{padding-top:.25rem!important}.pr-sm-1,.px-sm-1{padding-right:.25rem!important}.pb-sm-1,.py-sm-1{padding-bottom:.25rem!important}.pl-sm-1,.px-sm-1{padding-left:.25rem!important}.p-sm-2{padding:.5rem!important}.pt-sm-2,.py-sm-2{padding-top:.5rem!important}.pr-sm-2,.px-sm-2{padding-right:.5rem!important}.pb-sm-2,.py-sm-2{padding-bottom:.5rem!important}.pl-sm-2,.px-sm-2{padding-left:.5rem!important}.p-sm-3{padding:1rem!important}.pt-sm-3,.py-sm-3{padding-top:1rem!important}.pr-sm-3,.px-sm-3{padding-right:1rem!important}.pb-sm-3,.py-sm-3{padding-bottom:1rem!important}.pl-sm-3,.px-sm-3{padding-left:1rem!important}.p-sm-4{padding:1.5rem!important}.pt-sm-4,.py-sm-4{padding-top:1.5rem!important}.pr-sm-4,.px-sm-4{padding-right:1.5rem!important}.pb-sm-4,.py-sm-4{padding-bottom:1.5rem!important}.pl-sm-4,.px-sm-4{padding-left:1.5rem!important}.p-sm-5{padding:3rem!important}.pt-sm-5,.py-sm-5{padding-top:3rem!important}.pr-sm-5,.px-sm-5{padding-right:3rem!important}.pb-sm-5,.py-sm-5{padding-bottom:3rem!important}.pl-sm-5,.px-sm-5{padding-left:3rem!important}.m-sm-n1{margin:-.25rem!important}.mt-sm-n1,.my-sm-n1{margin-top:-.25rem!important}.mr-sm-n1,.mx-sm-n1{margin-right:-.25rem!important}.mb-sm-n1,.my-sm-n1{margin-bottom:-.25rem!important}.ml-sm-n1,.mx-sm-n1{margin-left:-.25rem!important}.m-sm-n2{margin:-.5rem!important}.mt-sm-n2,.my-sm-n2{margin-top:-.5rem!important}.mr-sm-n2,.mx-sm-n2{margin-right:-.5rem!important}.mb-sm-n2,.my-sm-n2{margin-bottom:-.5rem!important}.ml-sm-n2,.mx-sm-n2{margin-left:-.5rem!important}.m-sm-n3{margin:-1rem!important}.mt-sm-n3,.my-sm-n3{margin-top:-1rem!important}.mr-sm-n3,.mx-sm-n3{margin-right:-1rem!important}.mb-sm-n3,.my-sm-n3{margin-bottom:-1rem!important}.ml-sm-n3,.mx-sm-n3{margin-left:-1rem!important}.m-sm-n4{margin:-1.5rem!important}.mt-sm-n4,.my-sm-n4{margin-top:-1.5rem!important}.mr-sm-n4,.mx-sm-n4{margin-right:-1.5rem!important}.mb-sm-n4,.my-sm-n4{margin-bottom:-1.5rem!important}.ml-sm-n4,.mx-sm-n4{margin-left:-1.5rem!important}.m-sm-n5{margin:-3rem!important}.mt-sm-n5,.my-sm-n5{margin-top:-3rem!important}.mr-sm-n5,.mx-sm-n5{margin-right:-3rem!important}.mb-sm-n5,.my-sm-n5{margin-bottom:-3rem!important}.ml-sm-n5,.mx-sm-n5{margin-left:-3rem!important}.m-sm-auto{margin:auto!important}.mt-sm-auto,.my-sm-auto{margin-top:auto!important}.mr-sm-auto,.mx-sm-auto{margin-right:auto!important}.mb-sm-auto,.my-sm-auto{margin-bottom:auto!important}.ml-sm-auto,.mx-sm-auto{margin-left:auto!important}}@media (min-width:720px){.m-md-0{margin:0!important}.mt-md-0,.my-md-0{margin-top:0!important}.mr-md-0,.mx-md-0{margin-right:0!important}.mb-md-0,.my-md-0{margin-bottom:0!important}.ml-md-0,.mx-md-0{margin-left:0!important}.m-md-1{margin:.25rem!important}.mt-md-1,.my-md-1{margin-top:.25rem!important}.mr-md-1,.mx-md-1{margin-right:.25rem!important}.mb-md-1,.my-md-1{margin-bottom:.25rem!important}.ml-md-1,.mx-md-1{margin-left:.25rem!important}.m-md-2{margin:.5rem!important}.mt-md-2,.my-md-2{margin-top:.5rem!important}.mr-md-2,.mx-md-2{margin-right:.5rem!important}.mb-md-2,.my-md-2{margin-bottom:.5rem!important}.ml-md-2,.mx-md-2{margin-left:.5rem!important}.m-md-3{margin:1rem!important}.mt-md-3,.my-md-3{margin-top:1rem!important}.mr-md-3,.mx-md-3{margin-right:1rem!important}.mb-md-3,.my-md-3{margin-bottom:1rem!important}.ml-md-3,.mx-md-3{margin-left:1rem!important}.m-md-4{margin:1.5rem!important}.mt-md-4,.my-md-4{margin-top:1.5rem!important}.mr-md-4,.mx-md-4{margin-right:1.5rem!important}.mb-md-4,.my-md-4{margin-bottom:1.5rem!important}.ml-md-4,.mx-md-4{margin-left:1.5rem!important}.m-md-5{margin:3rem!important}.mt-md-5,.my-md-5{margin-top:3rem!important}.mr-md-5,.mx-md-5{margin-right:3rem!important}.mb-md-5,.my-md-5{margin-bottom:3rem!important}.ml-md-5,.mx-md-5{margin-left:3rem!important}.p-md-0{padding:0!important}.pt-md-0,.py-md-0{padding-top:0!important}.pr-md-0,.px-md-0{padding-right:0!important}.pb-md-0,.py-md-0{padding-bottom:0!important}.pl-md-0,.px-md-0{padding-left:0!important}.p-md-1{padding:.25rem!important}.pt-md-1,.py-md-1{padding-top:.25rem!important}.pr-md-1,.px-md-1{padding-right:.25rem!important}.pb-md-1,.py-md-1{padding-bottom:.25rem!important}.pl-md-1,.px-md-1{padding-left:.25rem!important}.p-md-2{padding:.5rem!important}.pt-md-2,.py-md-2{padding-top:.5rem!important}.pr-md-2,.px-md-2{padding-right:.5rem!important}.pb-md-2,.py-md-2{padding-bottom:.5rem!important}.pl-md-2,.px-md-2{padding-left:.5rem!important}.p-md-3{padding:1rem!important}.pt-md-3,.py-md-3{padding-top:1rem!important}.pr-md-3,.px-md-3{padding-right:1rem!important}.pb-md-3,.py-md-3{padding-bottom:1rem!important}.pl-md-3,.px-md-3{padding-left:1rem!important}.p-md-4{padding:1.5rem!important}.pt-md-4,.py-md-4{padding-top:1.5rem!important}.pr-md-4,.px-md-4{padding-right:1.5rem!important}.pb-md-4,.py-md-4{padding-bottom:1.5rem!important}.pl-md-4,.px-md-4{padding-left:1.5rem!important}.p-md-5{padding:3rem!important}.pt-md-5,.py-md-5{padding-top:3rem!important}.pr-md-5,.px-md-5{padding-right:3rem!important}.pb-md-5,.py-md-5{padding-bottom:3rem!important}.pl-md-5,.px-md-5{padding-left:3rem!important}.m-md-n1{margin:-.25rem!important}.mt-md-n1,.my-md-n1{margin-top:-.25rem!important}.mr-md-n1,.mx-md-n1{margin-right:-.25rem!important}.mb-md-n1,.my-md-n1{margin-bottom:-.25rem!important}.ml-md-n1,.mx-md-n1{margin-left:-.25rem!important}.m-md-n2{margin:-.5rem!important}.mt-md-n2,.my-md-n2{margin-top:-.5rem!important}.mr-md-n2,.mx-md-n2{margin-right:-.5rem!important}.mb-md-n2,.my-md-n2{margin-bottom:-.5rem!important}.ml-md-n2,.mx-md-n2{margin-left:-.5rem!important}.m-md-n3{margin:-1rem!important}.mt-md-n3,.my-md-n3{margin-top:-1rem!important}.mr-md-n3,.mx-md-n3{margin-right:-1rem!important}.mb-md-n3,.my-md-n3{margin-bottom:-1rem!important}.ml-md-n3,.mx-md-n3{margin-left:-1rem!important}.m-md-n4{margin:-1.5rem!important}.mt-md-n4,.my-md-n4{margin-top:-1.5rem!important}.mr-md-n4,.mx-md-n4{margin-right:-1.5rem!important}.mb-md-n4,.my-md-n4{margin-bottom:-1.5rem!important}.ml-md-n4,.mx-md-n4{margin-left:-1.5rem!important}.m-md-n5{margin:-3rem!important}.mt-md-n5,.my-md-n5{margin-top:-3rem!important}.mr-md-n5,.mx-md-n5{margin-right:-3rem!important}.mb-md-n5,.my-md-n5{margin-bottom:-3rem!important}.ml-md-n5,.mx-md-n5{margin-left:-3rem!important}.m-md-auto{margin:auto!important}.mt-md-auto,.my-md-auto{margin-top:auto!important}.mr-md-auto,.mx-md-auto{margin-right:auto!important}.mb-md-auto,.my-md-auto{margin-bottom:auto!important}.ml-md-auto,.mx-md-auto{margin-left:auto!important}}@media (min-width:960px){.m-lg-0{margin:0!important}.mt-lg-0,.my-lg-0{margin-top:0!important}.mr-lg-0,.mx-lg-0{margin-right:0!important}.mb-lg-0,.my-lg-0{margin-bottom:0!important}.ml-lg-0,.mx-lg-0{margin-left:0!important}.m-lg-1{margin:.25rem!important}.mt-lg-1,.my-lg-1{margin-top:.25rem!important}.mr-lg-1,.mx-lg-1{margin-right:.25rem!important}.mb-lg-1,.my-lg-1{margin-bottom:.25rem!important}.ml-lg-1,.mx-lg-1{margin-left:.25rem!important}.m-lg-2{margin:.5rem!important}.mt-lg-2,.my-lg-2{margin-top:.5rem!important}.mr-lg-2,.mx-lg-2{margin-right:.5rem!important}.mb-lg-2,.my-lg-2{margin-bottom:.5rem!important}.ml-lg-2,.mx-lg-2{margin-left:.5rem!important}.m-lg-3{margin:1rem!important}.mt-lg-3,.my-lg-3{margin-top:1rem!important}.mr-lg-3,.mx-lg-3{margin-right:1rem!important}.mb-lg-3,.my-lg-3{margin-bottom:1rem!important}.ml-lg-3,.mx-lg-3{margin-left:1rem!important}.m-lg-4{margin:1.5rem!important}.mt-lg-4,.my-lg-4{margin-top:1.5rem!important}.mr-lg-4,.mx-lg-4{margin-right:1.5rem!important}.mb-lg-4,.my-lg-4{margin-bottom:1.5rem!important}.ml-lg-4,.mx-lg-4{margin-left:1.5rem!important}.m-lg-5{margin:3rem!important}.mt-lg-5,.my-lg-5{margin-top:3rem!important}.mr-lg-5,.mx-lg-5{margin-right:3rem!important}.mb-lg-5,.my-lg-5{margin-bottom:3rem!important}.ml-lg-5,.mx-lg-5{margin-left:3rem!important}.p-lg-0{padding:0!important}.pt-lg-0,.py-lg-0{padding-top:0!important}.pr-lg-0,.px-lg-0{padding-right:0!important}.pb-lg-0,.py-lg-0{padding-bottom:0!important}.pl-lg-0,.px-lg-0{padding-left:0!important}.p-lg-1{padding:.25rem!important}.pt-lg-1,.py-lg-1{padding-top:.25rem!important}.pr-lg-1,.px-lg-1{padding-right:.25rem!important}.pb-lg-1,.py-lg-1{padding-bottom:.25rem!important}.pl-lg-1,.px-lg-1{padding-left:.25rem!important}.p-lg-2{padding:.5rem!important}.pt-lg-2,.py-lg-2{padding-top:.5rem!important}.pr-lg-2,.px-lg-2{padding-right:.5rem!important}.pb-lg-2,.py-lg-2{padding-bottom:.5rem!important}.pl-lg-2,.px-lg-2{padding-left:.5rem!important}.p-lg-3{padding:1rem!important}.pt-lg-3,.py-lg-3{padding-top:1rem!important}.pr-lg-3,.px-lg-3{padding-right:1rem!important}.pb-lg-3,.py-lg-3{padding-bottom:1rem!important}.pl-lg-3,.px-lg-3{padding-left:1rem!important}.p-lg-4{padding:1.5rem!important}.pt-lg-4,.py-lg-4{padding-top:1.5rem!important}.pr-lg-4,.px-lg-4{padding-right:1.5rem!important}.pb-lg-4,.py-lg-4{padding-bottom:1.5rem!important}.pl-lg-4,.px-lg-4{padding-left:1.5rem!important}.p-lg-5{padding:3rem!important}.pt-lg-5,.py-lg-5{padding-top:3rem!important}.pr-lg-5,.px-lg-5{padding-right:3rem!important}.pb-lg-5,.py-lg-5{padding-bottom:3rem!important}.pl-lg-5,.px-lg-5{padding-left:3rem!important}.m-lg-n1{margin:-.25rem!important}.mt-lg-n1,.my-lg-n1{margin-top:-.25rem!important}.mr-lg-n1,.mx-lg-n1{margin-right:-.25rem!important}.mb-lg-n1,.my-lg-n1{margin-bottom:-.25rem!important}.ml-lg-n1,.mx-lg-n1{margin-left:-.25rem!important}.m-lg-n2{margin:-.5rem!important}.mt-lg-n2,.my-lg-n2{margin-top:-.5rem!important}.mr-lg-n2,.mx-lg-n2{margin-right:-.5rem!important}.mb-lg-n2,.my-lg-n2{margin-bottom:-.5rem!important}.ml-lg-n2,.mx-lg-n2{margin-left:-.5rem!important}.m-lg-n3{margin:-1rem!important}.mt-lg-n3,.my-lg-n3{margin-top:-1rem!important}.mr-lg-n3,.mx-lg-n3{margin-right:-1rem!important}.mb-lg-n3,.my-lg-n3{margin-bottom:-1rem!important}.ml-lg-n3,.mx-lg-n3{margin-left:-1rem!important}.m-lg-n4{margin:-1.5rem!important}.mt-lg-n4,.my-lg-n4{margin-top:-1.5rem!important}.mr-lg-n4,.mx-lg-n4{margin-right:-1.5rem!important}.mb-lg-n4,.my-lg-n4{margin-bottom:-1.5rem!important}.ml-lg-n4,.mx-lg-n4{margin-left:-1.5rem!important}.m-lg-n5{margin:-3rem!important}.mt-lg-n5,.my-lg-n5{margin-top:-3rem!important}.mr-lg-n5,.mx-lg-n5{margin-right:-3rem!important}.mb-lg-n5,.my-lg-n5{margin-bottom:-3rem!important}.ml-lg-n5,.mx-lg-n5{margin-left:-3rem!important}.m-lg-auto{margin:auto!important}.mt-lg-auto,.my-lg-auto{margin-top:auto!important}.mr-lg-auto,.mx-lg-auto{margin-right:auto!important}.mb-lg-auto,.my-lg-auto{margin-bottom:auto!important}.ml-lg-auto,.mx-lg-auto{margin-left:auto!important}}@media (min-width:1200px){.m-xl-0{margin:0!important}.mt-xl-0,.my-xl-0{margin-top:0!important}.mr-xl-0,.mx-xl-0{margin-right:0!important}.mb-xl-0,.my-xl-0{margin-bottom:0!important}.ml-xl-0,.mx-xl-0{margin-left:0!important}.m-xl-1{margin:.25rem!important}.mt-xl-1,.my-xl-1{margin-top:.25rem!important}.mr-xl-1,.mx-xl-1{margin-right:.25rem!important}.mb-xl-1,.my-xl-1{margin-bottom:.25rem!important}.ml-xl-1,.mx-xl-1{margin-left:.25rem!important}.m-xl-2{margin:.5rem!important}.mt-xl-2,.my-xl-2{margin-top:.5rem!important}.mr-xl-2,.mx-xl-2{margin-right:.5rem!important}.mb-xl-2,.my-xl-2{margin-bottom:.5rem!important}.ml-xl-2,.mx-xl-2{margin-left:.5rem!important}.m-xl-3{margin:1rem!important}.mt-xl-3,.my-xl-3{margin-top:1rem!important}.mr-xl-3,.mx-xl-3{margin-right:1rem!important}.mb-xl-3,.my-xl-3{margin-bottom:1rem!important}.ml-xl-3,.mx-xl-3{margin-left:1rem!important}.m-xl-4{margin:1.5rem!important}.mt-xl-4,.my-xl-4{margin-top:1.5rem!important}.mr-xl-4,.mx-xl-4{margin-right:1.5rem!important}.mb-xl-4,.my-xl-4{margin-bottom:1.5rem!important}.ml-xl-4,.mx-xl-4{margin-left:1.5rem!important}.m-xl-5{margin:3rem!important}.mt-xl-5,.my-xl-5{margin-top:3rem!important}.mr-xl-5,.mx-xl-5{margin-right:3rem!important}.mb-xl-5,.my-xl-5{margin-bottom:3rem!important}.ml-xl-5,.mx-xl-5{margin-left:3rem!important}.p-xl-0{padding:0!important}.pt-xl-0,.py-xl-0{padding-top:0!important}.pr-xl-0,.px-xl-0{padding-right:0!important}.pb-xl-0,.py-xl-0{padding-bottom:0!important}.pl-xl-0,.px-xl-0{padding-left:0!important}.p-xl-1{padding:.25rem!important}.pt-xl-1,.py-xl-1{padding-top:.25rem!important}.pr-xl-1,.px-xl-1{padding-right:.25rem!important}.pb-xl-1,.py-xl-1{padding-bottom:.25rem!important}.pl-xl-1,.px-xl-1{padding-left:.25rem!important}.p-xl-2{padding:.5rem!important}.pt-xl-2,.py-xl-2{padding-top:.5rem!important}.pr-xl-2,.px-xl-2{padding-right:.5rem!important}.pb-xl-2,.py-xl-2{padding-bottom:.5rem!important}.pl-xl-2,.px-xl-2{padding-left:.5rem!important}.p-xl-3{padding:1rem!important}.pt-xl-3,.py-xl-3{padding-top:1rem!important}.pr-xl-3,.px-xl-3{padding-right:1rem!important}.pb-xl-3,.py-xl-3{padding-bottom:1rem!important}.pl-xl-3,.px-xl-3{padding-left:1rem!important}.p-xl-4{padding:1.5rem!important}.pt-xl-4,.py-xl-4{padding-top:1.5rem!important}.pr-xl-4,.px-xl-4{padding-right:1.5rem!important}.pb-xl-4,.py-xl-4{padding-bottom:1.5rem!important}.pl-xl-4,.px-xl-4{padding-left:1.5rem!important}.p-xl-5{padding:3rem!important}.pt-xl-5,.py-xl-5{padding-top:3rem!important}.pr-xl-5,.px-xl-5{padding-right:3rem!important}.pb-xl-5,.py-xl-5{padding-bottom:3rem!important}.pl-xl-5,.px-xl-5{padding-left:3rem!important}.m-xl-n1{margin:-.25rem!important}.mt-xl-n1,.my-xl-n1{margin-top:-.25rem!important}.mr-xl-n1,.mx-xl-n1{margin-right:-.25rem!important}.mb-xl-n1,.my-xl-n1{margin-bottom:-.25rem!important}.ml-xl-n1,.mx-xl-n1{margin-left:-.25rem!important}.m-xl-n2{margin:-.5rem!important}.mt-xl-n2,.my-xl-n2{margin-top:-.5rem!important}.mr-xl-n2,.mx-xl-n2{margin-right:-.5rem!important}.mb-xl-n2,.my-xl-n2{margin-bottom:-.5rem!important}.ml-xl-n2,.mx-xl-n2{margin-left:-.5rem!important}.m-xl-n3{margin:-1rem!important}.mt-xl-n3,.my-xl-n3{margin-top:-1rem!important}.mr-xl-n3,.mx-xl-n3{margin-right:-1rem!important}.mb-xl-n3,.my-xl-n3{margin-bottom:-1rem!important}.ml-xl-n3,.mx-xl-n3{margin-left:-1rem!important}.m-xl-n4{margin:-1.5rem!important}.mt-xl-n4,.my-xl-n4{margin-top:-1.5rem!important}.mr-xl-n4,.mx-xl-n4{margin-right:-1.5rem!important}.mb-xl-n4,.my-xl-n4{margin-bottom:-1.5rem!important}.ml-xl-n4,.mx-xl-n4{margin-left:-1.5rem!important}.m-xl-n5{margin:-3rem!important}.mt-xl-n5,.my-xl-n5{margin-top:-3rem!important}.mr-xl-n5,.mx-xl-n5{margin-right:-3rem!important}.mb-xl-n5,.my-xl-n5{margin-bottom:-3rem!important}.ml-xl-n5,.mx-xl-n5{margin-left:-3rem!important}.m-xl-auto{margin:auto!important}.mt-xl-auto,.my-xl-auto{margin-top:auto!important}.mr-xl-auto,.mx-xl-auto{margin-right:auto!important}.mb-xl-auto,.my-xl-auto{margin-bottom:auto!important}.ml-xl-auto,.mx-xl-auto{margin-left:auto!important}}.stretched-link:after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;pointer-events:auto;content:"";background-color:transparent}.text-monospace{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace!important}.text-justify{text-align:justify!important}.text-wrap{white-space:normal!important}.text-nowrap{white-space:nowrap!important}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text-left{text-align:left!important}.text-right{text-align:right!important}.text-center{text-align:center!important}@media (min-width:540px){.text-sm-left{text-align:left!important}.text-sm-right{text-align:right!important}.text-sm-center{text-align:center!important}}@media (min-width:720px){.text-md-left{text-align:left!important}.text-md-right{text-align:right!important}.text-md-center{text-align:center!important}}@media (min-width:960px){.text-lg-left{text-align:left!important}.text-lg-right{text-align:right!important}.text-lg-center{text-align:center!important}}@media (min-width:1200px){.text-xl-left{text-align:left!important}.text-xl-right{text-align:right!important}.text-xl-center{text-align:center!important}}.text-lowercase{text-transform:lowercase!important}.text-uppercase{text-transform:uppercase!important}.text-capitalize{text-transform:capitalize!important}.font-weight-light{font-weight:300!important}.font-weight-lighter{font-weight:lighter!important}.font-weight-normal{font-weight:400!important}.font-weight-bold{font-weight:700!important}.font-weight-bolder{font-weight:bolder!important}.font-italic{font-style:italic!important}.text-white{color:#fff!important}.text-primary{color:#007bff!important}a.text-primary:focus,a.text-primary:hover{color:#0056b3!important}.text-secondary{color:#6c757d!important}a.text-secondary:focus,a.text-secondary:hover{color:#494f54!important}.text-success{color:#28a745!important}a.text-success:focus,a.text-success:hover{color:#19692c!important}.text-info{color:#17a2b8!important}a.text-info:focus,a.text-info:hover{color:#0f6674!important}.text-warning{color:#ffc107!important}a.text-warning:focus,a.text-warning:hover{color:#ba8b00!important}.text-danger{color:#dc3545!important}a.text-danger:focus,a.text-danger:hover{color:#a71d2a!important}.text-light{color:#f8f9fa!important}a.text-light:focus,a.text-light:hover{color:#cbd3da!important}.text-dark{color:#343a40!important}a.text-dark:focus,a.text-dark:hover{color:#121416!important}.text-body{color:#212529!important}.text-muted{color:#6c757d!important}.text-black-50{color:rgba(0,0,0,.5)!important}.text-white-50{color:hsla(0,0%,100%,.5)!important}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.text-decoration-none{text-decoration:none!important}.text-break{word-wrap:break-word!important}.text-reset{color:inherit!important}.visible{visibility:visible!important}.invisible{visibility:hidden!important}@media print{*,:after,:before{text-shadow:none!important;box-shadow:none!important}a:not(.btn){text-decoration:underline}abbr[title]:after{content:" (" attr(title) ")"}pre{white-space:pre-wrap!important}blockquote,pre{border:1px solid #adb5bd;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}@page{size:a3}.container,body{min-width:960px!important}.navbar{display:none}.badge{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #dee2e6!important}.table-dark{color:inherit}.table-dark tbody+tbody,.table-dark td,.table-dark th,.table-dark thead th{border-color:#dee2e6}.table .thead-dark th{color:inherit;border-color:#dee2e6}}html{font-size:var(--pst-font-size-base);scroll-padding-top:calc(var(--pst-header-height) + 12px)}body{padding-top:calc(var(--pst-header-height) + 20px);background-color:#fff;font-family:var(--pst-font-family-base);font-weight:400;line-height:1.65;color:rgba(var(--pst-color-text-base),1)}p{margin-bottom:1.15rem;font-size:1em;color:rgba(var(--pst-color-paragraph),1)}p.rubric{border-bottom:1px solid #c9c9c9}a{color:rgba(var(--pst-color-link),1);text-decoration:none}a:hover{color:rgba(var(--pst-color-link-hover),1);text-decoration:underline}a.headerlink{color:rgba(var(--pst-color-headerlink),1);font-size:.8em;padding:0 4px;text-decoration:none}a.headerlink:hover{background-color:rgba(var(--pst-color-headerlink),1);color:rgba(var(--pst-color-headerlink-hover),1)}.heading-style,h1,h2,h3,h4,h5,h6{margin:2.75rem 0 1.05rem;font-family:var(--pst-font-family-heading);font-weight:400;line-height:1.15}h1{margin-top:0;font-size:var(--pst-font-size-h1);color:rgba(var(--pst-color-h1),1)}h2{font-size:var(--pst-font-size-h2);color:rgba(var(--pst-color-h2),1)}h3{font-size:var(--pst-font-size-h3);color:rgba(var(--pst-color-h3),1)}h4{font-size:var(--pst-font-size-h4);color:rgba(var(--pst-color-h4),1)}h5{font-size:var(--pst-font-size-h5);color:rgba(var(--pst-color-h5),1)}h6{font-size:var(--pst-font-size-h6);color:rgba(var(--pst-color-h6),1)}.text_small,small{font-size:var(--pst-font-size-milli)}hr{border:0;border-top:1px solid #e5e5e5}code,kbd,pre,samp{font-family:var(--pst-font-family-monospace)}pre{margin:1.5em 0;padding:10px;background-color:rgba(var(--pst-color-preformatted-background),1);color:rgba(var(--pst-color-preformatted-text),1);line-height:1.2em;border:1px solid #c9c9c9;box-shadow:1px 1px 1px #d8d8d8}.navbar{position:fixed;min-height:var(--pst-header-height);width:100%;padding:0}.navbar .container-xl{height:100%}.navbar-brand{position:relative;height:var(--pst-header-height);width:auto;padding:.5rem 0}.navbar-brand img{max-width:100%;height:100%;width:auto}.navbar-light{background:#fff!important;box-shadow:0 .125rem .25rem 0 rgba(0,0,0,.11)}.navbar-light .navbar-nav li a.nav-link{padding:0 .5rem;color:rgba(var(--pst-color-navbar-link),1)}.navbar-light .navbar-nav li a.nav-link:hover{color:rgba(var(--pst-color-navbar-link-hover),1)}.navbar-light .navbar-nav>.active>.nav-link{font-weight:600;color:rgba(var(--pst-color-navbar-link-active),1)}.navbar-header a{padding:0 15px}.admonition{margin:1.5625em auto;padding:0 .6rem .8rem!important;overflow:hidden;page-break-inside:avoid;border-left:.2rem solid;border-left-color:rgba(var(--pst-color-admonition-default),1);border-bottom-color:rgba(var(--pst-color-admonition-default),1);border-right-color:rgba(var(--pst-color-admonition-default),1);border-top-color:rgba(var(--pst-color-admonition-default),1);border-radius:.1rem;box-shadow:0 .2rem .5rem rgba(0,0,0,.05),0 0 .05rem rgba(0,0,0,.1);transition:color .25s,background-color .25s,border-color .25s}.admonition :last-child{margin-bottom:0}.admonition p.admonition-title~*{padding:0 1.4rem}.admonition>ol,.admonition>ul{margin-left:1em}.admonition .admonition-title{position:relative;margin:0 -.6rem!important;padding:.4rem .6rem .4rem 2rem;font-weight:700;background-color:rgba(var(--pst-color-admonition-default),.1)}.admonition .admonition-title:before{position:absolute;left:.6rem;width:1rem;height:1rem;color:rgba(var(--pst-color-admonition-default),1);font-family:Font Awesome\ 5 Free;font-weight:900;content:var(--pst-icon-admonition-default)}.admonition .admonition-title+*{margin-top:.4em}.admonition.attention{border-color:rgba(var(--pst-color-admonition-attention),1)}.admonition.attention .admonition-title{background-color:rgba(var(--pst-color-admonition-attention),.1)}.admonition.attention .admonition-title:before{color:rgba(var(--pst-color-admonition-attention),1);content:var(--pst-icon-admonition-attention)}.admonition.caution{border-color:rgba(var(--pst-color-admonition-caution),1)}.admonition.caution .admonition-title{background-color:rgba(var(--pst-color-admonition-caution),.1)}.admonition.caution .admonition-title:before{color:rgba(var(--pst-color-admonition-caution),1);content:var(--pst-icon-admonition-caution)}.admonition.warning{border-color:rgba(var(--pst-color-admonition-warning),1)}.admonition.warning .admonition-title{background-color:rgba(var(--pst-color-admonition-warning),.1)}.admonition.warning .admonition-title:before{color:rgba(var(--pst-color-admonition-warning),1);content:var(--pst-icon-admonition-warning)}.admonition.danger{border-color:rgba(var(--pst-color-admonition-danger),1)}.admonition.danger .admonition-title{background-color:rgba(var(--pst-color-admonition-danger),.1)}.admonition.danger .admonition-title:before{color:rgba(var(--pst-color-admonition-danger),1);content:var(--pst-icon-admonition-danger)}.admonition.error{border-color:rgba(var(--pst-color-admonition-error),1)}.admonition.error .admonition-title{background-color:rgba(var(--pst-color-admonition-error),.1)}.admonition.error .admonition-title:before{color:rgba(var(--pst-color-admonition-error),1);content:var(--pst-icon-admonition-error)}.admonition.hint{border-color:rgba(var(--pst-color-admonition-hint),1)}.admonition.hint .admonition-title{background-color:rgba(var(--pst-color-admonition-hint),.1)}.admonition.hint .admonition-title:before{color:rgba(var(--pst-color-admonition-hint),1);content:var(--pst-icon-admonition-hint)}.admonition.tip{border-color:rgba(var(--pst-color-admonition-tip),1)}.admonition.tip .admonition-title{background-color:rgba(var(--pst-color-admonition-tip),.1)}.admonition.tip .admonition-title:before{color:rgba(var(--pst-color-admonition-tip),1);content:var(--pst-icon-admonition-tip)}.admonition.important{border-color:rgba(var(--pst-color-admonition-important),1)}.admonition.important .admonition-title{background-color:rgba(var(--pst-color-admonition-important),.1)}.admonition.important .admonition-title:before{color:rgba(var(--pst-color-admonition-important),1);content:var(--pst-icon-admonition-important)}.admonition.note{border-color:rgba(var(--pst-color-admonition-note),1)}.admonition.note .admonition-title{background-color:rgba(var(--pst-color-admonition-note),.1)}.admonition.note .admonition-title:before{color:rgba(var(--pst-color-admonition-note),1);content:var(--pst-icon-admonition-note)}div.deprecated{margin-bottom:10px;margin-top:10px;padding:7px;background-color:#f3e5e5;border:1px solid #eed3d7;border-radius:.5rem}div.deprecated p{color:#b94a48;display:inline}.topic{background-color:#eee}.seealso dd{margin-top:0;margin-bottom:0}.viewcode-back{font-family:var(--pst-font-family-base)}.viewcode-block:target{background-color:#f4debf;border-top:1px solid #ac9;border-bottom:1px solid #ac9}span.guilabel{border:1px solid #7fbbe3;background:#e7f2fa;font-size:80%;font-weight:700;border-radius:4px;padding:2.4px 6px;margin:auto 2px}table.field-list{border-collapse:separate;border-spacing:10px;margin-left:1px}table.field-list th.field-name{padding:1px 8px 1px 5px;white-space:nowrap;background-color:#eee}table.field-list td.field-body p{font-style:italic}table.field-list td.field-body p>strong{font-style:normal}table.field-list td.field-body blockquote{border-left:none;margin:0 0 .3em;padding-left:30px}.table.autosummary td:first-child{white-space:nowrap}.footer{width:100%;border-top:1px solid #ccc;padding-top:10px}.bd-search{position:relative;padding:1rem 15px;margin-right:-15px;margin-left:-15px}.bd-search .icon{position:absolute;color:#a4a6a7;left:25px;top:25px}.bd-search input{border-radius:0;border:0;border-bottom:1px solid #e5e5e5;padding-left:35px}.bd-toc{-ms-flex-order:2;order:2;height:calc(100vh - 2rem);overflow-y:auto}@supports (position:-webkit-sticky) or (position:sticky){.bd-toc{position:-webkit-sticky;position:sticky;top:calc(var(--pst-header-height) + 20px);height:calc(100vh - 5rem);overflow-y:auto}}.bd-toc .onthispage{color:#a4a6a7}.section-nav{padding-left:0;border-left:1px solid #eee;border-bottom:none}.section-nav ul{padding-left:1rem}.toc-entry,.toc-entry a{display:block}.toc-entry a{padding:.125rem 1.5rem;color:rgba(var(--pst-color-toc-link),1)}@media (min-width:1200px){.toc-entry a{padding-right:0}}.toc-entry a:hover{color:rgba(var(--pst-color-toc-link-hover),1);text-decoration:none}.bd-sidebar{padding-top:1em}@media (min-width:720px){.bd-sidebar{border-right:1px solid rgba(0,0,0,.1)}@supports (position:-webkit-sticky) or (position:sticky){.bd-sidebar{position:-webkit-sticky;position:sticky;top:calc(var(--pst-header-height) + 20px);z-index:1000;height:calc(100vh - 4rem)}}}.bd-sidebar.no-sidebar{border-right:0}.bd-links{padding-top:1rem;padding-bottom:1rem;margin-right:-15px;margin-left:-15px}@media (min-width:720px){.bd-links{display:block!important}@supports (position:-webkit-sticky) or (position:sticky){.bd-links{max-height:calc(100vh - 9rem);overflow-y:auto}}}.bd-sidenav{display:none}.bd-content{padding-top:20px}.bd-content .section{max-width:100%}.bd-content .section table{display:block;overflow:auto}.bd-toc-link{display:block;padding:.25rem 1.5rem;font-weight:600;color:rgba(0,0,0,.65)}.bd-toc-link:hover{color:rgba(0,0,0,.85);text-decoration:none}.bd-toc-item.active{margin-bottom:1rem}.bd-toc-item.active:not(:first-child){margin-top:1rem}.bd-toc-item.active>.bd-toc-link{color:rgba(0,0,0,.85)}.bd-toc-item.active>.bd-toc-link:hover{background-color:transparent}.bd-toc-item.active>.bd-sidenav{display:block}.bd-sidebar .nav ul{list-style:none;padding:0 1.5rem}.bd-sidebar .nav li>a{display:block;padding:.25rem 1.5rem;font-size:.9em;color:rgba(var(--pst-color-sidebar-link),1)}.bd-sidebar .nav li>a:hover{color:rgba(var(--pst-color-sidebar-link-hover),1);text-decoration:none;background-color:transparent}.bd-sidebar .nav .active:hover>a,.bd-sidebar .nav .active>a{font-weight:600;color:rgba(var(--pst-color-sidebar-link-active),1)}.toc-h2{font-size:.85rem}.toc-h3{font-size:.75rem}.toc-h4{font-size:.65rem}.toc-entry>.nav-link.active{font-weight:600;color:#130654;color:rgba(var(--pst-color-toc-link-active),1);background-color:transparent;border-left:2px solid rgba(var(--pst-color-toc-link-active),1)}.nav-link:hover{border-style:none}#navbar-main-elements li.nav-item i{font-size:.7rem;padding-left:2px;vertical-align:middle}.bd-toc .nav .nav{display:none}.bd-toc .nav .nav.visible,.bd-toc .nav>.active>ul{display:block}.prev-next-bottom{margin:20px 0}.prev-next-bottom a.left-prev,.prev-next-bottom a.right-next{padding:10px;border:1px solid rgba(0,0,0,.2);max-width:45%;overflow-x:hidden;color:rgba(0,0,0,.65)}.prev-next-bottom a.left-prev{float:left}.prev-next-bottom a.left-prev:before{content:"<< "}.prev-next-bottom a.right-next{float:right}.prev-next-bottom a.right-next:after{content:" >>"}.alert{padding-bottom:0}.alert-info a{color:#e83e8c}#navbar-icon-links i.fa,#navbar-icon-links i.fab,#navbar-icon-links i.far,#navbar-icon-links i.fas{vertical-align:middle;font-style:normal;font-size:1.5rem;line-height:1.25}#navbar-icon-links i.fa-github-square:before{color:#333}#navbar-icon-links i.fa-twitter-square:before{color:#55acee}#navbar-icon-links i.fa-gitlab:before{color:#548}.tocsection{border-left:1px solid #eee;padding:.3rem 1.5rem}.tocsection i{padding-right:.5rem}.editthispage{padding-top:2rem}.editthispage a{color:#130754}.xr-wrap[hidden]{display:block!important} \ No newline at end of file diff --git a/docs/_static/css/theme.css b/docs/_static/css/theme.css new file mode 100644 index 000000000..f90b09150 --- /dev/null +++ b/docs/_static/css/theme.css @@ -0,0 +1,111 @@ +:root { + /***************************************************************************** + * Theme config + **/ + --pst-header-height: 60px; + + /***************************************************************************** + * Font size + **/ + --pst-font-size-base: 15px; /* base font size - applied at body / html level */ + + /* heading font sizes */ + --pst-font-size-h1: 36px; + --pst-font-size-h2: 32px; + --pst-font-size-h3: 26px; + --pst-font-size-h4: 21px; + --pst-font-size-h5: 18px; + --pst-font-size-h6: 16px; + + /* smaller then heading font sizes*/ + --pst-font-size-milli: 12px; + + /***************************************************************************** + * Font family + **/ + /* These are adapted from https://systemfontstack.com/ */ + --pst-font-family-base-system: -apple-system, BlinkMacSystemFont, Segoe UI, "Helvetica Neue", + Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol; + --pst-font-family-monospace-system: "SFMono-Regular", Menlo, Consolas, Monaco, + Liberation Mono, Lucida Console, monospace; + + --pst-font-family-base: var(--pst-font-family-base-system); + --pst-font-family-heading: var(--pst-font-family-base); + --pst-font-family-monospace: var(--pst-font-family-monospace-system); + + /***************************************************************************** + * Color + * + * Colors are defined in rgb string way, "red, green, blue" + **/ + --pst-color-primary: 19, 6, 84; + --pst-color-success: 40, 167, 69; + --pst-color-info: 0, 123, 255; /*23, 162, 184;*/ + --pst-color-warning: 255, 193, 7; + --pst-color-danger: 220, 53, 69; + --pst-color-text-base: 51, 51, 51; + + --pst-color-h1: var(--pst-color-primary); + --pst-color-h2: var(--pst-color-primary); + --pst-color-h3: var(--pst-color-text-base); + --pst-color-h4: var(--pst-color-text-base); + --pst-color-h5: var(--pst-color-text-base); + --pst-color-h6: var(--pst-color-text-base); + --pst-color-paragraph: var(--pst-color-text-base); + --pst-color-link: 0, 91, 129; + --pst-color-link-hover: 227, 46, 0; + --pst-color-headerlink: 198, 15, 15; + --pst-color-headerlink-hover: 255, 255, 255; + --pst-color-preformatted-text: 34, 34, 34; + --pst-color-preformatted-background: 250, 250, 250; + + --pst-color-active-navigation: 19, 6, 84; + --pst-color-navbar-link: 77, 77, 77; + --pst-color-navbar-link-hover: var(--pst-color-active-navigation); + --pst-color-navbar-link-active: var(--pst-color-active-navigation); + --pst-color-sidebar-link: 77, 77, 77; + --pst-color-sidebar-link-hover: var(--pst-color-active-navigation); + --pst-color-sidebar-link-active: var(--pst-color-active-navigation); + --pst-color-toc-link: 119, 117, 122; + --pst-color-toc-link-hover: var(--pst-color-active-navigation); + --pst-color-toc-link-active: var(--pst-color-active-navigation); + + /***************************************************************************** + * Icon + **/ + + /* font awesome icons*/ + --pst-icon-check-circle: '\f058'; + --pst-icon-info-circle: '\f05a'; + --pst-icon-exclamation-triangle: '\f071'; + --pst-icon-exclamation-circle: '\f06a'; + --pst-icon-times-circle: '\f057'; + --pst-icon-lightbulb: '\f0eb'; + + /***************************************************************************** + * Admonitions + **/ + + --pst-color-admonition-default: var(--pst-color-info); + --pst-color-admonition-note: var(--pst-color-info); + --pst-color-admonition-attention: var(--pst-color-warning); + --pst-color-admonition-caution: var(--pst-color-warning); + --pst-color-admonition-warning: var(--pst-color-warning); + --pst-color-admonition-danger: var(--pst-color-danger); + --pst-color-admonition-error: var(--pst-color-danger); + --pst-color-admonition-hint: var(--pst-color-success); + --pst-color-admonition-tip: var(--pst-color-success); + --pst-color-admonition-important: var(--pst-color-success); + + --pst-icon-admonition-default: var(--pst-icon-info-circle); + --pst-icon-admonition-note: var(--pst-icon-info-circle); + --pst-icon-admonition-attention: var(--pst-icon-exclamation-circle); + --pst-icon-admonition-caution: var(--pst-icon-exclamation-triangle); + --pst-icon-admonition-warning: var(--pst-icon-exclamation-triangle); + --pst-icon-admonition-danger: var(--pst-icon-exclamation-triangle); + --pst-icon-admonition-error: var(--pst-icon-times-circle); + --pst-icon-admonition-hint: var(--pst-icon-lightbulb); + --pst-icon-admonition-tip: var(--pst-icon-lightbulb); + --pst-icon-admonition-important: var(--pst-icon-exclamation-circle); + +} diff --git a/docs/_static/doctools.js b/docs/_static/doctools.js index daccd209d..b33f87fcb 100644 --- a/docs/_static/doctools.js +++ b/docs/_static/doctools.js @@ -4,7 +4,7 @@ * * Sphinx JavaScript utilities for all documentation. * - * :copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS. + * :copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ @@ -283,11 +283,10 @@ var Documentation = { }, initOnKeyListeners: function() { - $(document).keydown(function(event) { + $(document).keyup(function(event) { var activeElementType = document.activeElement.tagName; // don't navigate when in search box or textarea - if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT' - && !event.altKey && !event.ctrlKey && !event.metaKey && !event.shiftKey) { + if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT') { switch (event.keyCode) { case 37: // left var prevHref = $('link[rel="prev"]').prop('href'); diff --git a/docs/_static/documentation_options.js b/docs/_static/documentation_options.js index 45d13f3f6..4fbdd0e85 100644 --- a/docs/_static/documentation_options.js +++ b/docs/_static/documentation_options.js @@ -3,9 +3,7 @@ var DOCUMENTATION_OPTIONS = { VERSION: '2.0', LANGUAGE: 'None', COLLAPSE_INDEX: false, - BUILDER: 'html', FILE_SUFFIX: '.html', - LINK_SUFFIX: '.html', HAS_SOURCE: true, SOURCELINK_SUFFIX: '.txt', NAVIGATION_WITH_KEYS: true diff --git a/docs/_static/jquery-3.4.1.js b/docs/_static/jquery-3.4.1.js new file mode 100644 index 000000000..773ad95c5 --- /dev/null +++ b/docs/_static/jquery-3.4.1.js @@ -0,0 +1,10598 @@ +/*! + * jQuery JavaScript Library v3.4.1 + * https://jquery.com/ + * + * Includes Sizzle.js + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://jquery.org/license + * + * Date: 2019-05-01T21:04Z + */ +( function( global, factory ) { + + "use strict"; + + if ( typeof module === "object" && typeof module.exports === "object" ) { + + // For CommonJS and CommonJS-like environments where a proper `window` + // is present, execute the factory and get jQuery. + // For environments that do not have a `window` with a `document` + // (such as Node.js), expose a factory as module.exports. + // This accentuates the need for the creation of a real `window`. + // e.g. var jQuery = require("jquery")(window); + // See ticket #14549 for more info. + module.exports = global.document ? + factory( global, true ) : + function( w ) { + if ( !w.document ) { + throw new Error( "jQuery requires a window with a document" ); + } + return factory( w ); + }; + } else { + factory( global ); + } + +// Pass this if window is not defined yet +} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { + +// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 +// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode +// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common +// enough that all such attempts are guarded in a try block. +"use strict"; + +var arr = []; + +var document = window.document; + +var getProto = Object.getPrototypeOf; + +var slice = arr.slice; + +var concat = arr.concat; + +var push = arr.push; + +var indexOf = arr.indexOf; + +var class2type = {}; + +var toString = class2type.toString; + +var hasOwn = class2type.hasOwnProperty; + +var fnToString = hasOwn.toString; + +var ObjectFunctionString = fnToString.call( Object ); + +var support = {}; + +var isFunction = function isFunction( obj ) { + + // Support: Chrome <=57, Firefox <=52 + // In some browsers, typeof returns "function" for HTML elements + // (i.e., `typeof document.createElement( "object" ) === "function"`). + // We don't want to classify *any* DOM node as a function. + return typeof obj === "function" && typeof obj.nodeType !== "number"; + }; + + +var isWindow = function isWindow( obj ) { + return obj != null && obj === obj.window; + }; + + + + + var preservedScriptAttributes = { + type: true, + src: true, + nonce: true, + noModule: true + }; + + function DOMEval( code, node, doc ) { + doc = doc || document; + + var i, val, + script = doc.createElement( "script" ); + + script.text = code; + if ( node ) { + for ( i in preservedScriptAttributes ) { + + // Support: Firefox 64+, Edge 18+ + // Some browsers don't support the "nonce" property on scripts. + // On the other hand, just using `getAttribute` is not enough as + // the `nonce` attribute is reset to an empty string whenever it + // becomes browsing-context connected. + // See https://github.com/whatwg/html/issues/2369 + // See https://html.spec.whatwg.org/#nonce-attributes + // The `node.getAttribute` check was added for the sake of + // `jQuery.globalEval` so that it can fake a nonce-containing node + // via an object. + val = node[ i ] || node.getAttribute && node.getAttribute( i ); + if ( val ) { + script.setAttribute( i, val ); + } + } + } + doc.head.appendChild( script ).parentNode.removeChild( script ); + } + + +function toType( obj ) { + if ( obj == null ) { + return obj + ""; + } + + // Support: Android <=2.3 only (functionish RegExp) + return typeof obj === "object" || typeof obj === "function" ? + class2type[ toString.call( obj ) ] || "object" : + typeof obj; +} +/* global Symbol */ +// Defining this global in .eslintrc.json would create a danger of using the global +// unguarded in another place, it seems safer to define global only for this module + + + +var + version = "3.4.1", + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + + // The jQuery object is actually just the init constructor 'enhanced' + // Need init if jQuery is called (just allow error to be thrown if not included) + return new jQuery.fn.init( selector, context ); + }, + + // Support: Android <=4.0 only + // Make sure we trim BOM and NBSP + rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g; + +jQuery.fn = jQuery.prototype = { + + // The current version of jQuery being used + jquery: version, + + constructor: jQuery, + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + + // Return all the elements in a clean array + if ( num == null ) { + return slice.call( this ); + } + + // Return just the one element from the set + return num < 0 ? this[ num + this.length ] : this[ num ]; + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + each: function( callback ) { + return jQuery.each( this, callback ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map( this, function( elem, i ) { + return callback.call( elem, i, elem ); + } ) ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); + }, + + end: function() { + return this.prevObject || this.constructor(); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: arr.sort, + splice: arr.splice +}; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[ 0 ] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + + // Skip the boolean and the target + target = arguments[ i ] || {}; + i++; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !isFunction( target ) ) { + target = {}; + } + + // Extend jQuery itself if only one argument is passed + if ( i === length ) { + target = this; + i--; + } + + for ( ; i < length; i++ ) { + + // Only deal with non-null/undefined values + if ( ( options = arguments[ i ] ) != null ) { + + // Extend the base object + for ( name in options ) { + copy = options[ name ]; + + // Prevent Object.prototype pollution + // Prevent never-ending loop + if ( name === "__proto__" || target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject( copy ) || + ( copyIsArray = Array.isArray( copy ) ) ) ) { + src = target[ name ]; + + // Ensure proper type for the source value + if ( copyIsArray && !Array.isArray( src ) ) { + clone = []; + } else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) { + clone = {}; + } else { + clone = src; + } + copyIsArray = false; + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend( { + + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), + + // Assume jQuery is ready without the ready module + isReady: true, + + error: function( msg ) { + throw new Error( msg ); + }, + + noop: function() {}, + + isPlainObject: function( obj ) { + var proto, Ctor; + + // Detect obvious negatives + // Use toString instead of jQuery.type to catch host objects + if ( !obj || toString.call( obj ) !== "[object Object]" ) { + return false; + } + + proto = getProto( obj ); + + // Objects with no prototype (e.g., `Object.create( null )`) are plain + if ( !proto ) { + return true; + } + + // Objects with prototype are plain iff they were constructed by a global Object function + Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; + return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; + }, + + isEmptyObject: function( obj ) { + var name; + + for ( name in obj ) { + return false; + } + return true; + }, + + // Evaluates a script in a global context + globalEval: function( code, options ) { + DOMEval( code, { nonce: options && options.nonce } ); + }, + + each: function( obj, callback ) { + var length, i = 0; + + if ( isArrayLike( obj ) ) { + length = obj.length; + for ( ; i < length; i++ ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } else { + for ( i in obj ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } + + return obj; + }, + + // Support: Android <=4.0 only + trim: function( text ) { + return text == null ? + "" : + ( text + "" ).replace( rtrim, "" ); + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArrayLike( Object( arr ) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + return arr == null ? -1 : indexOf.call( arr, elem, i ); + }, + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + merge: function( first, second ) { + var len = +second.length, + j = 0, + i = first.length; + + for ( ; j < len; j++ ) { + first[ i++ ] = second[ j ]; + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, invert ) { + var callbackInverse, + matches = [], + i = 0, + length = elems.length, + callbackExpect = !invert; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + callbackInverse = !callback( elems[ i ], i ); + if ( callbackInverse !== callbackExpect ) { + matches.push( elems[ i ] ); + } + } + + return matches; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var length, value, + i = 0, + ret = []; + + // Go through the array, translating each of the items to their new values + if ( isArrayLike( elems ) ) { + length = elems.length; + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + } + + // Flatten any nested arrays + return concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // jQuery.support is not used in Core but other projects attach their + // properties to it so it needs to exist. + support: support +} ); + +if ( typeof Symbol === "function" ) { + jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; +} + +// Populate the class2type map +jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), +function( i, name ) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +} ); + +function isArrayLike( obj ) { + + // Support: real iOS 8.2 only (not reproducible in simulator) + // `in` check used to prevent JIT error (gh-2145) + // hasOwn isn't used here due to false negatives + // regarding Nodelist length in IE + var length = !!obj && "length" in obj && obj.length, + type = toType( obj ); + + if ( isFunction( obj ) || isWindow( obj ) ) { + return false; + } + + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v2.3.4 + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://js.foundation/ + * + * Date: 2019-04-08 + */ +(function( window ) { + +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + 1 * new Date(), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + nonnativeSelectorCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // Instance methods + hasOwn = ({}).hasOwnProperty, + arr = [], + pop = arr.pop, + push_native = arr.push, + push = arr.push, + slice = arr.slice, + // Use a stripped-down indexOf as it's faster than native + // https://jsperf.com/thor-indexof-vs-for/5 + indexOf = function( list, elem ) { + var i = 0, + len = list.length; + for ( ; i < len; i++ ) { + if ( list[i] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + + // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier + identifier = "(?:\\\\.|[\\w-]|[^\0-\\xa0])+", + + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + + // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + + "*\\]", + + pseudos = ":(" + identifier + ")(?:\\((" + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + // 3. anything else (capture 2) + ".*" + + ")\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rwhitespace = new RegExp( whitespace + "+", "g" ), + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), + rdescend = new RegExp( whitespace + "|>" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + identifier + ")" ), + "CLASS": new RegExp( "^\\.(" + identifier + ")" ), + "TAG": new RegExp( "^(" + identifier + "|[*])" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + + whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rhtml = /HTML$/i, + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + + // CSS escapes + // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), + funescape = function( _, escaped, escapedWhitespace ) { + var high = "0x" + escaped - 0x10000; + // NaN means non-codepoint + // Support: Firefox<24 + // Workaround erroneous numeric interpretation of +"0x" + return high !== high || escapedWhitespace ? + escaped : + high < 0 ? + // BMP codepoint + String.fromCharCode( high + 0x10000 ) : + // Supplemental Plane codepoint (surrogate pair) + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }, + + // CSS string/identifier serialization + // https://drafts.csswg.org/cssom/#common-serializing-idioms + rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, + fcssescape = function( ch, asCodePoint ) { + if ( asCodePoint ) { + + // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER + if ( ch === "\0" ) { + return "\uFFFD"; + } + + // Control characters and (dependent upon position) numbers get escaped as code points + return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; + } + + // Other potentially-special ASCII characters get backslash-escaped + return "\\" + ch; + }, + + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function() { + setDocument(); + }, + + inDisabledFieldset = addCombinator( + function( elem ) { + return elem.disabled === true && elem.nodeName.toLowerCase() === "fieldset"; + }, + { dir: "parentNode", next: "legend" } + ); + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + (arr = slice.call( preferredDoc.childNodes )), + preferredDoc.childNodes + ); + // Support: Android<4.0 + // Detect silently failing push.apply + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + push_native.apply( target, slice.call(els) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + // Can't trust NodeList.length + while ( (target[j++] = els[i++]) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var m, i, elem, nid, match, groups, newSelector, + newContext = context && context.ownerDocument, + + // nodeType defaults to 9, since context defaults to document + nodeType = context ? context.nodeType : 9; + + results = results || []; + + // Return early from calls with invalid selector or context + if ( typeof selector !== "string" || !selector || + nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { + + return results; + } + + // Try to shortcut find operations (as opposed to filters) in HTML documents + if ( !seed ) { + + if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { + setDocument( context ); + } + context = context || document; + + if ( documentIsHTML ) { + + // If the selector is sufficiently simple, try using a "get*By*" DOM method + // (excepting DocumentFragment context, where the methods don't exist) + if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) { + + // ID selector + if ( (m = match[1]) ) { + + // Document context + if ( nodeType === 9 ) { + if ( (elem = context.getElementById( m )) ) { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + + // Element context + } else { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( newContext && (elem = newContext.getElementById( m )) && + contains( context, elem ) && + elem.id === m ) { + + results.push( elem ); + return results; + } + } + + // Type selector + } else if ( match[2] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Class selector + } else if ( (m = match[3]) && support.getElementsByClassName && + context.getElementsByClassName ) { + + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // Take advantage of querySelectorAll + if ( support.qsa && + !nonnativeSelectorCache[ selector + " " ] && + (!rbuggyQSA || !rbuggyQSA.test( selector )) && + + // Support: IE 8 only + // Exclude object elements + (nodeType !== 1 || context.nodeName.toLowerCase() !== "object") ) { + + newSelector = selector; + newContext = context; + + // qSA considers elements outside a scoping root when evaluating child or + // descendant combinators, which is not what we want. + // In such cases, we work around the behavior by prefixing every selector in the + // list with an ID selector referencing the scope context. + // Thanks to Andrew Dupont for this technique. + if ( nodeType === 1 && rdescend.test( selector ) ) { + + // Capture the context ID, setting it first if necessary + if ( (nid = context.getAttribute( "id" )) ) { + nid = nid.replace( rcssescape, fcssescape ); + } else { + context.setAttribute( "id", (nid = expando) ); + } + + // Prefix every selector in the list + groups = tokenize( selector ); + i = groups.length; + while ( i-- ) { + groups[i] = "#" + nid + " " + toSelector( groups[i] ); + } + newSelector = groups.join( "," ); + + // Expand context for sibling selectors + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || + context; + } + + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch ( qsaError ) { + nonnativeSelectorCache( selector, true ); + } finally { + if ( nid === expando ) { + context.removeAttribute( "id" ); + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {function(string, object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return (cache[ key + " " ] = value); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created element and returns a boolean result + */ +function assert( fn ) { + var el = document.createElement("fieldset"); + + try { + return !!fn( el ); + } catch (e) { + return false; + } finally { + // Remove from its parent by default + if ( el.parentNode ) { + el.parentNode.removeChild( el ); + } + // release memory in IE + el = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split("|"), + i = arr.length; + + while ( i-- ) { + Expr.attrHandle[ arr[i] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + a.sourceIndex - b.sourceIndex; + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( (cur = cur.nextSibling) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for :enabled/:disabled + * @param {Boolean} disabled true for :disabled; false for :enabled + */ +function createDisabledPseudo( disabled ) { + + // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable + return function( elem ) { + + // Only certain elements can match :enabled or :disabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled + if ( "form" in elem ) { + + // Check for inherited disabledness on relevant non-disabled elements: + // * listed form-associated elements in a disabled fieldset + // https://html.spec.whatwg.org/multipage/forms.html#category-listed + // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled + // * option elements in a disabled optgroup + // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled + // All such elements have a "form" property. + if ( elem.parentNode && elem.disabled === false ) { + + // Option elements defer to a parent optgroup if present + if ( "label" in elem ) { + if ( "label" in elem.parentNode ) { + return elem.parentNode.disabled === disabled; + } else { + return elem.disabled === disabled; + } + } + + // Support: IE 6 - 11 + // Use the isDisabled shortcut property to check for disabled fieldset ancestors + return elem.isDisabled === disabled || + + // Where there is no isDisabled, check manually + /* jshint -W018 */ + elem.isDisabled !== !disabled && + inDisabledFieldset( elem ) === disabled; + } + + return elem.disabled === disabled; + + // Try to winnow out elements that can't be disabled before trusting the disabled property. + // Some victims get caught in our net (label, legend, menu, track), but it shouldn't + // even exist on them, let alone have a boolean value. + } else if ( "label" in elem ) { + return elem.disabled === disabled; + } + + // Remaining elements are neither :enabled nor :disabled + return false; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction(function( argument ) { + argument = +argument; + return markFunction(function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ (j = matchIndexes[i]) ] ) { + seed[j] = !(matches[j] = seed[j]); + } + } + }); + }); +} + +/** + * Checks a node for validity as a Sizzle context + * @param {Element|Object=} context + * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value + */ +function testContext( context ) { + return context && typeof context.getElementsByTagName !== "undefined" && context; +} + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Detects XML nodes + * @param {Element|Object} elem An element or a document + * @returns {Boolean} True iff elem is a non-HTML XML node + */ +isXML = Sizzle.isXML = function( elem ) { + var namespace = elem.namespaceURI, + docElem = (elem.ownerDocument || elem).documentElement; + + // Support: IE <=8 + // Assume HTML when documentElement doesn't yet exist, such as inside loading iframes + // https://bugs.jquery.com/ticket/4833 + return !rhtml.test( namespace || docElem && docElem.nodeName || "HTML" ); +}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var hasCompare, subWindow, + doc = node ? node.ownerDocument || node : preferredDoc; + + // Return early if doc is invalid or already selected + if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Update global variables + document = doc; + docElem = document.documentElement; + documentIsHTML = !isXML( document ); + + // Support: IE 9-11, Edge + // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) + if ( preferredDoc !== document && + (subWindow = document.defaultView) && subWindow.top !== subWindow ) { + + // Support: IE 11, Edge + if ( subWindow.addEventListener ) { + subWindow.addEventListener( "unload", unloadHandler, false ); + + // Support: IE 9 - 10 only + } else if ( subWindow.attachEvent ) { + subWindow.attachEvent( "onunload", unloadHandler ); + } + } + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties + // (excepting IE8 booleans) + support.attributes = assert(function( el ) { + el.className = "i"; + return !el.getAttribute("className"); + }); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert(function( el ) { + el.appendChild( document.createComment("") ); + return !el.getElementsByTagName("*").length; + }); + + // Support: IE<9 + support.getElementsByClassName = rnative.test( document.getElementsByClassName ); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programmatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert(function( el ) { + docElem.appendChild( el ).id = expando; + return !document.getElementsByName || !document.getElementsByName( expando ).length; + }); + + // ID filter and find + if ( support.getById ) { + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute("id") === attrId; + }; + }; + Expr.find["ID"] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var elem = context.getElementById( id ); + return elem ? [ elem ] : []; + } + }; + } else { + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== "undefined" && + elem.getAttributeNode("id"); + return node && node.value === attrId; + }; + }; + + // Support: IE 6 - 7 only + // getElementById is not reliable as a find shortcut + Expr.find["ID"] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var node, i, elems, + elem = context.getElementById( id ); + + if ( elem ) { + + // Verify the id attribute + node = elem.getAttributeNode("id"); + if ( node && node.value === id ) { + return [ elem ]; + } + + // Fall back on getElementsByName + elems = context.getElementsByName( id ); + i = 0; + while ( (elem = elems[i++]) ) { + node = elem.getAttributeNode("id"); + if ( node && node.value === id ) { + return [ elem ]; + } + } + } + + return []; + } + }; + } + + // Tag + Expr.find["TAG"] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( tag ); + + // DocumentFragment nodes don't have gEBTN + } else if ( support.qsa ) { + return context.querySelectorAll( tag ); + } + } : + + function( tag, context ) { + var elem, + tmp = [], + i = 0, + // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( (elem = results[i++]) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See https://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( (support.qsa = rnative.test( document.querySelectorAll )) ) { + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert(function( el ) { + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // https://bugs.jquery.com/ticket/12359 + docElem.appendChild( el ).innerHTML = "" + + ""; + + // Support: IE8, Opera 11-12.16 + // Nothing should be selected when empty strings follow ^= or $= or *= + // The test attribute must be unknown in Opera but "safe" for WinRT + // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section + if ( el.querySelectorAll("[msallowcapture^='']").length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !el.querySelectorAll("[selected]").length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ + if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { + rbuggyQSA.push("~="); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !el.querySelectorAll(":checked").length ) { + rbuggyQSA.push(":checked"); + } + + // Support: Safari 8+, iOS 8+ + // https://bugs.webkit.org/show_bug.cgi?id=136851 + // In-page `selector#id sibling-combinator selector` fails + if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { + rbuggyQSA.push(".#.+[+~]"); + } + }); + + assert(function( el ) { + el.innerHTML = "" + + ""; + + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + var input = document.createElement("input"); + input.setAttribute( "type", "hidden" ); + el.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE8 + // Enforce case-sensitivity of name attribute + if ( el.querySelectorAll("[name=d]").length ) { + rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( el.querySelectorAll(":enabled").length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: IE9-11+ + // IE's :disabled selector does not pick up the children of disabled fieldsets + docElem.appendChild( el ).disabled = true; + if ( el.querySelectorAll(":disabled").length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Opera 10-11 does not throw on post-comma invalid pseudos + el.querySelectorAll("*,:x"); + rbuggyQSA.push(",.*:"); + }); + } + + if ( (support.matchesSelector = rnative.test( (matches = docElem.matches || + docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector) )) ) { + + assert(function( el ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( el, "*" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( el, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + }); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); + + /* Contains + ---------------------------------------------------------------------- */ + hasCompare = rnative.test( docElem.compareDocumentPosition ); + + // Element contains another + // Purposefully self-exclusive + // As in, an element does not contain itself + contains = hasCompare || rnative.test( docElem.contains ) ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + )); + } : + function( a, b ) { + if ( b ) { + while ( (b = b.parentNode) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = hasCompare ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + // Sort on method existence if only one input has compareDocumentPosition + var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; + if ( compare ) { + return compare; + } + + // Calculate position if both inputs belong to the same document + compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ? + a.compareDocumentPosition( b ) : + + // Otherwise we know they are disconnected + 1; + + // Disconnected nodes + if ( compare & 1 || + (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { + + // Choose the first element that is related to our preferred document + if ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) { + return -1; + } + if ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } : + function( a, b ) { + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Parentless nodes are either documents or disconnected + if ( !aup || !bup ) { + return a === document ? -1 : + b === document ? 1 : + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( (cur = cur.parentNode) ) { + ap.unshift( cur ); + } + cur = b; + while ( (cur = cur.parentNode) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[i] === bp[i] ) { + i++; + } + + return i ? + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[i], bp[i] ) : + + // Otherwise nodes in our document sort first + ap[i] === preferredDoc ? -1 : + bp[i] === preferredDoc ? 1 : + 0; + }; + + return document; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + if ( support.matchesSelector && documentIsHTML && + !nonnativeSelectorCache[ expr + " " ] && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch (e) { + nonnativeSelectorCache( expr, true ); + } + } + + return Sizzle( expr, document, null, [ elem ] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + // Set document vars if needed + if ( ( context.ownerDocument || context ) !== document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val !== undefined ? + val : + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + (val = elem.getAttributeNode(name)) && val.specified ? + val.value : + null; +}; + +Sizzle.escape = function( sel ) { + return (sel + "").replace( rcssescape, fcssescape ); +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( (elem = results[i++]) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + // Clear input after sorting to release objects + // See https://github.com/jquery/sizzle/pull/225 + sortInput = null; + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + // If no nodeType, this is expected to be an array + while ( (node = elem[i++]) ) { + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + // Use textContent for elements + // innerText usage removed for consistency of new lines (jQuery #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[1] = match[1].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape ); + + if ( match[2] === "~=" ) { + match[3] = " " + match[3] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[1] = match[1].toLowerCase(); + + if ( match[1].slice( 0, 3 ) === "nth" ) { + // nth-* requires argument + if ( !match[3] ) { + Sizzle.error( match[0] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); + match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); + + // other types prohibit arguments + } else if ( match[3] ) { + Sizzle.error( match[0] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[6] && match[2]; + + if ( matchExpr["CHILD"].test( match[0] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[3] ) { + match[2] = match[4] || match[5] || ""; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + // Get excess from tokenize (recursively) + (excess = tokenize( unquoted, true )) && + // advance to the next closing parenthesis + (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { + + // excess is a negative index + match[0] = match[0].slice( 0, excess ); + match[2] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { return true; } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && + classCache( className, function( elem ) { + return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" ); + }); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + }; + }, + + "CHILD": function( type, what, argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, context, xml ) { + var cache, uniqueCache, outerCache, node, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType, + diff = false; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( (node = node[ dir ]) ) { + if ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) { + + return false; + } + } + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + + // Seek `elem` from a previously-cached index + + // ...in a gzip-friendly way + node = parent; + outerCache = node[ expando ] || (node[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + (outerCache[ node.uniqueID ] = {}); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex && cache[ 2 ]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( (node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + (diff = nodeIndex = 0) || start.pop()) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + } else { + // Use previously-cached element index if available + if ( useCache ) { + // ...in a gzip-friendly way + node = elem; + outerCache = node[ expando ] || (node[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + (outerCache[ node.uniqueID ] = {}); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex; + } + + // xml :nth-child(...) + // or :nth-last-child(...) or :nth(-last)?-of-type(...) + if ( diff === false ) { + // Use the same loop as above to seek `elem` from the start + while ( (node = ++nodeIndex && node && node[ dir ] || + (diff = nodeIndex = 0) || start.pop()) ) { + + if ( ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) && + ++diff ) { + + // Cache the index of each encountered element + if ( useCache ) { + outerCache = node[ expando ] || (node[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + (outerCache[ node.uniqueID ] = {}); + + uniqueCache[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction(function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf( seed, matched[i] ); + seed[ idx ] = !( matches[ idx ] = matched[i] ); + } + }) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + // Potentially complex pseudos + "not": markFunction(function( selector ) { + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction(function( seed, matches, context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( (elem = unmatched[i]) ) { + seed[i] = !(matches[i] = elem); + } + } + }) : + function( elem, context, xml ) { + input[0] = elem; + matcher( input, null, xml, results ); + // Don't keep the element (issue #299) + input[0] = null; + return !results.pop(); + }; + }), + + "has": markFunction(function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + }), + + "contains": markFunction(function( text ) { + text = text.replace( runescape, funescape ); + return function( elem ) { + return ( elem.textContent || getText( elem ) ).indexOf( text ) > -1; + }; + }), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + // lang value must be a valid identifier + if ( !ridentifier.test(lang || "") ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( (elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); + return false; + }; + }), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); + }, + + // Boolean properties + "enabled": createDisabledPseudo( false ), + "disabled": createDisabledPseudo( true ), + + "checked": function( elem ) { + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); + }, + + "selected": function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), + // but not by others (comment: 8; processing instruction: 7; etc.) + // nodeType < 6 works because attributes (2) do not appear as children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeType < 6 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos["empty"]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + + // Support: IE<8 + // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" + ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" ); + }, + + // Position-in-collection + "first": createPositionalPseudo(function() { + return [ 0 ]; + }), + + "last": createPositionalPseudo(function( matchIndexes, length ) { + return [ length - 1 ]; + }), + + "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + }), + + "even": createPositionalPseudo(function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "odd": createPositionalPseudo(function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? + argument + length : + argument > length ? + length : + argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }) + } +}; + +Expr.pseudos["nth"] = Expr.pseudos["eq"]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +tokenize = Sizzle.tokenize = function( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || (match = rcomma.exec( soFar )) ) { + if ( match ) { + // Don't consume trailing commas as valid + soFar = soFar.slice( match[0].length ) || soFar; + } + groups.push( (tokens = []) ); + } + + matched = false; + + // Combinators + if ( (match = rcombinators.exec( soFar )) ) { + matched = match.shift(); + tokens.push({ + value: matched, + // Cast descendant combinators to space + type: match[0].replace( rtrim, " " ) + }); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || + (match = preFilters[ type ]( match ))) ) { + matched = match.shift(); + tokens.push({ + value: matched, + type: type, + matches: match + }); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +}; + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[i].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + skip = combinator.next, + key = skip || dir, + checkNonElements = base && key === "parentNode", + doneName = done++; + + return combinator.first ? + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + return false; + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var oldCache, uniqueCache, outerCache, + newCache = [ dirruns, doneName ]; + + // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching + if ( xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || (elem[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {}); + + if ( skip && skip === elem.nodeName.toLowerCase() ) { + elem = elem[ dir ] || elem; + } else if ( (oldCache = uniqueCache[ key ]) && + oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { + + // Assign to newCache so results back-propagate to previous elements + return (newCache[ 2 ] = oldCache[ 2 ]); + } else { + // Reuse newcache so results back-propagate to previous elements + uniqueCache[ key ] = newCache; + + // A match means we're done; a fail means we have to keep checking + if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) { + return true; + } + } + } + } + } + return false; + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[i]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[0]; +} + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[i], results ); + } + return results; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( (elem = unmatched[i]) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction(function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( (elem = temp[i]) ) { + matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) ) { + // Restore matcherIn since elem is not yet a final match + temp.push( (matcherIn[i] = elem) ); + } + } + postFinder( null, (matcherOut = []), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) && + (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) { + + seed[temp] = !(results[temp] = elem); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + }); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[0].type ], + implicitRelative = leadingRelative || Expr.relative[" "], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + (checkContext = context).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + // Avoid hanging onto element (issue #299) + checkContext = null; + return ret; + } ]; + + for ( ; i < len; i++ ) { + if ( (matcher = Expr.relative[ tokens[i].type ]) ) { + matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; + } else { + matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[j].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + var bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, outermost ) { + var elem, j, matcher, + matchedCount = 0, + i = "0", + unmatched = seed && [], + setMatched = [], + contextBackup = outermostContext, + // We must always have either seed elements or outermost context + elems = seed || byElement && Expr.find["TAG"]( "*", outermost ), + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1), + len = elems.length; + + if ( outermost ) { + outermostContext = context === document || context || outermost; + } + + // Add elements passing elementMatchers directly to results + // Support: IE<9, Safari + // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id + for ( ; i !== len && (elem = elems[i]) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + if ( !context && elem.ownerDocument !== document ) { + setDocument( elem ); + xml = !documentIsHTML; + } + while ( (matcher = elementMatchers[j++]) ) { + if ( matcher( elem, context || document, xml) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + // They will have gone through all possible matchers + if ( (elem = !matcher && elem) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // `i` is now the count of elements visited above, and adding it to `matchedCount` + // makes the latter nonnegative. + matchedCount += i; + + // Apply set filters to unmatched elements + // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` + // equals `i`), unless we didn't visit _any_ elements in the above loop because we have + // no element matchers and no seed. + // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that + // case, which will result in a "00" `matchedCount` that differs from `i` but is also + // numerically zero. + if ( bySet && i !== matchedCount ) { + j = 0; + while ( (matcher = setMatchers[j++]) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !(unmatched[i] || setMatched[i]) ) { + setMatched[i] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + // Generate a function of recursive functions that can be used to check each element + if ( !match ) { + match = tokenize( selector ); + } + i = match.length; + while ( i-- ) { + cached = matcherFromTokens( match[i] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); + + // Save selector and tokenization + cached.selector = selector; + } + return cached; +}; + +/** + * A low-level selection function that works with Sizzle's compiled + * selector functions + * @param {String|Function} selector A selector or a pre-compiled + * selector function built with Sizzle.compile + * @param {Element} context + * @param {Array} [results] + * @param {Array} [seed] A set of elements to match against + */ +select = Sizzle.select = function( selector, context, results, seed ) { + var i, tokens, token, type, find, + compiled = typeof selector === "function" && selector, + match = !seed && tokenize( (selector = compiled.selector || selector) ); + + results = results || []; + + // Try to minimize operations if there is only one selector in the list and no seed + // (the latter of which guarantees us context) + if ( match.length === 1 ) { + + // Reduce context if the leading compound selector is an ID + tokens = match[0] = match[0].slice( 0 ); + if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && + context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[1].type ] ) { + + context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; + if ( !context ) { + return results; + + // Precompiled matchers will still verify ancestry, so step up a level + } else if ( compiled ) { + context = context.parentNode; + } + + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[i]; + + // Abort if we hit a combinator + if ( Expr.relative[ (type = token.type) ] ) { + break; + } + if ( (find = Expr.find[ type ]) ) { + // Search, expanding context for leading sibling combinators + if ( (seed = find( + token.matches[0].replace( runescape, funescape ), + rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context + )) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + + // Compile and execute a filtering function if one is not provided + // Provide `match` to avoid retokenization if we modified the selector above + ( compiled || compile( selector, match ) )( + seed, + context, + !documentIsHTML, + results, + !context || rsibling.test( selector ) && testContext( context.parentNode ) || context + ); + return results; +}; + +// One-time assignments + +// Sort stability +support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; + +// Support: Chrome 14-35+ +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = !!hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert(function( el ) { + // Should return 1, but returns 4 (following) + return el.compareDocumentPosition( document.createElement("fieldset") ) & 1; +}); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert(function( el ) { + el.innerHTML = ""; + return el.firstChild.getAttribute("href") === "#" ; +}) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + }); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert(function( el ) { + el.innerHTML = ""; + el.firstChild.setAttribute( "value", "" ); + return el.firstChild.getAttribute( "value" ) === ""; +}) ) { + addHandle( "value", function( elem, name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + }); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert(function( el ) { + return el.getAttribute("disabled") == null; +}) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return elem[ name ] === true ? name.toLowerCase() : + (val = elem.getAttributeNode( name )) && val.specified ? + val.value : + null; + } + }); +} + +return Sizzle; + +})( window ); + + + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; + +// Deprecated +jQuery.expr[ ":" ] = jQuery.expr.pseudos; +jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; +jQuery.escapeSelector = Sizzle.escape; + + + + +var dir = function( elem, dir, until ) { + var matched = [], + truncate = until !== undefined; + + while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { + if ( elem.nodeType === 1 ) { + if ( truncate && jQuery( elem ).is( until ) ) { + break; + } + matched.push( elem ); + } + } + return matched; +}; + + +var siblings = function( n, elem ) { + var matched = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + matched.push( n ); + } + } + + return matched; +}; + + +var rneedsContext = jQuery.expr.match.needsContext; + + + +function nodeName( elem, name ) { + + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + +}; +var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); + + + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + return !!qualifier.call( elem, i, elem ) !== not; + } ); + } + + // Single element + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + } ); + } + + // Arraylike of elements (jQuery, arguments, Array) + if ( typeof qualifier !== "string" ) { + return jQuery.grep( elements, function( elem ) { + return ( indexOf.call( qualifier, elem ) > -1 ) !== not; + } ); + } + + // Filtered directly for both simple and complex selectors + return jQuery.filter( qualifier, elements, not ); +} + +jQuery.filter = function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + if ( elems.length === 1 && elem.nodeType === 1 ) { + return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : []; + } + + return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + } ) ); +}; + +jQuery.fn.extend( { + find: function( selector ) { + var i, ret, + len = this.length, + self = this; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter( function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + } ) ); + } + + ret = this.pushStack( [] ); + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + return len > 1 ? jQuery.uniqueSort( ret ) : ret; + }, + filter: function( selector ) { + return this.pushStack( winnow( this, selector || [], false ) ); + }, + not: function( selector ) { + return this.pushStack( winnow( this, selector || [], true ) ); + }, + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + } +} ); + + +// Initialize a jQuery object + + +// A central reference to the root jQuery(document) +var rootjQuery, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + // Shortcut simple #id case for speed + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/, + + init = jQuery.fn.init = function( selector, context, root ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Method init() accepts an alternate rootjQuery + // so migrate can support jQuery.sub (gh-2101) + root = root || rootjQuery; + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector[ 0 ] === "<" && + selector[ selector.length - 1 ] === ">" && + selector.length >= 3 ) { + + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && ( match[ 1 ] || !context ) ) { + + // HANDLE: $(html) -> $(array) + if ( match[ 1 ] ) { + context = context instanceof jQuery ? context[ 0 ] : context; + + // Option to run scripts is true for back-compat + // Intentionally let the error be thrown if parseHTML is not present + jQuery.merge( this, jQuery.parseHTML( + match[ 1 ], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + + // Properties of context are called as methods if possible + if ( isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[ 2 ] ); + + if ( elem ) { + + // Inject the element directly into the jQuery object + this[ 0 ] = elem; + this.length = 1; + } + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || root ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this[ 0 ] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( isFunction( selector ) ) { + return root.ready !== undefined ? + root.ready( selector ) : + + // Execute immediately if ready is not present + selector( jQuery ); + } + + return jQuery.makeArray( selector, this ); + }; + +// Give the init function the jQuery prototype for later instantiation +init.prototype = jQuery.fn; + +// Initialize central reference +rootjQuery = jQuery( document ); + + +var rparentsprev = /^(?:parents|prev(?:Until|All))/, + + // Methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend( { + has: function( target ) { + var targets = jQuery( target, this ), + l = targets.length; + + return this.filter( function() { + var i = 0; + for ( ; i < l; i++ ) { + if ( jQuery.contains( this, targets[ i ] ) ) { + return true; + } + } + } ); + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + matched = [], + targets = typeof selectors !== "string" && jQuery( selectors ); + + // Positional selectors never match, since there's no _selection_ context + if ( !rneedsContext.test( selectors ) ) { + for ( ; i < l; i++ ) { + for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { + + // Always skip document fragments + if ( cur.nodeType < 11 && ( targets ? + targets.index( cur ) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector( cur, selectors ) ) ) { + + matched.push( cur ); + break; + } + } + } + } + + return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); + }, + + // Determine the position of an element within the set + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; + } + + // Index in selector + if ( typeof elem === "string" ) { + return indexOf.call( jQuery( elem ), this[ 0 ] ); + } + + // Locate the position of the desired element + return indexOf.call( this, + + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[ 0 ] : elem + ); + }, + + add: function( selector, context ) { + return this.pushStack( + jQuery.uniqueSort( + jQuery.merge( this.get(), jQuery( selector, context ) ) + ) + ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter( selector ) + ); + } +} ); + +function sibling( cur, dir ) { + while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {} + return cur; +} + +jQuery.each( { + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return siblings( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return siblings( elem.firstChild ); + }, + contents: function( elem ) { + if ( typeof elem.contentDocument !== "undefined" ) { + return elem.contentDocument; + } + + // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only + // Treat the template element as a regular one in browsers that + // don't support it. + if ( nodeName( elem, "template" ) ) { + elem = elem.content || elem; + } + + return jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var matched = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + matched = jQuery.filter( selector, matched ); + } + + if ( this.length > 1 ) { + + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + jQuery.uniqueSort( matched ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + matched.reverse(); + } + } + + return this.pushStack( matched ); + }; +} ); +var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g ); + + + +// Convert String-formatted options into Object-formatted ones +function createOptions( options ) { + var object = {}; + jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) { + object[ flag ] = true; + } ); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + createOptions( options ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + + // Last fire value for non-forgettable lists + memory, + + // Flag to know if list was already fired + fired, + + // Flag to prevent firing + locked, + + // Actual callback list + list = [], + + // Queue of execution data for repeatable lists + queue = [], + + // Index of currently firing callback (modified by add/remove as needed) + firingIndex = -1, + + // Fire callbacks + fire = function() { + + // Enforce single-firing + locked = locked || options.once; + + // Execute callbacks for all pending executions, + // respecting firingIndex overrides and runtime changes + fired = firing = true; + for ( ; queue.length; firingIndex = -1 ) { + memory = queue.shift(); + while ( ++firingIndex < list.length ) { + + // Run callback and check for early termination + if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && + options.stopOnFalse ) { + + // Jump to end and forget the data so .add doesn't re-fire + firingIndex = list.length; + memory = false; + } + } + } + + // Forget the data if we're done with it + if ( !options.memory ) { + memory = false; + } + + firing = false; + + // Clean up if we're done firing for good + if ( locked ) { + + // Keep an empty list if we have data for future add calls + if ( memory ) { + list = []; + + // Otherwise, this object is spent + } else { + list = ""; + } + } + }, + + // Actual Callbacks object + self = { + + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + + // If we have memory from a past run, we should fire after adding + if ( memory && !firing ) { + firingIndex = list.length - 1; + queue.push( memory ); + } + + ( function add( args ) { + jQuery.each( args, function( _, arg ) { + if ( isFunction( arg ) ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && toType( arg ) !== "string" ) { + + // Inspect recursively + add( arg ); + } + } ); + } )( arguments ); + + if ( memory && !firing ) { + fire(); + } + } + return this; + }, + + // Remove a callback from the list + remove: function() { + jQuery.each( arguments, function( _, arg ) { + var index; + while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + + // Handle firing indexes + if ( index <= firingIndex ) { + firingIndex--; + } + } + } ); + return this; + }, + + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? + jQuery.inArray( fn, list ) > -1 : + list.length > 0; + }, + + // Remove all callbacks from the list + empty: function() { + if ( list ) { + list = []; + } + return this; + }, + + // Disable .fire and .add + // Abort any current/pending executions + // Clear all callbacks and values + disable: function() { + locked = queue = []; + list = memory = ""; + return this; + }, + disabled: function() { + return !list; + }, + + // Disable .fire + // Also disable .add unless we have memory (since it would have no effect) + // Abort any pending executions + lock: function() { + locked = queue = []; + if ( !memory && !firing ) { + list = memory = ""; + } + return this; + }, + locked: function() { + return !!locked; + }, + + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( !locked ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + queue.push( args ); + if ( !firing ) { + fire(); + } + } + return this; + }, + + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; + + +function Identity( v ) { + return v; +} +function Thrower( ex ) { + throw ex; +} + +function adoptValue( value, resolve, reject, noValue ) { + var method; + + try { + + // Check for promise aspect first to privilege synchronous behavior + if ( value && isFunction( ( method = value.promise ) ) ) { + method.call( value ).done( resolve ).fail( reject ); + + // Other thenables + } else if ( value && isFunction( ( method = value.then ) ) ) { + method.call( value, resolve, reject ); + + // Other non-thenables + } else { + + // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer: + // * false: [ value ].slice( 0 ) => resolve( value ) + // * true: [ value ].slice( 1 ) => resolve() + resolve.apply( undefined, [ value ].slice( noValue ) ); + } + + // For Promises/A+, convert exceptions into rejections + // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in + // Deferred#then to conditionally suppress rejection. + } catch ( value ) { + + // Support: Android 4.0 only + // Strict mode functions invoked without .call/.apply get global-object context + reject.apply( undefined, [ value ] ); + } +} + +jQuery.extend( { + + Deferred: function( func ) { + var tuples = [ + + // action, add listener, callbacks, + // ... .then handlers, argument index, [final state] + [ "notify", "progress", jQuery.Callbacks( "memory" ), + jQuery.Callbacks( "memory" ), 2 ], + [ "resolve", "done", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 0, "resolved" ], + [ "reject", "fail", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 1, "rejected" ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + "catch": function( fn ) { + return promise.then( null, fn ); + }, + + // Keep pipe for back-compat + pipe: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + + return jQuery.Deferred( function( newDefer ) { + jQuery.each( tuples, function( i, tuple ) { + + // Map tuples (progress, done, fail) to arguments (done, fail, progress) + var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ]; + + // deferred.progress(function() { bind to newDefer or newDefer.notify }) + // deferred.done(function() { bind to newDefer or newDefer.resolve }) + // deferred.fail(function() { bind to newDefer or newDefer.reject }) + deferred[ tuple[ 1 ] ]( function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && isFunction( returned.promise ) ) { + returned.promise() + .progress( newDefer.notify ) + .done( newDefer.resolve ) + .fail( newDefer.reject ); + } else { + newDefer[ tuple[ 0 ] + "With" ]( + this, + fn ? [ returned ] : arguments + ); + } + } ); + } ); + fns = null; + } ).promise(); + }, + then: function( onFulfilled, onRejected, onProgress ) { + var maxDepth = 0; + function resolve( depth, deferred, handler, special ) { + return function() { + var that = this, + args = arguments, + mightThrow = function() { + var returned, then; + + // Support: Promises/A+ section 2.3.3.3.3 + // https://promisesaplus.com/#point-59 + // Ignore double-resolution attempts + if ( depth < maxDepth ) { + return; + } + + returned = handler.apply( that, args ); + + // Support: Promises/A+ section 2.3.1 + // https://promisesaplus.com/#point-48 + if ( returned === deferred.promise() ) { + throw new TypeError( "Thenable self-resolution" ); + } + + // Support: Promises/A+ sections 2.3.3.1, 3.5 + // https://promisesaplus.com/#point-54 + // https://promisesaplus.com/#point-75 + // Retrieve `then` only once + then = returned && + + // Support: Promises/A+ section 2.3.4 + // https://promisesaplus.com/#point-64 + // Only check objects and functions for thenability + ( typeof returned === "object" || + typeof returned === "function" ) && + returned.then; + + // Handle a returned thenable + if ( isFunction( then ) ) { + + // Special processors (notify) just wait for resolution + if ( special ) { + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ) + ); + + // Normal processors (resolve) also hook into progress + } else { + + // ...and disregard older resolution values + maxDepth++; + + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ), + resolve( maxDepth, deferred, Identity, + deferred.notifyWith ) + ); + } + + // Handle all other returned values + } else { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Identity ) { + that = undefined; + args = [ returned ]; + } + + // Process the value(s) + // Default process is resolve + ( special || deferred.resolveWith )( that, args ); + } + }, + + // Only normal processors (resolve) catch and reject exceptions + process = special ? + mightThrow : + function() { + try { + mightThrow(); + } catch ( e ) { + + if ( jQuery.Deferred.exceptionHook ) { + jQuery.Deferred.exceptionHook( e, + process.stackTrace ); + } + + // Support: Promises/A+ section 2.3.3.3.4.1 + // https://promisesaplus.com/#point-61 + // Ignore post-resolution exceptions + if ( depth + 1 >= maxDepth ) { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Thrower ) { + that = undefined; + args = [ e ]; + } + + deferred.rejectWith( that, args ); + } + } + }; + + // Support: Promises/A+ section 2.3.3.3.1 + // https://promisesaplus.com/#point-57 + // Re-resolve promises immediately to dodge false rejection from + // subsequent errors + if ( depth ) { + process(); + } else { + + // Call an optional hook to record the stack, in case of exception + // since it's otherwise lost when execution goes async + if ( jQuery.Deferred.getStackHook ) { + process.stackTrace = jQuery.Deferred.getStackHook(); + } + window.setTimeout( process ); + } + }; + } + + return jQuery.Deferred( function( newDefer ) { + + // progress_handlers.add( ... ) + tuples[ 0 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onProgress ) ? + onProgress : + Identity, + newDefer.notifyWith + ) + ); + + // fulfilled_handlers.add( ... ) + tuples[ 1 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onFulfilled ) ? + onFulfilled : + Identity + ) + ); + + // rejected_handlers.add( ... ) + tuples[ 2 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onRejected ) ? + onRejected : + Thrower + ) + ); + } ).promise(); + }, + + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 5 ]; + + // promise.progress = list.add + // promise.done = list.add + // promise.fail = list.add + promise[ tuple[ 1 ] ] = list.add; + + // Handle state + if ( stateString ) { + list.add( + function() { + + // state = "resolved" (i.e., fulfilled) + // state = "rejected" + state = stateString; + }, + + // rejected_callbacks.disable + // fulfilled_callbacks.disable + tuples[ 3 - i ][ 2 ].disable, + + // rejected_handlers.disable + // fulfilled_handlers.disable + tuples[ 3 - i ][ 3 ].disable, + + // progress_callbacks.lock + tuples[ 0 ][ 2 ].lock, + + // progress_handlers.lock + tuples[ 0 ][ 3 ].lock + ); + } + + // progress_handlers.fire + // fulfilled_handlers.fire + // rejected_handlers.fire + list.add( tuple[ 3 ].fire ); + + // deferred.notify = function() { deferred.notifyWith(...) } + // deferred.resolve = function() { deferred.resolveWith(...) } + // deferred.reject = function() { deferred.rejectWith(...) } + deferred[ tuple[ 0 ] ] = function() { + deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments ); + return this; + }; + + // deferred.notifyWith = list.fireWith + // deferred.resolveWith = list.fireWith + // deferred.rejectWith = list.fireWith + deferred[ tuple[ 0 ] + "With" ] = list.fireWith; + } ); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( singleValue ) { + var + + // count of uncompleted subordinates + remaining = arguments.length, + + // count of unprocessed arguments + i = remaining, + + // subordinate fulfillment data + resolveContexts = Array( i ), + resolveValues = slice.call( arguments ), + + // the master Deferred + master = jQuery.Deferred(), + + // subordinate callback factory + updateFunc = function( i ) { + return function( value ) { + resolveContexts[ i ] = this; + resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; + if ( !( --remaining ) ) { + master.resolveWith( resolveContexts, resolveValues ); + } + }; + }; + + // Single- and empty arguments are adopted like Promise.resolve + if ( remaining <= 1 ) { + adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject, + !remaining ); + + // Use .then() to unwrap secondary thenables (cf. gh-3000) + if ( master.state() === "pending" || + isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { + + return master.then(); + } + } + + // Multiple arguments are aggregated like Promise.all array elements + while ( i-- ) { + adoptValue( resolveValues[ i ], updateFunc( i ), master.reject ); + } + + return master.promise(); + } +} ); + + +// These usually indicate a programmer mistake during development, +// warn about them ASAP rather than swallowing them by default. +var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; + +jQuery.Deferred.exceptionHook = function( error, stack ) { + + // Support: IE 8 - 9 only + // Console exists when dev tools are open, which can happen at any time + if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) { + window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack ); + } +}; + + + + +jQuery.readyException = function( error ) { + window.setTimeout( function() { + throw error; + } ); +}; + + + + +// The deferred used on DOM ready +var readyList = jQuery.Deferred(); + +jQuery.fn.ready = function( fn ) { + + readyList + .then( fn ) + + // Wrap jQuery.readyException in a function so that the lookup + // happens at the time of error handling instead of callback + // registration. + .catch( function( error ) { + jQuery.readyException( error ); + } ); + + return this; +}; + +jQuery.extend( { + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + } +} ); + +jQuery.ready.then = readyList.then; + +// The ready event handler and self cleanup method +function completed() { + document.removeEventListener( "DOMContentLoaded", completed ); + window.removeEventListener( "load", completed ); + jQuery.ready(); +} + +// Catch cases where $(document).ready() is called +// after the browser event has already occurred. +// Support: IE <=9 - 10 only +// Older IE sometimes signals "interactive" too soon +if ( document.readyState === "complete" || + ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { + + // Handle it asynchronously to allow scripts the opportunity to delay ready + window.setTimeout( jQuery.ready ); + +} else { + + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed ); +} + + + + +// Multifunctional method to get and set values of a collection +// The value/s can optionally be executed if it's a function +var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + len = elems.length, + bulk = key == null; + + // Sets many values + if ( toType( key ) === "object" ) { + chainable = true; + for ( i in key ) { + access( elems, fn, i, key[ i ], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < len; i++ ) { + fn( + elems[ i ], key, raw ? + value : + value.call( elems[ i ], i, fn( elems[ i ], key ) ) + ); + } + } + } + + if ( chainable ) { + return elems; + } + + // Gets + if ( bulk ) { + return fn.call( elems ); + } + + return len ? fn( elems[ 0 ], key ) : emptyGet; +}; + + +// Matches dashed string for camelizing +var rmsPrefix = /^-ms-/, + rdashAlpha = /-([a-z])/g; + +// Used by camelCase as callback to replace() +function fcamelCase( all, letter ) { + return letter.toUpperCase(); +} + +// Convert dashed to camelCase; used by the css and data modules +// Support: IE <=9 - 11, Edge 12 - 15 +// Microsoft forgot to hump their vendor prefix (#9572) +function camelCase( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); +} +var acceptData = function( owner ) { + + // Accepts only: + // - Node + // - Node.ELEMENT_NODE + // - Node.DOCUMENT_NODE + // - Object + // - Any + return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); +}; + + + + +function Data() { + this.expando = jQuery.expando + Data.uid++; +} + +Data.uid = 1; + +Data.prototype = { + + cache: function( owner ) { + + // Check if the owner object already has a cache + var value = owner[ this.expando ]; + + // If not, create one + if ( !value ) { + value = {}; + + // We can accept data for non-element nodes in modern browsers, + // but we should not, see #8335. + // Always return an empty object. + if ( acceptData( owner ) ) { + + // If it is a node unlikely to be stringify-ed or looped over + // use plain assignment + if ( owner.nodeType ) { + owner[ this.expando ] = value; + + // Otherwise secure it in a non-enumerable property + // configurable must be true to allow the property to be + // deleted when data is removed + } else { + Object.defineProperty( owner, this.expando, { + value: value, + configurable: true + } ); + } + } + } + + return value; + }, + set: function( owner, data, value ) { + var prop, + cache = this.cache( owner ); + + // Handle: [ owner, key, value ] args + // Always use camelCase key (gh-2257) + if ( typeof data === "string" ) { + cache[ camelCase( data ) ] = value; + + // Handle: [ owner, { properties } ] args + } else { + + // Copy the properties one-by-one to the cache object + for ( prop in data ) { + cache[ camelCase( prop ) ] = data[ prop ]; + } + } + return cache; + }, + get: function( owner, key ) { + return key === undefined ? + this.cache( owner ) : + + // Always use camelCase key (gh-2257) + owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ]; + }, + access: function( owner, key, value ) { + + // In cases where either: + // + // 1. No key was specified + // 2. A string key was specified, but no value provided + // + // Take the "read" path and allow the get method to determine + // which value to return, respectively either: + // + // 1. The entire cache object + // 2. The data stored at the key + // + if ( key === undefined || + ( ( key && typeof key === "string" ) && value === undefined ) ) { + + return this.get( owner, key ); + } + + // When the key is not a string, or both a key and value + // are specified, set or extend (existing objects) with either: + // + // 1. An object of properties + // 2. A key and value + // + this.set( owner, key, value ); + + // Since the "set" path can have two possible entry points + // return the expected data based on which path was taken[*] + return value !== undefined ? value : key; + }, + remove: function( owner, key ) { + var i, + cache = owner[ this.expando ]; + + if ( cache === undefined ) { + return; + } + + if ( key !== undefined ) { + + // Support array or space separated string of keys + if ( Array.isArray( key ) ) { + + // If key is an array of keys... + // We always set camelCase keys, so remove that. + key = key.map( camelCase ); + } else { + key = camelCase( key ); + + // If a key with the spaces exists, use it. + // Otherwise, create an array by matching non-whitespace + key = key in cache ? + [ key ] : + ( key.match( rnothtmlwhite ) || [] ); + } + + i = key.length; + + while ( i-- ) { + delete cache[ key[ i ] ]; + } + } + + // Remove the expando if there's no more data + if ( key === undefined || jQuery.isEmptyObject( cache ) ) { + + // Support: Chrome <=35 - 45 + // Webkit & Blink performance suffers when deleting properties + // from DOM nodes, so set to undefined instead + // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted) + if ( owner.nodeType ) { + owner[ this.expando ] = undefined; + } else { + delete owner[ this.expando ]; + } + } + }, + hasData: function( owner ) { + var cache = owner[ this.expando ]; + return cache !== undefined && !jQuery.isEmptyObject( cache ); + } +}; +var dataPriv = new Data(); + +var dataUser = new Data(); + + + +// Implementation Summary +// +// 1. Enforce API surface and semantic compatibility with 1.9.x branch +// 2. Improve the module's maintainability by reducing the storage +// paths to a single mechanism. +// 3. Use the same single mechanism to support "private" and "user" data. +// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) +// 5. Avoid exposing implementation details on user objects (eg. expando properties) +// 6. Provide a clear path for implementation upgrade to WeakMap in 2014 + +var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, + rmultiDash = /[A-Z]/g; + +function getData( data ) { + if ( data === "true" ) { + return true; + } + + if ( data === "false" ) { + return false; + } + + if ( data === "null" ) { + return null; + } + + // Only convert to a number if it doesn't change the string + if ( data === +data + "" ) { + return +data; + } + + if ( rbrace.test( data ) ) { + return JSON.parse( data ); + } + + return data; +} + +function dataAttr( elem, key, data ) { + var name; + + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase(); + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = getData( data ); + } catch ( e ) {} + + // Make sure we set the data so it isn't changed later + dataUser.set( elem, key, data ); + } else { + data = undefined; + } + } + return data; +} + +jQuery.extend( { + hasData: function( elem ) { + return dataUser.hasData( elem ) || dataPriv.hasData( elem ); + }, + + data: function( elem, name, data ) { + return dataUser.access( elem, name, data ); + }, + + removeData: function( elem, name ) { + dataUser.remove( elem, name ); + }, + + // TODO: Now that all calls to _data and _removeData have been replaced + // with direct calls to dataPriv methods, these can be deprecated. + _data: function( elem, name, data ) { + return dataPriv.access( elem, name, data ); + }, + + _removeData: function( elem, name ) { + dataPriv.remove( elem, name ); + } +} ); + +jQuery.fn.extend( { + data: function( key, value ) { + var i, name, data, + elem = this[ 0 ], + attrs = elem && elem.attributes; + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = dataUser.get( elem ); + + if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) { + i = attrs.length; + while ( i-- ) { + + // Support: IE 11 only + // The attrs elements can be null (#14894) + if ( attrs[ i ] ) { + name = attrs[ i ].name; + if ( name.indexOf( "data-" ) === 0 ) { + name = camelCase( name.slice( 5 ) ); + dataAttr( elem, name, data[ name ] ); + } + } + } + dataPriv.set( elem, "hasDataAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each( function() { + dataUser.set( this, key ); + } ); + } + + return access( this, function( value ) { + var data; + + // The calling jQuery object (element matches) is not empty + // (and therefore has an element appears at this[ 0 ]) and the + // `value` parameter was not undefined. An empty jQuery object + // will result in `undefined` for elem = this[ 0 ] which will + // throw an exception if an attempt to read a data cache is made. + if ( elem && value === undefined ) { + + // Attempt to get data from the cache + // The key will always be camelCased in Data + data = dataUser.get( elem, key ); + if ( data !== undefined ) { + return data; + } + + // Attempt to "discover" the data in + // HTML5 custom data-* attrs + data = dataAttr( elem, key ); + if ( data !== undefined ) { + return data; + } + + // We tried really hard, but the data doesn't exist. + return; + } + + // Set the data... + this.each( function() { + + // We always store the camelCased key + dataUser.set( this, key, value ); + } ); + }, null, value, arguments.length > 1, null, true ); + }, + + removeData: function( key ) { + return this.each( function() { + dataUser.remove( this, key ); + } ); + } +} ); + + +jQuery.extend( { + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = dataPriv.get( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || Array.isArray( data ) ) { + queue = dataPriv.access( elem, type, jQuery.makeArray( data ) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // Clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // Not public - generate a queueHooks object, or return the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return dataPriv.get( elem, key ) || dataPriv.access( elem, key, { + empty: jQuery.Callbacks( "once memory" ).add( function() { + dataPriv.remove( elem, [ type + "queue", key ] ); + } ) + } ); + } +} ); + +jQuery.fn.extend( { + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[ 0 ], type ); + } + + return data === undefined ? + this : + this.each( function() { + var queue = jQuery.queue( this, type, data ); + + // Ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + } ); + }, + dequeue: function( type ) { + return this.each( function() { + jQuery.dequeue( this, type ); + } ); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while ( i-- ) { + tmp = dataPriv.get( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +} ); +var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; + +var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); + + +var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; + +var documentElement = document.documentElement; + + + + var isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ); + }, + composed = { composed: true }; + + // Support: IE 9 - 11+, Edge 12 - 18+, iOS 10.0 - 10.2 only + // Check attachment across shadow DOM boundaries when possible (gh-3504) + // Support: iOS 10.0-10.2 only + // Early iOS 10 versions support `attachShadow` but not `getRootNode`, + // leading to errors. We need to check for `getRootNode`. + if ( documentElement.getRootNode ) { + isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ) || + elem.getRootNode( composed ) === elem.ownerDocument; + }; + } +var isHiddenWithinTree = function( elem, el ) { + + // isHiddenWithinTree might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + + // Inline style trumps all + return elem.style.display === "none" || + elem.style.display === "" && + + // Otherwise, check computed style + // Support: Firefox <=43 - 45 + // Disconnected elements can have computed display: none, so first confirm that elem is + // in the document. + isAttached( elem ) && + + jQuery.css( elem, "display" ) === "none"; + }; + +var swap = function( elem, options, callback, args ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.apply( elem, args || [] ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; +}; + + + + +function adjustCSS( elem, prop, valueParts, tween ) { + var adjusted, scale, + maxIterations = 20, + currentValue = tween ? + function() { + return tween.cur(); + } : + function() { + return jQuery.css( elem, prop, "" ); + }, + initial = currentValue(), + unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), + + // Starting value computation is required for potential unit mismatches + initialInUnit = elem.nodeType && + ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && + rcssNum.exec( jQuery.css( elem, prop ) ); + + if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { + + // Support: Firefox <=54 + // Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144) + initial = initial / 2; + + // Trust units reported by jQuery.css + unit = unit || initialInUnit[ 3 ]; + + // Iteratively approximate from a nonzero starting point + initialInUnit = +initial || 1; + + while ( maxIterations-- ) { + + // Evaluate and update our best guess (doubling guesses that zero out). + // Finish if the scale equals or crosses 1 (making the old*new product non-positive). + jQuery.style( elem, prop, initialInUnit + unit ); + if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) { + maxIterations = 0; + } + initialInUnit = initialInUnit / scale; + + } + + initialInUnit = initialInUnit * 2; + jQuery.style( elem, prop, initialInUnit + unit ); + + // Make sure we update the tween properties later on + valueParts = valueParts || []; + } + + if ( valueParts ) { + initialInUnit = +initialInUnit || +initial || 0; + + // Apply relative offset (+=/-=) if specified + adjusted = valueParts[ 1 ] ? + initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : + +valueParts[ 2 ]; + if ( tween ) { + tween.unit = unit; + tween.start = initialInUnit; + tween.end = adjusted; + } + } + return adjusted; +} + + +var defaultDisplayMap = {}; + +function getDefaultDisplay( elem ) { + var temp, + doc = elem.ownerDocument, + nodeName = elem.nodeName, + display = defaultDisplayMap[ nodeName ]; + + if ( display ) { + return display; + } + + temp = doc.body.appendChild( doc.createElement( nodeName ) ); + display = jQuery.css( temp, "display" ); + + temp.parentNode.removeChild( temp ); + + if ( display === "none" ) { + display = "block"; + } + defaultDisplayMap[ nodeName ] = display; + + return display; +} + +function showHide( elements, show ) { + var display, elem, + values = [], + index = 0, + length = elements.length; + + // Determine new display value for elements that need to change + for ( ; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + + display = elem.style.display; + if ( show ) { + + // Since we force visibility upon cascade-hidden elements, an immediate (and slow) + // check is required in this first loop unless we have a nonempty display value (either + // inline or about-to-be-restored) + if ( display === "none" ) { + values[ index ] = dataPriv.get( elem, "display" ) || null; + if ( !values[ index ] ) { + elem.style.display = ""; + } + } + if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) { + values[ index ] = getDefaultDisplay( elem ); + } + } else { + if ( display !== "none" ) { + values[ index ] = "none"; + + // Remember what we're overwriting + dataPriv.set( elem, "display", display ); + } + } + } + + // Set the display of the elements in a second loop to avoid constant reflow + for ( index = 0; index < length; index++ ) { + if ( values[ index ] != null ) { + elements[ index ].style.display = values[ index ]; + } + } + + return elements; +} + +jQuery.fn.extend( { + show: function() { + return showHide( this, true ); + }, + hide: function() { + return showHide( this ); + }, + toggle: function( state ) { + if ( typeof state === "boolean" ) { + return state ? this.show() : this.hide(); + } + + return this.each( function() { + if ( isHiddenWithinTree( this ) ) { + jQuery( this ).show(); + } else { + jQuery( this ).hide(); + } + } ); + } +} ); +var rcheckableType = ( /^(?:checkbox|radio)$/i ); + +var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]*)/i ); + +var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i ); + + + +// We have to close these tags to support XHTML (#13200) +var wrapMap = { + + // Support: IE <=9 only + option: [ 1, "" ], + + // XHTML parsers do not magically insert elements in the + // same way that tag soup parsers do. So we cannot shorten + // this by omitting

        ", "
        " ], + col: [ 2, "", "
        " ], + tr: [ 2, "", "
        " ], + td: [ 3, "", "
        " ], + + _default: [ 0, "", "" ] +}; + +// Support: IE <=9 only +wrapMap.optgroup = wrapMap.option; + +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + + +function getAll( context, tag ) { + + // Support: IE <=9 - 11 only + // Use typeof to avoid zero-argument method invocation on host objects (#15151) + var ret; + + if ( typeof context.getElementsByTagName !== "undefined" ) { + ret = context.getElementsByTagName( tag || "*" ); + + } else if ( typeof context.querySelectorAll !== "undefined" ) { + ret = context.querySelectorAll( tag || "*" ); + + } else { + ret = []; + } + + if ( tag === undefined || tag && nodeName( context, tag ) ) { + return jQuery.merge( [ context ], ret ); + } + + return ret; +} + + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + dataPriv.set( + elems[ i ], + "globalEval", + !refElements || dataPriv.get( refElements[ i ], "globalEval" ) + ); + } +} + + +var rhtml = /<|&#?\w+;/; + +function buildFragment( elems, context, scripts, selection, ignored ) { + var elem, tmp, tag, wrap, attached, j, + fragment = context.createDocumentFragment(), + nodes = [], + i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( toType( elem ) === "object" ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || fragment.appendChild( context.createElement( "div" ) ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; + + // Descend through wrappers to the right content + j = wrap[ 0 ]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, tmp.childNodes ); + + // Remember the top-level container + tmp = fragment.firstChild; + + // Ensure the created nodes are orphaned (#12392) + tmp.textContent = ""; + } + } + } + + // Remove wrapper from fragment + fragment.textContent = ""; + + i = 0; + while ( ( elem = nodes[ i++ ] ) ) { + + // Skip elements already in the context collection (trac-4087) + if ( selection && jQuery.inArray( elem, selection ) > -1 ) { + if ( ignored ) { + ignored.push( elem ); + } + continue; + } + + attached = isAttached( elem ); + + // Append to fragment + tmp = getAll( fragment.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( attached ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( ( elem = tmp[ j++ ] ) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + return fragment; +} + + +( function() { + var fragment = document.createDocumentFragment(), + div = fragment.appendChild( document.createElement( "div" ) ), + input = document.createElement( "input" ); + + // Support: Android 4.0 - 4.3 only + // Check state lost if the name is set (#11217) + // Support: Windows Web Apps (WWA) + // `name` and `type` must use .setAttribute for WWA (#14901) + input.setAttribute( "type", "radio" ); + input.setAttribute( "checked", "checked" ); + input.setAttribute( "name", "t" ); + + div.appendChild( input ); + + // Support: Android <=4.1 only + // Older WebKit doesn't clone checked state correctly in fragments + support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE <=11 only + // Make sure textarea (and checkbox) defaultValue is properly cloned + div.innerHTML = ""; + support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; +} )(); + + +var + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +// Support: IE <=9 - 11+ +// focus() and blur() are asynchronous, except when they are no-op. +// So expect focus to be synchronous when the element is already active, +// and blur to be synchronous when the element is not already active. +// (focus and blur are always synchronous in other supported browsers, +// this just defines when we can count on it). +function expectSync( elem, type ) { + return ( elem === safeActiveElement() ) === ( type === "focus" ); +} + +// Support: IE <=9 only +// Accessing document.activeElement can throw unexpectedly +// https://bugs.jquery.com/ticket/13393 +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +function on( elem, types, selector, data, fn, one ) { + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + on( elem, type, selector, data, types[ type ], one ); + } + return elem; + } + + if ( data == null && fn == null ) { + + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return elem; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return elem.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + } ); +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + + var handleObjIn, eventHandle, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.get( elem ); + + // Don't attach events to noData or text/comment nodes (but allow plain objects) + if ( !elemData ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Ensure that invalid selectors throw exceptions at attach time + // Evaluate against documentElement in case elem is a non-element node (e.g., document) + if ( selector ) { + jQuery.find.matchesSelector( documentElement, selector ); + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !( events = elemData.events ) ) { + events = elemData.events = {}; + } + if ( !( eventHandle = elemData.handle ) ) { + eventHandle = elemData.handle = function( e ) { + + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? + jQuery.event.dispatch.apply( elem, arguments ) : undefined; + }; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend( { + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join( "." ) + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !( handlers = events[ type ] ) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener if the special events handler returns false + if ( !special.setup || + special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + + var j, origCount, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); + + if ( !elemData || !( events = elemData.events ) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[ 2 ] && + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || + selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || + special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove data and the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + dataPriv.remove( elem, "handle events" ); + } + }, + + dispatch: function( nativeEvent ) { + + // Make a writable jQuery.Event from the native event object + var event = jQuery.event.fix( nativeEvent ); + + var i, j, ret, matched, handleObj, handlerQueue, + args = new Array( arguments.length ), + handlers = ( dataPriv.get( this, "events" ) || {} )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[ 0 ] = event; + + for ( i = 1; i < arguments.length; i++ ) { + args[ i ] = arguments[ i ]; + } + + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( ( handleObj = matched.handlers[ j++ ] ) && + !event.isImmediatePropagationStopped() ) { + + // If the event is namespaced, then each handler is only invoked if it is + // specially universal or its namespaces are a superset of the event's. + if ( !event.rnamespace || handleObj.namespace === false || + event.rnamespace.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || + handleObj.handler ).apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( ( event.result = ret ) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var i, handleObj, sel, matchedHandlers, matchedSelectors, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + if ( delegateCount && + + // Support: IE <=9 + // Black-hole SVG instance trees (trac-13180) + cur.nodeType && + + // Support: Firefox <=42 + // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) + // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click + // Support: IE 11 only + // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) + !( event.type === "click" && event.button >= 1 ) ) { + + for ( ; cur !== this; cur = cur.parentNode || this ) { + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) { + matchedHandlers = []; + matchedSelectors = {}; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matchedSelectors[ sel ] === undefined ) { + matchedSelectors[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) > -1 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matchedSelectors[ sel ] ) { + matchedHandlers.push( handleObj ); + } + } + if ( matchedHandlers.length ) { + handlerQueue.push( { elem: cur, handlers: matchedHandlers } ); + } + } + } + } + + // Add the remaining (directly-bound) handlers + cur = this; + if ( delegateCount < handlers.length ) { + handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } ); + } + + return handlerQueue; + }, + + addProp: function( name, hook ) { + Object.defineProperty( jQuery.Event.prototype, name, { + enumerable: true, + configurable: true, + + get: isFunction( hook ) ? + function() { + if ( this.originalEvent ) { + return hook( this.originalEvent ); + } + } : + function() { + if ( this.originalEvent ) { + return this.originalEvent[ name ]; + } + }, + + set: function( value ) { + Object.defineProperty( this, name, { + enumerable: true, + configurable: true, + writable: true, + value: value + } ); + } + } ); + }, + + fix: function( originalEvent ) { + return originalEvent[ jQuery.expando ] ? + originalEvent : + new jQuery.Event( originalEvent ); + }, + + special: { + load: { + + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + click: { + + // Utilize native event to ensure correct state for checkable inputs + setup: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Claim the first handler + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + // dataPriv.set( el, "click", ... ) + leverageNative( el, "click", returnTrue ); + } + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Force setup before triggering a click + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + leverageNative( el, "click" ); + } + + // Return non-false to allow normal event-path propagation + return true; + }, + + // For cross-browser consistency, suppress native .click() on links + // Also prevent it if we're currently inside a leveraged native-event stack + _default: function( event ) { + var target = event.target; + return rcheckableType.test( target.type ) && + target.click && nodeName( target, "input" ) && + dataPriv.get( target, "click" ) || + nodeName( target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Support: Firefox 20+ + // Firefox doesn't alert if the returnValue field is not set. + if ( event.result !== undefined && event.originalEvent ) { + event.originalEvent.returnValue = event.result; + } + } + } + } +}; + +// Ensure the presence of an event listener that handles manually-triggered +// synthetic events by interrupting progress until reinvoked in response to +// *native* events that it fires directly, ensuring that state changes have +// already occurred before other listeners are invoked. +function leverageNative( el, type, expectSync ) { + + // Missing expectSync indicates a trigger call, which must force setup through jQuery.event.add + if ( !expectSync ) { + if ( dataPriv.get( el, type ) === undefined ) { + jQuery.event.add( el, type, returnTrue ); + } + return; + } + + // Register the controller as a special universal handler for all event namespaces + dataPriv.set( el, type, false ); + jQuery.event.add( el, type, { + namespace: false, + handler: function( event ) { + var notAsync, result, + saved = dataPriv.get( this, type ); + + if ( ( event.isTrigger & 1 ) && this[ type ] ) { + + // Interrupt processing of the outer synthetic .trigger()ed event + // Saved data should be false in such cases, but might be a leftover capture object + // from an async native handler (gh-4350) + if ( !saved.length ) { + + // Store arguments for use when handling the inner native event + // There will always be at least one argument (an event object), so this array + // will not be confused with a leftover capture object. + saved = slice.call( arguments ); + dataPriv.set( this, type, saved ); + + // Trigger the native event and capture its result + // Support: IE <=9 - 11+ + // focus() and blur() are asynchronous + notAsync = expectSync( this, type ); + this[ type ](); + result = dataPriv.get( this, type ); + if ( saved !== result || notAsync ) { + dataPriv.set( this, type, false ); + } else { + result = {}; + } + if ( saved !== result ) { + + // Cancel the outer synthetic event + event.stopImmediatePropagation(); + event.preventDefault(); + return result.value; + } + + // If this is an inner synthetic event for an event with a bubbling surrogate + // (focus or blur), assume that the surrogate already propagated from triggering the + // native event and prevent that from happening again here. + // This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the + // bubbling surrogate propagates *after* the non-bubbling base), but that seems + // less bad than duplication. + } else if ( ( jQuery.event.special[ type ] || {} ).delegateType ) { + event.stopPropagation(); + } + + // If this is a native event triggered above, everything is now in order + // Fire an inner synthetic event with the original arguments + } else if ( saved.length ) { + + // ...and capture the result + dataPriv.set( this, type, { + value: jQuery.event.trigger( + + // Support: IE <=9 - 11+ + // Extend with the prototype to reset the above stopImmediatePropagation() + jQuery.extend( saved[ 0 ], jQuery.Event.prototype ), + saved.slice( 1 ), + this + ) + } ); + + // Abort handling of the native event + event.stopImmediatePropagation(); + } + } + } ); +} + +jQuery.removeEvent = function( elem, type, handle ) { + + // This "if" is needed for plain objects + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle ); + } +}; + +jQuery.Event = function( src, props ) { + + // Allow instantiation without the 'new' keyword + if ( !( this instanceof jQuery.Event ) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = src.defaultPrevented || + src.defaultPrevented === undefined && + + // Support: Android <=2.3 only + src.returnValue === false ? + returnTrue : + returnFalse; + + // Create target properties + // Support: Safari <=6 - 7 only + // Target should not be a text node (#504, #13143) + this.target = ( src.target && src.target.nodeType === 3 ) ? + src.target.parentNode : + src.target; + + this.currentTarget = src.currentTarget; + this.relatedTarget = src.relatedTarget; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || Date.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + constructor: jQuery.Event, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + isSimulated: false, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + + if ( e && !this.isSimulated ) { + e.preventDefault(); + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopPropagation(); + } + }, + stopImmediatePropagation: function() { + var e = this.originalEvent; + + this.isImmediatePropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopImmediatePropagation(); + } + + this.stopPropagation(); + } +}; + +// Includes all common event props including KeyEvent and MouseEvent specific props +jQuery.each( { + altKey: true, + bubbles: true, + cancelable: true, + changedTouches: true, + ctrlKey: true, + detail: true, + eventPhase: true, + metaKey: true, + pageX: true, + pageY: true, + shiftKey: true, + view: true, + "char": true, + code: true, + charCode: true, + key: true, + keyCode: true, + button: true, + buttons: true, + clientX: true, + clientY: true, + offsetX: true, + offsetY: true, + pointerId: true, + pointerType: true, + screenX: true, + screenY: true, + targetTouches: true, + toElement: true, + touches: true, + + which: function( event ) { + var button = event.button; + + // Add which for key events + if ( event.which == null && rkeyEvent.test( event.type ) ) { + return event.charCode != null ? event.charCode : event.keyCode; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) { + if ( button & 1 ) { + return 1; + } + + if ( button & 2 ) { + return 3; + } + + if ( button & 4 ) { + return 2; + } + + return 0; + } + + return event.which; + } +}, jQuery.event.addProp ); + +jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) { + jQuery.event.special[ type ] = { + + // Utilize native event if possible so blur/focus sequence is correct + setup: function() { + + // Claim the first handler + // dataPriv.set( this, "focus", ... ) + // dataPriv.set( this, "blur", ... ) + leverageNative( this, type, expectSync ); + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function() { + + // Force setup before trigger + leverageNative( this, type ); + + // Return non-false to allow normal event-path propagation + return true; + }, + + delegateType: delegateType + }; +} ); + +// Create mouseenter/leave events using mouseover/out and event-time checks +// so that event delegation works in jQuery. +// Do the same for pointerenter/pointerleave and pointerover/pointerout +// +// Support: Safari 7 only +// Safari sends mouseenter too often; see: +// https://bugs.chromium.org/p/chromium/issues/detail?id=470258 +// for the description of the bug (it existed in older Chrome versions as well). +jQuery.each( { + mouseenter: "mouseover", + mouseleave: "mouseout", + pointerenter: "pointerover", + pointerleave: "pointerout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mouseenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +} ); + +jQuery.fn.extend( { + + on: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn ); + }, + one: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? + handleObj.origType + "." + handleObj.namespace : + handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each( function() { + jQuery.event.remove( this, types, fn, selector ); + } ); + } +} ); + + +var + + /* eslint-disable max-len */ + + // See https://github.com/eslint/eslint/issues/3229 + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi, + + /* eslint-enable */ + + // Support: IE <=10 - 11, Edge 12 - 13 only + // In IE/Edge using regex groups here causes severe slowdowns. + // See https://connect.microsoft.com/IE/feedback/details/1736512/ + rnoInnerhtml = /\s*$/g; + +// Prefer a tbody over its parent table for containing new rows +function manipulationTarget( elem, content ) { + if ( nodeName( elem, "table" ) && + nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) { + + return jQuery( elem ).children( "tbody" )[ 0 ] || elem; + } + + return elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) { + elem.type = elem.type.slice( 5 ); + } else { + elem.removeAttribute( "type" ); + } + + return elem; +} + +function cloneCopyEvent( src, dest ) { + var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events; + + if ( dest.nodeType !== 1 ) { + return; + } + + // 1. Copy private data: events, handlers, etc. + if ( dataPriv.hasData( src ) ) { + pdataOld = dataPriv.access( src ); + pdataCur = dataPriv.set( dest, pdataOld ); + events = pdataOld.events; + + if ( events ) { + delete pdataCur.handle; + pdataCur.events = {}; + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + } + + // 2. Copy user data + if ( dataUser.hasData( src ) ) { + udataOld = dataUser.access( src ); + udataCur = jQuery.extend( {}, udataOld ); + + dataUser.set( dest, udataCur ); + } +} + +// Fix IE bugs, see support tests +function fixInput( src, dest ) { + var nodeName = dest.nodeName.toLowerCase(); + + // Fails to persist the checked state of a cloned checkbox or radio button. + if ( nodeName === "input" && rcheckableType.test( src.type ) ) { + dest.checked = src.checked; + + // Fails to return the selected option to the default selected state when cloning options + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +function domManip( collection, args, callback, ignored ) { + + // Flatten any nested arrays + args = concat.apply( [], args ); + + var fragment, first, scripts, hasScripts, node, doc, + i = 0, + l = collection.length, + iNoClone = l - 1, + value = args[ 0 ], + valueIsFunction = isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( valueIsFunction || + ( l > 1 && typeof value === "string" && + !support.checkClone && rchecked.test( value ) ) ) { + return collection.each( function( index ) { + var self = collection.eq( index ); + if ( valueIsFunction ) { + args[ 0 ] = value.call( this, index, self.html() ); + } + domManip( self, args, callback, ignored ); + } ); + } + + if ( l ) { + fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + // Require either new content or an interest in ignored elements to invoke the callback + if ( first || ignored ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item + // instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( collection[ i ], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !dataPriv.access( node, "globalEval" ) && + jQuery.contains( doc, node ) ) { + + if ( node.src && ( node.type || "" ).toLowerCase() !== "module" ) { + + // Optional AJAX dependency, but won't run scripts if not present + if ( jQuery._evalUrl && !node.noModule ) { + jQuery._evalUrl( node.src, { + nonce: node.nonce || node.getAttribute( "nonce" ) + } ); + } + } else { + DOMEval( node.textContent.replace( rcleanScript, "" ), node, doc ); + } + } + } + } + } + } + + return collection; +} + +function remove( elem, selector, keepData ) { + var node, + nodes = selector ? jQuery.filter( selector, elem ) : elem, + i = 0; + + for ( ; ( node = nodes[ i ] ) != null; i++ ) { + if ( !keepData && node.nodeType === 1 ) { + jQuery.cleanData( getAll( node ) ); + } + + if ( node.parentNode ) { + if ( keepData && isAttached( node ) ) { + setGlobalEval( getAll( node, "script" ) ); + } + node.parentNode.removeChild( node ); + } + } + + return elem; +} + +jQuery.extend( { + htmlPrefilter: function( html ) { + return html.replace( rxhtmlTag, "<$1>" ); + }, + + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var i, l, srcElements, destElements, + clone = elem.cloneNode( true ), + inPage = isAttached( elem ); + + // Fix IE cloning issues + if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && + !jQuery.isXMLDoc( elem ) ) { + + // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + fixInput( srcElements[ i ], destElements[ i ] ); + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + cloneCopyEvent( srcElements[ i ], destElements[ i ] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + // Return the cloned set + return clone; + }, + + cleanData: function( elems ) { + var data, elem, type, + special = jQuery.event.special, + i = 0; + + for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) { + if ( acceptData( elem ) ) { + if ( ( data = elem[ dataPriv.expando ] ) ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataPriv.expando ] = undefined; + } + if ( elem[ dataUser.expando ] ) { + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataUser.expando ] = undefined; + } + } + } + } +} ); + +jQuery.fn.extend( { + detach: function( selector ) { + return remove( this, selector, true ); + }, + + remove: function( selector ) { + return remove( this, selector ); + }, + + text: function( value ) { + return access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().each( function() { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + this.textContent = value; + } + } ); + }, null, value, arguments.length ); + }, + + append: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + } ); + }, + + prepend: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + } ); + }, + + before: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + } ); + }, + + after: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + } ); + }, + + empty: function() { + var elem, + i = 0; + + for ( ; ( elem = this[ i ] ) != null; i++ ) { + if ( elem.nodeType === 1 ) { + + // Prevent memory leaks + jQuery.cleanData( getAll( elem, false ) ); + + // Remove any remaining nodes + elem.textContent = ""; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function() { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + } ); + }, + + html: function( value ) { + return access( this, function( value ) { + var elem = this[ 0 ] || {}, + i = 0, + l = this.length; + + if ( value === undefined && elem.nodeType === 1 ) { + return elem.innerHTML; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { + + value = jQuery.htmlPrefilter( value ); + + try { + for ( ; i < l; i++ ) { + elem = this[ i ] || {}; + + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch ( e ) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var ignored = []; + + // Make the changes, replacing each non-ignored context element with the new content + return domManip( this, arguments, function( elem ) { + var parent = this.parentNode; + + if ( jQuery.inArray( this, ignored ) < 0 ) { + jQuery.cleanData( getAll( this ) ); + if ( parent ) { + parent.replaceChild( elem, this ); + } + } + + // Force callback invocation + }, ignored ); + } +} ); + +jQuery.each( { + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1, + i = 0; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone( true ); + jQuery( insert[ i ] )[ original ]( elems ); + + // Support: Android <=4.0 only, PhantomJS 1 only + // .get() because push.apply(_, arraylike) throws on ancient WebKit + push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +} ); +var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); + +var getStyles = function( elem ) { + + // Support: IE <=11 only, Firefox <=30 (#15098, #14150) + // IE throws on elements created in popups + // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" + var view = elem.ownerDocument.defaultView; + + if ( !view || !view.opener ) { + view = window; + } + + return view.getComputedStyle( elem ); + }; + +var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); + + + +( function() { + + // Executing both pixelPosition & boxSizingReliable tests require only one layout + // so they're executed at the same time to save the second computation. + function computeStyleTests() { + + // This is a singleton, we need to execute it only once + if ( !div ) { + return; + } + + container.style.cssText = "position:absolute;left:-11111px;width:60px;" + + "margin-top:1px;padding:0;border:0"; + div.style.cssText = + "position:relative;display:block;box-sizing:border-box;overflow:scroll;" + + "margin:auto;border:1px;padding:1px;" + + "width:60%;top:1%"; + documentElement.appendChild( container ).appendChild( div ); + + var divStyle = window.getComputedStyle( div ); + pixelPositionVal = divStyle.top !== "1%"; + + // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44 + reliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12; + + // Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3 + // Some styles come back with percentage values, even though they shouldn't + div.style.right = "60%"; + pixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36; + + // Support: IE 9 - 11 only + // Detect misreporting of content dimensions for box-sizing:border-box elements + boxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36; + + // Support: IE 9 only + // Detect overflow:scroll screwiness (gh-3699) + // Support: Chrome <=64 + // Don't get tricked when zoom affects offsetWidth (gh-4029) + div.style.position = "absolute"; + scrollboxSizeVal = roundPixelMeasures( div.offsetWidth / 3 ) === 12; + + documentElement.removeChild( container ); + + // Nullify the div so it wouldn't be stored in the memory and + // it will also be a sign that checks already performed + div = null; + } + + function roundPixelMeasures( measure ) { + return Math.round( parseFloat( measure ) ); + } + + var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal, + reliableMarginLeftVal, + container = document.createElement( "div" ), + div = document.createElement( "div" ); + + // Finish early in limited (non-browser) environments + if ( !div.style ) { + return; + } + + // Support: IE <=9 - 11 only + // Style of cloned element affects source element cloned (#8908) + div.style.backgroundClip = "content-box"; + div.cloneNode( true ).style.backgroundClip = ""; + support.clearCloneStyle = div.style.backgroundClip === "content-box"; + + jQuery.extend( support, { + boxSizingReliable: function() { + computeStyleTests(); + return boxSizingReliableVal; + }, + pixelBoxStyles: function() { + computeStyleTests(); + return pixelBoxStylesVal; + }, + pixelPosition: function() { + computeStyleTests(); + return pixelPositionVal; + }, + reliableMarginLeft: function() { + computeStyleTests(); + return reliableMarginLeftVal; + }, + scrollboxSize: function() { + computeStyleTests(); + return scrollboxSizeVal; + } + } ); +} )(); + + +function curCSS( elem, name, computed ) { + var width, minWidth, maxWidth, ret, + + // Support: Firefox 51+ + // Retrieving style before computed somehow + // fixes an issue with getting wrong values + // on detached elements + style = elem.style; + + computed = computed || getStyles( elem ); + + // getPropertyValue is needed for: + // .css('filter') (IE 9 only, #12537) + // .css('--customProperty) (#3144) + if ( computed ) { + ret = computed.getPropertyValue( name ) || computed[ name ]; + + if ( ret === "" && !isAttached( elem ) ) { + ret = jQuery.style( elem, name ); + } + + // A tribute to the "awesome hack by Dean Edwards" + // Android Browser returns percentage for some values, + // but width seems to be reliably pixels. + // This is against the CSSOM draft spec: + // https://drafts.csswg.org/cssom/#resolved-values + if ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) { + + // Remember the original values + width = style.width; + minWidth = style.minWidth; + maxWidth = style.maxWidth; + + // Put in the new values to get a computed value out + style.minWidth = style.maxWidth = style.width = ret; + ret = computed.width; + + // Revert the changed values + style.width = width; + style.minWidth = minWidth; + style.maxWidth = maxWidth; + } + } + + return ret !== undefined ? + + // Support: IE <=9 - 11 only + // IE returns zIndex value as an integer. + ret + "" : + ret; +} + + +function addGetHookIf( conditionFn, hookFn ) { + + // Define the hook, we'll check on the first run if it's really needed. + return { + get: function() { + if ( conditionFn() ) { + + // Hook not needed (or it's not possible to use it due + // to missing dependency), remove it. + delete this.get; + return; + } + + // Hook needed; redefine it so that the support test is not executed again. + return ( this.get = hookFn ).apply( this, arguments ); + } + }; +} + + +var cssPrefixes = [ "Webkit", "Moz", "ms" ], + emptyStyle = document.createElement( "div" ).style, + vendorProps = {}; + +// Return a vendor-prefixed property or undefined +function vendorPropName( name ) { + + // Check for vendor prefixed names + var capName = name[ 0 ].toUpperCase() + name.slice( 1 ), + i = cssPrefixes.length; + + while ( i-- ) { + name = cssPrefixes[ i ] + capName; + if ( name in emptyStyle ) { + return name; + } + } +} + +// Return a potentially-mapped jQuery.cssProps or vendor prefixed property +function finalPropName( name ) { + var final = jQuery.cssProps[ name ] || vendorProps[ name ]; + + if ( final ) { + return final; + } + if ( name in emptyStyle ) { + return name; + } + return vendorProps[ name ] = vendorPropName( name ) || name; +} + + +var + + // Swappable if display is none or starts with table + // except "table", "table-cell", or "table-caption" + // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display + rdisplayswap = /^(none|table(?!-c[ea]).+)/, + rcustomProp = /^--/, + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssNormalTransform = { + letterSpacing: "0", + fontWeight: "400" + }; + +function setPositiveNumber( elem, value, subtract ) { + + // Any relative (+/-) values have already been + // normalized at this point + var matches = rcssNum.exec( value ); + return matches ? + + // Guard against undefined "subtract", e.g., when used as in cssHooks + Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) : + value; +} + +function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) { + var i = dimension === "width" ? 1 : 0, + extra = 0, + delta = 0; + + // Adjustment may not be necessary + if ( box === ( isBorderBox ? "border" : "content" ) ) { + return 0; + } + + for ( ; i < 4; i += 2 ) { + + // Both box models exclude margin + if ( box === "margin" ) { + delta += jQuery.css( elem, box + cssExpand[ i ], true, styles ); + } + + // If we get here with a content-box, we're seeking "padding" or "border" or "margin" + if ( !isBorderBox ) { + + // Add padding + delta += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + + // For "border" or "margin", add border + if ( box !== "padding" ) { + delta += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + + // But still keep track of it otherwise + } else { + extra += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + + // If we get here with a border-box (content + padding + border), we're seeking "content" or + // "padding" or "margin" + } else { + + // For "content", subtract padding + if ( box === "content" ) { + delta -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + } + + // For "content" or "padding", subtract border + if ( box !== "margin" ) { + delta -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } + } + + // Account for positive content-box scroll gutter when requested by providing computedVal + if ( !isBorderBox && computedVal >= 0 ) { + + // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border + // Assuming integer scroll gutter, subtract the rest and round down + delta += Math.max( 0, Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + computedVal - + delta - + extra - + 0.5 + + // If offsetWidth/offsetHeight is unknown, then we can't determine content-box scroll gutter + // Use an explicit zero to avoid NaN (gh-3964) + ) ) || 0; + } + + return delta; +} + +function getWidthOrHeight( elem, dimension, extra ) { + + // Start with computed style + var styles = getStyles( elem ), + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-4322). + // Fake content-box until we know it's needed to know the true value. + boxSizingNeeded = !support.boxSizingReliable() || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + valueIsBorderBox = isBorderBox, + + val = curCSS( elem, dimension, styles ), + offsetProp = "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ); + + // Support: Firefox <=54 + // Return a confounding non-pixel value or feign ignorance, as appropriate. + if ( rnumnonpx.test( val ) ) { + if ( !extra ) { + return val; + } + val = "auto"; + } + + + // Fall back to offsetWidth/offsetHeight when value is "auto" + // This happens for inline elements with no explicit setting (gh-3571) + // Support: Android <=4.1 - 4.3 only + // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602) + // Support: IE 9-11 only + // Also use offsetWidth/offsetHeight for when box sizing is unreliable + // We use getClientRects() to check for hidden/disconnected. + // In those cases, the computed value can be trusted to be border-box + if ( ( !support.boxSizingReliable() && isBorderBox || + val === "auto" || + !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) && + elem.getClientRects().length ) { + + isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; + + // Where available, offsetWidth/offsetHeight approximate border box dimensions. + // Where not available (e.g., SVG), assume unreliable box-sizing and interpret the + // retrieved value as a content box dimension. + valueIsBorderBox = offsetProp in elem; + if ( valueIsBorderBox ) { + val = elem[ offsetProp ]; + } + } + + // Normalize "" and auto + val = parseFloat( val ) || 0; + + // Adjust for the element's box model + return ( val + + boxModelAdjustment( + elem, + dimension, + extra || ( isBorderBox ? "border" : "content" ), + valueIsBorderBox, + styles, + + // Provide the current computed size to request scroll gutter calculation (gh-3589) + val + ) + ) + "px"; +} + +jQuery.extend( { + + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity" ); + return ret === "" ? "1" : ret; + } + } + } + }, + + // Don't automatically add "px" to these possibly-unitless properties + cssNumber: { + "animationIterationCount": true, + "columnCount": true, + "fillOpacity": true, + "flexGrow": true, + "flexShrink": true, + "fontWeight": true, + "gridArea": true, + "gridColumn": true, + "gridColumnEnd": true, + "gridColumnStart": true, + "gridRow": true, + "gridRowEnd": true, + "gridRowStart": true, + "lineHeight": true, + "opacity": true, + "order": true, + "orphans": true, + "widows": true, + "zIndex": true, + "zoom": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: {}, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ), + style = elem.style; + + // Make sure that we're working with the right name. We don't + // want to query the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Gets hook for the prefixed version, then unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // Convert "+=" or "-=" to relative numbers (#7345) + if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { + value = adjustCSS( elem, name, ret ); + + // Fixes bug #9237 + type = "number"; + } + + // Make sure that null and NaN values aren't set (#7116) + if ( value == null || value !== value ) { + return; + } + + // If a number was passed in, add the unit (except for certain CSS properties) + // The isCustomProp check can be removed in jQuery 4.0 when we only auto-append + // "px" to a few hardcoded values. + if ( type === "number" && !isCustomProp ) { + value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" ); + } + + // background-* props affect original clone's values + if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { + style[ name ] = "inherit"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !( "set" in hooks ) || + ( value = hooks.set( elem, value, extra ) ) !== undefined ) { + + if ( isCustomProp ) { + style.setProperty( name, value ); + } else { + style[ name ] = value; + } + } + + } else { + + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && + ( ret = hooks.get( elem, false, extra ) ) !== undefined ) { + + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra, styles ) { + var val, num, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ); + + // Make sure that we're working with the right name. We don't + // want to modify the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Try prefixed name followed by the unprefixed name + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks ) { + val = hooks.get( elem, true, extra ); + } + + // Otherwise, if a way to get the computed value exists, use that + if ( val === undefined ) { + val = curCSS( elem, name, styles ); + } + + // Convert "normal" to computed value + if ( val === "normal" && name in cssNormalTransform ) { + val = cssNormalTransform[ name ]; + } + + // Make numeric if forced or a qualifier was provided and val looks numeric + if ( extra === "" || extra ) { + num = parseFloat( val ); + return extra === true || isFinite( num ) ? num || 0 : val; + } + + return val; + } +} ); + +jQuery.each( [ "height", "width" ], function( i, dimension ) { + jQuery.cssHooks[ dimension ] = { + get: function( elem, computed, extra ) { + if ( computed ) { + + // Certain elements can have dimension info if we invisibly show them + // but it must have a current display style that would benefit + return rdisplayswap.test( jQuery.css( elem, "display" ) ) && + + // Support: Safari 8+ + // Table columns in Safari have non-zero offsetWidth & zero + // getBoundingClientRect().width unless display is changed. + // Support: IE <=11 only + // Running getBoundingClientRect on a disconnected node + // in IE throws an error. + ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ? + swap( elem, cssShow, function() { + return getWidthOrHeight( elem, dimension, extra ); + } ) : + getWidthOrHeight( elem, dimension, extra ); + } + }, + + set: function( elem, value, extra ) { + var matches, + styles = getStyles( elem ), + + // Only read styles.position if the test has a chance to fail + // to avoid forcing a reflow. + scrollboxSizeBuggy = !support.scrollboxSize() && + styles.position === "absolute", + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-3991) + boxSizingNeeded = scrollboxSizeBuggy || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + subtract = extra ? + boxModelAdjustment( + elem, + dimension, + extra, + isBorderBox, + styles + ) : + 0; + + // Account for unreliable border-box dimensions by comparing offset* to computed and + // faking a content-box to get border and padding (gh-3699) + if ( isBorderBox && scrollboxSizeBuggy ) { + subtract -= Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + parseFloat( styles[ dimension ] ) - + boxModelAdjustment( elem, dimension, "border", false, styles ) - + 0.5 + ); + } + + // Convert to pixels if value adjustment is needed + if ( subtract && ( matches = rcssNum.exec( value ) ) && + ( matches[ 3 ] || "px" ) !== "px" ) { + + elem.style[ dimension ] = value; + value = jQuery.css( elem, dimension ); + } + + return setPositiveNumber( elem, value, subtract ); + } + }; +} ); + +jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, + function( elem, computed ) { + if ( computed ) { + return ( parseFloat( curCSS( elem, "marginLeft" ) ) || + elem.getBoundingClientRect().left - + swap( elem, { marginLeft: 0 }, function() { + return elem.getBoundingClientRect().left; + } ) + ) + "px"; + } + } +); + +// These hooks are used by animate to expand properties +jQuery.each( { + margin: "", + padding: "", + border: "Width" +}, function( prefix, suffix ) { + jQuery.cssHooks[ prefix + suffix ] = { + expand: function( value ) { + var i = 0, + expanded = {}, + + // Assumes a single number if not a string + parts = typeof value === "string" ? value.split( " " ) : [ value ]; + + for ( ; i < 4; i++ ) { + expanded[ prefix + cssExpand[ i ] + suffix ] = + parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; + } + + return expanded; + } + }; + + if ( prefix !== "margin" ) { + jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; + } +} ); + +jQuery.fn.extend( { + css: function( name, value ) { + return access( this, function( elem, name, value ) { + var styles, len, + map = {}, + i = 0; + + if ( Array.isArray( name ) ) { + styles = getStyles( elem ); + len = name.length; + + for ( ; i < len; i++ ) { + map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); + } + + return map; + } + + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); + } +} ); + + +function Tween( elem, options, prop, end, easing ) { + return new Tween.prototype.init( elem, options, prop, end, easing ); +} +jQuery.Tween = Tween; + +Tween.prototype = { + constructor: Tween, + init: function( elem, options, prop, end, easing, unit ) { + this.elem = elem; + this.prop = prop; + this.easing = easing || jQuery.easing._default; + this.options = options; + this.start = this.now = this.cur(); + this.end = end; + this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); + }, + cur: function() { + var hooks = Tween.propHooks[ this.prop ]; + + return hooks && hooks.get ? + hooks.get( this ) : + Tween.propHooks._default.get( this ); + }, + run: function( percent ) { + var eased, + hooks = Tween.propHooks[ this.prop ]; + + if ( this.options.duration ) { + this.pos = eased = jQuery.easing[ this.easing ]( + percent, this.options.duration * percent, 0, 1, this.options.duration + ); + } else { + this.pos = eased = percent; + } + this.now = ( this.end - this.start ) * eased + this.start; + + if ( this.options.step ) { + this.options.step.call( this.elem, this.now, this ); + } + + if ( hooks && hooks.set ) { + hooks.set( this ); + } else { + Tween.propHooks._default.set( this ); + } + return this; + } +}; + +Tween.prototype.init.prototype = Tween.prototype; + +Tween.propHooks = { + _default: { + get: function( tween ) { + var result; + + // Use a property on the element directly when it is not a DOM element, + // or when there is no matching style property that exists. + if ( tween.elem.nodeType !== 1 || + tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) { + return tween.elem[ tween.prop ]; + } + + // Passing an empty string as a 3rd parameter to .css will automatically + // attempt a parseFloat and fallback to a string if the parse fails. + // Simple values such as "10px" are parsed to Float; + // complex values such as "rotate(1rad)" are returned as-is. + result = jQuery.css( tween.elem, tween.prop, "" ); + + // Empty strings, null, undefined and "auto" are converted to 0. + return !result || result === "auto" ? 0 : result; + }, + set: function( tween ) { + + // Use step hook for back compat. + // Use cssHook if its there. + // Use .style if available and use plain properties where available. + if ( jQuery.fx.step[ tween.prop ] ) { + jQuery.fx.step[ tween.prop ]( tween ); + } else if ( tween.elem.nodeType === 1 && ( + jQuery.cssHooks[ tween.prop ] || + tween.elem.style[ finalPropName( tween.prop ) ] != null ) ) { + jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); + } else { + tween.elem[ tween.prop ] = tween.now; + } + } + } +}; + +// Support: IE <=9 only +// Panic based approach to setting things on disconnected nodes +Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { + set: function( tween ) { + if ( tween.elem.nodeType && tween.elem.parentNode ) { + tween.elem[ tween.prop ] = tween.now; + } + } +}; + +jQuery.easing = { + linear: function( p ) { + return p; + }, + swing: function( p ) { + return 0.5 - Math.cos( p * Math.PI ) / 2; + }, + _default: "swing" +}; + +jQuery.fx = Tween.prototype.init; + +// Back compat <1.8 extension point +jQuery.fx.step = {}; + + + + +var + fxNow, inProgress, + rfxtypes = /^(?:toggle|show|hide)$/, + rrun = /queueHooks$/; + +function schedule() { + if ( inProgress ) { + if ( document.hidden === false && window.requestAnimationFrame ) { + window.requestAnimationFrame( schedule ); + } else { + window.setTimeout( schedule, jQuery.fx.interval ); + } + + jQuery.fx.tick(); + } +} + +// Animations created synchronously will run synchronously +function createFxNow() { + window.setTimeout( function() { + fxNow = undefined; + } ); + return ( fxNow = Date.now() ); +} + +// Generate parameters to create a standard animation +function genFx( type, includeWidth ) { + var which, + i = 0, + attrs = { height: type }; + + // If we include width, step value is 1 to do all cssExpand values, + // otherwise step value is 2 to skip over Left and Right + includeWidth = includeWidth ? 1 : 0; + for ( ; i < 4; i += 2 - includeWidth ) { + which = cssExpand[ i ]; + attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; + } + + if ( includeWidth ) { + attrs.opacity = attrs.width = type; + } + + return attrs; +} + +function createTween( value, prop, animation ) { + var tween, + collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ), + index = 0, + length = collection.length; + for ( ; index < length; index++ ) { + if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) { + + // We're done with this property + return tween; + } + } +} + +function defaultPrefilter( elem, props, opts ) { + var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display, + isBox = "width" in props || "height" in props, + anim = this, + orig = {}, + style = elem.style, + hidden = elem.nodeType && isHiddenWithinTree( elem ), + dataShow = dataPriv.get( elem, "fxshow" ); + + // Queue-skipping animations hijack the fx hooks + if ( !opts.queue ) { + hooks = jQuery._queueHooks( elem, "fx" ); + if ( hooks.unqueued == null ) { + hooks.unqueued = 0; + oldfire = hooks.empty.fire; + hooks.empty.fire = function() { + if ( !hooks.unqueued ) { + oldfire(); + } + }; + } + hooks.unqueued++; + + anim.always( function() { + + // Ensure the complete handler is called before this completes + anim.always( function() { + hooks.unqueued--; + if ( !jQuery.queue( elem, "fx" ).length ) { + hooks.empty.fire(); + } + } ); + } ); + } + + // Detect show/hide animations + for ( prop in props ) { + value = props[ prop ]; + if ( rfxtypes.test( value ) ) { + delete props[ prop ]; + toggle = toggle || value === "toggle"; + if ( value === ( hidden ? "hide" : "show" ) ) { + + // Pretend to be hidden if this is a "show" and + // there is still data from a stopped show/hide + if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { + hidden = true; + + // Ignore all other no-op show/hide data + } else { + continue; + } + } + orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); + } + } + + // Bail out if this is a no-op like .hide().hide() + propTween = !jQuery.isEmptyObject( props ); + if ( !propTween && jQuery.isEmptyObject( orig ) ) { + return; + } + + // Restrict "overflow" and "display" styles during box animations + if ( isBox && elem.nodeType === 1 ) { + + // Support: IE <=9 - 11, Edge 12 - 15 + // Record all 3 overflow attributes because IE does not infer the shorthand + // from identically-valued overflowX and overflowY and Edge just mirrors + // the overflowX value there. + opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; + + // Identify a display type, preferring old show/hide data over the CSS cascade + restoreDisplay = dataShow && dataShow.display; + if ( restoreDisplay == null ) { + restoreDisplay = dataPriv.get( elem, "display" ); + } + display = jQuery.css( elem, "display" ); + if ( display === "none" ) { + if ( restoreDisplay ) { + display = restoreDisplay; + } else { + + // Get nonempty value(s) by temporarily forcing visibility + showHide( [ elem ], true ); + restoreDisplay = elem.style.display || restoreDisplay; + display = jQuery.css( elem, "display" ); + showHide( [ elem ] ); + } + } + + // Animate inline elements as inline-block + if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) { + if ( jQuery.css( elem, "float" ) === "none" ) { + + // Restore the original display value at the end of pure show/hide animations + if ( !propTween ) { + anim.done( function() { + style.display = restoreDisplay; + } ); + if ( restoreDisplay == null ) { + display = style.display; + restoreDisplay = display === "none" ? "" : display; + } + } + style.display = "inline-block"; + } + } + } + + if ( opts.overflow ) { + style.overflow = "hidden"; + anim.always( function() { + style.overflow = opts.overflow[ 0 ]; + style.overflowX = opts.overflow[ 1 ]; + style.overflowY = opts.overflow[ 2 ]; + } ); + } + + // Implement show/hide animations + propTween = false; + for ( prop in orig ) { + + // General show/hide setup for this element animation + if ( !propTween ) { + if ( dataShow ) { + if ( "hidden" in dataShow ) { + hidden = dataShow.hidden; + } + } else { + dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } ); + } + + // Store hidden/visible for toggle so `.stop().toggle()` "reverses" + if ( toggle ) { + dataShow.hidden = !hidden; + } + + // Show elements before animating them + if ( hidden ) { + showHide( [ elem ], true ); + } + + /* eslint-disable no-loop-func */ + + anim.done( function() { + + /* eslint-enable no-loop-func */ + + // The final step of a "hide" animation is actually hiding the element + if ( !hidden ) { + showHide( [ elem ] ); + } + dataPriv.remove( elem, "fxshow" ); + for ( prop in orig ) { + jQuery.style( elem, prop, orig[ prop ] ); + } + } ); + } + + // Per-property setup + propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); + if ( !( prop in dataShow ) ) { + dataShow[ prop ] = propTween.start; + if ( hidden ) { + propTween.end = propTween.start; + propTween.start = 0; + } + } + } +} + +function propFilter( props, specialEasing ) { + var index, name, easing, value, hooks; + + // camelCase, specialEasing and expand cssHook pass + for ( index in props ) { + name = camelCase( index ); + easing = specialEasing[ name ]; + value = props[ index ]; + if ( Array.isArray( value ) ) { + easing = value[ 1 ]; + value = props[ index ] = value[ 0 ]; + } + + if ( index !== name ) { + props[ name ] = value; + delete props[ index ]; + } + + hooks = jQuery.cssHooks[ name ]; + if ( hooks && "expand" in hooks ) { + value = hooks.expand( value ); + delete props[ name ]; + + // Not quite $.extend, this won't overwrite existing keys. + // Reusing 'index' because we have the correct "name" + for ( index in value ) { + if ( !( index in props ) ) { + props[ index ] = value[ index ]; + specialEasing[ index ] = easing; + } + } + } else { + specialEasing[ name ] = easing; + } + } +} + +function Animation( elem, properties, options ) { + var result, + stopped, + index = 0, + length = Animation.prefilters.length, + deferred = jQuery.Deferred().always( function() { + + // Don't match elem in the :animated selector + delete tick.elem; + } ), + tick = function() { + if ( stopped ) { + return false; + } + var currentTime = fxNow || createFxNow(), + remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), + + // Support: Android 2.3 only + // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497) + temp = remaining / animation.duration || 0, + percent = 1 - temp, + index = 0, + length = animation.tweens.length; + + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( percent ); + } + + deferred.notifyWith( elem, [ animation, percent, remaining ] ); + + // If there's more to do, yield + if ( percent < 1 && length ) { + return remaining; + } + + // If this was an empty animation, synthesize a final progress notification + if ( !length ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + } + + // Resolve the animation and report its conclusion + deferred.resolveWith( elem, [ animation ] ); + return false; + }, + animation = deferred.promise( { + elem: elem, + props: jQuery.extend( {}, properties ), + opts: jQuery.extend( true, { + specialEasing: {}, + easing: jQuery.easing._default + }, options ), + originalProperties: properties, + originalOptions: options, + startTime: fxNow || createFxNow(), + duration: options.duration, + tweens: [], + createTween: function( prop, end ) { + var tween = jQuery.Tween( elem, animation.opts, prop, end, + animation.opts.specialEasing[ prop ] || animation.opts.easing ); + animation.tweens.push( tween ); + return tween; + }, + stop: function( gotoEnd ) { + var index = 0, + + // If we are going to the end, we want to run all the tweens + // otherwise we skip this part + length = gotoEnd ? animation.tweens.length : 0; + if ( stopped ) { + return this; + } + stopped = true; + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( 1 ); + } + + // Resolve when we played the last frame; otherwise, reject + if ( gotoEnd ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + deferred.resolveWith( elem, [ animation, gotoEnd ] ); + } else { + deferred.rejectWith( elem, [ animation, gotoEnd ] ); + } + return this; + } + } ), + props = animation.props; + + propFilter( props, animation.opts.specialEasing ); + + for ( ; index < length; index++ ) { + result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts ); + if ( result ) { + if ( isFunction( result.stop ) ) { + jQuery._queueHooks( animation.elem, animation.opts.queue ).stop = + result.stop.bind( result ); + } + return result; + } + } + + jQuery.map( props, createTween, animation ); + + if ( isFunction( animation.opts.start ) ) { + animation.opts.start.call( elem, animation ); + } + + // Attach callbacks from options + animation + .progress( animation.opts.progress ) + .done( animation.opts.done, animation.opts.complete ) + .fail( animation.opts.fail ) + .always( animation.opts.always ); + + jQuery.fx.timer( + jQuery.extend( tick, { + elem: elem, + anim: animation, + queue: animation.opts.queue + } ) + ); + + return animation; +} + +jQuery.Animation = jQuery.extend( Animation, { + + tweeners: { + "*": [ function( prop, value ) { + var tween = this.createTween( prop, value ); + adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween ); + return tween; + } ] + }, + + tweener: function( props, callback ) { + if ( isFunction( props ) ) { + callback = props; + props = [ "*" ]; + } else { + props = props.match( rnothtmlwhite ); + } + + var prop, + index = 0, + length = props.length; + + for ( ; index < length; index++ ) { + prop = props[ index ]; + Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || []; + Animation.tweeners[ prop ].unshift( callback ); + } + }, + + prefilters: [ defaultPrefilter ], + + prefilter: function( callback, prepend ) { + if ( prepend ) { + Animation.prefilters.unshift( callback ); + } else { + Animation.prefilters.push( callback ); + } + } +} ); + +jQuery.speed = function( speed, easing, fn ) { + var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { + complete: fn || !fn && easing || + isFunction( speed ) && speed, + duration: speed, + easing: fn && easing || easing && !isFunction( easing ) && easing + }; + + // Go to the end state if fx are off + if ( jQuery.fx.off ) { + opt.duration = 0; + + } else { + if ( typeof opt.duration !== "number" ) { + if ( opt.duration in jQuery.fx.speeds ) { + opt.duration = jQuery.fx.speeds[ opt.duration ]; + + } else { + opt.duration = jQuery.fx.speeds._default; + } + } + } + + // Normalize opt.queue - true/undefined/null -> "fx" + if ( opt.queue == null || opt.queue === true ) { + opt.queue = "fx"; + } + + // Queueing + opt.old = opt.complete; + + opt.complete = function() { + if ( isFunction( opt.old ) ) { + opt.old.call( this ); + } + + if ( opt.queue ) { + jQuery.dequeue( this, opt.queue ); + } + }; + + return opt; +}; + +jQuery.fn.extend( { + fadeTo: function( speed, to, easing, callback ) { + + // Show any hidden elements after setting opacity to 0 + return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show() + + // Animate to the value specified + .end().animate( { opacity: to }, speed, easing, callback ); + }, + animate: function( prop, speed, easing, callback ) { + var empty = jQuery.isEmptyObject( prop ), + optall = jQuery.speed( speed, easing, callback ), + doAnimation = function() { + + // Operate on a copy of prop so per-property easing won't be lost + var anim = Animation( this, jQuery.extend( {}, prop ), optall ); + + // Empty animations, or finishing resolves immediately + if ( empty || dataPriv.get( this, "finish" ) ) { + anim.stop( true ); + } + }; + doAnimation.finish = doAnimation; + + return empty || optall.queue === false ? + this.each( doAnimation ) : + this.queue( optall.queue, doAnimation ); + }, + stop: function( type, clearQueue, gotoEnd ) { + var stopQueue = function( hooks ) { + var stop = hooks.stop; + delete hooks.stop; + stop( gotoEnd ); + }; + + if ( typeof type !== "string" ) { + gotoEnd = clearQueue; + clearQueue = type; + type = undefined; + } + if ( clearQueue && type !== false ) { + this.queue( type || "fx", [] ); + } + + return this.each( function() { + var dequeue = true, + index = type != null && type + "queueHooks", + timers = jQuery.timers, + data = dataPriv.get( this ); + + if ( index ) { + if ( data[ index ] && data[ index ].stop ) { + stopQueue( data[ index ] ); + } + } else { + for ( index in data ) { + if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { + stopQueue( data[ index ] ); + } + } + } + + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && + ( type == null || timers[ index ].queue === type ) ) { + + timers[ index ].anim.stop( gotoEnd ); + dequeue = false; + timers.splice( index, 1 ); + } + } + + // Start the next in the queue if the last step wasn't forced. + // Timers currently will call their complete callbacks, which + // will dequeue but only if they were gotoEnd. + if ( dequeue || !gotoEnd ) { + jQuery.dequeue( this, type ); + } + } ); + }, + finish: function( type ) { + if ( type !== false ) { + type = type || "fx"; + } + return this.each( function() { + var index, + data = dataPriv.get( this ), + queue = data[ type + "queue" ], + hooks = data[ type + "queueHooks" ], + timers = jQuery.timers, + length = queue ? queue.length : 0; + + // Enable finishing flag on private data + data.finish = true; + + // Empty the queue first + jQuery.queue( this, type, [] ); + + if ( hooks && hooks.stop ) { + hooks.stop.call( this, true ); + } + + // Look for any active animations, and finish them + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && timers[ index ].queue === type ) { + timers[ index ].anim.stop( true ); + timers.splice( index, 1 ); + } + } + + // Look for any animations in the old queue and finish them + for ( index = 0; index < length; index++ ) { + if ( queue[ index ] && queue[ index ].finish ) { + queue[ index ].finish.call( this ); + } + } + + // Turn off finishing flag + delete data.finish; + } ); + } +} ); + +jQuery.each( [ "toggle", "show", "hide" ], function( i, name ) { + var cssFn = jQuery.fn[ name ]; + jQuery.fn[ name ] = function( speed, easing, callback ) { + return speed == null || typeof speed === "boolean" ? + cssFn.apply( this, arguments ) : + this.animate( genFx( name, true ), speed, easing, callback ); + }; +} ); + +// Generate shortcuts for custom animations +jQuery.each( { + slideDown: genFx( "show" ), + slideUp: genFx( "hide" ), + slideToggle: genFx( "toggle" ), + fadeIn: { opacity: "show" }, + fadeOut: { opacity: "hide" }, + fadeToggle: { opacity: "toggle" } +}, function( name, props ) { + jQuery.fn[ name ] = function( speed, easing, callback ) { + return this.animate( props, speed, easing, callback ); + }; +} ); + +jQuery.timers = []; +jQuery.fx.tick = function() { + var timer, + i = 0, + timers = jQuery.timers; + + fxNow = Date.now(); + + for ( ; i < timers.length; i++ ) { + timer = timers[ i ]; + + // Run the timer and safely remove it when done (allowing for external removal) + if ( !timer() && timers[ i ] === timer ) { + timers.splice( i--, 1 ); + } + } + + if ( !timers.length ) { + jQuery.fx.stop(); + } + fxNow = undefined; +}; + +jQuery.fx.timer = function( timer ) { + jQuery.timers.push( timer ); + jQuery.fx.start(); +}; + +jQuery.fx.interval = 13; +jQuery.fx.start = function() { + if ( inProgress ) { + return; + } + + inProgress = true; + schedule(); +}; + +jQuery.fx.stop = function() { + inProgress = null; +}; + +jQuery.fx.speeds = { + slow: 600, + fast: 200, + + // Default speed + _default: 400 +}; + + +// Based off of the plugin by Clint Helfers, with permission. +// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/ +jQuery.fn.delay = function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = window.setTimeout( next, time ); + hooks.stop = function() { + window.clearTimeout( timeout ); + }; + } ); +}; + + +( function() { + var input = document.createElement( "input" ), + select = document.createElement( "select" ), + opt = select.appendChild( document.createElement( "option" ) ); + + input.type = "checkbox"; + + // Support: Android <=4.3 only + // Default value for a checkbox should be "on" + support.checkOn = input.value !== ""; + + // Support: IE <=11 only + // Must access selectedIndex to make default options select + support.optSelected = opt.selected; + + // Support: IE <=11 only + // An input loses its value after becoming a radio + input = document.createElement( "input" ); + input.value = "t"; + input.type = "radio"; + support.radioValue = input.value === "t"; +} )(); + + +var boolHook, + attrHandle = jQuery.expr.attrHandle; + +jQuery.fn.extend( { + attr: function( name, value ) { + return access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each( function() { + jQuery.removeAttr( this, name ); + } ); + } +} ); + +jQuery.extend( { + attr: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set attributes on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === "undefined" ) { + return jQuery.prop( elem, name, value ); + } + + // Attribute hooks are determined by the lowercase version + // Grab necessary hook if one is defined + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + hooks = jQuery.attrHooks[ name.toLowerCase() ] || + ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined ); + } + + if ( value !== undefined ) { + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return; + } + + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + elem.setAttribute( name, value + "" ); + return value; + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + ret = jQuery.find.attr( elem, name ); + + // Non-existent attributes return null, we normalize to undefined + return ret == null ? undefined : ret; + }, + + attrHooks: { + type: { + set: function( elem, value ) { + if ( !support.radioValue && value === "radio" && + nodeName( elem, "input" ) ) { + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + } + }, + + removeAttr: function( elem, value ) { + var name, + i = 0, + + // Attribute names can contain non-HTML whitespace characters + // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 + attrNames = value && value.match( rnothtmlwhite ); + + if ( attrNames && elem.nodeType === 1 ) { + while ( ( name = attrNames[ i++ ] ) ) { + elem.removeAttribute( name ); + } + } + } +} ); + +// Hooks for boolean attributes +boolHook = { + set: function( elem, value, name ) { + if ( value === false ) { + + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + elem.setAttribute( name, name ); + } + return name; + } +}; + +jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) { + var getter = attrHandle[ name ] || jQuery.find.attr; + + attrHandle[ name ] = function( elem, name, isXML ) { + var ret, handle, + lowercaseName = name.toLowerCase(); + + if ( !isXML ) { + + // Avoid an infinite loop by temporarily removing this function from the getter + handle = attrHandle[ lowercaseName ]; + attrHandle[ lowercaseName ] = ret; + ret = getter( elem, name, isXML ) != null ? + lowercaseName : + null; + attrHandle[ lowercaseName ] = handle; + } + return ret; + }; +} ); + + + + +var rfocusable = /^(?:input|select|textarea|button)$/i, + rclickable = /^(?:a|area)$/i; + +jQuery.fn.extend( { + prop: function( name, value ) { + return access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + return this.each( function() { + delete this[ jQuery.propFix[ name ] || name ]; + } ); + } +} ); + +jQuery.extend( { + prop: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set properties on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + return ( elem[ name ] = value ); + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + return elem[ name ]; + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + + // Support: IE <=9 - 11 only + // elem.tabIndex doesn't always return the + // correct value when it hasn't been explicitly set + // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + // Use proper attribute retrieval(#12072) + var tabindex = jQuery.find.attr( elem, "tabindex" ); + + if ( tabindex ) { + return parseInt( tabindex, 10 ); + } + + if ( + rfocusable.test( elem.nodeName ) || + rclickable.test( elem.nodeName ) && + elem.href + ) { + return 0; + } + + return -1; + } + } + }, + + propFix: { + "for": "htmlFor", + "class": "className" + } +} ); + +// Support: IE <=11 only +// Accessing the selectedIndex property +// forces the browser to respect setting selected +// on the option +// The getter ensures a default option is selected +// when in an optgroup +// eslint rule "no-unused-expressions" is disabled for this code +// since it considers such accessions noop +if ( !support.optSelected ) { + jQuery.propHooks.selected = { + get: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent && parent.parentNode ) { + parent.parentNode.selectedIndex; + } + return null; + }, + set: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent ) { + parent.selectedIndex; + + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + }; +} + +jQuery.each( [ + "tabIndex", + "readOnly", + "maxLength", + "cellSpacing", + "cellPadding", + "rowSpan", + "colSpan", + "useMap", + "frameBorder", + "contentEditable" +], function() { + jQuery.propFix[ this.toLowerCase() ] = this; +} ); + + + + + // Strip and collapse whitespace according to HTML spec + // https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace + function stripAndCollapse( value ) { + var tokens = value.match( rnothtmlwhite ) || []; + return tokens.join( " " ); + } + + +function getClass( elem ) { + return elem.getAttribute && elem.getAttribute( "class" ) || ""; +} + +function classesToArray( value ) { + if ( Array.isArray( value ) ) { + return value; + } + if ( typeof value === "string" ) { + return value.match( rnothtmlwhite ) || []; + } + return []; +} + +jQuery.fn.extend( { + addClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + if ( !arguments.length ) { + return this.attr( "class", "" ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) > -1 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isValidValue = type === "string" || Array.isArray( value ); + + if ( typeof stateVal === "boolean" && isValidValue ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } + + if ( isFunction( value ) ) { + return this.each( function( i ) { + jQuery( this ).toggleClass( + value.call( this, i, getClass( this ), stateVal ), + stateVal + ); + } ); + } + + return this.each( function() { + var className, i, self, classNames; + + if ( isValidValue ) { + + // Toggle individual class names + i = 0; + self = jQuery( this ); + classNames = classesToArray( value ); + + while ( ( className = classNames[ i++ ] ) ) { + + // Check each className given, space separated list + if ( self.hasClass( className ) ) { + self.removeClass( className ); + } else { + self.addClass( className ); + } + } + + // Toggle whole class name + } else if ( value === undefined || type === "boolean" ) { + className = getClass( this ); + if ( className ) { + + // Store className if set + dataPriv.set( this, "__className__", className ); + } + + // If the element has a class name or if we're passed `false`, + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. + if ( this.setAttribute ) { + this.setAttribute( "class", + className || value === false ? + "" : + dataPriv.get( this, "__className__" ) || "" + ); + } + } + } ); + }, + + hasClass: function( selector ) { + var className, elem, + i = 0; + + className = " " + selector + " "; + while ( ( elem = this[ i++ ] ) ) { + if ( elem.nodeType === 1 && + ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) { + return true; + } + } + + return false; + } +} ); + + + + +var rreturn = /\r/g; + +jQuery.fn.extend( { + val: function( value ) { + var hooks, ret, valueIsFunction, + elem = this[ 0 ]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || + jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && + "get" in hooks && + ( ret = hooks.get( elem, "value" ) ) !== undefined + ) { + return ret; + } + + ret = elem.value; + + // Handle most common string cases + if ( typeof ret === "string" ) { + return ret.replace( rreturn, "" ); + } + + // Handle cases where value is null/undef or number + return ret == null ? "" : ret; + } + + return; + } + + valueIsFunction = isFunction( value ); + + return this.each( function( i ) { + var val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( valueIsFunction ) { + val = value.call( this, i, jQuery( this ).val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + + } else if ( typeof val === "number" ) { + val += ""; + + } else if ( Array.isArray( val ) ) { + val = jQuery.map( val, function( value ) { + return value == null ? "" : value + ""; + } ); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + } ); + } +} ); + +jQuery.extend( { + valHooks: { + option: { + get: function( elem ) { + + var val = jQuery.find.attr( elem, "value" ); + return val != null ? + val : + + // Support: IE <=10 - 11 only + // option.text throws exceptions (#14686, #14858) + // Strip and collapse whitespace + // https://html.spec.whatwg.org/#strip-and-collapse-whitespace + stripAndCollapse( jQuery.text( elem ) ); + } + }, + select: { + get: function( elem ) { + var value, option, i, + options = elem.options, + index = elem.selectedIndex, + one = elem.type === "select-one", + values = one ? null : [], + max = one ? index + 1 : options.length; + + if ( index < 0 ) { + i = max; + + } else { + i = one ? index : 0; + } + + // Loop through all the selected options + for ( ; i < max; i++ ) { + option = options[ i ]; + + // Support: IE <=9 only + // IE8-9 doesn't update selected after form reset (#2551) + if ( ( option.selected || i === index ) && + + // Don't return options that are disabled or in a disabled optgroup + !option.disabled && + ( !option.parentNode.disabled || + !nodeName( option.parentNode, "optgroup" ) ) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + }, + + set: function( elem, value ) { + var optionSet, option, + options = elem.options, + values = jQuery.makeArray( value ), + i = options.length; + + while ( i-- ) { + option = options[ i ]; + + /* eslint-disable no-cond-assign */ + + if ( option.selected = + jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1 + ) { + optionSet = true; + } + + /* eslint-enable no-cond-assign */ + } + + // Force browsers to behave consistently when non-matching value is set + if ( !optionSet ) { + elem.selectedIndex = -1; + } + return values; + } + } + } +} ); + +// Radios and checkboxes getter/setter +jQuery.each( [ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + set: function( elem, value ) { + if ( Array.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 ); + } + } + }; + if ( !support.checkOn ) { + jQuery.valHooks[ this ].get = function( elem ) { + return elem.getAttribute( "value" ) === null ? "on" : elem.value; + }; + } +} ); + + + + +// Return jQuery for attributes-only inclusion + + +support.focusin = "onfocusin" in window; + + +var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + stopPropagationCallback = function( e ) { + e.stopPropagation(); + }; + +jQuery.extend( jQuery.event, { + + trigger: function( event, data, elem, onlyHandlers ) { + + var i, cur, tmp, bubbleType, ontype, handle, special, lastElement, + eventPath = [ elem || document ], + type = hasOwn.call( event, "type" ) ? event.type : event, + namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; + + cur = lastElement = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf( "." ) > -1 ) { + + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split( "." ); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf( ":" ) < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join( "." ); + event.rnamespace = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === ( elem.ownerDocument || document ) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) { + lastElement = cur; + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( dataPriv.get( cur, "events" ) || {} )[ event.type ] && + dataPriv.get( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && handle.apply && acceptData( cur ) ) { + event.result = handle.apply( cur, data ); + if ( event.result === false ) { + event.preventDefault(); + } + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( ( !special._default || + special._default.apply( eventPath.pop(), data ) === false ) && + acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name as the event. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + + if ( event.isPropagationStopped() ) { + lastElement.addEventListener( type, stopPropagationCallback ); + } + + elem[ type ](); + + if ( event.isPropagationStopped() ) { + lastElement.removeEventListener( type, stopPropagationCallback ); + } + + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + // Piggyback on a donor event to simulate a different one + // Used only for `focus(in | out)` events + simulate: function( type, elem, event ) { + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true + } + ); + + jQuery.event.trigger( e, null, elem ); + } + +} ); + +jQuery.fn.extend( { + + trigger: function( type, data ) { + return this.each( function() { + jQuery.event.trigger( type, data, this ); + } ); + }, + triggerHandler: function( type, data ) { + var elem = this[ 0 ]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +} ); + + +// Support: Firefox <=44 +// Firefox doesn't have focus(in | out) events +// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 +// +// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 +// focus(in | out) events fire after focus & blur events, +// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order +// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 +if ( !support.focusin ) { + jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler on the document while someone wants focusin/focusout + var handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + var doc = this.ownerDocument || this, + attaches = dataPriv.access( doc, fix ); + + if ( !attaches ) { + doc.addEventListener( orig, handler, true ); + } + dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); + }, + teardown: function() { + var doc = this.ownerDocument || this, + attaches = dataPriv.access( doc, fix ) - 1; + + if ( !attaches ) { + doc.removeEventListener( orig, handler, true ); + dataPriv.remove( doc, fix ); + + } else { + dataPriv.access( doc, fix, attaches ); + } + } + }; + } ); +} +var location = window.location; + +var nonce = Date.now(); + +var rquery = ( /\?/ ); + + + +// Cross-browser xml parsing +jQuery.parseXML = function( data ) { + var xml; + if ( !data || typeof data !== "string" ) { + return null; + } + + // Support: IE 9 - 11 only + // IE throws on parseFromString with invalid input. + try { + xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); + } catch ( e ) { + xml = undefined; + } + + if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; +}; + + +var + rbracket = /\[\]$/, + rCRLF = /\r?\n/g, + rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, + rsubmittable = /^(?:input|select|textarea|keygen)/i; + +function buildParams( prefix, obj, traditional, add ) { + var name; + + if ( Array.isArray( obj ) ) { + + // Serialize array item. + jQuery.each( obj, function( i, v ) { + if ( traditional || rbracket.test( prefix ) ) { + + // Treat each array item as a scalar. + add( prefix, v ); + + } else { + + // Item is non-scalar (array or object), encode its numeric index. + buildParams( + prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]", + v, + traditional, + add + ); + } + } ); + + } else if ( !traditional && toType( obj ) === "object" ) { + + // Serialize object item. + for ( name in obj ) { + buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); + } + + } else { + + // Serialize scalar item. + add( prefix, obj ); + } +} + +// Serialize an array of form elements or a set of +// key/values into a query string +jQuery.param = function( a, traditional ) { + var prefix, + s = [], + add = function( key, valueOrFunction ) { + + // If value is a function, invoke it and use its return value + var value = isFunction( valueOrFunction ) ? + valueOrFunction() : + valueOrFunction; + + s[ s.length ] = encodeURIComponent( key ) + "=" + + encodeURIComponent( value == null ? "" : value ); + }; + + if ( a == null ) { + return ""; + } + + // If an array was passed in, assume that it is an array of form elements. + if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { + + // Serialize the form elements + jQuery.each( a, function() { + add( this.name, this.value ); + } ); + + } else { + + // If traditional, encode the "old" way (the way 1.3.2 or older + // did it), otherwise encode params recursively. + for ( prefix in a ) { + buildParams( prefix, a[ prefix ], traditional, add ); + } + } + + // Return the resulting serialization + return s.join( "&" ); +}; + +jQuery.fn.extend( { + serialize: function() { + return jQuery.param( this.serializeArray() ); + }, + serializeArray: function() { + return this.map( function() { + + // Can add propHook for "elements" to filter or add form elements + var elements = jQuery.prop( this, "elements" ); + return elements ? jQuery.makeArray( elements ) : this; + } ) + .filter( function() { + var type = this.type; + + // Use .is( ":disabled" ) so that fieldset[disabled] works + return this.name && !jQuery( this ).is( ":disabled" ) && + rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && + ( this.checked || !rcheckableType.test( type ) ); + } ) + .map( function( i, elem ) { + var val = jQuery( this ).val(); + + if ( val == null ) { + return null; + } + + if ( Array.isArray( val ) ) { + return jQuery.map( val, function( val ) { + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ); + } + + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ).get(); + } +} ); + + +var + r20 = /%20/g, + rhash = /#.*$/, + rantiCache = /([?&])_=[^&]*/, + rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, + + // #7653, #8125, #8152: local protocol detection + rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, + rnoContent = /^(?:GET|HEAD)$/, + rprotocol = /^\/\//, + + /* Prefilters + * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) + * 2) These are called: + * - BEFORE asking for a transport + * - AFTER param serialization (s.data is a string if s.processData is true) + * 3) key is the dataType + * 4) the catchall symbol "*" can be used + * 5) execution will start with transport dataType and THEN continue down to "*" if needed + */ + prefilters = {}, + + /* Transports bindings + * 1) key is the dataType + * 2) the catchall symbol "*" can be used + * 3) selection will start with transport dataType and THEN go to "*" if needed + */ + transports = {}, + + // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression + allTypes = "*/".concat( "*" ), + + // Anchor tag for parsing the document origin + originAnchor = document.createElement( "a" ); + originAnchor.href = location.href; + +// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport +function addToPrefiltersOrTransports( structure ) { + + // dataTypeExpression is optional and defaults to "*" + return function( dataTypeExpression, func ) { + + if ( typeof dataTypeExpression !== "string" ) { + func = dataTypeExpression; + dataTypeExpression = "*"; + } + + var dataType, + i = 0, + dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || []; + + if ( isFunction( func ) ) { + + // For each dataType in the dataTypeExpression + while ( ( dataType = dataTypes[ i++ ] ) ) { + + // Prepend if requested + if ( dataType[ 0 ] === "+" ) { + dataType = dataType.slice( 1 ) || "*"; + ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func ); + + // Otherwise append + } else { + ( structure[ dataType ] = structure[ dataType ] || [] ).push( func ); + } + } + } + }; +} + +// Base inspection function for prefilters and transports +function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { + + var inspected = {}, + seekingTransport = ( structure === transports ); + + function inspect( dataType ) { + var selected; + inspected[ dataType ] = true; + jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { + var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); + if ( typeof dataTypeOrTransport === "string" && + !seekingTransport && !inspected[ dataTypeOrTransport ] ) { + + options.dataTypes.unshift( dataTypeOrTransport ); + inspect( dataTypeOrTransport ); + return false; + } else if ( seekingTransport ) { + return !( selected = dataTypeOrTransport ); + } + } ); + return selected; + } + + return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); +} + +// A special extend for ajax options +// that takes "flat" options (not to be deep extended) +// Fixes #9887 +function ajaxExtend( target, src ) { + var key, deep, + flatOptions = jQuery.ajaxSettings.flatOptions || {}; + + for ( key in src ) { + if ( src[ key ] !== undefined ) { + ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; + } + } + if ( deep ) { + jQuery.extend( true, target, deep ); + } + + return target; +} + +/* Handles responses to an ajax request: + * - finds the right dataType (mediates between content-type and expected dataType) + * - returns the corresponding response + */ +function ajaxHandleResponses( s, jqXHR, responses ) { + + var ct, type, finalDataType, firstDataType, + contents = s.contents, + dataTypes = s.dataTypes; + + // Remove auto dataType and get content-type in the process + while ( dataTypes[ 0 ] === "*" ) { + dataTypes.shift(); + if ( ct === undefined ) { + ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" ); + } + } + + // Check if we're dealing with a known content-type + if ( ct ) { + for ( type in contents ) { + if ( contents[ type ] && contents[ type ].test( ct ) ) { + dataTypes.unshift( type ); + break; + } + } + } + + // Check to see if we have a response for the expected dataType + if ( dataTypes[ 0 ] in responses ) { + finalDataType = dataTypes[ 0 ]; + } else { + + // Try convertible dataTypes + for ( type in responses ) { + if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) { + finalDataType = type; + break; + } + if ( !firstDataType ) { + firstDataType = type; + } + } + + // Or just use first one + finalDataType = finalDataType || firstDataType; + } + + // If we found a dataType + // We add the dataType to the list if needed + // and return the corresponding response + if ( finalDataType ) { + if ( finalDataType !== dataTypes[ 0 ] ) { + dataTypes.unshift( finalDataType ); + } + return responses[ finalDataType ]; + } +} + +/* Chain conversions given the request and the original response + * Also sets the responseXXX fields on the jqXHR instance + */ +function ajaxConvert( s, response, jqXHR, isSuccess ) { + var conv2, current, conv, tmp, prev, + converters = {}, + + // Work with a copy of dataTypes in case we need to modify it for conversion + dataTypes = s.dataTypes.slice(); + + // Create converters map with lowercased keys + if ( dataTypes[ 1 ] ) { + for ( conv in s.converters ) { + converters[ conv.toLowerCase() ] = s.converters[ conv ]; + } + } + + current = dataTypes.shift(); + + // Convert to each sequential dataType + while ( current ) { + + if ( s.responseFields[ current ] ) { + jqXHR[ s.responseFields[ current ] ] = response; + } + + // Apply the dataFilter if provided + if ( !prev && isSuccess && s.dataFilter ) { + response = s.dataFilter( response, s.dataType ); + } + + prev = current; + current = dataTypes.shift(); + + if ( current ) { + + // There's only work to do if current dataType is non-auto + if ( current === "*" ) { + + current = prev; + + // Convert response if prev dataType is non-auto and differs from current + } else if ( prev !== "*" && prev !== current ) { + + // Seek a direct converter + conv = converters[ prev + " " + current ] || converters[ "* " + current ]; + + // If none found, seek a pair + if ( !conv ) { + for ( conv2 in converters ) { + + // If conv2 outputs current + tmp = conv2.split( " " ); + if ( tmp[ 1 ] === current ) { + + // If prev can be converted to accepted input + conv = converters[ prev + " " + tmp[ 0 ] ] || + converters[ "* " + tmp[ 0 ] ]; + if ( conv ) { + + // Condense equivalence converters + if ( conv === true ) { + conv = converters[ conv2 ]; + + // Otherwise, insert the intermediate dataType + } else if ( converters[ conv2 ] !== true ) { + current = tmp[ 0 ]; + dataTypes.unshift( tmp[ 1 ] ); + } + break; + } + } + } + } + + // Apply converter (if not an equivalence) + if ( conv !== true ) { + + // Unless errors are allowed to bubble, catch and return them + if ( conv && s.throws ) { + response = conv( response ); + } else { + try { + response = conv( response ); + } catch ( e ) { + return { + state: "parsererror", + error: conv ? e : "No conversion from " + prev + " to " + current + }; + } + } + } + } + } + } + + return { state: "success", data: response }; +} + +jQuery.extend( { + + // Counter for holding the number of active queries + active: 0, + + // Last-Modified header cache for next request + lastModified: {}, + etag: {}, + + ajaxSettings: { + url: location.href, + type: "GET", + isLocal: rlocalProtocol.test( location.protocol ), + global: true, + processData: true, + async: true, + contentType: "application/x-www-form-urlencoded; charset=UTF-8", + + /* + timeout: 0, + data: null, + dataType: null, + username: null, + password: null, + cache: null, + throws: false, + traditional: false, + headers: {}, + */ + + accepts: { + "*": allTypes, + text: "text/plain", + html: "text/html", + xml: "application/xml, text/xml", + json: "application/json, text/javascript" + }, + + contents: { + xml: /\bxml\b/, + html: /\bhtml/, + json: /\bjson\b/ + }, + + responseFields: { + xml: "responseXML", + text: "responseText", + json: "responseJSON" + }, + + // Data converters + // Keys separate source (or catchall "*") and destination types with a single space + converters: { + + // Convert anything to text + "* text": String, + + // Text to html (true = no transformation) + "text html": true, + + // Evaluate text as a json expression + "text json": JSON.parse, + + // Parse text as xml + "text xml": jQuery.parseXML + }, + + // For options that shouldn't be deep extended: + // you can add your own custom options here if + // and when you create one that shouldn't be + // deep extended (see ajaxExtend) + flatOptions: { + url: true, + context: true + } + }, + + // Creates a full fledged settings object into target + // with both ajaxSettings and settings fields. + // If target is omitted, writes into ajaxSettings. + ajaxSetup: function( target, settings ) { + return settings ? + + // Building a settings object + ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : + + // Extending ajaxSettings + ajaxExtend( jQuery.ajaxSettings, target ); + }, + + ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), + ajaxTransport: addToPrefiltersOrTransports( transports ), + + // Main method + ajax: function( url, options ) { + + // If url is an object, simulate pre-1.5 signature + if ( typeof url === "object" ) { + options = url; + url = undefined; + } + + // Force options to be an object + options = options || {}; + + var transport, + + // URL without anti-cache param + cacheURL, + + // Response headers + responseHeadersString, + responseHeaders, + + // timeout handle + timeoutTimer, + + // Url cleanup var + urlAnchor, + + // Request state (becomes false upon send and true upon completion) + completed, + + // To know if global events are to be dispatched + fireGlobals, + + // Loop variable + i, + + // uncached part of the url + uncached, + + // Create the final options object + s = jQuery.ajaxSetup( {}, options ), + + // Callbacks context + callbackContext = s.context || s, + + // Context for global events is callbackContext if it is a DOM node or jQuery collection + globalEventContext = s.context && + ( callbackContext.nodeType || callbackContext.jquery ) ? + jQuery( callbackContext ) : + jQuery.event, + + // Deferreds + deferred = jQuery.Deferred(), + completeDeferred = jQuery.Callbacks( "once memory" ), + + // Status-dependent callbacks + statusCode = s.statusCode || {}, + + // Headers (they are sent all at once) + requestHeaders = {}, + requestHeadersNames = {}, + + // Default abort message + strAbort = "canceled", + + // Fake xhr + jqXHR = { + readyState: 0, + + // Builds headers hashtable if needed + getResponseHeader: function( key ) { + var match; + if ( completed ) { + if ( !responseHeaders ) { + responseHeaders = {}; + while ( ( match = rheaders.exec( responseHeadersString ) ) ) { + responseHeaders[ match[ 1 ].toLowerCase() + " " ] = + ( responseHeaders[ match[ 1 ].toLowerCase() + " " ] || [] ) + .concat( match[ 2 ] ); + } + } + match = responseHeaders[ key.toLowerCase() + " " ]; + } + return match == null ? null : match.join( ", " ); + }, + + // Raw string + getAllResponseHeaders: function() { + return completed ? responseHeadersString : null; + }, + + // Caches the header + setRequestHeader: function( name, value ) { + if ( completed == null ) { + name = requestHeadersNames[ name.toLowerCase() ] = + requestHeadersNames[ name.toLowerCase() ] || name; + requestHeaders[ name ] = value; + } + return this; + }, + + // Overrides response content-type header + overrideMimeType: function( type ) { + if ( completed == null ) { + s.mimeType = type; + } + return this; + }, + + // Status-dependent callbacks + statusCode: function( map ) { + var code; + if ( map ) { + if ( completed ) { + + // Execute the appropriate callbacks + jqXHR.always( map[ jqXHR.status ] ); + } else { + + // Lazy-add the new callbacks in a way that preserves old ones + for ( code in map ) { + statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; + } + } + } + return this; + }, + + // Cancel the request + abort: function( statusText ) { + var finalText = statusText || strAbort; + if ( transport ) { + transport.abort( finalText ); + } + done( 0, finalText ); + return this; + } + }; + + // Attach deferreds + deferred.promise( jqXHR ); + + // Add protocol if not provided (prefilters might expect it) + // Handle falsy url in the settings object (#10093: consistency with old signature) + // We also use the url parameter if available + s.url = ( ( url || s.url || location.href ) + "" ) + .replace( rprotocol, location.protocol + "//" ); + + // Alias method option to type as per ticket #12004 + s.type = options.method || options.type || s.method || s.type; + + // Extract dataTypes list + s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ]; + + // A cross-domain request is in order when the origin doesn't match the current origin. + if ( s.crossDomain == null ) { + urlAnchor = document.createElement( "a" ); + + // Support: IE <=8 - 11, Edge 12 - 15 + // IE throws exception on accessing the href property if url is malformed, + // e.g. http://example.com:80x/ + try { + urlAnchor.href = s.url; + + // Support: IE <=8 - 11 only + // Anchor's host property isn't correctly set when s.url is relative + urlAnchor.href = urlAnchor.href; + s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== + urlAnchor.protocol + "//" + urlAnchor.host; + } catch ( e ) { + + // If there is an error parsing the URL, assume it is crossDomain, + // it can be rejected by the transport if it is invalid + s.crossDomain = true; + } + } + + // Convert data if not already a string + if ( s.data && s.processData && typeof s.data !== "string" ) { + s.data = jQuery.param( s.data, s.traditional ); + } + + // Apply prefilters + inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); + + // If request was aborted inside a prefilter, stop there + if ( completed ) { + return jqXHR; + } + + // We can fire global events as of now if asked to + // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) + fireGlobals = jQuery.event && s.global; + + // Watch for a new set of requests + if ( fireGlobals && jQuery.active++ === 0 ) { + jQuery.event.trigger( "ajaxStart" ); + } + + // Uppercase the type + s.type = s.type.toUpperCase(); + + // Determine if request has content + s.hasContent = !rnoContent.test( s.type ); + + // Save the URL in case we're toying with the If-Modified-Since + // and/or If-None-Match header later on + // Remove hash to simplify url manipulation + cacheURL = s.url.replace( rhash, "" ); + + // More options handling for requests with no content + if ( !s.hasContent ) { + + // Remember the hash so we can put it back + uncached = s.url.slice( cacheURL.length ); + + // If data is available and should be processed, append data to url + if ( s.data && ( s.processData || typeof s.data === "string" ) ) { + cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data; + + // #9682: remove data so that it's not used in an eventual retry + delete s.data; + } + + // Add or update anti-cache param if needed + if ( s.cache === false ) { + cacheURL = cacheURL.replace( rantiCache, "$1" ); + uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce++ ) + uncached; + } + + // Put hash and anti-cache on the URL that will be requested (gh-1732) + s.url = cacheURL + uncached; + + // Change '%20' to '+' if this is encoded form body content (gh-2658) + } else if ( s.data && s.processData && + ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) { + s.data = s.data.replace( r20, "+" ); + } + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + if ( jQuery.lastModified[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); + } + if ( jQuery.etag[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); + } + } + + // Set the correct header, if data is being sent + if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { + jqXHR.setRequestHeader( "Content-Type", s.contentType ); + } + + // Set the Accepts header for the server, depending on the dataType + jqXHR.setRequestHeader( + "Accept", + s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ? + s.accepts[ s.dataTypes[ 0 ] ] + + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : + s.accepts[ "*" ] + ); + + // Check for headers option + for ( i in s.headers ) { + jqXHR.setRequestHeader( i, s.headers[ i ] ); + } + + // Allow custom headers/mimetypes and early abort + if ( s.beforeSend && + ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) { + + // Abort if not done already and return + return jqXHR.abort(); + } + + // Aborting is no longer a cancellation + strAbort = "abort"; + + // Install callbacks on deferreds + completeDeferred.add( s.complete ); + jqXHR.done( s.success ); + jqXHR.fail( s.error ); + + // Get transport + transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); + + // If no transport, we auto-abort + if ( !transport ) { + done( -1, "No Transport" ); + } else { + jqXHR.readyState = 1; + + // Send global event + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); + } + + // If request was aborted inside ajaxSend, stop there + if ( completed ) { + return jqXHR; + } + + // Timeout + if ( s.async && s.timeout > 0 ) { + timeoutTimer = window.setTimeout( function() { + jqXHR.abort( "timeout" ); + }, s.timeout ); + } + + try { + completed = false; + transport.send( requestHeaders, done ); + } catch ( e ) { + + // Rethrow post-completion exceptions + if ( completed ) { + throw e; + } + + // Propagate others as results + done( -1, e ); + } + } + + // Callback for when everything is done + function done( status, nativeStatusText, responses, headers ) { + var isSuccess, success, error, response, modified, + statusText = nativeStatusText; + + // Ignore repeat invocations + if ( completed ) { + return; + } + + completed = true; + + // Clear timeout if it exists + if ( timeoutTimer ) { + window.clearTimeout( timeoutTimer ); + } + + // Dereference transport for early garbage collection + // (no matter how long the jqXHR object will be used) + transport = undefined; + + // Cache response headers + responseHeadersString = headers || ""; + + // Set readyState + jqXHR.readyState = status > 0 ? 4 : 0; + + // Determine if successful + isSuccess = status >= 200 && status < 300 || status === 304; + + // Get response data + if ( responses ) { + response = ajaxHandleResponses( s, jqXHR, responses ); + } + + // Convert no matter what (that way responseXXX fields are always set) + response = ajaxConvert( s, response, jqXHR, isSuccess ); + + // If successful, handle type chaining + if ( isSuccess ) { + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + modified = jqXHR.getResponseHeader( "Last-Modified" ); + if ( modified ) { + jQuery.lastModified[ cacheURL ] = modified; + } + modified = jqXHR.getResponseHeader( "etag" ); + if ( modified ) { + jQuery.etag[ cacheURL ] = modified; + } + } + + // if no content + if ( status === 204 || s.type === "HEAD" ) { + statusText = "nocontent"; + + // if not modified + } else if ( status === 304 ) { + statusText = "notmodified"; + + // If we have data, let's convert it + } else { + statusText = response.state; + success = response.data; + error = response.error; + isSuccess = !error; + } + } else { + + // Extract error from statusText and normalize for non-aborts + error = statusText; + if ( status || !statusText ) { + statusText = "error"; + if ( status < 0 ) { + status = 0; + } + } + } + + // Set data for the fake xhr object + jqXHR.status = status; + jqXHR.statusText = ( nativeStatusText || statusText ) + ""; + + // Success/Error + if ( isSuccess ) { + deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); + } else { + deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); + } + + // Status-dependent callbacks + jqXHR.statusCode( statusCode ); + statusCode = undefined; + + if ( fireGlobals ) { + globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", + [ jqXHR, s, isSuccess ? success : error ] ); + } + + // Complete + completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); + + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); + + // Handle the global AJAX counter + if ( !( --jQuery.active ) ) { + jQuery.event.trigger( "ajaxStop" ); + } + } + } + + return jqXHR; + }, + + getJSON: function( url, data, callback ) { + return jQuery.get( url, data, callback, "json" ); + }, + + getScript: function( url, callback ) { + return jQuery.get( url, undefined, callback, "script" ); + } +} ); + +jQuery.each( [ "get", "post" ], function( i, method ) { + jQuery[ method ] = function( url, data, callback, type ) { + + // Shift arguments if data argument was omitted + if ( isFunction( data ) ) { + type = type || callback; + callback = data; + data = undefined; + } + + // The url can be an options object (which then must have .url) + return jQuery.ajax( jQuery.extend( { + url: url, + type: method, + dataType: type, + data: data, + success: callback + }, jQuery.isPlainObject( url ) && url ) ); + }; +} ); + + +jQuery._evalUrl = function( url, options ) { + return jQuery.ajax( { + url: url, + + // Make this explicit, since user can override this through ajaxSetup (#11264) + type: "GET", + dataType: "script", + cache: true, + async: false, + global: false, + + // Only evaluate the response if it is successful (gh-4126) + // dataFilter is not invoked for failure responses, so using it instead + // of the default converter is kludgy but it works. + converters: { + "text script": function() {} + }, + dataFilter: function( response ) { + jQuery.globalEval( response, options ); + } + } ); +}; + + +jQuery.fn.extend( { + wrapAll: function( html ) { + var wrap; + + if ( this[ 0 ] ) { + if ( isFunction( html ) ) { + html = html.call( this[ 0 ] ); + } + + // The elements to wrap the target around + wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); + + if ( this[ 0 ].parentNode ) { + wrap.insertBefore( this[ 0 ] ); + } + + wrap.map( function() { + var elem = this; + + while ( elem.firstElementChild ) { + elem = elem.firstElementChild; + } + + return elem; + } ).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( isFunction( html ) ) { + return this.each( function( i ) { + jQuery( this ).wrapInner( html.call( this, i ) ); + } ); + } + + return this.each( function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + } ); + }, + + wrap: function( html ) { + var htmlIsFunction = isFunction( html ); + + return this.each( function( i ) { + jQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html ); + } ); + }, + + unwrap: function( selector ) { + this.parent( selector ).not( "body" ).each( function() { + jQuery( this ).replaceWith( this.childNodes ); + } ); + return this; + } +} ); + + +jQuery.expr.pseudos.hidden = function( elem ) { + return !jQuery.expr.pseudos.visible( elem ); +}; +jQuery.expr.pseudos.visible = function( elem ) { + return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); +}; + + + + +jQuery.ajaxSettings.xhr = function() { + try { + return new window.XMLHttpRequest(); + } catch ( e ) {} +}; + +var xhrSuccessStatus = { + + // File protocol always yields status code 0, assume 200 + 0: 200, + + // Support: IE <=9 only + // #1450: sometimes IE returns 1223 when it should be 204 + 1223: 204 + }, + xhrSupported = jQuery.ajaxSettings.xhr(); + +support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); +support.ajax = xhrSupported = !!xhrSupported; + +jQuery.ajaxTransport( function( options ) { + var callback, errorCallback; + + // Cross domain only allowed if supported through XMLHttpRequest + if ( support.cors || xhrSupported && !options.crossDomain ) { + return { + send: function( headers, complete ) { + var i, + xhr = options.xhr(); + + xhr.open( + options.type, + options.url, + options.async, + options.username, + options.password + ); + + // Apply custom fields if provided + if ( options.xhrFields ) { + for ( i in options.xhrFields ) { + xhr[ i ] = options.xhrFields[ i ]; + } + } + + // Override mime type if needed + if ( options.mimeType && xhr.overrideMimeType ) { + xhr.overrideMimeType( options.mimeType ); + } + + // X-Requested-With header + // For cross-domain requests, seeing as conditions for a preflight are + // akin to a jigsaw puzzle, we simply never set it to be sure. + // (it can always be set on a per-request basis or even using ajaxSetup) + // For same-domain requests, won't change header if already provided. + if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) { + headers[ "X-Requested-With" ] = "XMLHttpRequest"; + } + + // Set headers + for ( i in headers ) { + xhr.setRequestHeader( i, headers[ i ] ); + } + + // Callback + callback = function( type ) { + return function() { + if ( callback ) { + callback = errorCallback = xhr.onload = + xhr.onerror = xhr.onabort = xhr.ontimeout = + xhr.onreadystatechange = null; + + if ( type === "abort" ) { + xhr.abort(); + } else if ( type === "error" ) { + + // Support: IE <=9 only + // On a manual native abort, IE9 throws + // errors on any property access that is not readyState + if ( typeof xhr.status !== "number" ) { + complete( 0, "error" ); + } else { + complete( + + // File: protocol always yields status 0; see #8605, #14207 + xhr.status, + xhr.statusText + ); + } + } else { + complete( + xhrSuccessStatus[ xhr.status ] || xhr.status, + xhr.statusText, + + // Support: IE <=9 only + // IE9 has no XHR2 but throws on binary (trac-11426) + // For XHR2 non-text, let the caller handle it (gh-2498) + ( xhr.responseType || "text" ) !== "text" || + typeof xhr.responseText !== "string" ? + { binary: xhr.response } : + { text: xhr.responseText }, + xhr.getAllResponseHeaders() + ); + } + } + }; + }; + + // Listen to events + xhr.onload = callback(); + errorCallback = xhr.onerror = xhr.ontimeout = callback( "error" ); + + // Support: IE 9 only + // Use onreadystatechange to replace onabort + // to handle uncaught aborts + if ( xhr.onabort !== undefined ) { + xhr.onabort = errorCallback; + } else { + xhr.onreadystatechange = function() { + + // Check readyState before timeout as it changes + if ( xhr.readyState === 4 ) { + + // Allow onerror to be called first, + // but that will not handle a native abort + // Also, save errorCallback to a variable + // as xhr.onerror cannot be accessed + window.setTimeout( function() { + if ( callback ) { + errorCallback(); + } + } ); + } + }; + } + + // Create the abort callback + callback = callback( "abort" ); + + try { + + // Do send the request (this may raise an exception) + xhr.send( options.hasContent && options.data || null ); + } catch ( e ) { + + // #14683: Only rethrow if this hasn't been notified as an error yet + if ( callback ) { + throw e; + } + } + }, + + abort: function() { + if ( callback ) { + callback(); + } + } + }; + } +} ); + + + + +// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432) +jQuery.ajaxPrefilter( function( s ) { + if ( s.crossDomain ) { + s.contents.script = false; + } +} ); + +// Install script dataType +jQuery.ajaxSetup( { + accepts: { + script: "text/javascript, application/javascript, " + + "application/ecmascript, application/x-ecmascript" + }, + contents: { + script: /\b(?:java|ecma)script\b/ + }, + converters: { + "text script": function( text ) { + jQuery.globalEval( text ); + return text; + } + } +} ); + +// Handle cache's special case and crossDomain +jQuery.ajaxPrefilter( "script", function( s ) { + if ( s.cache === undefined ) { + s.cache = false; + } + if ( s.crossDomain ) { + s.type = "GET"; + } +} ); + +// Bind script tag hack transport +jQuery.ajaxTransport( "script", function( s ) { + + // This transport only deals with cross domain or forced-by-attrs requests + if ( s.crossDomain || s.scriptAttrs ) { + var script, callback; + return { + send: function( _, complete ) { + script = jQuery( " + {% endmacro %} \ No newline at end of file diff --git a/docs/aberrations.html b/docs/aberrations.html index 6be38c603..815ed5afb 100644 --- a/docs/aberrations.html +++ b/docs/aberrations.html @@ -1,13 +1,13 @@ - + - aberrations — DeepTrack 2.0 documentation - + + - - + - - - - - + + + + + @@ -44,39 +40,44 @@ -
      @@ -273,14 +258,14 @@

      Documentation + diff --git a/docs/features.html b/docs/features.html index 7fadb7060..8b4e327e3 100644 --- a/docs/features.html +++ b/docs/features.html @@ -1,13 +1,13 @@ - + - features — DeepTrack 2.0 documentation - + + - - + - - - - - + + + + + @@ -44,40 +40,45 @@ -