diff --git a/.gitignore b/.gitignore index f2ae1102ba8b2bf060abea69901ef2a583f271d6..e76966fae0e2663403c0546db4a4b616ace52d0b 100755 --- a/.gitignore +++ b/.gitignore @@ -5,7 +5,6 @@ __pycache__ *==*==.ipynb stderr.txt stdout.txt -fidle/log/finished.json run/ figs/ data/ diff --git a/GTSRB/00-Test.ipynb b/GTSRB/00-Test.ipynb deleted file mode 100644 index 89bf5775b89e16754a8c43896feac8d652412bbe..0000000000000000000000000000000000000000 --- a/GTSRB/00-Test.ipynb +++ /dev/null @@ -1,233 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# TEST" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "<style>\n", - "\n", - "div.warn { \n", - " background-color: #fcf2f2;\n", - " border-color: #dFb5b4;\n", - " border-left: 5px solid #dfb5b4;\n", - " padding: 0.5em;\n", - " font-weight: bold;\n", - " font-size: 1.1em;;\n", - " }\n", - "\n", - "\n", - "\n", - "div.nota { \n", - " background-color: #DAFFDE;\n", - " border-left: 5px solid #92CC99;\n", - " padding: 0.5em;\n", - " }\n", - "\n", - "div.todo:before { content:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI1My44OTEyIiBoZWlnaHQ9IjE0My4zOTAyIiB2aWV3Qm94PSIwIDAgNTMuODkxMiAxNDMuMzkwMiI+PHRpdGxlPjAwLUJvYi10b2RvPC90aXRsZT48cGF0aCBkPSJNMjMuNDU2OCwxMTQuMzAxNmExLjgwNjMsMS44MDYzLDAsMSwxLDEuODE1NywxLjgyNEExLjgyMDksMS44MjA5LDAsMCwxLDIzLjQ1NjgsMTE0LjMwMTZabS0xMC42NjEyLDEuODIyQTEuODI3MiwxLjgyNzIsMCwxLDAsMTAuOTgsMTE0LjMsMS44MiwxLjgyLDAsMCwwLDEyLjc5NTYsMTE2LjEyMzZabS03LjcwNyw0LjU4NzR2LTVzLjQ4NjMtOS4xMjIzLDguMDIxNS0xMS45Njc1YTE5LjIwODIsMTkuMjA4MiwwLDAsMSw2LjA0ODYtMS4yNDU0LDE5LjE3NzgsMTkuMTc3OCwwLDAsMSw2LjA0ODcsMS4yNDc1YzcuNTM1MSwyLjgzNDcsOC4wMTc0LDExLjk2NzQsOC4wMTc0LDExLjk2NzR2NS4wMjM0bC4wMDQyLDcuNjgydjIuNGMuMDE2Ny4xOTkyLjAzMzYuMzkyMS4wMzM2LjU4NzEsMCwuMjEzOC0uMDE2OC40MTA5LS4wMzM2LjYzMzJ2LjA1ODdoLS4wMDg0YTguMzcxOSw4LjM3MTksMCwwLDEtNy4zNzM4LDcuNjU0N3MtLjk5NTMsMy42MzgtNi42OTMzLDMuNjM4LTYuNjkzNC0zLjYzOC02LjY5MzQtMy42MzhhOC4zNyw4LjM3LDAsMCwxLTcuMzcxNi03LjY1NDdINS4wODQzdi0uMDU4N2MtLjAxODktLjIyLS4wMjk0LS40MTk0LS4wMjk0LS42MzMyLDAtLjE5MjkuMDE2Ny0uMzgzNy4wMjk0LS41ODcxdi0yLjRtMTguMDkzNy00LjA0YTEuMTU2NSwxLjE1NjUsMCwxLDAtMi4zMTI2LDAsMS4xNTY0LDEuMTU2NCwwLDEsMCwyLjMxMjYsMFptNC4wODM0LDBhMS4xNTk1LDEuMTU5NSwwLDEsMC0xLjE2MzYsMS4xN0ExLjE3NSwxLjE3NSwwLDAsMCwyNy4yNjE0LDEyNC4zNzc5Wk05LjM3MzksMTE0LjYzNWMwLDMuMTA5MywyLjQxMzIsMy4zMSwyLjQxMzIsMy4zMWExMzMuOTI0MywxMzMuOTI0MywwLDAsMCwxNC43MzQ4LDBzMi40MTExLS4xOTI5LDIuNDExMS0zLjMxYTguMDc3Myw4LjA3NzMsMCwwLDAtMi40MTExLTUuNTUxOWMtNC41LTMuNTAzMy05LjkxMjYtMy41MDMzLTE0Ljc0MTEsMEE4LjA4NTEsOC4wODUxLDAsMCwwLDkuMzczOSwxMTQuNjM1WiIgc3R5bGU9ImZpbGw6IzAxMDEwMSIvPjxjaXJjbGUgY3g9IjMzLjE0MzYiIGN5PSIxMjQuNTM0IiByPSIzLjgzNjMiIHN0eWxlPSJmaWxsOiMwMTAxMDEiLz48cmVjdCB4PSIzNS42NjU5IiB5PSIxMTIuOTYyNSIgd2lkdGg9IjIuMDc3IiBoZWlnaHQ9IjEwLjU0NTgiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDIxLjYgMjQxLjExMjEpIHJvdGF0ZSgtMTU1Ljc0NikiIHN0eWxlPSJmaWxsOiMwMTAxMDEiLz48Y2lyY2xlIGN4PSIzOC44NzA0IiBjeT0iMTEzLjQyNzkiIHI9IjIuNDA4NSIgc3R5bGU9ImZpbGw6IzAxMDEwMSIvPjxjaXJjbGUgY3g9IjUuMjI0OCIgY3k9IjEyNC41MzQiIHI9IjMuODM2MyIgc3R5bGU9ImZpbGw6IzAxMDEwMSIvPjxyZWN0IHg9IjEuNDE2NCIgeT0iMTI0LjYzMDEiIHdpZHRoPSIyLjA3NyIgaGVpZ2h0PSIxMC41NDU4IiB0cmFuc2Zvcm09InRyYW5zbGF0ZSg0LjkwOTcgMjU5LjgwNikgcm90YXRlKC0xODApIiBzdHlsZT0iZmlsbDojMDEwMTAxIi8+PGNpcmNsZSBjeD0iMi40MDkxIiBjeT0iMTM3LjA5OTYiIHI9IjIuNDA4NSIgc3R5bGU9ImZpbGw6IzAxMDEwMSIvPjxwYXRoIGQ9Ik0xOC4wNTExLDEwMC4xMDY2aC0uMDE0NlYxMDIuNjFoMi4zdi0yLjQyNzlhMi40MjI5LDIuNDIyOSwwLDEsMC0yLjI4NTQtLjA3NTVaIiBzdHlsZT0iZmlsbDojMDEwMTAxIi8+PHBhdGggZD0iTTM5LjQyMTQsMjcuMjU4djEuMDVBMTEuOTQ1MiwxMS45NDUyLDAsMCwwLDQ0LjU5NTQsNS43OWEuMjQ0OS4yNDQ5LDAsMCwxLS4wMjM1LS40MjI3TDQ2Ljc1LDMuOTUxNWEuMzg5Mi4zODkyLDAsMCwxLC40MjYyLDAsMTQuODQ0MiwxNC44NDQyLDAsMCwxLTcuNzU0MywyNy4yNTkxdjEuMDY3YS40NS40NSwwLDAsMS0uNzA0Ny4zNzU4bC0zLjg0MTktMi41MWEuNDUuNDUsMCwwLDEsMC0uNzUxNmwzLjg0MTktMi41MWEuNDUuNDUsMCwwLDEsLjY5NDYuMzc1OFpNNDMuMjMsMi41ODkyLDM5LjM4NzguMDc5NGEuNDUuNDUsMCwwLDAtLjcwNDYuMzc1OHYxLjA2N2ExNC44NDQyLDE0Ljg0NDIsMCwwLDAtNy43NTQzLDI3LjI1OTEuMzg5LjM4OSwwLDAsMCwuNDI2MSwwbDIuMTc3Ny0xLjQxOTNhLjI0NS4yNDUsMCwwLDAtLjAyMzUtLjQyMjgsMTEuOTQ1MSwxMS45NDUxLDAsMCwxLDUuMTc0LTIyLjUxNDZ2MS4wNWEuNDUuNDUsMCwwLDAsLjcwNDYuMzc1OGwzLjg1NTMtMi41MWEuNDUuNDUsMCwwLDAsMC0uNzUxNlpNMzkuMDUyMywxNC4yNDU4YTIuMTIwNiwyLjEyMDYsMCwxLDAsMi4xMjA2LDIuMTIwNmgwQTIuMTI0LDIuMTI0LDAsMCwwLDM5LjA1MjMsMTQuMjQ1OFptNi4wNzMyLTQuNzc4MS44MjU0LjgyNTVhMS4wNTY4LDEuMDU2OCwwLDAsMSwuMTE3NSwxLjM0MjFsLS44MDIsMS4xNDQyYTcuMTAxOCw3LjEwMTgsMCwwLDEsLjcxMTQsMS43MTEybDEuMzc1Ny4yNDE2YTEuMDU2OSwxLjA1NjksMCwwLDEsLjg3NTcsMS4wNHYxLjE2NDNhMS4wNTY5LDEuMDU2OSwwLDAsMS0uODc1NywxLjA0bC0xLjM3MjQuMjQxNkE3LjExLDcuMTEsMCwwLDEsNDUuMjcsMTkuOTNsLjgwMTksMS4xNDQyYTEuMDU3LDEuMDU3LDAsMCwxLS4xMTc0LDEuMzQyMmwtLjgyODguODQ4OWExLjA1NywxLjA1NywwLDAsMS0xLjM0MjEuMTE3NGwtMS4xNDQyLS44MDE5YTcuMTMzOCw3LjEzMzgsMCwwLDEtMS43MTEzLjcxMTNsLS4yNDE2LDEuMzcyNGExLjA1NjgsMS4wNTY4LDAsMCwxLTEuMDQuODc1N0gzOC40Njg0YTEuMDU2OCwxLjA1NjgsMCwwLDEtMS4wNC0uODc1N2wtLjI0MTYtMS4zNzI0YTcuMTM1NSw3LjEzNTUsMCwwLDEtMS43MTEzLS43MTEzbC0xLjE0NDEuODAxOWExLjA1NzEsMS4wNTcxLDAsMCwxLTEuMzQyMi0uMTE3NGwtLjgzNTUtLjgyNTVhMS4wNTcsMS4wNTcsMCwwLDEtLjExNzQtMS4zNDIxbC44MDE5LTEuMTQ0MmE3LjEyMSw3LjEyMSwwLDAsMS0uNzExMy0xLjcxMTJsLTEuMzcyNC0uMjQxNmExLjA1NjksMS4wNTY5LDAsMCwxLS44NzU3LTEuMDRWMTUuNzgyNmExLjA1NjksMS4wNTY5LDAsMCwxLC44NzU3LTEuMDRsMS4zNzU3LS4yNDE2YTcuMTEsNy4xMSwwLDAsMSwuNzExNC0xLjcxMTJsLS44MDItMS4xNDQyYTEuMDU3LDEuMDU3LDAsMCwxLC4xMTc1LTEuMzQyMmwuODI1NC0uODI1NEExLjA1NjgsMS4wNTY4LDAsMCwxLDM0LjMyNDUsOS4zNmwxLjE0NDIuODAxOUE3LjEzNTUsNy4xMzU1LDAsMCwxLDM3LjE4LDkuNDUxbC4yNDE2LTEuMzcyNGExLjA1NjgsMS4wNTY4LDAsMCwxLDEuMDQtLjg3NTdoMS4xNjc3YTEuMDU2OSwxLjA1NjksMCwwLDEsMS4wNC44NzU3bC4yNDE2LDEuMzcyNGE3LjEyNSw3LjEyNSwwLDAsMSwxLjcxMTIuNzExM0w0My43NjY2LDkuMzZBMS4wNTY5LDEuMDU2OSwwLDAsMSw0NS4xMjU1LDkuNDY3N1ptLTIuMDMsNi44OTg3QTQuMDQzMyw0LjA0MzMsMCwxLDAsMzkuMDUyMywyMC40MWgwQTQuMDQ2NSw0LjA0NjUsMCwwLDAsNDMuMDk1NSwxNi4zNjY0WiIgc3R5bGU9ImZpbGw6I2UxMjIyOSIvPjxwb2x5Z29uIHBvaW50cz0iMzkuNDEzIDM0Ljc1NyAzOS41MzcgMzQuNzU3IDM5LjY3NSAzNC43NTcgMzkuNjc1IDEwOS41MSAzOS41MzcgMTA5LjUxIDM5LjQxMyAxMDkuNTEgMzkuNDEzIDM0Ljc1NyAzOS40MTMgMzQuNzU3IiBzdHlsZT0iZmlsbDpub25lO3N0cm9rZTojOTk5O3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1taXRlcmxpbWl0OjEwO3N0cm9rZS13aWR0aDowLjMwODg1NDQ1MDU2MDE2MThweDtmaWxsLXJ1bGU6ZXZlbm9kZCIvPjwvc3ZnPg==);\n", - " float:left;\n", - " margin-right:20px;\n", - " margin-top:-20px;\n", - " margin-bottom:20px;\n", - "}\n", - "div.todo{\n", - " font-weight: bold;\n", - " font-size: 1.1em;\n", - " margin-top:40px;\n", - "}\n", - "div.todo ul{\n", - " margin: 0.2em;\n", - "}\n", - "div.todo li{\n", - " margin-left:60px;\n", - " margin-top:0;\n", - " margin-bottom:0;\n", - "}\n", - "\n", - "div .comment{\n", - " font-size:0.8em;\n", - " color:#696969;\n", - "}\n", - "\n", - "\n", - "\n", - "</style>\n", - "\n" - ], - "text/plain": [ - "<IPython.core.display.HTML object>" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/markdown": [ - "<br>**FIDLE 2020 - Practical Work Module**" - ], - "text/plain": [ - "<IPython.core.display.Markdown object>" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Version : 1.2b1 DEV\n", - "Notebook id : GTSRB0\n", - "Run time : Saturday 9 January 2021, 18:01:32\n", - "TensorFlow version : 2.2.0\n", - "Keras version : 2.3.0-tf\n", - "Datasets dir : /home/pjluc/datasets/fidle\n", - "Run dir : ./run/GTSRB0\n", - "Update keras cache : False\n", - "Save figs : True\n", - "Path figs : ./run/GTSRB0/figs\n" - ] - } - ], - "source": [ - "import os, time, sys\n", - "import csv\n", - "import math, random\n", - "\n", - "import numpy as np\n", - "import pandas as pd\n", - "import matplotlib.pyplot as plt\n", - "import h5py\n", - "\n", - "from skimage.morphology import disk\n", - "from skimage.util import img_as_ubyte\n", - "from skimage.filters import rank\n", - "from skimage import io, color, exposure, transform\n", - "\n", - "from importlib import reload\n", - "\n", - "sys.path.append('..')\n", - "import fidle.pwk as pwk\n", - "\n", - "run_dir='./run/GTSRB0'\n", - "datasets_dir = pwk.init('GTSRB0', run_dir)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Step 2 - Parameters" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "# ---- For smart tests :\n", - "#\n", - "scale = 1\n", - "output_dir = './data' \n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Override parameters (batch mode) - Just forget this cell" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "pwk.override('scale', 'output_dir')" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "scale : 1\n", - "output_dir : ./data\n", - "run_dir : ./run/GTSRB0\n" - ] - } - ], - "source": [ - "print('scale : ', scale)\n", - "print('output_dir : ', output_dir)\n", - "print('run_dir : ', run_dir)" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'/home/pjluc/dev/fidle/GTSRB'" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "import os\n", - "os.getcwd()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.7.9" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/LinearReg/01-Linear-Regression.ipynb b/LinearReg/01-Linear-Regression.ipynb index 7229a69334565407ae157efc0bc0d0166b6e85b5..d47cb0a34d401fd31208bfdb7f4a7e4cd432f0f3 100644 --- a/LinearReg/01-Linear-Regression.ipynb +++ b/LinearReg/01-Linear-Regression.ipynb @@ -94,7 +94,7 @@ { "data": { "text/markdown": [ - "**FIDLE 2020 - Practical Work Module**" + "<br>**FIDLE 2020 - Practical Work Module**" ], "text/plain": [ "<IPython.core.display.Markdown object>" @@ -107,13 +107,13 @@ "name": "stdout", "output_type": "stream", "text": [ - "Version : 0.6.1 DEV\n", + "Version : 1.2b1 DEV\n", "Notebook id : LINR1\n", - "Run time : Thursday 17 December 2020, 16:30:24\n", - "TensorFlow version : 2.1.0\n", - "Keras version : 2.2.4-tf\n", - "Datasets dir : /gpfswork/rech/mlh/uja62cb/datasets\n", - "Running mode : full\n", + "Run time : Sunday 10 January 2021, 21:51:29\n", + "TensorFlow version : 2.2.0\n", + "Keras version : 2.3.0-tf\n", + "Datasets dir : /home/pjluc/datasets/fidle\n", + "Run dir : ./run\n", "Update keras cache : False\n" ] } @@ -185,7 +185,7 @@ "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ "<Figure size 864x432 with 1 Axes>" ] @@ -241,8 +241,8 @@ " [2]] \n", "\n", "theta hat :\n", - " [[6.57350113]\n", - " [1.53229674]]\n" + " [[3.60312881]\n", + " [1.99988269]]\n" ] } ], @@ -266,7 +266,7 @@ "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ "<Figure size 864x432 with 1 Axes>" ] @@ -299,8 +299,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "End time is : Thursday 17 December 2020, 16:30:38\n", - "Duration is : 00:00:13 289ms\n", + "End time is : Sunday 10 January 2021, 21:51:29\n", + "Duration is : 00:00:00 308ms\n", "This notebook ends here\n" ] } diff --git a/README.ipynb b/README.ipynb index 1edfa1efcfe55cb58b6da6d7bf4889a00314a927..dd5f7df5af6a23452a9bb4ab7c2460e0b6845d5c 100644 --- a/README.ipynb +++ b/README.ipynb @@ -5,10 +5,10 @@ "execution_count": 1, "metadata": { "execution": { - "iopub.execute_input": "2021-01-09T18:32:21.410112Z", - "iopub.status.busy": "2021-01-09T18:32:21.409590Z", - "iopub.status.idle": "2021-01-09T18:32:21.417639Z", - "shell.execute_reply": "2021-01-09T18:32:21.417225Z" + "iopub.execute_input": "2021-01-10T20:53:42.241597Z", + "iopub.status.busy": "2021-01-10T20:53:42.241103Z", + "iopub.status.idle": "2021-01-10T20:53:42.245307Z", + "shell.execute_reply": "2021-01-10T20:53:42.244901Z" }, "jupyter": { "source_hidden": true @@ -85,8 +85,6 @@ "An example of classification using a dense neural network for the famous MNIST dataset\n", "\n", "### Images classification with Convolutional Neural Networks (CNN)\n", - "- **[??](GTSRB/00-Test.ipynb)** - [??](GTSRB/00-Test.ipynb) \n", - "??\n", "- **[GTSRB1](GTSRB/01-Preparation-of-data.ipynb)** - [Dataset analysis and preparation](GTSRB/01-Preparation-of-data.ipynb) \n", "Episode 1 : Analysis of the GTSRB dataset and creation of an enhanced dataset\n", "- **[GTSRB2](GTSRB/02-First-convolutions.ipynb)** - [First convolutions](GTSRB/02-First-convolutions.ipynb) \n", diff --git a/README.md b/README.md index 95fce7bd865bfa59af79f571d295cd4d4fd9c35d..1baaa8e12620e2040aebc5d8f3d45bd607233dcd 100644 --- a/README.md +++ b/README.md @@ -65,8 +65,6 @@ A more advanced implementation of the precedent example An example of classification using a dense neural network for the famous MNIST dataset ### Images classification with Convolutional Neural Networks (CNN) -- **[??](GTSRB/00-Test.ipynb)** - [??](GTSRB/00-Test.ipynb) -?? - **[GTSRB1](GTSRB/01-Preparation-of-data.ipynb)** - [Dataset analysis and preparation](GTSRB/01-Preparation-of-data.ipynb) Episode 1 : Analysis of the GTSRB dataset and creation of an enhanced dataset - **[GTSRB2](GTSRB/02-First-convolutions.ipynb)** - [First convolutions](GTSRB/02-First-convolutions.ipynb) diff --git a/fidle/01 - Set and reset.ipynb b/fidle/01 - Update index.ipynb similarity index 94% rename from fidle/01 - Set and reset.ipynb rename to fidle/01 - Update index.ipynb index b5065b10011a140e508522e9e078c6681263d453..571142bd5a623a5a35d5edb576f10a361673d10e 100644 --- a/fidle/01 - Set and reset.ipynb +++ b/fidle/01 - Update index.ipynb @@ -8,10 +8,13 @@ "\n", "\n", "## Mise a jour du catalog des notebooks et des READMEs\n", - " - Génération du **catalog des notebooks** : `./log/catalog_nb.json`\n", - " - Génération automatique de la **table des matières**\n", - " - Mise à jour des **README** `README.md` et `REAME.ipynb`\n", - " - #Reset du **finihed_file**\n", + " - Génération du **catalog des notebooks** : [./logs/catalog.json](./logs/catalog.json) \n", + " Ce fichier comporte une liste détaillée de tous les notebooks et scripts.\n", + " \n", + " \n", + " - Génération automatique de la table des matières et mise à jour des **README**\n", + " - [README.md](../README.md)\n", + " - [README.ipynb](../README.ipynb)\n", "\n" ] }, @@ -42,14 +45,15 @@ "sys.path.append('..')\n", "import fidle.pwk as pwk\n", "import fidle.config as config\n", - "import fidle.cooker as cooker\n" + "import fidle.cookindex as cookindex\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Step 2 - List of folders containing notebooks to be indexed :" + "## Step 2 - List of folders containing notebooks to be indexed :\n", + "Order wil be index order" ] }, { @@ -88,19 +92,19 @@ "name": "stdout", "output_type": "stream", "text": [ - "Catalog saved as ../fidle/log/catalog.json\n", - "Entries : 37\n" + "Catalog saved as ../fidle/logs/catalog.json\n", + "Entries : 36\n" ] } ], "source": [ "# ---- Get the notebook list\n", "#\n", - "files_list = cooker.get_files(directories_to_index.keys())\n", + "files_list = cookindex.get_files(directories_to_index.keys())\n", "\n", "# ---- Get a detailled catalog for this list\n", "#\n", - "catalog = cooker.get_catalog(files_list)\n", + "catalog = cookindex.get_catalog(files_list)\n", "\n", "with open(config.CATALOG_FILE,'wt') as fp:\n", " json.dump(catalog,fp,indent=4)\n", @@ -161,8 +165,6 @@ "An example of classification using a dense neural network for the famous MNIST dataset\n", "\n", "### Images classification with Convolutional Neural Networks (CNN)\n", - "- **[??](GTSRB/00-Test.ipynb)** - [??](GTSRB/00-Test.ipynb) \n", - "??\n", "- **[GTSRB1](GTSRB/01-Preparation-of-data.ipynb)** - [Dataset analysis and preparation](GTSRB/01-Preparation-of-data.ipynb) \n", "Episode 1 : Analysis of the GTSRB dataset and creation of an enhanced dataset\n", "- **[GTSRB2](GTSRB/02-First-convolutions.ipynb)** - [First convolutions](GTSRB/02-First-convolutions.ipynb) \n", @@ -308,8 +310,8 @@ " \n", "# ---- Update index, version\n", "#\n", - "readme = cooker.tag('INDEX', index_md, readme)\n", - "readme = cooker.tag('VERSION', config.VERSION, readme)\n", + "readme = cookindex.tag('INDEX', index_md, readme)\n", + "readme = cookindex.tag('VERSION', config.VERSION, readme)\n", "\n", "# ---- Save it\n", "#\n", @@ -407,22 +409,6 @@ "print('README.ipynb built and saved')" ] }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Step 7 - Reset Finished_file" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [], - "source": [ - "# pwk.reset_finished_file()" - ] - }, { "cell_type": "markdown", "metadata": {}, diff --git a/fidle/02 - Running test.ipynb b/fidle/02 - Running test.ipynb index 0076fa2d43c32e7663e3f99b5ad0f02010d4dfa1..bce3a2538b43833362b9f35c244258243094ae60 100644 --- a/fidle/02 - Running test.ipynb +++ b/fidle/02 - Running test.ipynb @@ -7,14 +7,19 @@ "<img width=\"800px\" src=\"../fidle/img/00-Fidle-header-01.svg\"></img>\n", "\n", "\n", - "## Continuous integration report\n", + "# Gestion des tests d'intégration continue\n", "\n", - "Each notebook indicates its start and end of execution:\n", - " - at the beginning, with `pwk.init()`\n", - " - at the end, with `pwk.end()` \n", - " \n", - "All of theses informations are saved in a json file - Final report is below and in a HTML file. \n", - "See ./log" + "**La liste des notebooks a éxécuter** et de leurs paramètres (override) est définie dans un **profile**. \n", + " - Un profile est un fichier yaml\n", + " - Un profile par défaut est généré en (1).\n", + "\n", + "Lorqu'un **profile** est prêt, il peut être soumis pour **éxécution** (2)\n", + " - Pour chaque notebook, les paramètres sont positionnés (variables d'env.)\n", + " - Le notebook est lu, puis éxécuté\n", + " - Après éxécution, le notebook est sauvegardé sous son nom moodifié (output_tag)\n", + "\n", + "Un **rapport d'éxécution** est généré durant l'éxécution des tests : [./logs/ci_report.json](./logs/ci_report.json) \n", + "A la fin des tests, ce rapport peut être visualisé via le notebook : [./03-ci_report.ipynb](./03%20-%20ci_report.ipynb)\n" ] }, { @@ -23,46 +28,84 @@ "metadata": {}, "outputs": [], "source": [ - "import sys,os\n", - "import json\n", - "import datetime, time\n", - "import nbformat\n", - "from nbconvert.preprocessors import ExecutePreprocessor\n", - "import re\n", - "import yaml\n", - "from collections import OrderedDict\n", - "from IPython.display import display\n", - "sys.path.append('..')\n", - "import fidle.config as config\n", - "import fidle.cooker as cooker" + "import cookci" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Get and Save default profile\n", + "Génère un profile par défaut comprenant tous les notebooks du moment... \n", + "...en tout cas présent dans catalog.json ;-)" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Catalog saved as ./ci/default.yml\n", + "Entries : 36\n" + ] + } + ], + "source": [ + "profile = cookci.get_ci_profile()\n", + "cookci.save_profile(profile, './ci/default.yml')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Load a saved profile" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "./ci/smart.yml loaded.\n", - "Entries : 4\n", + "Entries : 3\n" + ] + } + ], + "source": [ + "smart_profile = cookci.load_profile('./ci/smart.yml')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Run this profile" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ "\n", "Notebook : LINR1\n", " Run notebook.....done.\n", " Duration : 0:00:04\n", " Saved as : 01-Linear-Regression==done==.ipynb\n", "\n", - "Notebook : GTSRB0\n", - " set overrides :\n", - " FIDLE_OVERRIDE_GTSRB0_scale = 0.7\n", - " FIDLE_OVERRIDE_GTSRB0_output_dir = ./data/foobar\n", - " FIDLE_OVERRIDE_GTSRB0_run_dir = ./run/xxx\n", - " Run notebook.....done.\n", - " Duration : 0:00:02\n", - " Saved as : 00-Test==done==.ipynb\n", - "\n", "Notebook : GTSRB1\n", " set overrides :\n", " FIDLE_OVERRIDE_GTSRB1_scale = 0.1\n", @@ -78,159 +121,46 @@ " FIDLE_OVERRIDE_GTSRB2_batch_size = 32\n", " FIDLE_OVERRIDE_GTSRB2_epochs = 3\n", " FIDLE_OVERRIDE_GTSRB2_scale = 1\n", - " Run notebook.....done.\n", - " Duration : 0:03:02\n", - " Saved as : 02-First-convolutions==done==.ipynb\n" + " Run notebook..." + ] + }, + { + "ename": "DeadKernelError", + "evalue": "Kernel died", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mCancelledError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m~/anaconda3/envs/fidle/lib/python3.7/site-packages/nbclient/client.py\u001b[0m in \u001b[0;36masync_execute_cell\u001b[0;34m(self, cell, cell_index, execution_count, store_history)\u001b[0m\n\u001b[1;32m 815\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 816\u001b[0;31m \u001b[0mexec_reply\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;32mawait\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtask_poll_for_reply\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 817\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0masyncio\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mCancelledError\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/anaconda3/envs/fidle/lib/python3.7/asyncio/futures.py\u001b[0m in \u001b[0;36m__await__\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 262\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_asyncio_future_blocking\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;32mTrue\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 263\u001b[0;31m \u001b[0;32myield\u001b[0m \u001b[0mself\u001b[0m \u001b[0;31m# This tells Task to wait for completion.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 264\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdone\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/anaconda3/envs/fidle/lib/python3.7/asyncio/tasks.py\u001b[0m in \u001b[0;36m__wakeup\u001b[0;34m(self, future)\u001b[0m\n\u001b[1;32m 317\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 318\u001b[0;31m \u001b[0mfuture\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mresult\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 319\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mException\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0mexc\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/anaconda3/envs/fidle/lib/python3.7/asyncio/futures.py\u001b[0m in \u001b[0;36mresult\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 175\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_state\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0m_CANCELLED\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 176\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mCancelledError\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 177\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_state\u001b[0m \u001b[0;34m!=\u001b[0m \u001b[0m_FINISHED\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mCancelledError\u001b[0m: ", + "\nDuring handling of the above exception, another exception occurred:\n", + "\u001b[0;31mDeadKernelError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m<ipython-input-4-36d9a3afb9e4>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mcookci\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrun_profile\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0msmart_profile\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;32m~/dev/fidle/fidle/cookci.py\u001b[0m in \u001b[0;36mrun_profile\u001b[0;34m(profile, top_dir)\u001b[0m\n\u001b[1;32m 165\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m' Run notebook...'\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mend\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m''\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 166\u001b[0m \u001b[0mep\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mExecutePreprocessor\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtimeout\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m600\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mkernel_name\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m\"python3\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 167\u001b[0;31m \u001b[0mep\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpreprocess\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnotebook\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 168\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'..done.'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 169\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/anaconda3/envs/fidle/lib/python3.7/site-packages/nbconvert/preprocessors/execute.py\u001b[0m in \u001b[0;36mpreprocess\u001b[0;34m(self, nb, resources, km)\u001b[0m\n\u001b[1;32m 77\u001b[0m \u001b[0mNotebookClient\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__init__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnb\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mkm\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 78\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_check_assign_resources\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mresources\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 79\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mexecute\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 80\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnb\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mresources\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 81\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/anaconda3/envs/fidle/lib/python3.7/site-packages/nbclient/util.py\u001b[0m in \u001b[0;36mwrapped\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m 72\u001b[0m \"\"\"\n\u001b[1;32m 73\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mwrapped\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 74\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mjust_run\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcoro\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 75\u001b[0m \u001b[0mwrapped\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__doc__\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mcoro\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__doc__\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 76\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mwrapped\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/anaconda3/envs/fidle/lib/python3.7/site-packages/nbclient/util.py\u001b[0m in \u001b[0;36mjust_run\u001b[0;34m(coro)\u001b[0m\n\u001b[1;32m 51\u001b[0m \u001b[0mnest_asyncio\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mapply\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 52\u001b[0m \u001b[0mcheck_patch_tornado\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 53\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mloop\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrun_until_complete\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcoro\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 54\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 55\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/anaconda3/envs/fidle/lib/python3.7/site-packages/nest_asyncio.py\u001b[0m in \u001b[0;36mrun_until_complete\u001b[0;34m(self, future)\u001b[0m\n\u001b[1;32m 96\u001b[0m raise RuntimeError(\n\u001b[1;32m 97\u001b[0m 'Event loop stopped before Future completed.')\n\u001b[0;32m---> 98\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mf\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mresult\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 99\u001b[0m \u001b[0;32mfinally\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 100\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_thread_id\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mold_thread_id\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/anaconda3/envs/fidle/lib/python3.7/asyncio/futures.py\u001b[0m in \u001b[0;36mresult\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 179\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__log_traceback\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;32mFalse\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 180\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_exception\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 181\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_exception\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 182\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_result\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 183\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/anaconda3/envs/fidle/lib/python3.7/asyncio/tasks.py\u001b[0m in \u001b[0;36m__step\u001b[0;34m(***failed resolving arguments***)\u001b[0m\n\u001b[1;32m 247\u001b[0m \u001b[0;31m# We use the `send` method directly, because coroutines\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 248\u001b[0m \u001b[0;31m# don't have `__iter__` and `__next__` methods.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 249\u001b[0;31m \u001b[0mresult\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mcoro\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 250\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 251\u001b[0m \u001b[0mresult\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mcoro\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mthrow\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mexc\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/anaconda3/envs/fidle/lib/python3.7/site-packages/nbclient/client.py\u001b[0m in \u001b[0;36masync_execute\u001b[0;34m(self, reset_kc, **kwargs)\u001b[0m\n\u001b[1;32m 539\u001b[0m \u001b[0;31m# when store_history is False\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 540\u001b[0m await self.async_execute_cell(\n\u001b[0;32m--> 541\u001b[0;31m \u001b[0mcell\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mindex\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mexecution_count\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcode_cells_executed\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 542\u001b[0m )\n\u001b[1;32m 543\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mset_widgets_metadata\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/anaconda3/envs/fidle/lib/python3.7/site-packages/nbconvert/preprocessors/execute.py\u001b[0m in \u001b[0;36masync_execute_cell\u001b[0;34m(self, cell, cell_index, execution_count, store_history)\u001b[0m\n\u001b[1;32m 121\u001b[0m \u001b[0;31m# Copied and intercepted to allow for custom preprocess_cell contracts to be fullfilled\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 122\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mstore_history\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mstore_history\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 123\u001b[0;31m \u001b[0mcell\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mresources\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpreprocess_cell\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcell\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mresources\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcell_index\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 124\u001b[0m \u001b[0;31m# Apply rules from nbclient for where to apply execution counts\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 125\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mexecution_count\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0mcell\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcell_type\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;34m'code'\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0mcell\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msource\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mstrip\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/anaconda3/envs/fidle/lib/python3.7/site-packages/nbconvert/preprocessors/execute.py\u001b[0m in \u001b[0;36mpreprocess_cell\u001b[0;34m(self, cell, resources, index, **kwargs)\u001b[0m\n\u001b[1;32m 144\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_check_assign_resources\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mresources\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 145\u001b[0m \u001b[0;31m# Because nbclient is an async library, we need to wrap the parent async call to generate a syncronous version.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 146\u001b[0;31m \u001b[0mcell\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mrun_sync\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mNotebookClient\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0masync_execute_cell\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcell\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mindex\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mstore_history\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mstore_history\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 147\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mcell\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mresources\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/anaconda3/envs/fidle/lib/python3.7/site-packages/nbclient/util.py\u001b[0m in \u001b[0;36mwrapped\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m 72\u001b[0m \"\"\"\n\u001b[1;32m 73\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mwrapped\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 74\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mjust_run\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcoro\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 75\u001b[0m \u001b[0mwrapped\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__doc__\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mcoro\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__doc__\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 76\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mwrapped\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/anaconda3/envs/fidle/lib/python3.7/site-packages/nbclient/util.py\u001b[0m in \u001b[0;36mjust_run\u001b[0;34m(coro)\u001b[0m\n\u001b[1;32m 51\u001b[0m \u001b[0mnest_asyncio\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mapply\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 52\u001b[0m \u001b[0mcheck_patch_tornado\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 53\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mloop\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrun_until_complete\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcoro\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 54\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 55\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/anaconda3/envs/fidle/lib/python3.7/site-packages/nest_asyncio.py\u001b[0m in \u001b[0;36mrun_until_complete\u001b[0;34m(self, future)\u001b[0m\n\u001b[1;32m 96\u001b[0m raise RuntimeError(\n\u001b[1;32m 97\u001b[0m 'Event loop stopped before Future completed.')\n\u001b[0;32m---> 98\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mf\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mresult\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 99\u001b[0m \u001b[0;32mfinally\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 100\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_thread_id\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mold_thread_id\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/anaconda3/envs/fidle/lib/python3.7/asyncio/futures.py\u001b[0m in \u001b[0;36mresult\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 179\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__log_traceback\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;32mFalse\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 180\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_exception\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 181\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_exception\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 182\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_result\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 183\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/anaconda3/envs/fidle/lib/python3.7/asyncio/tasks.py\u001b[0m in \u001b[0;36m__step\u001b[0;34m(***failed resolving arguments***)\u001b[0m\n\u001b[1;32m 249\u001b[0m \u001b[0mresult\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mcoro\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 250\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 251\u001b[0;31m \u001b[0mresult\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mcoro\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mthrow\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mexc\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 252\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mStopIteration\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0mexc\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 253\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_must_cancel\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/anaconda3/envs/fidle/lib/python3.7/site-packages/nbclient/client.py\u001b[0m in \u001b[0;36masync_execute_cell\u001b[0;34m(self, cell, cell_index, execution_count, store_history)\u001b[0m\n\u001b[1;32m 818\u001b[0m \u001b[0;31m# can only be cancelled by task_poll_kernel_alive when the kernel is dead\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 819\u001b[0m \u001b[0mtask_poll_output_msg\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcancel\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 820\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mDeadKernelError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Kernel died\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 821\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mException\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0me\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 822\u001b[0m \u001b[0;31m# Best effort to cancel request if it hasn't been resolved\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mDeadKernelError\u001b[0m: Kernel died" ] } ], "source": [ - "\n", - "_start_time=None\n", - "\n", - "def get_profile(existant_config=None, output_tag='==done==', save_figs=True):\n", - " \n", - " catalog = cooker.read_catalog()\n", - "\n", - " config = {'version':'1.0', 'output_tag':output_tag, 'save_figs':save_figs}\n", - " profile = { 'config':config }\n", - " for id, about in catalog.items():\n", - " \n", - " id = about['id']\n", - " title = about['title']\n", - " dirname = about['dirname']\n", - " basename = about['basename']\n", - " overrides = about.get('overrides',None)\n", - " \n", - " notebook = {}\n", - " notebook['notebook_dir'] = dirname\n", - " notebook['notebook_src'] = basename\n", - " notebook['notebook_out'] = 'default'\n", - " if len(overrides)>0:\n", - " notebook['overrides']={ name:'default' for name in overrides }\n", - " \n", - " profile[id]=notebook\n", - " \n", - " return profile\n", - "\n", - "\n", - "def save_profile(profile, filename):\n", - " with open(filename,'wt') as fp:\n", - " yaml.dump(profile, fp, sort_keys=False)\n", - " print(f'Catalog saved as {filename}')\n", - " print('Entries : ',len(profile)-1)\n", - "\n", - "def load_profile(filename):\n", - " with open(filename,'r') as fp:\n", - " profile=yaml.load(fp, Loader=yaml.FullLoader)\n", - " print(f'{filename} loaded.')\n", - " print('Entries : ',len(profile)-1)\n", - " return profile\n", - " \n", - "def chrono_start():\n", - " global _start_time\n", - " _start_time = time.time()\n", - "\n", - "def chrono_hdelay():\n", - " global _start_time\n", - " delay=int( time.time() - _start_time )\n", - " return str(datetime.timedelta(seconds=delay))\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "def run_profile(profile, top_dir='..'):\n", - "\n", - " # ---- My place\n", - " #\n", - " home = os.getcwd()\n", - " \n", - " # ---- Read profile\n", - " #\n", - " config = profile['config']\n", - " notebooks = profile\n", - " del notebooks['config']\n", - " \n", - " # ---- Save figs or not ?\n", - " #\n", - " os.environ['FIDLE_SAVE_FIGS']=str(config['save_figs'])\n", - "\n", - " # ---- For each notebook\n", - " #\n", - " for id,about in notebooks.items():\n", - " \n", - " print(f'\\nNotebook : {id}')\n", - "\n", - " # ---- Get notebook infos ---------------------------------------------\n", - " #\n", - " notebook_dir = about['notebook_dir']\n", - " notebook_src = about['notebook_src']\n", - " notebook_out = about['notebook_out']\n", - " overrides = about.get('overrides',None)\n", - "\n", - " # ---- notebook_out (Default)\n", - " #\n", - " if notebook_out=='default':\n", - " notebook_out = notebook_src.replace('.ipynb', config['output_tag']+'.ipynb')\n", - " \n", - " # ---- Override ------------------------------------------------------- \n", - " \n", - " to_unset=[]\n", - " if isinstance(overrides,dict):\n", - " print(' set overrides :')\n", - " for name,value in overrides.items():\n", - " # ---- Default : no nothing\n", - " if value=='default' : continue\n", - " # ---- Set env\n", - " env_name = f'FIDLE_OVERRIDE_{id.upper()}_{name}'\n", - " env_value = str(value)\n", - " os.environ[env_name] = env_value\n", - " # ---- For cleaning\n", - " to_unset.append(env_name)\n", - " # ---- Fine :(-)\n", - " print(f' {env_name:38s} = {env_value}')\n", - " \n", - " # ---- Run it ! -------------------------------------------------------\n", - " \n", - " # ---- Go to the right place\n", - " #\n", - " os.chdir(f'{top_dir}/{notebook_dir}')\n", - " notebook = nbformat.read( f'{notebook_src}', nbformat.NO_CONVERT)\n", - "\n", - " print(' Run notebook...',end='')\n", - " ep = ExecutePreprocessor(timeout=600, kernel_name=\"python3\")\n", - " chrono_start()\n", - " ep.preprocess(notebook)\n", - " print('..done.')\n", - " print(' Duration : ',chrono_hdelay() )\n", - " \n", - " # ---- Save it\n", - " #\n", - " with open( f'{notebook_out}', mode=\"w\", encoding='utf-8') as fp:\n", - " nbformat.write(notebook, fp)\n", - " print(' Saved as : ',notebook_out)\n", - " \n", - " # ---- Back to home and clean\n", - " #\n", - " os.chdir(home)\n", - " for env_name in to_unset:\n", - " del os.environ[env_name] \n", - " \n", - " \n", - "# ---- Save profile\n", - " \n", - "# profile = get_profile()\n", - "# save_profile(profile, './ci/default.yml')\n", - "# profile=load_profile('./ci/default.yml')\n", - " \n", - " \n", - "# ---- Run profile \n", - " \n", - "profile = load_profile('./ci/smart.yml')\n", - "\n", - "run_profile(profile)\n", - "\n" + "cookci.run_profile(smart_profile)" ] }, { @@ -240,20 +170,6 @@ "---\n", "<img width=\"80px\" src=\"../fidle/img/00-Fidle-logo-01.svg\"></img>" ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { diff --git a/fidle/03 - Finished report.ipynb b/fidle/03 - ci_report.ipynb similarity index 57% rename from fidle/03 - Finished report.ipynb rename to fidle/03 - ci_report.ipynb index f397cbc5c449bad0c3e2ed44baf276b8ffc04bb6..6403c5a2cd155a2d48faebf348ed97e1e261d0da 100644 --- a/fidle/03 - Finished report.ipynb +++ b/fidle/03 - ci_report.ipynb @@ -17,16 +17,6 @@ "See ./log" ] }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import sys\n", - "import cooker as cooker" - ] - }, { "cell_type": "code", "execution_count": 2, @@ -36,142 +26,142 @@ "data": { "text/html": [ "<style type=\"text/css\" >\n", - " #T_8a68a_ td {\n", + " #T_15a01_ td {\n", " font-size: 110%;\n", " text-align: left;\n", - " } #T_8a68a_ th {\n", + " } #T_15a01_ th {\n", " font-size: 110%;\n", " text-align: left;\n", - " }#T_8a68a_row13_col5,#T_8a68a_row14_col5{\n", + " }#T_15a01_row4_col5,#T_15a01_row13_col5,#T_15a01_row14_col5{\n", " background-color: OrangeRed;\n", " color: white;\n", " background-color: OrangeRed;\n", " color: white;\n", - " }</style><table id=\"T_8a68a_\" ><thead> <tr> <th class=\"col_heading level0 col0\" >id</th> <th class=\"col_heading level0 col1\" >Repo</th> <th class=\"col_heading level0 col2\" >Name</th> <th class=\"col_heading level0 col3\" >Start</th> <th class=\"col_heading level0 col4\" >End</th> <th class=\"col_heading level0 col5\" >Duration</th> </tr></thead><tbody>\n", + " }</style><table id=\"T_15a01_\" ><thead> <tr> <th class=\"col_heading level0 col0\" >id</th> <th class=\"col_heading level0 col1\" >Repo</th> <th class=\"col_heading level0 col2\" >Name</th> <th class=\"col_heading level0 col3\" >Start</th> <th class=\"col_heading level0 col4\" >End</th> <th class=\"col_heading level0 col5\" >Duration</th> </tr></thead><tbody>\n", " <tr>\n", - " <td id=\"T_8a68a_row0_col0\" class=\"data row0 col0\" ><a href=\"../LinearReg/01-Linear-Regression.ipynb\">LINR1</a></td>\n", - " <td id=\"T_8a68a_row0_col1\" class=\"data row0 col1\" >LinearReg</td>\n", - " <td id=\"T_8a68a_row0_col2\" class=\"data row0 col2\" ><a href=\"../LinearReg/01-Linear-Regression.ipynb\"><b>01-Linear-Regression.ipynb</b></a></td>\n", - " <td id=\"T_8a68a_row0_col3\" class=\"data row0 col3\" >Saturday 9 January 2021, 19:34:10</td>\n", - " <td id=\"T_8a68a_row0_col4\" class=\"data row0 col4\" >Saturday 9 January 2021, 19:34:11</td>\n", - " <td id=\"T_8a68a_row0_col5\" class=\"data row0 col5\" >00:00:01 667ms</td>\n", + " <td id=\"T_15a01_row0_col0\" class=\"data row0 col0\" ><a href=\"../LinearReg/01-Linear-Regression.ipynb\">LINR1</a></td>\n", + " <td id=\"T_15a01_row0_col1\" class=\"data row0 col1\" >LinearReg</td>\n", + " <td id=\"T_15a01_row0_col2\" class=\"data row0 col2\" ><a href=\"../LinearReg/01-Linear-Regression.ipynb\"><b>01-Linear-Regression.ipynb</b></a></td>\n", + " <td id=\"T_15a01_row0_col3\" class=\"data row0 col3\" >Sunday 10 January 2021, 22:54:49</td>\n", + " <td id=\"T_15a01_row0_col4\" class=\"data row0 col4\" >Sunday 10 January 2021, 22:54:53</td>\n", + " <td id=\"T_15a01_row0_col5\" class=\"data row0 col5\" >0:00:04</td>\n", " </tr>\n", " <tr>\n", - " <td id=\"T_8a68a_row1_col0\" class=\"data row1 col0\" ><a href=\"../BHPD/01-DNN-Regression.ipynb\">BHPD1</a></td>\n", - " <td id=\"T_8a68a_row1_col1\" class=\"data row1 col1\" >BHPD</td>\n", - " <td id=\"T_8a68a_row1_col2\" class=\"data row1 col2\" ><a href=\"../BHPD/01-DNN-Regression.ipynb\"><b>01-DNN-Regression.ipynb</b></a></td>\n", - " <td id=\"T_8a68a_row1_col3\" class=\"data row1 col3\" >Friday 8 January 2021, 01:09:13</td>\n", - " <td id=\"T_8a68a_row1_col4\" class=\"data row1 col4\" >Friday 8 January 2021, 01:09:24</td>\n", - " <td id=\"T_8a68a_row1_col5\" class=\"data row1 col5\" >00:00:11 984ms</td>\n", + " <td id=\"T_15a01_row1_col0\" class=\"data row1 col0\" ><a href=\"../BHPD/01-DNN-Regression.ipynb\">BHPD1</a></td>\n", + " <td id=\"T_15a01_row1_col1\" class=\"data row1 col1\" >BHPD</td>\n", + " <td id=\"T_15a01_row1_col2\" class=\"data row1 col2\" ><a href=\"../BHPD/01-DNN-Regression.ipynb\"><b>01-DNN-Regression.ipynb</b></a></td>\n", + " <td id=\"T_15a01_row1_col3\" class=\"data row1 col3\" >Friday 8 January 2021, 01:09:13</td>\n", + " <td id=\"T_15a01_row1_col4\" class=\"data row1 col4\" >Friday 8 January 2021, 01:09:24</td>\n", + " <td id=\"T_15a01_row1_col5\" class=\"data row1 col5\" >00:00:11 984ms</td>\n", " </tr>\n", " <tr>\n", - " <td id=\"T_8a68a_row2_col0\" class=\"data row2 col0\" ><a href=\"../BHPD/02-DNN-Regression-Premium.ipynb\">BHPD2</a></td>\n", - " <td id=\"T_8a68a_row2_col1\" class=\"data row2 col1\" >BHPD</td>\n", - " <td id=\"T_8a68a_row2_col2\" class=\"data row2 col2\" ><a href=\"../BHPD/02-DNN-Regression-Premium.ipynb\"><b>02-DNN-Regression-Premium.ipynb</b></a></td>\n", - " <td id=\"T_8a68a_row2_col3\" class=\"data row2 col3\" >Friday 8 January 2021, 01:10:28</td>\n", - " <td id=\"T_8a68a_row2_col4\" class=\"data row2 col4\" >Friday 8 January 2021, 01:10:39</td>\n", - " <td id=\"T_8a68a_row2_col5\" class=\"data row2 col5\" >00:00:12 582ms</td>\n", + " <td id=\"T_15a01_row2_col0\" class=\"data row2 col0\" ><a href=\"../BHPD/02-DNN-Regression-Premium.ipynb\">BHPD2</a></td>\n", + " <td id=\"T_15a01_row2_col1\" class=\"data row2 col1\" >BHPD</td>\n", + " <td id=\"T_15a01_row2_col2\" class=\"data row2 col2\" ><a href=\"../BHPD/02-DNN-Regression-Premium.ipynb\"><b>02-DNN-Regression-Premium.ipynb</b></a></td>\n", + " <td id=\"T_15a01_row2_col3\" class=\"data row2 col3\" >Friday 8 January 2021, 01:10:28</td>\n", + " <td id=\"T_15a01_row2_col4\" class=\"data row2 col4\" >Friday 8 January 2021, 01:10:39</td>\n", + " <td id=\"T_15a01_row2_col5\" class=\"data row2 col5\" >00:00:12 582ms</td>\n", " </tr>\n", " <tr>\n", - " <td id=\"T_8a68a_row3_col0\" class=\"data row3 col0\" ><a href=\"../GTSRB/01-Preparation-of-data.ipynb\">GTSRB1</a></td>\n", - " <td id=\"T_8a68a_row3_col1\" class=\"data row3 col1\" >GTSRB</td>\n", - " <td id=\"T_8a68a_row3_col2\" class=\"data row3 col2\" ><a href=\"../GTSRB/01-Preparation-of-data.ipynb\"><b>01-Preparation-of-data.ipynb</b></a></td>\n", - " <td id=\"T_8a68a_row3_col3\" class=\"data row3 col3\" >Saturday 9 January 2021, 19:34:16</td>\n", - " <td id=\"T_8a68a_row3_col4\" class=\"data row3 col4\" >Saturday 9 January 2021, 19:36:14</td>\n", - " <td id=\"T_8a68a_row3_col5\" class=\"data row3 col5\" >00:01:58 919ms</td>\n", + " <td id=\"T_15a01_row3_col0\" class=\"data row3 col0\" ><a href=\"../GTSRB/01-Preparation-of-data.ipynb\">GTSRB1</a></td>\n", + " <td id=\"T_15a01_row3_col1\" class=\"data row3 col1\" >GTSRB</td>\n", + " <td id=\"T_15a01_row3_col2\" class=\"data row3 col2\" ><a href=\"../GTSRB/01-Preparation-of-data.ipynb\"><b>01-Preparation-of-data.ipynb</b></a></td>\n", + " <td id=\"T_15a01_row3_col3\" class=\"data row3 col3\" >Sunday 10 January 2021, 22:54:53</td>\n", + " <td id=\"T_15a01_row3_col4\" class=\"data row3 col4\" >Sunday 10 January 2021, 22:56:54</td>\n", + " <td id=\"T_15a01_row3_col5\" class=\"data row3 col5\" >0:02:00</td>\n", " </tr>\n", " <tr>\n", - " <td id=\"T_8a68a_row4_col0\" class=\"data row4 col0\" ><a href=\"../GTSRB/02-First-convolutions.ipynb\">GTSRB2</a></td>\n", - " <td id=\"T_8a68a_row4_col1\" class=\"data row4 col1\" >GTSRB</td>\n", - " <td id=\"T_8a68a_row4_col2\" class=\"data row4 col2\" ><a href=\"../GTSRB/02-First-convolutions.ipynb\"><b>02-First-convolutions.ipynb</b></a></td>\n", - " <td id=\"T_8a68a_row4_col3\" class=\"data row4 col3\" >Saturday 9 January 2021, 19:36:17</td>\n", - " <td id=\"T_8a68a_row4_col4\" class=\"data row4 col4\" >Saturday 9 January 2021, 19:39:16</td>\n", - " <td id=\"T_8a68a_row4_col5\" class=\"data row4 col5\" >00:02:59 895ms</td>\n", + " <td id=\"T_15a01_row4_col0\" class=\"data row4 col0\" ><a href=\"../GTSRB/02-First-convolutions.ipynb\">GTSRB2</a></td>\n", + " <td id=\"T_15a01_row4_col1\" class=\"data row4 col1\" >GTSRB</td>\n", + " <td id=\"T_15a01_row4_col2\" class=\"data row4 col2\" ><a href=\"../GTSRB/02-First-convolutions.ipynb\"><b>02-First-convolutions.ipynb</b></a></td>\n", + " <td id=\"T_15a01_row4_col3\" class=\"data row4 col3\" >Sunday 10 January 2021, 22:56:54</td>\n", + " <td id=\"T_15a01_row4_col4\" class=\"data row4 col4\" ></td>\n", + " <td id=\"T_15a01_row4_col5\" class=\"data row4 col5\" >Unfinished...</td>\n", " </tr>\n", " <tr>\n", - " <td id=\"T_8a68a_row5_col0\" class=\"data row5 col0\" ><a href=\"../GTSRB/03-Tracking-and-visualizing.ipynb\">GTSRB3</a></td>\n", - " <td id=\"T_8a68a_row5_col1\" class=\"data row5 col1\" >GTSRB</td>\n", - " <td id=\"T_8a68a_row5_col2\" class=\"data row5 col2\" ><a href=\"../GTSRB/03-Tracking-and-visualizing.ipynb\"><b>03-Tracking-and-visualizing.ipynb</b></a></td>\n", - " <td id=\"T_8a68a_row5_col3\" class=\"data row5 col3\" >Thursday 7 January 2021, 12:15:52</td>\n", - " <td id=\"T_8a68a_row5_col4\" class=\"data row5 col4\" >Thursday 7 January 2021, 12:20:01</td>\n", - " <td id=\"T_8a68a_row5_col5\" class=\"data row5 col5\" >00:04:09 711ms</td>\n", + " <td id=\"T_15a01_row5_col0\" class=\"data row5 col0\" ><a href=\"../GTSRB/03-Tracking-and-visualizing.ipynb\">GTSRB3</a></td>\n", + " <td id=\"T_15a01_row5_col1\" class=\"data row5 col1\" >GTSRB</td>\n", + " <td id=\"T_15a01_row5_col2\" class=\"data row5 col2\" ><a href=\"../GTSRB/03-Tracking-and-visualizing.ipynb\"><b>03-Tracking-and-visualizing.ipynb</b></a></td>\n", + " <td id=\"T_15a01_row5_col3\" class=\"data row5 col3\" >Thursday 7 January 2021, 12:15:52</td>\n", + " <td id=\"T_15a01_row5_col4\" class=\"data row5 col4\" >Thursday 7 January 2021, 12:20:01</td>\n", + " <td id=\"T_15a01_row5_col5\" class=\"data row5 col5\" >00:04:09 711ms</td>\n", " </tr>\n", " <tr>\n", - " <td id=\"T_8a68a_row6_col0\" class=\"data row6 col0\" ><a href=\"../GTSRB/04-Data-augmentation.ipynb\">GTSRB4</a></td>\n", - " <td id=\"T_8a68a_row6_col1\" class=\"data row6 col1\" >GTSRB</td>\n", - " <td id=\"T_8a68a_row6_col2\" class=\"data row6 col2\" ><a href=\"../GTSRB/04-Data-augmentation.ipynb\"><b>04-Data-augmentation.ipynb</b></a></td>\n", - " <td id=\"T_8a68a_row6_col3\" class=\"data row6 col3\" >Thursday 7 January 2021, 13:40:52</td>\n", - " <td id=\"T_8a68a_row6_col4\" class=\"data row6 col4\" >Thursday 7 January 2021, 13:41:31</td>\n", - " <td id=\"T_8a68a_row6_col5\" class=\"data row6 col5\" >00:00:39 161ms</td>\n", + " <td id=\"T_15a01_row6_col0\" class=\"data row6 col0\" ><a href=\"../GTSRB/04-Data-augmentation.ipynb\">GTSRB4</a></td>\n", + " <td id=\"T_15a01_row6_col1\" class=\"data row6 col1\" >GTSRB</td>\n", + " <td id=\"T_15a01_row6_col2\" class=\"data row6 col2\" ><a href=\"../GTSRB/04-Data-augmentation.ipynb\"><b>04-Data-augmentation.ipynb</b></a></td>\n", + " <td id=\"T_15a01_row6_col3\" class=\"data row6 col3\" >Thursday 7 January 2021, 13:40:52</td>\n", + " <td id=\"T_15a01_row6_col4\" class=\"data row6 col4\" >Thursday 7 January 2021, 13:41:31</td>\n", + " <td id=\"T_15a01_row6_col5\" class=\"data row6 col5\" >00:00:39 161ms</td>\n", " </tr>\n", " <tr>\n", - " <td id=\"T_8a68a_row7_col0\" class=\"data row7 col0\" ><a href=\"../GTSRB/05-Full-convolutions.ipynb\">GTSRB5</a></td>\n", - " <td id=\"T_8a68a_row7_col1\" class=\"data row7 col1\" >GTSRB</td>\n", - " <td id=\"T_8a68a_row7_col2\" class=\"data row7 col2\" ><a href=\"../GTSRB/05-Full-convolutions.ipynb\"><b>05-Full-convolutions.ipynb</b></a></td>\n", - " <td id=\"T_8a68a_row7_col3\" class=\"data row7 col3\" >Thursday 7 January 2021, 14:47:12</td>\n", - " <td id=\"T_8a68a_row7_col4\" class=\"data row7 col4\" >Thursday 7 January 2021, 14:48:44</td>\n", - " <td id=\"T_8a68a_row7_col5\" class=\"data row7 col5\" >00:01:32 269ms</td>\n", + " <td id=\"T_15a01_row7_col0\" class=\"data row7 col0\" ><a href=\"../GTSRB/05-Full-convolutions.ipynb\">GTSRB5</a></td>\n", + " <td id=\"T_15a01_row7_col1\" class=\"data row7 col1\" >GTSRB</td>\n", + " <td id=\"T_15a01_row7_col2\" class=\"data row7 col2\" ><a href=\"../GTSRB/05-Full-convolutions.ipynb\"><b>05-Full-convolutions.ipynb</b></a></td>\n", + " <td id=\"T_15a01_row7_col3\" class=\"data row7 col3\" >Thursday 7 January 2021, 14:47:12</td>\n", + " <td id=\"T_15a01_row7_col4\" class=\"data row7 col4\" >Thursday 7 January 2021, 14:48:44</td>\n", + " <td id=\"T_15a01_row7_col5\" class=\"data row7 col5\" >00:01:32 269ms</td>\n", " </tr>\n", " <tr>\n", - " <td id=\"T_8a68a_row8_col0\" class=\"data row8 col0\" ><a href=\"../GTSRB/06-Notebook-as-a-batch.ipynb\">GTSRB6</a></td>\n", - " <td id=\"T_8a68a_row8_col1\" class=\"data row8 col1\" >GTSRB</td>\n", - " <td id=\"T_8a68a_row8_col2\" class=\"data row8 col2\" ><a href=\"../GTSRB/06-Notebook-as-a-batch.ipynb\"><b>06-Notebook-as-a-batch.ipynb</b></a></td>\n", - " <td id=\"T_8a68a_row8_col3\" class=\"data row8 col3\" >Thursday 7 January 2021, 15:41:17</td>\n", - " <td id=\"T_8a68a_row8_col4\" class=\"data row8 col4\" >Thursday 7 January 2021, 15:41:18</td>\n", - " <td id=\"T_8a68a_row8_col5\" class=\"data row8 col5\" >00:00:01 101ms</td>\n", + " <td id=\"T_15a01_row8_col0\" class=\"data row8 col0\" ><a href=\"../GTSRB/06-Notebook-as-a-batch.ipynb\">GTSRB6</a></td>\n", + " <td id=\"T_15a01_row8_col1\" class=\"data row8 col1\" >GTSRB</td>\n", + " <td id=\"T_15a01_row8_col2\" class=\"data row8 col2\" ><a href=\"../GTSRB/06-Notebook-as-a-batch.ipynb\"><b>06-Notebook-as-a-batch.ipynb</b></a></td>\n", + " <td id=\"T_15a01_row8_col3\" class=\"data row8 col3\" >Thursday 7 January 2021, 15:41:17</td>\n", + " <td id=\"T_15a01_row8_col4\" class=\"data row8 col4\" >Thursday 7 January 2021, 15:41:18</td>\n", + " <td id=\"T_15a01_row8_col5\" class=\"data row8 col5\" >00:00:01 101ms</td>\n", " </tr>\n", " <tr>\n", - " <td id=\"T_8a68a_row9_col0\" class=\"data row9 col0\" ><a href=\"../GTSRB/07-Show-report.ipynb\">GTSRB7</a></td>\n", - " <td id=\"T_8a68a_row9_col1\" class=\"data row9 col1\" >GTSRB</td>\n", - " <td id=\"T_8a68a_row9_col2\" class=\"data row9 col2\" ><a href=\"../GTSRB/07-Show-report.ipynb\"><b>07-Show-report.ipynb</b></a></td>\n", - " <td id=\"T_8a68a_row9_col3\" class=\"data row9 col3\" >Thursday 7 January 2021, 15:16:05</td>\n", - " <td id=\"T_8a68a_row9_col4\" class=\"data row9 col4\" >Thursday 7 January 2021, 15:16:06</td>\n", - " <td id=\"T_8a68a_row9_col5\" class=\"data row9 col5\" >00:00:00 116ms</td>\n", + " <td id=\"T_15a01_row9_col0\" class=\"data row9 col0\" ><a href=\"../GTSRB/07-Show-report.ipynb\">GTSRB7</a></td>\n", + " <td id=\"T_15a01_row9_col1\" class=\"data row9 col1\" >GTSRB</td>\n", + " <td id=\"T_15a01_row9_col2\" class=\"data row9 col2\" ><a href=\"../GTSRB/07-Show-report.ipynb\"><b>07-Show-report.ipynb</b></a></td>\n", + " <td id=\"T_15a01_row9_col3\" class=\"data row9 col3\" >Thursday 7 January 2021, 15:16:05</td>\n", + " <td id=\"T_15a01_row9_col4\" class=\"data row9 col4\" >Thursday 7 January 2021, 15:16:06</td>\n", + " <td id=\"T_15a01_row9_col5\" class=\"data row9 col5\" >00:00:00 116ms</td>\n", " </tr>\n", " <tr>\n", - " <td id=\"T_8a68a_row10_col0\" class=\"data row10 col0\" ><a href=\"../SYNOP/01-Preparation-of-data.ipynb\">SYNOP1</a></td>\n", - " <td id=\"T_8a68a_row10_col1\" class=\"data row10 col1\" >SYNOP</td>\n", - " <td id=\"T_8a68a_row10_col2\" class=\"data row10 col2\" ><a href=\"../SYNOP/01-Preparation-of-data.ipynb\"><b>01-Preparation-of-data.ipynb</b></a></td>\n", - " <td id=\"T_8a68a_row10_col3\" class=\"data row10 col3\" >Saturday 9 January 2021, 10:04:28</td>\n", - " <td id=\"T_8a68a_row10_col4\" class=\"data row10 col4\" >Saturday 9 January 2021, 10:04:34</td>\n", - " <td id=\"T_8a68a_row10_col5\" class=\"data row10 col5\" >00:00:05 236ms</td>\n", + " <td id=\"T_15a01_row10_col0\" class=\"data row10 col0\" ><a href=\"../SYNOP/01-Preparation-of-data.ipynb\">SYNOP1</a></td>\n", + " <td id=\"T_15a01_row10_col1\" class=\"data row10 col1\" >SYNOP</td>\n", + " <td id=\"T_15a01_row10_col2\" class=\"data row10 col2\" ><a href=\"../SYNOP/01-Preparation-of-data.ipynb\"><b>01-Preparation-of-data.ipynb</b></a></td>\n", + " <td id=\"T_15a01_row10_col3\" class=\"data row10 col3\" >Saturday 9 January 2021, 10:04:28</td>\n", + " <td id=\"T_15a01_row10_col4\" class=\"data row10 col4\" >Saturday 9 January 2021, 10:04:34</td>\n", + " <td id=\"T_15a01_row10_col5\" class=\"data row10 col5\" >00:00:05 236ms</td>\n", " </tr>\n", " <tr>\n", - " <td id=\"T_8a68a_row11_col0\" class=\"data row11 col0\" ><a href=\"../SYNOP/02-First-predictions.ipynb\">SYNOP2</a></td>\n", - " <td id=\"T_8a68a_row11_col1\" class=\"data row11 col1\" >SYNOP</td>\n", - " <td id=\"T_8a68a_row11_col2\" class=\"data row11 col2\" ><a href=\"../SYNOP/02-First-predictions.ipynb\"><b>02-First-predictions.ipynb</b></a></td>\n", - " <td id=\"T_8a68a_row11_col3\" class=\"data row11 col3\" >Saturday 9 January 2021, 10:30:55</td>\n", - " <td id=\"T_8a68a_row11_col4\" class=\"data row11 col4\" >Saturday 9 January 2021, 10:31:11</td>\n", - " <td id=\"T_8a68a_row11_col5\" class=\"data row11 col5\" >00:00:16 248ms</td>\n", + " <td id=\"T_15a01_row11_col0\" class=\"data row11 col0\" ><a href=\"../SYNOP/02-First-predictions.ipynb\">SYNOP2</a></td>\n", + " <td id=\"T_15a01_row11_col1\" class=\"data row11 col1\" >SYNOP</td>\n", + " <td id=\"T_15a01_row11_col2\" class=\"data row11 col2\" ><a href=\"../SYNOP/02-First-predictions.ipynb\"><b>02-First-predictions.ipynb</b></a></td>\n", + " <td id=\"T_15a01_row11_col3\" class=\"data row11 col3\" >Saturday 9 January 2021, 10:30:55</td>\n", + " <td id=\"T_15a01_row11_col4\" class=\"data row11 col4\" >Saturday 9 January 2021, 10:31:11</td>\n", + " <td id=\"T_15a01_row11_col5\" class=\"data row11 col5\" >00:00:16 248ms</td>\n", " </tr>\n", " <tr>\n", - " <td id=\"T_8a68a_row12_col0\" class=\"data row12 col0\" ><a href=\"../SYNOP/03-12h-predictions.ipynb\">SYNOP3</a></td>\n", - " <td id=\"T_8a68a_row12_col1\" class=\"data row12 col1\" >SYNOP</td>\n", - " <td id=\"T_8a68a_row12_col2\" class=\"data row12 col2\" ><a href=\"../SYNOP/03-12h-predictions.ipynb\"><b>03-12h-predictions.ipynb</b></a></td>\n", - " <td id=\"T_8a68a_row12_col3\" class=\"data row12 col3\" >Saturday 9 January 2021, 10:27:54</td>\n", - " <td id=\"T_8a68a_row12_col4\" class=\"data row12 col4\" >Saturday 9 January 2021, 10:27:59</td>\n", - " <td id=\"T_8a68a_row12_col5\" class=\"data row12 col5\" >00:00:05 249ms</td>\n", + " <td id=\"T_15a01_row12_col0\" class=\"data row12 col0\" ><a href=\"../SYNOP/03-12h-predictions.ipynb\">SYNOP3</a></td>\n", + " <td id=\"T_15a01_row12_col1\" class=\"data row12 col1\" >SYNOP</td>\n", + " <td id=\"T_15a01_row12_col2\" class=\"data row12 col2\" ><a href=\"../SYNOP/03-12h-predictions.ipynb\"><b>03-12h-predictions.ipynb</b></a></td>\n", + " <td id=\"T_15a01_row12_col3\" class=\"data row12 col3\" >Saturday 9 January 2021, 10:27:54</td>\n", + " <td id=\"T_15a01_row12_col4\" class=\"data row12 col4\" >Saturday 9 January 2021, 10:27:59</td>\n", + " <td id=\"T_15a01_row12_col5\" class=\"data row12 col5\" >00:00:05 249ms</td>\n", " </tr>\n", " <tr>\n", - " <td id=\"T_8a68a_row13_col0\" class=\"data row13 col0\" ><a href=\"../VAE/01-VAE-with-MNIST.ipynb\">VAE1</a></td>\n", - " <td id=\"T_8a68a_row13_col1\" class=\"data row13 col1\" >VAE</td>\n", - " <td id=\"T_8a68a_row13_col2\" class=\"data row13 col2\" ><a href=\"../VAE/01-VAE-with-MNIST.ipynb\"><b>01-VAE-with-MNIST.ipynb</b></a></td>\n", - " <td id=\"T_8a68a_row13_col3\" class=\"data row13 col3\" >Thursday 7 January 2021, 09:37:44</td>\n", - " <td id=\"T_8a68a_row13_col4\" class=\"data row13 col4\" ></td>\n", - " <td id=\"T_8a68a_row13_col5\" class=\"data row13 col5\" >Unfinished...</td>\n", + " <td id=\"T_15a01_row13_col0\" class=\"data row13 col0\" ><a href=\"../VAE/01-VAE-with-MNIST.ipynb\">VAE1</a></td>\n", + " <td id=\"T_15a01_row13_col1\" class=\"data row13 col1\" >VAE</td>\n", + " <td id=\"T_15a01_row13_col2\" class=\"data row13 col2\" ><a href=\"../VAE/01-VAE-with-MNIST.ipynb\"><b>01-VAE-with-MNIST.ipynb</b></a></td>\n", + " <td id=\"T_15a01_row13_col3\" class=\"data row13 col3\" >Thursday 7 January 2021, 09:37:44</td>\n", + " <td id=\"T_15a01_row13_col4\" class=\"data row13 col4\" ></td>\n", + " <td id=\"T_15a01_row13_col5\" class=\"data row13 col5\" >Unfinished...</td>\n", " </tr>\n", " <tr>\n", - " <td id=\"T_8a68a_row14_col0\" class=\"data row14 col0\" ><a href=\"../VAE/08-VAE-with-CelebA.ipynb\">VAE8</a></td>\n", - " <td id=\"T_8a68a_row14_col1\" class=\"data row14 col1\" >VAE</td>\n", - " <td id=\"T_8a68a_row14_col2\" class=\"data row14 col2\" ><a href=\"../VAE/08-VAE-with-CelebA.ipynb\"><b>08-VAE-with-CelebA.ipynb</b></a></td>\n", - " <td id=\"T_8a68a_row14_col3\" class=\"data row14 col3\" >Wednesday 6 January 2021, 22:17:12</td>\n", - " <td id=\"T_8a68a_row14_col4\" class=\"data row14 col4\" ></td>\n", - " <td id=\"T_8a68a_row14_col5\" class=\"data row14 col5\" >Unfinished...</td>\n", + " <td id=\"T_15a01_row14_col0\" class=\"data row14 col0\" ><a href=\"../VAE/08-VAE-with-CelebA.ipynb\">VAE8</a></td>\n", + " <td id=\"T_15a01_row14_col1\" class=\"data row14 col1\" >VAE</td>\n", + " <td id=\"T_15a01_row14_col2\" class=\"data row14 col2\" ><a href=\"../VAE/08-VAE-with-CelebA.ipynb\"><b>08-VAE-with-CelebA.ipynb</b></a></td>\n", + " <td id=\"T_15a01_row14_col3\" class=\"data row14 col3\" >Wednesday 6 January 2021, 22:17:12</td>\n", + " <td id=\"T_15a01_row14_col4\" class=\"data row14 col4\" ></td>\n", + " <td id=\"T_15a01_row14_col5\" class=\"data row14 col5\" >Unfinished...</td>\n", " </tr>\n", " </tbody></table>" ], "text/plain": [ - "<pandas.io.formats.style.Styler at 0x7f9920e2ded0>" + "<pandas.io.formats.style.Styler at 0x7ff03f60f5d0>" ] }, "metadata": {}, @@ -179,7 +169,8 @@ } ], "source": [ - "cooker.build_finished_report()" + "import cookci\n", + "cookci.build_ci_report()" ] }, { diff --git a/fidle/ci/default.yml b/fidle/ci/default.yml index 31d334b8c5bb4e5ea191f4d22c4a8ffc8bba872c..9853a84605bec890afc3aad6509bb74fd358e8cb 100644 --- a/fidle/ci/default.yml +++ b/fidle/ci/default.yml @@ -4,7 +4,7 @@ config: save_figs: true LINR1: notebook_dir: LinearReg - notebook_src: 01-Linear-Regression==ci==.ipynb + notebook_src: 01-Linear-Regression.ipynb notebook_out: default GRAD1: notebook_dir: LinearReg @@ -34,17 +34,9 @@ MNIST1: notebook_dir: MNIST notebook_src: 01-DNN-MNIST.ipynb notebook_out: default -??: - notebook_dir: GTSRB - notebook_src: 00-Test==done==.ipynb - notebook_out: default - overrides: - run_dir: default - scale: default - output_dir: default GTSRB1: notebook_dir: GTSRB - notebook_src: 01-Preparation-of-data==ci==.ipynb + notebook_src: 01-Preparation-of-data.ipynb notebook_out: default overrides: scale: default diff --git a/fidle/ci/smart.yml b/fidle/ci/smart.yml index 57ff0f4adb2a7af93bf81d9dce05cef14fd5fe3c..8f970289e363e3084928180e80b1b438b6eb8849 100644 --- a/fidle/ci/smart.yml +++ b/fidle/ci/smart.yml @@ -6,14 +6,6 @@ LINR1: notebook_dir: LinearReg notebook_src: 01-Linear-Regression.ipynb notebook_out: default -GTSRB0: - notebook_dir: GTSRB - notebook_src: 00-Test.ipynb - notebook_out: default - overrides: - scale: 0.7 - output_dir: ./data/foobar - run_dir: ./run/xxx GTSRB1: notebook_dir: GTSRB notebook_src: 01-Preparation-of-data.ipynb @@ -30,4 +22,4 @@ GTSRB2: dataset_name: set-24x24-L batch_size: 32 epochs: 3 - scale: 1 \ No newline at end of file + scale: 0.1 \ No newline at end of file diff --git a/fidle/config.py b/fidle/config.py index 5bf592b52f5dff13354236c9181a335fe83907ff..76fb1911443f9c825516adb54694b18fb146dd45 100644 --- a/fidle/config.py +++ b/fidle/config.py @@ -32,14 +32,10 @@ SAVE_FIGS = False # ---- Catalog file, a json description of all notebooks ------------ # -CATALOG_FILE = '../fidle/log/catalog.json' +CATALOG_FILE = '../fidle/logs/catalog.json' -# ---- CI Done files, to keep track of finished notebooks ----------- -# Used for continous integration +# ---- CI report files ---------------------------------------------- # -FINISHED_FILE = '../fidle/log/finished.json' - -# ---- CI Report ---------------------------------------------------- -# -FINISHED_REPORT = '../fidle/log/finished_report.html' +CI_REPORT_JSON = '../fidle/logs/ci_report.json' +CI_REPORT_HTML = '../fidle/logs/ci_report.html' diff --git a/fidle/cookci.py b/fidle/cookci.py new file mode 100644 index 0000000000000000000000000000000000000000..7cc8d22e0f01dc49ac60ff0e17d7fcc69c8d830c --- /dev/null +++ b/fidle/cookci.py @@ -0,0 +1,342 @@ + +# ----------------------------------------------------------------------------- +# ____ _ ____ _ +# / ___|___ ___ ___| | __ / ___(_) +# | | / _ \ / _ \ / __| |/ / | | | | +# | |__| (_) | (_) | (__| < | |___| | +# \____\___/ \___/ \___|_|\_\ \____|_| +# +# Fidle mod for continous integration +# ----------------------------------------------------------------------------- +# +# A simple module to run all notebooks with parameters overriding +# Jean-Luc Parouty 2021 + +import sys,os +import json +import datetime, time +import nbformat +from nbconvert.preprocessors import ExecutePreprocessor +import re +import yaml +from collections import OrderedDict +from IPython.display import display +import pandas as pd + +sys.path.append('..') +import fidle.config as config +import fidle.cookindex as cookindex + +start_time = None +end_time = None + +def get_ci_profile(catalog=None, output_tag='==done==', save_figs=True): + ''' + Return a profile for continous integration. + Ce profile contient une liste des notebooks avec les paramètres modifiables. + Il peut être modifié et sauvegardé, puis être utilisé pour lancer l'éxécution + des notebooks. + params: + catalog : Notebooks catalog. if None (default), load config.CATALOG_FILE + output_tag : tag name of generated notebook + save_figs : save figs or not for generated notebooks (True) + return: + profile : dict with run parameters + ''' + + if catalog is None: + catalog = cookindex.read_catalog() + + config = {'version':'1.0', 'output_tag':output_tag, 'save_figs':save_figs} + profile = { 'config':config } + for id, about in catalog.items(): + + id = about['id'] + title = about['title'] + dirname = about['dirname'] + basename = about['basename'] + overrides = about.get('overrides',None) + + notebook = {} + notebook['notebook_dir'] = dirname + notebook['notebook_src'] = basename + notebook['notebook_out'] = 'default' + if len(overrides)>0: + notebook['overrides']={ name:'default' for name in overrides } + + profile[id]=notebook + + return profile + + +def save_profile(profile, filename): + '''Save profile in yaml format''' + with open(filename,'wt') as fp: + yaml.dump(profile, fp, sort_keys=False) + print(f'Catalog saved as {filename}') + print('Entries : ',len(profile)-1) + + +def load_profile(filename): + '''Load yaml profile''' + with open(filename,'r') as fp: + profile=yaml.load(fp, Loader=yaml.FullLoader) + print(f'{filename} loaded.') + print('Entries : ',len(profile)-1) + return profile + + +def run_profile(profile, top_dir='..'): + ''' + Récupère la liste des notebooks et des paramètres associés, + décrit dans le profile, et pour chaque notebook : + Positionner les variables d'environnement pour l'override + Charger le notebook + Exécuter celui-ci + Sauvegarder le notebook résultat, avec son nom taggé. + Params: + profile : dict, profile d'éxécution + top_dir : chemin relatif vers la racine fidle (..) + ''' + + # ---- My place + # + home = os.getcwd() + + # ---- Read profile + # + config = profile['config'] + notebooks = profile + del notebooks['config'] + + # ---- Save figs or not ? + # + os.environ['FIDLE_SAVE_FIGS']=str(config['save_figs']) + + # ---- For each notebook + # + for id,about in notebooks.items(): + + print(f'\nNotebook : {id}') + + # ---- Get notebook infos --------------------------------------------- + # + notebook_dir = about['notebook_dir'] + notebook_src = about['notebook_src'] + notebook_out = about['notebook_out'] + overrides = about.get('overrides',None) + + # ---- notebook_out (Default) + # + if notebook_out=='default': + notebook_out = notebook_src.replace('.ipynb', config['output_tag']+'.ipynb') + + # ---- Override ------------------------------------------------------- + + to_unset=[] + if isinstance(overrides,dict): + print(' set overrides :') + for name,value in overrides.items(): + # ---- Default : no nothing + if value=='default' : continue + # ---- Set env + env_name = f'FIDLE_OVERRIDE_{id.upper()}_{name}' + env_value = str(value) + os.environ[env_name] = env_value + # ---- For cleaning + to_unset.append(env_name) + # ---- Fine :(-) + print(f' {env_name:38s} = {env_value}') + + # ---- Run it ! ------------------------------------------------------- + + # ---- Go to the right place + # + os.chdir(f'{top_dir}/{notebook_dir}') + notebook = nbformat.read( f'{notebook_src}', nbformat.NO_CONVERT) + + # ---- Top chrono + # + chrono_start() + update_ci_report(id, start=True) + + # ---- Run, run, run... + # + print(' Run notebook...',end='') + ep = ExecutePreprocessor(timeout=600, kernel_name="python3") + ep.preprocess(notebook) + print('..done.') + + # ---- Top chrono + # + chrono_stop() + update_ci_report(id, end=True) + print(' Duration : ',chrono_delay() ) + + # ---- Save notebook + # + with open( f'{notebook_out}', mode="w", encoding='utf-8') as fp: + nbformat.write(notebook, fp) + print(' Saved as : ',notebook_out) + + # ---- Back to home and clean + # + os.chdir(home) + for env_name in to_unset: + del os.environ[env_name] + + +def chrono_start(): + global start_time + start_time = datetime.datetime.now() + +def chrono_stop(): + global end_time + end_time = datetime.datetime.now() + +def chrono_delay(in_seconds=False): + global start_time, end_time + delta = end_time - start_time + if in_seconds: + return round(delta.total_seconds(),2) + else: + delta = delta - datetime.timedelta(microseconds=delta.microseconds) + return str(delta) + + + +def reset_ci_report(verbose=True): + data={} + with open(config.CI_REPORT_JSON,'wt') as fp: + json.dump(data,fp,indent=4) + if verbose : print(f'Finished file has been reset.\n') + + +def update_ci_report(notebook_id, start=False, end=False): + global start_time, end_time + + if not os.access(config.CI_REPORT_JSON, os.W_OK): + reset_ci_report(verbose=True) + + # ---- Load it + with open(config.CI_REPORT_JSON) as fp: + data = json.load(fp) + + # ---- Update as a start + if start is True: + data[notebook_id] = {} + data[notebook_id]['path'] = os.getcwd() + data[notebook_id]['start'] = start_time.strftime("%A %-d %B %Y, %H:%M:%S") + data[notebook_id]['end'] = '' + data[notebook_id]['duration'] = 'Unfinished...' + + # ---- Update as an end + if end is True: + data[notebook_id]['end'] = end_time.strftime("%A %-d %B %Y, %H:%M:%S") + data[notebook_id]['duration'] = chrono_delay() + + # ---- Save it + with open(config.CI_REPORT_JSON,'wt') as fp: + json.dump(data,fp,indent=4) + + + +def build_ci_report(display_output=True, save_html=True): + + # ---- Load catalog (notebooks descriptions) + # + with open(config.CATALOG_FILE) as fp: + catalog = json.load(fp) + + # ---- Load ci report + # + with open(config.CI_REPORT_JSON) as infile: + ci_report = json.load( infile ) + + # ---- For each entry + # + col_id, col_repo, col_name, col_start, col_end, col_dur = [],[],[],[],[],[] + for id,about in catalog.items(): + if id in ci_report.keys(): + ci_entry = ci_report[id] + dirname = about['dirname'] + basename = about['basename'] + + col_id.append( f'<a href="../{dirname}/{basename}">{id}</a>' ) + col_repo.append( dirname ) + col_name.append( f'<a href="../{dirname}/{basename}"><b>{basename}</b></a>' ) + col_start.append( ci_entry['start'] ) + col_end.append( ci_entry['end'] ) + col_dur.append( ci_entry['duration'] ) + + df = pd.DataFrame( {'id':col_id, 'Repo':col_repo, 'Name':col_name, 'Start':col_start, 'End':col_end, 'Duration':col_dur} ) + + # ---- Add styles to be nice + # + styles = [ + dict(selector="td", props=[("font-size", "110%"), ("text-align", "left")]), + dict(selector="th", props=[("font-size", "110%"), ("text-align", "left")]) + ] + def still_pending(v): + return 'background-color: OrangeRed; color:white' if v == 'Unfinished...' else '' + + output = df[df.columns.values].style.set_table_styles(styles).hide_index().applymap(still_pending) + + # ---- html report + # + if save_html: + html = _get_html_report(output) + with open(config.CI_REPORT_HTML, "wt") as fp: + fp.write(html) + + # ---- display output + # + if display_output: + display(output) + + + + +def _get_html_report(output): + with open('./img/00-Fidle-logo-01-80px.svg','r') as fp: + logo = fp.read() + + now = datetime.datetime.now().strftime("%A %-d %B %Y, %H:%M:%S") + html = f"""\ + <html> + <head><title>FIDLE - CI Report</title></head> + <style> + body{{ + font-family: sans-serif; + }} + a{{ + color: SteelBlue; + text-decoration:none; + }} + table{{ + border-collapse : collapse; + font-size : 80% + }} + td{{ + border-style: solid; + border-width: thin; + border-color: lightgrey; + padding: 5px; + }} + .header{{ padding:20px 0px 0px 30px; }} + .result{{ padding:10px 0px 20px 30px; }} + </style> + <body> + <br>Hi, + <p>Below is the result of the continuous integration tests of the Fidle project:</p> + <div class="header"><b>Report date :</b> {now}</div> + <div class="result"> + {output.render()} + </div> + + {logo} + + </body> + </html> + """ + return html \ No newline at end of file diff --git a/fidle/cooker.py b/fidle/cookindex.py similarity index 58% rename from fidle/cooker.py rename to fidle/cookindex.py index e634cfb6d0c9d565529195129160780fdf1eea36..4e71a444ad16c9992d03d15ab9982ef611715858 100644 --- a/fidle/cooker.py +++ b/fidle/cookindex.py @@ -1,14 +1,17 @@ # ----------------------------------------------------------------------------- -# ____ _ _ ____ _ _ _ -# / ___|__ _| |_ __ _| | ___ __ _ | __ ) _ _(_) | __| | ___ _ __ -# | | / _` | __/ _` | |/ _ \ / _` | | _ \| | | | | |/ _` |/ _ \ '__| -# | |__| (_| | || (_| | | (_) | (_| | | |_) | |_| | | | (_| | __/ | -# \____\__,_|\__\__,_|_|\___/ \__, | |____/ \__,_|_|_|\__,_|\___|_| -# |___/ Module catalog_builder +# ____ _ ___ _ +# / ___|___ ___ ___| | __ |_ _|_ __ __| | _____ __ +# | | / _ \ / _ \ / __| |/ / | || '_ \ / _` |/ _ \ \/ / +# | |__| (_) | (_) | (__| < | || | | | (_| | __/> < +# \____\___/ \___/ \___|_|\_\ |___|_| |_|\__,_|\___/_/\_\ +# +# Fidle mod for index cooking # ----------------------------------------------------------------------------- # # A simple module to build the notebook catalog and update the README. +# Jean-Luc Parouty 2021 + import nbformat from nbconvert.preprocessors import ExecutePreprocessor @@ -190,109 +193,3 @@ def read_catalog(): catalog = json.load(fp) return catalog -# ----------------------------------------------------------------------------- -# To built : CI Report -# ----------------------------------------------------------------------------- -# get_ci_report : Get report of finished files -# ----------------------------------------------------------------------------- - - -def build_finished_report(display_output=True, save_html=True): - - # ---- Load catalog (notebooks descriptions) - # - with open(config.CATALOG_FILE) as fp: - catalog = json.load(fp) - - # ---- Load finished file - # - with open(config.FINISHED_FILE) as infile: - finished_files = json.load( infile ) - - # ---- For each entry - # - col_id, col_repo, col_name, col_start, col_end, col_dur = [],[],[],[],[],[] - for id,about in catalog.items(): - if id in finished_files.keys(): - finished = finished_files[id] - dirname = about['dirname'] - basename = about['basename'] - - col_id.append( f'<a href="../{dirname}/{basename}">{id}</a>' ) - col_repo.append( dirname ) - col_name.append( f'<a href="../{dirname}/{basename}"><b>{basename}</b></a>' ) - col_start.append( finished['start'] ) - col_end.append( finished['end'] ) - col_dur.append( finished['duration'] ) - - df = pd.DataFrame( {'id':col_id, 'Repo':col_repo, 'Name':col_name, 'Start':col_start, 'End':col_end, 'Duration':col_dur} ) - - # ---- Add styles to be nice - # - styles = [ - dict(selector="td", props=[("font-size", "110%"), ("text-align", "left")]), - dict(selector="th", props=[("font-size", "110%"), ("text-align", "left")]) - ] - def still_pending(v): - return 'background-color: OrangeRed; color:white' if v == 'Unfinished...' else '' - - output = df[df.columns.values].style.set_table_styles(styles).hide_index().applymap(still_pending) - - # ---- html report - # - if save_html: - html = _get_html_report(output) - with open(config.FINISHED_REPORT, "wt") as fp: - fp.write(html) - - # ---- display output - # - if display_output: - display(output) - - - - -def _get_html_report(output): - with open('./img/00-Fidle-logo-01-80px.svg','r') as fp: - logo = fp.read() - - now = datetime.now().strftime("%A %-d %B %Y, %H:%M:%S") - html = f"""\ - <html> - <head><title>FIDLE - CI Report</title></head> - <style> - body{{ - font-family: sans-serif; - }} - a{{ - color: SteelBlue; - text-decoration:none; - }} - table{{ - border-collapse : collapse; - font-size : 80% - }} - td{{ - border-style: solid; - border-width: thin; - border-color: lightgrey; - padding: 5px; - }} - .header{{ padding:20px 0px 0px 30px; }} - .result{{ padding:10px 0px 20px 30px; }} - </style> - <body> - <br>Hi, - <p>Below is the result of the continuous integration tests of the Fidle project:</p> - <div class="header"><b>Report date :</b> {now}</div> - <div class="result"> - {output.render()} - </div> - - {logo} - - </body> - </html> - """ - return html \ No newline at end of file diff --git a/fidle/log/catalog.json b/fidle/logs/catalog.json similarity index 97% rename from fidle/log/catalog.json rename to fidle/logs/catalog.json index 95b1e63865209aa908ebd0f49a8be390ac6b655d..e4712bc924675e76d2f4aed2cbadfb268a6e3396 100644 --- a/fidle/log/catalog.json +++ b/fidle/logs/catalog.json @@ -63,18 +63,6 @@ "description": "An example of classification using a dense neural network for the famous MNIST dataset", "overrides": [] }, - "??": { - "id": "??", - "dirname": "GTSRB", - "basename": "00-Test.ipynb", - "title": "??", - "description": "??", - "overrides": [ - "run_dir", - "scale", - "output_dir" - ] - }, "GTSRB1": { "id": "GTSRB1", "dirname": "GTSRB", diff --git a/fidle/log/finished_report.html b/fidle/logs/ci_report.html similarity index 59% rename from fidle/log/finished_report.html rename to fidle/logs/ci_report.html index e5a4bf309920b500dd43cde5e83e062a9486d900..374544b2c422fb1ea75e6e151f0f33f2188c677f 100644 --- a/fidle/log/finished_report.html +++ b/fidle/logs/ci_report.html @@ -24,138 +24,138 @@ <body> <br>Hi, <p>Below is the result of the continuous integration tests of the Fidle project:</p> - <div class="header"><b>Report date :</b> Saturday 9 January 2021, 22:56:56</div> + <div class="header"><b>Report date :</b> Sunday 10 January 2021, 22:58:46</div> <div class="result"> <style type="text/css" > - #T_8a68a_ td { + #T_15a01_ td { font-size: 110%; text-align: left; - } #T_8a68a_ th { + } #T_15a01_ th { font-size: 110%; text-align: left; - }#T_8a68a_row13_col5,#T_8a68a_row14_col5{ + }#T_15a01_row4_col5,#T_15a01_row13_col5,#T_15a01_row14_col5{ background-color: OrangeRed; color: white; - }</style><table id="T_8a68a_" ><thead> <tr> <th class="col_heading level0 col0" >id</th> <th class="col_heading level0 col1" >Repo</th> <th class="col_heading level0 col2" >Name</th> <th class="col_heading level0 col3" >Start</th> <th class="col_heading level0 col4" >End</th> <th class="col_heading level0 col5" >Duration</th> </tr></thead><tbody> + }</style><table id="T_15a01_" ><thead> <tr> <th class="col_heading level0 col0" >id</th> <th class="col_heading level0 col1" >Repo</th> <th class="col_heading level0 col2" >Name</th> <th class="col_heading level0 col3" >Start</th> <th class="col_heading level0 col4" >End</th> <th class="col_heading level0 col5" >Duration</th> </tr></thead><tbody> <tr> - <td id="T_8a68a_row0_col0" class="data row0 col0" ><a href="../LinearReg/01-Linear-Regression.ipynb">LINR1</a></td> - <td id="T_8a68a_row0_col1" class="data row0 col1" >LinearReg</td> - <td id="T_8a68a_row0_col2" class="data row0 col2" ><a href="../LinearReg/01-Linear-Regression.ipynb"><b>01-Linear-Regression.ipynb</b></a></td> - <td id="T_8a68a_row0_col3" class="data row0 col3" >Saturday 9 January 2021, 19:34:10</td> - <td id="T_8a68a_row0_col4" class="data row0 col4" >Saturday 9 January 2021, 19:34:11</td> - <td id="T_8a68a_row0_col5" class="data row0 col5" >00:00:01 667ms</td> + <td id="T_15a01_row0_col0" class="data row0 col0" ><a href="../LinearReg/01-Linear-Regression.ipynb">LINR1</a></td> + <td id="T_15a01_row0_col1" class="data row0 col1" >LinearReg</td> + <td id="T_15a01_row0_col2" class="data row0 col2" ><a href="../LinearReg/01-Linear-Regression.ipynb"><b>01-Linear-Regression.ipynb</b></a></td> + <td id="T_15a01_row0_col3" class="data row0 col3" >Sunday 10 January 2021, 22:54:49</td> + <td id="T_15a01_row0_col4" class="data row0 col4" >Sunday 10 January 2021, 22:54:53</td> + <td id="T_15a01_row0_col5" class="data row0 col5" >0:00:04</td> </tr> <tr> - <td id="T_8a68a_row1_col0" class="data row1 col0" ><a href="../BHPD/01-DNN-Regression.ipynb">BHPD1</a></td> - <td id="T_8a68a_row1_col1" class="data row1 col1" >BHPD</td> - <td id="T_8a68a_row1_col2" class="data row1 col2" ><a href="../BHPD/01-DNN-Regression.ipynb"><b>01-DNN-Regression.ipynb</b></a></td> - <td id="T_8a68a_row1_col3" class="data row1 col3" >Friday 8 January 2021, 01:09:13</td> - <td id="T_8a68a_row1_col4" class="data row1 col4" >Friday 8 January 2021, 01:09:24</td> - <td id="T_8a68a_row1_col5" class="data row1 col5" >00:00:11 984ms</td> + <td id="T_15a01_row1_col0" class="data row1 col0" ><a href="../BHPD/01-DNN-Regression.ipynb">BHPD1</a></td> + <td id="T_15a01_row1_col1" class="data row1 col1" >BHPD</td> + <td id="T_15a01_row1_col2" class="data row1 col2" ><a href="../BHPD/01-DNN-Regression.ipynb"><b>01-DNN-Regression.ipynb</b></a></td> + <td id="T_15a01_row1_col3" class="data row1 col3" >Friday 8 January 2021, 01:09:13</td> + <td id="T_15a01_row1_col4" class="data row1 col4" >Friday 8 January 2021, 01:09:24</td> + <td id="T_15a01_row1_col5" class="data row1 col5" >00:00:11 984ms</td> </tr> <tr> - <td id="T_8a68a_row2_col0" class="data row2 col0" ><a href="../BHPD/02-DNN-Regression-Premium.ipynb">BHPD2</a></td> - <td id="T_8a68a_row2_col1" class="data row2 col1" >BHPD</td> - <td id="T_8a68a_row2_col2" class="data row2 col2" ><a href="../BHPD/02-DNN-Regression-Premium.ipynb"><b>02-DNN-Regression-Premium.ipynb</b></a></td> - <td id="T_8a68a_row2_col3" class="data row2 col3" >Friday 8 January 2021, 01:10:28</td> - <td id="T_8a68a_row2_col4" class="data row2 col4" >Friday 8 January 2021, 01:10:39</td> - <td id="T_8a68a_row2_col5" class="data row2 col5" >00:00:12 582ms</td> + <td id="T_15a01_row2_col0" class="data row2 col0" ><a href="../BHPD/02-DNN-Regression-Premium.ipynb">BHPD2</a></td> + <td id="T_15a01_row2_col1" class="data row2 col1" >BHPD</td> + <td id="T_15a01_row2_col2" class="data row2 col2" ><a href="../BHPD/02-DNN-Regression-Premium.ipynb"><b>02-DNN-Regression-Premium.ipynb</b></a></td> + <td id="T_15a01_row2_col3" class="data row2 col3" >Friday 8 January 2021, 01:10:28</td> + <td id="T_15a01_row2_col4" class="data row2 col4" >Friday 8 January 2021, 01:10:39</td> + <td id="T_15a01_row2_col5" class="data row2 col5" >00:00:12 582ms</td> </tr> <tr> - <td id="T_8a68a_row3_col0" class="data row3 col0" ><a href="../GTSRB/01-Preparation-of-data.ipynb">GTSRB1</a></td> - <td id="T_8a68a_row3_col1" class="data row3 col1" >GTSRB</td> - <td id="T_8a68a_row3_col2" class="data row3 col2" ><a href="../GTSRB/01-Preparation-of-data.ipynb"><b>01-Preparation-of-data.ipynb</b></a></td> - <td id="T_8a68a_row3_col3" class="data row3 col3" >Saturday 9 January 2021, 19:34:16</td> - <td id="T_8a68a_row3_col4" class="data row3 col4" >Saturday 9 January 2021, 19:36:14</td> - <td id="T_8a68a_row3_col5" class="data row3 col5" >00:01:58 919ms</td> + <td id="T_15a01_row3_col0" class="data row3 col0" ><a href="../GTSRB/01-Preparation-of-data.ipynb">GTSRB1</a></td> + <td id="T_15a01_row3_col1" class="data row3 col1" >GTSRB</td> + <td id="T_15a01_row3_col2" class="data row3 col2" ><a href="../GTSRB/01-Preparation-of-data.ipynb"><b>01-Preparation-of-data.ipynb</b></a></td> + <td id="T_15a01_row3_col3" class="data row3 col3" >Sunday 10 January 2021, 22:54:53</td> + <td id="T_15a01_row3_col4" class="data row3 col4" >Sunday 10 January 2021, 22:56:54</td> + <td id="T_15a01_row3_col5" class="data row3 col5" >0:02:00</td> </tr> <tr> - <td id="T_8a68a_row4_col0" class="data row4 col0" ><a href="../GTSRB/02-First-convolutions.ipynb">GTSRB2</a></td> - <td id="T_8a68a_row4_col1" class="data row4 col1" >GTSRB</td> - <td id="T_8a68a_row4_col2" class="data row4 col2" ><a href="../GTSRB/02-First-convolutions.ipynb"><b>02-First-convolutions.ipynb</b></a></td> - <td id="T_8a68a_row4_col3" class="data row4 col3" >Saturday 9 January 2021, 19:36:17</td> - <td id="T_8a68a_row4_col4" class="data row4 col4" >Saturday 9 January 2021, 19:39:16</td> - <td id="T_8a68a_row4_col5" class="data row4 col5" >00:02:59 895ms</td> + <td id="T_15a01_row4_col0" class="data row4 col0" ><a href="../GTSRB/02-First-convolutions.ipynb">GTSRB2</a></td> + <td id="T_15a01_row4_col1" class="data row4 col1" >GTSRB</td> + <td id="T_15a01_row4_col2" class="data row4 col2" ><a href="../GTSRB/02-First-convolutions.ipynb"><b>02-First-convolutions.ipynb</b></a></td> + <td id="T_15a01_row4_col3" class="data row4 col3" >Sunday 10 January 2021, 22:56:54</td> + <td id="T_15a01_row4_col4" class="data row4 col4" ></td> + <td id="T_15a01_row4_col5" class="data row4 col5" >Unfinished...</td> </tr> <tr> - <td id="T_8a68a_row5_col0" class="data row5 col0" ><a href="../GTSRB/03-Tracking-and-visualizing.ipynb">GTSRB3</a></td> - <td id="T_8a68a_row5_col1" class="data row5 col1" >GTSRB</td> - <td id="T_8a68a_row5_col2" class="data row5 col2" ><a href="../GTSRB/03-Tracking-and-visualizing.ipynb"><b>03-Tracking-and-visualizing.ipynb</b></a></td> - <td id="T_8a68a_row5_col3" class="data row5 col3" >Thursday 7 January 2021, 12:15:52</td> - <td id="T_8a68a_row5_col4" class="data row5 col4" >Thursday 7 January 2021, 12:20:01</td> - <td id="T_8a68a_row5_col5" class="data row5 col5" >00:04:09 711ms</td> + <td id="T_15a01_row5_col0" class="data row5 col0" ><a href="../GTSRB/03-Tracking-and-visualizing.ipynb">GTSRB3</a></td> + <td id="T_15a01_row5_col1" class="data row5 col1" >GTSRB</td> + <td id="T_15a01_row5_col2" class="data row5 col2" ><a href="../GTSRB/03-Tracking-and-visualizing.ipynb"><b>03-Tracking-and-visualizing.ipynb</b></a></td> + <td id="T_15a01_row5_col3" class="data row5 col3" >Thursday 7 January 2021, 12:15:52</td> + <td id="T_15a01_row5_col4" class="data row5 col4" >Thursday 7 January 2021, 12:20:01</td> + <td id="T_15a01_row5_col5" class="data row5 col5" >00:04:09 711ms</td> </tr> <tr> - <td id="T_8a68a_row6_col0" class="data row6 col0" ><a href="../GTSRB/04-Data-augmentation.ipynb">GTSRB4</a></td> - <td id="T_8a68a_row6_col1" class="data row6 col1" >GTSRB</td> - <td id="T_8a68a_row6_col2" class="data row6 col2" ><a href="../GTSRB/04-Data-augmentation.ipynb"><b>04-Data-augmentation.ipynb</b></a></td> - <td id="T_8a68a_row6_col3" class="data row6 col3" >Thursday 7 January 2021, 13:40:52</td> - <td id="T_8a68a_row6_col4" class="data row6 col4" >Thursday 7 January 2021, 13:41:31</td> - <td id="T_8a68a_row6_col5" class="data row6 col5" >00:00:39 161ms</td> + <td id="T_15a01_row6_col0" class="data row6 col0" ><a href="../GTSRB/04-Data-augmentation.ipynb">GTSRB4</a></td> + <td id="T_15a01_row6_col1" class="data row6 col1" >GTSRB</td> + <td id="T_15a01_row6_col2" class="data row6 col2" ><a href="../GTSRB/04-Data-augmentation.ipynb"><b>04-Data-augmentation.ipynb</b></a></td> + <td id="T_15a01_row6_col3" class="data row6 col3" >Thursday 7 January 2021, 13:40:52</td> + <td id="T_15a01_row6_col4" class="data row6 col4" >Thursday 7 January 2021, 13:41:31</td> + <td id="T_15a01_row6_col5" class="data row6 col5" >00:00:39 161ms</td> </tr> <tr> - <td id="T_8a68a_row7_col0" class="data row7 col0" ><a href="../GTSRB/05-Full-convolutions.ipynb">GTSRB5</a></td> - <td id="T_8a68a_row7_col1" class="data row7 col1" >GTSRB</td> - <td id="T_8a68a_row7_col2" class="data row7 col2" ><a href="../GTSRB/05-Full-convolutions.ipynb"><b>05-Full-convolutions.ipynb</b></a></td> - <td id="T_8a68a_row7_col3" class="data row7 col3" >Thursday 7 January 2021, 14:47:12</td> - <td id="T_8a68a_row7_col4" class="data row7 col4" >Thursday 7 January 2021, 14:48:44</td> - <td id="T_8a68a_row7_col5" class="data row7 col5" >00:01:32 269ms</td> + <td id="T_15a01_row7_col0" class="data row7 col0" ><a href="../GTSRB/05-Full-convolutions.ipynb">GTSRB5</a></td> + <td id="T_15a01_row7_col1" class="data row7 col1" >GTSRB</td> + <td id="T_15a01_row7_col2" class="data row7 col2" ><a href="../GTSRB/05-Full-convolutions.ipynb"><b>05-Full-convolutions.ipynb</b></a></td> + <td id="T_15a01_row7_col3" class="data row7 col3" >Thursday 7 January 2021, 14:47:12</td> + <td id="T_15a01_row7_col4" class="data row7 col4" >Thursday 7 January 2021, 14:48:44</td> + <td id="T_15a01_row7_col5" class="data row7 col5" >00:01:32 269ms</td> </tr> <tr> - <td id="T_8a68a_row8_col0" class="data row8 col0" ><a href="../GTSRB/06-Notebook-as-a-batch.ipynb">GTSRB6</a></td> - <td id="T_8a68a_row8_col1" class="data row8 col1" >GTSRB</td> - <td id="T_8a68a_row8_col2" class="data row8 col2" ><a href="../GTSRB/06-Notebook-as-a-batch.ipynb"><b>06-Notebook-as-a-batch.ipynb</b></a></td> - <td id="T_8a68a_row8_col3" class="data row8 col3" >Thursday 7 January 2021, 15:41:17</td> - <td id="T_8a68a_row8_col4" class="data row8 col4" >Thursday 7 January 2021, 15:41:18</td> - <td id="T_8a68a_row8_col5" class="data row8 col5" >00:00:01 101ms</td> + <td id="T_15a01_row8_col0" class="data row8 col0" ><a href="../GTSRB/06-Notebook-as-a-batch.ipynb">GTSRB6</a></td> + <td id="T_15a01_row8_col1" class="data row8 col1" >GTSRB</td> + <td id="T_15a01_row8_col2" class="data row8 col2" ><a href="../GTSRB/06-Notebook-as-a-batch.ipynb"><b>06-Notebook-as-a-batch.ipynb</b></a></td> + <td id="T_15a01_row8_col3" class="data row8 col3" >Thursday 7 January 2021, 15:41:17</td> + <td id="T_15a01_row8_col4" class="data row8 col4" >Thursday 7 January 2021, 15:41:18</td> + <td id="T_15a01_row8_col5" class="data row8 col5" >00:00:01 101ms</td> </tr> <tr> - <td id="T_8a68a_row9_col0" class="data row9 col0" ><a href="../GTSRB/07-Show-report.ipynb">GTSRB7</a></td> - <td id="T_8a68a_row9_col1" class="data row9 col1" >GTSRB</td> - <td id="T_8a68a_row9_col2" class="data row9 col2" ><a href="../GTSRB/07-Show-report.ipynb"><b>07-Show-report.ipynb</b></a></td> - <td id="T_8a68a_row9_col3" class="data row9 col3" >Thursday 7 January 2021, 15:16:05</td> - <td id="T_8a68a_row9_col4" class="data row9 col4" >Thursday 7 January 2021, 15:16:06</td> - <td id="T_8a68a_row9_col5" class="data row9 col5" >00:00:00 116ms</td> + <td id="T_15a01_row9_col0" class="data row9 col0" ><a href="../GTSRB/07-Show-report.ipynb">GTSRB7</a></td> + <td id="T_15a01_row9_col1" class="data row9 col1" >GTSRB</td> + <td id="T_15a01_row9_col2" class="data row9 col2" ><a href="../GTSRB/07-Show-report.ipynb"><b>07-Show-report.ipynb</b></a></td> + <td id="T_15a01_row9_col3" class="data row9 col3" >Thursday 7 January 2021, 15:16:05</td> + <td id="T_15a01_row9_col4" class="data row9 col4" >Thursday 7 January 2021, 15:16:06</td> + <td id="T_15a01_row9_col5" class="data row9 col5" >00:00:00 116ms</td> </tr> <tr> - <td id="T_8a68a_row10_col0" class="data row10 col0" ><a href="../SYNOP/01-Preparation-of-data.ipynb">SYNOP1</a></td> - <td id="T_8a68a_row10_col1" class="data row10 col1" >SYNOP</td> - <td id="T_8a68a_row10_col2" class="data row10 col2" ><a href="../SYNOP/01-Preparation-of-data.ipynb"><b>01-Preparation-of-data.ipynb</b></a></td> - <td id="T_8a68a_row10_col3" class="data row10 col3" >Saturday 9 January 2021, 10:04:28</td> - <td id="T_8a68a_row10_col4" class="data row10 col4" >Saturday 9 January 2021, 10:04:34</td> - <td id="T_8a68a_row10_col5" class="data row10 col5" >00:00:05 236ms</td> + <td id="T_15a01_row10_col0" class="data row10 col0" ><a href="../SYNOP/01-Preparation-of-data.ipynb">SYNOP1</a></td> + <td id="T_15a01_row10_col1" class="data row10 col1" >SYNOP</td> + <td id="T_15a01_row10_col2" class="data row10 col2" ><a href="../SYNOP/01-Preparation-of-data.ipynb"><b>01-Preparation-of-data.ipynb</b></a></td> + <td id="T_15a01_row10_col3" class="data row10 col3" >Saturday 9 January 2021, 10:04:28</td> + <td id="T_15a01_row10_col4" class="data row10 col4" >Saturday 9 January 2021, 10:04:34</td> + <td id="T_15a01_row10_col5" class="data row10 col5" >00:00:05 236ms</td> </tr> <tr> - <td id="T_8a68a_row11_col0" class="data row11 col0" ><a href="../SYNOP/02-First-predictions.ipynb">SYNOP2</a></td> - <td id="T_8a68a_row11_col1" class="data row11 col1" >SYNOP</td> - <td id="T_8a68a_row11_col2" class="data row11 col2" ><a href="../SYNOP/02-First-predictions.ipynb"><b>02-First-predictions.ipynb</b></a></td> - <td id="T_8a68a_row11_col3" class="data row11 col3" >Saturday 9 January 2021, 10:30:55</td> - <td id="T_8a68a_row11_col4" class="data row11 col4" >Saturday 9 January 2021, 10:31:11</td> - <td id="T_8a68a_row11_col5" class="data row11 col5" >00:00:16 248ms</td> + <td id="T_15a01_row11_col0" class="data row11 col0" ><a href="../SYNOP/02-First-predictions.ipynb">SYNOP2</a></td> + <td id="T_15a01_row11_col1" class="data row11 col1" >SYNOP</td> + <td id="T_15a01_row11_col2" class="data row11 col2" ><a href="../SYNOP/02-First-predictions.ipynb"><b>02-First-predictions.ipynb</b></a></td> + <td id="T_15a01_row11_col3" class="data row11 col3" >Saturday 9 January 2021, 10:30:55</td> + <td id="T_15a01_row11_col4" class="data row11 col4" >Saturday 9 January 2021, 10:31:11</td> + <td id="T_15a01_row11_col5" class="data row11 col5" >00:00:16 248ms</td> </tr> <tr> - <td id="T_8a68a_row12_col0" class="data row12 col0" ><a href="../SYNOP/03-12h-predictions.ipynb">SYNOP3</a></td> - <td id="T_8a68a_row12_col1" class="data row12 col1" >SYNOP</td> - <td id="T_8a68a_row12_col2" class="data row12 col2" ><a href="../SYNOP/03-12h-predictions.ipynb"><b>03-12h-predictions.ipynb</b></a></td> - <td id="T_8a68a_row12_col3" class="data row12 col3" >Saturday 9 January 2021, 10:27:54</td> - <td id="T_8a68a_row12_col4" class="data row12 col4" >Saturday 9 January 2021, 10:27:59</td> - <td id="T_8a68a_row12_col5" class="data row12 col5" >00:00:05 249ms</td> + <td id="T_15a01_row12_col0" class="data row12 col0" ><a href="../SYNOP/03-12h-predictions.ipynb">SYNOP3</a></td> + <td id="T_15a01_row12_col1" class="data row12 col1" >SYNOP</td> + <td id="T_15a01_row12_col2" class="data row12 col2" ><a href="../SYNOP/03-12h-predictions.ipynb"><b>03-12h-predictions.ipynb</b></a></td> + <td id="T_15a01_row12_col3" class="data row12 col3" >Saturday 9 January 2021, 10:27:54</td> + <td id="T_15a01_row12_col4" class="data row12 col4" >Saturday 9 January 2021, 10:27:59</td> + <td id="T_15a01_row12_col5" class="data row12 col5" >00:00:05 249ms</td> </tr> <tr> - <td id="T_8a68a_row13_col0" class="data row13 col0" ><a href="../VAE/01-VAE-with-MNIST.ipynb">VAE1</a></td> - <td id="T_8a68a_row13_col1" class="data row13 col1" >VAE</td> - <td id="T_8a68a_row13_col2" class="data row13 col2" ><a href="../VAE/01-VAE-with-MNIST.ipynb"><b>01-VAE-with-MNIST.ipynb</b></a></td> - <td id="T_8a68a_row13_col3" class="data row13 col3" >Thursday 7 January 2021, 09:37:44</td> - <td id="T_8a68a_row13_col4" class="data row13 col4" ></td> - <td id="T_8a68a_row13_col5" class="data row13 col5" >Unfinished...</td> + <td id="T_15a01_row13_col0" class="data row13 col0" ><a href="../VAE/01-VAE-with-MNIST.ipynb">VAE1</a></td> + <td id="T_15a01_row13_col1" class="data row13 col1" >VAE</td> + <td id="T_15a01_row13_col2" class="data row13 col2" ><a href="../VAE/01-VAE-with-MNIST.ipynb"><b>01-VAE-with-MNIST.ipynb</b></a></td> + <td id="T_15a01_row13_col3" class="data row13 col3" >Thursday 7 January 2021, 09:37:44</td> + <td id="T_15a01_row13_col4" class="data row13 col4" ></td> + <td id="T_15a01_row13_col5" class="data row13 col5" >Unfinished...</td> </tr> <tr> - <td id="T_8a68a_row14_col0" class="data row14 col0" ><a href="../VAE/08-VAE-with-CelebA.ipynb">VAE8</a></td> - <td id="T_8a68a_row14_col1" class="data row14 col1" >VAE</td> - <td id="T_8a68a_row14_col2" class="data row14 col2" ><a href="../VAE/08-VAE-with-CelebA.ipynb"><b>08-VAE-with-CelebA.ipynb</b></a></td> - <td id="T_8a68a_row14_col3" class="data row14 col3" >Wednesday 6 January 2021, 22:17:12</td> - <td id="T_8a68a_row14_col4" class="data row14 col4" ></td> - <td id="T_8a68a_row14_col5" class="data row14 col5" >Unfinished...</td> + <td id="T_15a01_row14_col0" class="data row14 col0" ><a href="../VAE/08-VAE-with-CelebA.ipynb">VAE8</a></td> + <td id="T_15a01_row14_col1" class="data row14 col1" >VAE</td> + <td id="T_15a01_row14_col2" class="data row14 col2" ><a href="../VAE/08-VAE-with-CelebA.ipynb"><b>08-VAE-with-CelebA.ipynb</b></a></td> + <td id="T_15a01_row14_col3" class="data row14 col3" >Wednesday 6 January 2021, 22:17:12</td> + <td id="T_15a01_row14_col4" class="data row14 col4" ></td> + <td id="T_15a01_row14_col5" class="data row14 col5" >Unfinished...</td> </tr> </tbody></table> </div> diff --git a/fidle/logs/ci_report.json b/fidle/logs/ci_report.json new file mode 100644 index 0000000000000000000000000000000000000000..933e2a7684a6c5cc17d9c834e897553d225830eb --- /dev/null +++ b/fidle/logs/ci_report.json @@ -0,0 +1,98 @@ +{ + "VAE8": { + "path": "/home/pjluc/dev/fidle/VAE", + "start": "Wednesday 6 January 2021, 22:17:12", + "end": "", + "duration": "Unfinished..." + }, + "VAE1": { + "path": "/home/pjluc/dev/fidle/VAE", + "start": "Thursday 7 January 2021, 09:37:44", + "end": "", + "duration": "Unfinished..." + }, + "GTSRB1": { + "path": "/home/pjluc/dev/fidle/GTSRB", + "start": "Sunday 10 January 2021, 22:54:53", + "end": "Sunday 10 January 2021, 22:56:54", + "duration": "0:02:00" + }, + "GTSRB2": { + "path": "/home/pjluc/dev/fidle/GTSRB", + "start": "Sunday 10 January 2021, 22:56:54", + "end": "", + "duration": "Unfinished..." + }, + "GTSRB3": { + "path": "/home/pjluc/dev/fidle/GTSRB", + "start": "Thursday 7 January 2021, 12:15:52", + "end": "Thursday 7 January 2021, 12:20:01", + "duration": "00:04:09 711ms" + }, + "GTSRB4": { + "path": "/home/pjluc/dev/fidle/GTSRB", + "start": "Thursday 7 January 2021, 13:40:52", + "end": "Thursday 7 January 2021, 13:41:31", + "duration": "00:00:39 161ms" + }, + "GTSRB5": { + "path": "/home/pjluc/dev/fidle/GTSRB", + "start": "Thursday 7 January 2021, 14:47:12", + "end": "Thursday 7 January 2021, 14:48:44", + "duration": "00:01:32 269ms" + }, + "GTSRB6": { + "path": "/home/pjluc/dev/fidle/GTSRB", + "start": "Thursday 7 January 2021, 15:41:17", + "end": "Thursday 7 January 2021, 15:41:18", + "duration": "00:00:01 101ms" + }, + "GTSRB7": { + "path": "/home/pjluc/dev/fidle/GTSRB", + "start": "Thursday 7 January 2021, 15:16:05", + "end": "Thursday 7 January 2021, 15:16:06", + "duration": "00:00:00 116ms" + }, + "BHPD1": { + "path": "/home/pjluc/dev/fidle/BHPD ", + "start": "Friday 8 January 2021, 01:09:13", + "end": "Friday 8 January 2021, 01:09:24", + "duration": "00:00:11 984ms" + }, + "BHPD2": { + "path": "/home/pjluc/dev/fidle/BHPD ", + "start": "Friday 8 January 2021, 01:10:28", + "end": "Friday 8 January 2021, 01:10:39", + "duration": "00:00:12 582ms" + }, + "SYNOP1": { + "path": "/home/pjluc/dev/fidle/SYNOP", + "start": "Saturday 9 January 2021, 10:04:28", + "end": "Saturday 9 January 2021, 10:04:34", + "duration": "00:00:05 236ms" + }, + "SYNOP2": { + "path": "/home/pjluc/dev/fidle/SYNOP", + "start": "Saturday 9 January 2021, 10:30:55", + "end": "Saturday 9 January 2021, 10:31:11", + "duration": "00:00:16 248ms" + }, + "SYNOP3": { + "path": "/home/pjluc/dev/fidle/SYNOP", + "start": "Saturday 9 January 2021, 10:27:54", + "end": "Saturday 9 January 2021, 10:27:59", + "duration": "00:00:05 249ms" + }, + "LINR1": { + "path": "/home/pjluc/dev/fidle/LinearReg", + "start": "Sunday 10 January 2021, 22:54:49", + "end": "Sunday 10 January 2021, 22:54:53", + "duration": "0:00:04" + }, + "GTSRB0": { + "path": "/home/pjluc/dev/fidle/GTSRB", + "start": "Saturday 9 January 2021, 19:34:14", + "end": "", + "duration": "Unfinished..." + } +} \ No newline at end of file diff --git a/fidle/pwk.py b/fidle/pwk.py index a4778682fbae7883ed6a1c1b8a694cf234b131bc..48c19f2df51b666bbbdfbad3f89b73159ce42eec 100644 --- a/fidle/pwk.py +++ b/fidle/pwk.py @@ -5,7 +5,7 @@ # | |_) | '__/ _` |/ __| __| |/ __/ _` | | \ \ /\ / / _ \| '__| |/ / # | __/| | | (_| | (__| |_| | (_| (_| | | \ V V / (_) | | | < # |_| |_| \__,_|\___|\__|_|\___\__,_|_| \_/\_/ \___/|_| |_|\_\ -# module pwk +# Fidle module pwk # ================================================================== # A simple module to host some common functions for practical work # Jean-Luc Parouty 2020 @@ -116,9 +116,6 @@ def init(name=None, run_directory='./run'): save_figs = os.getenv('FIDLE_SAVE_FIGS', str(config.SAVE_FIGS) ) if save_figs.lower() == 'true': set_save_fig(save=True, figs_dir=f'{run_dir}/figs', figs_name='fig_', figs_id=0) - - - update_finished_file(start=True) return datasets_dir @@ -744,63 +741,12 @@ def np_print(*args, precision=3, linewidth=120): with np.printoptions(precision=precision, linewidth=linewidth): for a in args: print(a) - - -def check_finished_file(): - if not os.access(config.FINISHED_FILE, os.W_OK): - print("\n** Error : Cannot access finished file in write mode for reset...") - print(f'** Finished file should be at : {config.FINISHED_FILE}\n') - return False - return True - - -def reset_finished_file(verbose=False): - try: - data={} - with open(config.FINISHED_FILE,'wt') as fp: - json.dump(data,fp,indent=4) - if verbose : print(f'Finished file has been reset.\n') - except: - print(f'\n**Warning : cannot reset finished file ({config.FINISHED_FILE})\n') - return False - return True - - -def update_finished_file(start=False, end=False): - - # ---- No writable finished file ? - if not os.access(config.FINISHED_FILE, os.W_OK): - done = reset_finished_file() - if not done : return - - # ---- Load it - with open(config.FINISHED_FILE) as fp: - data = json.load(fp) - - # ---- Update as a start - if start is True: - data[notebook_id] = {} - data[notebook_id]['path'] = os.getcwd() - data[notebook_id]['start'] = _start_time.strftime("%A %-d %B %Y, %H:%M:%S") - data[notebook_id]['end'] = '' - data[notebook_id]['duration'] = 'Unfinished...' - - # ---- Update as an end - if end is True: - data[notebook_id]['end'] = _end_time.strftime("%A %-d %B %Y, %H:%M:%S") - data[notebook_id]['duration'] = hdelay_ms(_end_time - _start_time) - - # ---- Save it - with open(config.FINISHED_FILE,'wt') as fp: - json.dump(data,fp,indent=4) def end(): global _end_time _end_time = datetime.datetime.now() - - update_finished_file(end=True) - + print('End time is :', time.strftime("%A %-d %B %Y, %H:%M:%S")) print('Duration is :', hdelay_ms(_end_time - _start_time)) print('This notebook ends here')