diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..393c694944beadeeaa696c0e8039edf84a264d73 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.vscode/ +.ipynb_checkpoint/ +#Python and module cache +__pycache__/ +*.egg-info \ No newline at end of file diff --git a/README.md b/README.md index ba820ea9917488ae92b227e3ade1629278a9cc6f..091edf5a07dca38768f8a5f68c1a3b1f19139cb9 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,69 @@ -# Auto Research Note +# Auto-research-note generator from Jupyter notebook + +**Author :** jhjung + + +From jupyter notebook, making the research note to md file with simple syntax. + +- TOC(Table of contents) +- code +- figure +- table +- Daily note + +## Installation + +Using pip : + +```shell +pip install nbresnote +``` + +## Usage + +- For autorun when `git commit`, run below on your git repository : + +```shell +nbresnote install +``` + +- For run specific `.ipynb` files + +```shell +nbresnote note1.ipynb note2.ipynb ... +``` + +## Documentation + +### Syntax + +Basically, `nbresnote` ignore all code cells. The module will read only markdown cell for making research notes. + +Internelly, `nbresnote` trace the diff of git commit files, and get folder and filename of `.ipynb` in commit, +and auto documenting the markdown and daily note for the git repository. + +You can check the example folder. + +Here we prepare for specific syntax `!(command)` + +- TOC(Table of contents) : + + Table of Contents is simple anchor of whole notebook headers + >example) + >`!TOC` in jupyter notebook + ![toc](png/TOC.png) + + +- code +- figure +- table +- Daily note + +See wiki tabs. + +## future work : + +- configuration change +- directive of rst +- reference of outputs -automatic conversion from ipynb to note \ No newline at end of file diff --git a/bin/nbresnote b/bin/nbresnote new file mode 100755 index 0000000000000000000000000000000000000000..b320aa659a8d6b70752a31783e9e934c4289b746 --- /dev/null +++ b/bin/nbresnote @@ -0,0 +1,3 @@ +#!/bin/bash + +python -m nbresnote $1 \ No newline at end of file diff --git a/example/daily/daily.md b/example/daily/daily.md new file mode 100644 index 0000000000000000000000000000000000000000..da497196807b1cdd3b2f9c67c56bdeb1a2eb3970 --- /dev/null +++ b/example/daily/daily.md @@ -0,0 +1,21 @@ +# Daily notes +--- + + +## 2022-05-23 +### File : [example](../example/example.ipynb) +#### Added headers: +- Table capture +- H3 header +- Daily note +- Second H3 header +- Cell with no caption will be ignored +- Table of Contents +- Auto Research Note Example +- Figure capture +- Every hearder will be recorded by nbresnote +- 마치며 +- Cell +- Code +- Code and Cell capture + diff --git a/example/daily/data.pickle b/example/daily/data.pickle new file mode 100644 index 0000000000000000000000000000000000000000..73847a8e87867fa8aabc82def65f0305edfbf711 Binary files /dev/null and b/example/daily/data.pickle differ diff --git a/example/example.ipynb b/example/example.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..790e5d1fd686c47a623e4ae2e224c0947731bba1 --- /dev/null +++ b/example/example.ipynb @@ -0,0 +1,563 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Auto Research Note Example" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Table of Contents" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Table of Contents(TOC)는 해당 마크다운에 등장하는 모든 헤더의 참조를 달아서 리스트로 정리한 것을 말한다. 여기서는 단순히 `!TOC`를 이용해 구현할 수 있다." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "!TOC" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Cell with no caption will be ignored" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`nbresnote`는 기본적으로 모든 코드 셀을 무시한다. 오직 마크다운 셀만이 남겨진다." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "a = 1" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "b = 2" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "3" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a+b" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Some useless code'" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\"Some useless code\"" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n", + "1\n", + "2\n", + "3\n", + "4\n", + "5\n", + "6\n", + "7\n", + "8\n", + "9\n" + ] + } + ], + "source": [ + "for i in range(10):\n", + " print(i)" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "ename": "SyntaxError", + "evalue": "invalid syntax (, line 1)", + "output_type": "error", + "traceback": [ + "\u001b[0;36m File \u001b[0;32m\"\"\u001b[0;36m, line \u001b[0;32m1\u001b[0m\n\u001b[0;31m Some error code\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n" + ] + } + ], + "source": [ + "Some error code" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Every hearder will be recorded by `nbresnote`" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### H3 header" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Second H3 header " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Figure capture" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "연구노트에는 그림만 이용하여 표현하는것이 편리하다. \n", + "기본적으로 모든 셀을 무시하기 때문에 특정 그림을 남기고 싶다면 *해당 셀 밑*에 마크다운셀을 만들고 다음과 같이 입력하면 된다. \n", + "```\n", + "!figure
\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.plot(range(5))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "!figure Figure caption here" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Not Implemented yet :\n", + ">if you want reference, `--ref=` will capture the title of figure" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXQAAAD4CAYAAAD8Zh1EAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjQuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8rg+JYAAAACXBIWXMAAAsTAAALEwEAmpwYAAAolElEQVR4nO3deVjU5f4+8FsWl3DBJMEA0QpLtIVsJDPDzEq0BAwVQXFFxAU3wKVILctCCBA3RFQQEE0UJTGzzLIUnGJAOG6gZhAhoYmIpCLP74/vOfwOR5RBZnyG4X5d1/u6HD4fZu7zHLiDmeHztAAgQERETZ6B7ABERKQZLHQiIj3BQici0hMsdCIiPcFCJyLSE0ayHrikpAQXL16U9fBERE2SjY0NOnfuXOcxaYV+8eJFKBQKWQ9PRNQkKZXKex7jUy5ERHqChU5EpCdY6EREeoKFTkSkJ1joRER6Qu1CNzAwQGZmJlJTU+s8HhERgby8PGRnZ8Pe3l5jAYmISD1qF/rs2bNx6tSpOo85OTnB1tYWtra2mDp1KtatW6exgEREpB61Ct3S0hLDhg3Dxo0b6zzu7OyMuLg4AEBGRgZMTU1hYWGhuZT/xaSjKYYHzkbrtiZauX8ioqZKrUIPDw9HYGAgqqur6zxuaWmJgoKCmtuFhYWwtLS86zxvb28olUoolUqYmZk9UGBbh5cwwGMkAlO2wc7x1Qe6DyIifVRvoQ8bNgwlJSXIzMy85zktWrS462NC3L1vRnR0NBQKBRQKBUpLSxsY9f9kff0tVnl6o6KsDJNXr4Tn58tg0tH0ge6LiEif1Fvo/fv3x/Dhw3HhwgUkJSVh0KBB2Lp1a61zCgsLYW1tXXPbysoKRUVFmk/7bwX/OoXw0RPx9ZpoPPfm61iwZxvsh76ltccjImoqhLrj6OgoUlNT7/r40KFDRVpamgAgHBwcREZGRr33pVQq1X7c+435k92FX3y0CM05JiavDhGm5p01cr8cDoeji3O/7nzg96H7+PjAx8cHAJCWlobz588jPz8f0dHRmD59+oPebYNdOncBkV4+2BMcgaf69kFASiJeHulS59NARET6Tuf+K/Og86jV42JadKQIzTkmfDetEWZdraT/15TD4XA0OVr5CV0XXSkswnrvWdj+4aewfNoW/snxGDjeAwaGhrKjERFpnV4V+n8c352KYBcPnDmajnf9Z2FW/AZ06fGk7FhERFqll4UOANf+KsXm2QsR5/8BOnaxwNykLXh7hjcMjY1lRyMi0gq9LfT/yD7wHYKdx0D19UG8NW0S5u3Ygq7P9ZIdi4hI4/S+0AHgRtk1bFv8EaKnz0Mrk0cwa+sGDA+cjZZtWsuORkSkMc2i0P/j9JFjWOnqiWM7dsNxnDv8d8XD1uEl2bGIiDSiWRU6ANysuIFdn4RgzQRfVFfdwbSNkRi1dBFat2srOxoRUaM0u0L/j/O/ZiHEzQuHYuLwkvNQBKYkoveg12THIiJ6YM220AGg6uZN7Atfh1WeU3D9yt+YGPE5xoUsR9tOHWVHIyJqsGZd6P9RePIMwsdMQtqq9ej9+gAEpmxDn3eGyI5FRNQgLPR/q666g++iYxHq5oW/fvsdHiuWYMraUJhamMuORkSkFhb6/yi5cBGrx0/D7hWheKLPCwhIScAro0fwYl9EpPNY6HUQ1dX4KXEnVrp64mJ2Lt77IAC+m9fgsW5dZUcjIronFvp9/F1UjA0+c5D0wcfoYvsk5u+Mw6DJ43ixLyLSSSx0NSj3pCHY2QOnfjyKYXOmwy9xIx5/2lZ2LCKiWljoaiovvYzYeYuxZe4idOj8GOYkbYLTLB8YtWwpOxoREQA1Cr1Vq1bIyMhAVlYWcnNzsXTp0rvOcXR0xNWrV6FSqaBSqRAUFKSNrDoh59vDCHb2QOa+Axg8dQLmfRmLbs8/KzsWEREANXbIMDExEQCEkZGRSE9PFw4ODrWO32uv0fuNNnYsetjz9CsO4v0Du8TK7J+Fy8K5omWbNtIzcTgc/Z5G71hUUVEBADA2NoaxsTGEEOp8mt47czQDIa5jcTQpGf3HuCFgdwJ69OsrOxYRNVNqFbqBgQFUKhVKSkpw8OBBHD9+/K5z+vXrh6ysLKSlpcHOzq7O+/H29oZSqYRSqYSZmVnjkuuImzduYPeKL7BmvC+qbt2Cz4YIjP74fbRp3152NCJqhtT+Ub9Dhw7i0KFDolevXrU+3q5du5qnZZycnMTZs2cb9WtDUx2jli2F0ywfEaw6IpZ8/5V4dvBA6Zk4HI5+jcY2iS4rK8Phw4cxZEjt65yUl5fXPC2zf/9+GBsbo1OnTg25a71QdesW9kdGIdx9Eq6VlGJC2Ap4hX6Cdp0elR2NiJqBegvdzMwMHTp0AAC0bt0agwcPxunTp2udY27+/693olAoYGBggMuXL2s4atNRdCYPEZ6TsS98Lewc+yNwzzYonIfKjkVEes6ovhO6dOmC2NhYGBoawsDAADt27MC+ffvg4+MDAIiKioKbmxt8fX1RVVWFyspKuLu7az24rquuuoNDMVuR890PGLV0EdyXB8He6U18+dHn+LuoWHY8ItJTOvc8kL5NixYtxCujR4hP0r8Vn2Z8J171cBMtWrSQnovD4TS90dhz6PRghBA4un0XQlzH4nxmNlwXzceM2PXo3N1GdjQi0iMs9Ifo7z+LsdF3HhIXLUPn7jaYvzMOb0wZDwMjXuyLiBqPhS7Br199jWCXMcj9/giGzp6GOYmbYNmzh+xYRNTEsdAluX75b2z1/wCbZy9EO7NHMTsxBkNn+8KoVSvZ0YioiWKhS5Z76AcEu3jglz1peGOKF+Z/GYvuLz4vOxYRNUEsdB1Qea0cO5auwHpvPxgaG2Nm7HqMeN8frR55RHY0ImpCWOg6JC9diZARnvhhaxL6jXJFQEoCnnn1ZdmxiKiJYKHrmFuV/2BvcARWe/ng5o1KeK8Lw5hPPsQjHXixLyK6Pxa6jrqYnYsvRo7HN+s3wd7pTQTu2Ybn3hokOxYR6TAWug67c/s2DqyJRpj7BFwtvoTxoZ9gQvhnaP+Yflx6mIg0i4XeBPx59hxWeXojNXQ1nun/MgJTEtHX9V3ZsYhIx7DQm4jqO3dweEsCQt4bi6Kz+Rj90WL4RK/Co1aPy45GRDqChd7ElP5eiHWTZmDnR8Ho2tsO/snxGDB2NFoY8P9KouaOLdAECSFw7MvdWOnigXPKTLgsmIOZceth/kQ32dGISCIWehN29VIJYmb6I37BEjzW1RrzvozFYJ+JMDSq9zL3RKSHWOh6QJX2DT53HoOcbw/DaeZUzNm+Gda9esqORUQPWb2F3qpVK2RkZCArKwu5ublYunRpnedFREQgLy8P2dnZsLe313ROqkfF31cRv2AJNs0KgEmHDvBLiMY7c2fAuDUv9kXUnNS7Q4aJiYkAIIyMjER6erpwcHCoddzJyUmkpaUJAMLBwUGkp6c3atcNTuOmdVsT4bZkgQjNOSYWfrVDPPGSvfRMHA5HM9PoHYsqKioAAMbGxjA2NoYQotZxZ2dnxMXFAQAyMjJgamoKCwsLde6atOCf6xXYuexzrJs8Ey0MWmDG5rV4LygQrUx4sS8ifaZWoRsYGEClUqGkpAQHDx7E8ePHax23tLREQUFBze3CwkJYWlredT/e3t5QKpVQKpUwM+NfO2pb/vFfETJiLA7HJuLl94YjMCURPQe8IjsWEWmJWoVeXV0Ne3t7WFlZoW/fvujVq1et4y1atLjrc/73p3gAiI6OhkKhgEKhQGlp6QNGpoa4/c9NpIZEYtXYqagsv44pa0Ph+dlSmHQ0lR2NiDSsQe9yKSsrw+HDhzFkyJBaHy8sLIS1tXXNbSsrKxQVFWkmIWlEQe5JhI2agANrovHcW4MQmJKIF4YMlh2LiDSo3kI3MzNDhw4dAACtW7fG4MGDcfr06Vrn7N27F15eXgAABwcHlJWVobi4WAtxqTHuVFXhm/WbEDZqAi4XFmHcyo8xaVUw2nd+THY0ItKQ+76i+uyzz4rMzEyRnZ0tcnJyRFBQkAAgfHx8hI+PT815q1evFvn5+eLEiROiT58+jXqllqP9aWFgIF7zchcrjn8vlh89KBzeGy49E4fDqX/q6U6dDMV5SNPJylJM2xgpQnOOiWkbI0UnK0vpmTgczr2n0W9bJP11ufAPrJ8yCzuWroCV3TPw3xUPR68xvNgXURPE71oCAGQk70Wwiwfy0pUYHuAHv/hoWDz1hOxYRNQALHSqca3kL2zyC8RW/w/Q8XELzN2xBW/5TubFvoiaCBY63SXrwHdY6eKB7APf4e3pUzB3xxZY97aTHYuI6sFCpzpVXC1D4qJl2Dh9Ptq0awu/+A14138WL/ZFpMNY6HRfp44cRbCLB9J37sHA8R7w3xWPJxUvyo5FRHVgoVO9blbcQPLylVgzcTpEtcD0TWvgtmQBWrdrKzsaEf0XFjqp7fwvKoS6jcP3m+Lh4PouAncnotfAV2XHIqJ/Y6FTg9z+5ya+CluDCI8pqCgrw6TIlRgb/BHaPtpRdjSiZo+FTg+k8ORphI+eiP2RUXj2DUcEpiTixWFvyY5F1Kyx0OmB3amqwrcbtuCLkePx1+8F8PxsGSavDoGpeWfZ0YiaJRY6Ndql879htdc0pHwWhicVLyIgJRH9RrrWeZ18ItIeFjpphKiuxpGEHQh5byx+zz0Jtw8D4btpDcy6WsmORtRssNBJo64UFiHK2w/bgz7B4z2egn9yPF6f6AkDQ0PZ0Yj0HgudtOJ4ylcIdvHAmaPpeGfeTPglRKNLj6dkxyLSa/UWupWVFQ4dOoSTJ08iNzcXfn5+d53j6OiIq1evQqVSQaVSISgoSCthqWm59lcpNs9eiNj578PUwhxzkzZjyMypMDQ2lh2NSG/d92LqFhYWwt7eXgAQbdu2FWfOnBE9e/asdY6jo6NITU3V2EXaOfo3j3RoL9yXB4nQnGMiICVR2DzfW3omDqcpTqM2uCguLoZKpQIAXL9+HadOnYKlpWV9n0ZUy42ya0j64GNE+85Fq0faYGZcFJwD56Blm9ayoxHpjQY9h25jYwN7e3tkZGTcdaxfv37IyspCWloa7OzqvtSqt7c3lEollEolzMzMHiwxNWmnf0rHShdPHN2+C6+NGw3/XQmwfVkhOxaR3lDrx3wTExPxyy+/CFdX17uOtWvXTpiYmAgAwsnJSZw9e7ZRvzZwmsd0f/F5sTB1uwjNOSZGLVss2rRvJz0Th6Pr0+hNoo2MjMTXX38t5s6dq9YDXrhwQXTq1KkxoTjNZIxatRJDZ/uKYNURseRQqug9yFF6Jg5Hl6fRm0THxMTg1KlTCAsLq/O4ubl5zb8VCgUMDAxw+fJlde6amrmqmzeRFrEOqzynoPzyFUyM+AzjQpajbSde7IuooerdLLJ///7w8vLCiRMnal4cXbx4Mbp27QoAiIqKgpubG3x9fVFVVYXKykq4u7trNzXpncKTZxA+ZhJenzAWb/lOQo+XFUj5PBy/pu6XHY2oSdG5Xxs4zXs6d7cRM+OiRGjOMTFl3RfC1MJceiYOR1em0U+5ED1MJRcuYs34adi9IhRPvPg8AlIS0N/9PV7si6geLHTSSUII/JS4EytdPXExOxcj3vfH9M1r8Vi3rrKjEeksFjrptL+LirHBZw6SPvgYFrZPYP7OOAyaPA4GRrzYF9H/YqFTk6Dck4bg4WNw6sejGDZnOmYnxMDymR6yYxHpFBY6NRnll68gdt5ibJm7CO07m2H2thg4zfKBUcuWsqMR6QQWOjU5Od8eRrCzB3796msMnjoB83fGodsLz8mORSQdC52apMpr17A96BNETZ0No5YtMSN2HVwWzkXLNm1kRyOShoVOTdrZY8ex0tUTP2/bif5j3BCQkoCnX3GQHYtIChY6NXm3KiuR8lkY1oz3RdXNW5gaFQ735R+gTfv2sqMRPVQsdNIbv2WdQKibF77dsAUvDnsbgXsS8ezggbJjET00LHTSK1W3bmF/ZBTC3SfhWkkpJoStwPgvPkU7s06yoxFpHQud9FLRmTxEeE7GvvC16PnaKwjckwiF81DZsYi0ioVOequ66g4OxWxFqJsXivPOw315EKZGhaPj4xayoxFpBQud9N5fv/2OtROnI3n5Stg83xsBuxPwqsdItDDglz/pF35FU7MghMDR7bsQ4joW5zOz4bpoHmZsWYfO3W1kRyPSGBY6NSt//1mMjb7zkLhoGTp3t8H8nXF4w3s8L/ZFeqHeQreyssKhQ4dw8uRJ5Obmws/Pr87zIiIikJeXh+zsbNjb22s8KJEm/frV1wh2GYPc749gqN80zNm2CZY9ebEvavruuzuGhYWFsLe3FwBE27ZtxZkzZ0TPnj1rnePk5CTS0tIEAOHg4CDS09MbtesGh/Mwp/cgR7HkUKoIVh0Rw+b4CqNWraRn4nDuNY3asai4uLhmL9Hr16/j1KlTsLS0rHWOs7Mz4uLiAAAZGRkwNTWFhQXfSUBNQ+6hHxDs4oFf9u7HoMle8N8Zh+4vPi87FlGDNeg5dBsbG9jb2yMjI6PWxy0tLVFQUFBzu7Cw8K7SBwBvb28olUoolUqYmZk9YGQizau8Vo4dSz7Fem8/GBgZYWbseox43x+tTB6RHY1IbWoXuomJCZKTkzFnzhyUl5fXOlbXXo9CiLs+Fh0dDYVCAYVCgdLS0geIS6RdeelKhIwYix+2JqHfKFcE7E7AM6++LDsWkVrUKnQjIyMkJycjISEBu3fvvut4YWEhrK2ta25bWVmhqKhIcymJHqJblZXYGxyB1V4+uHmjEt7rwjDmkw/xSAde7It0m1qFHhMTg1OnTiEsLKzO43v37oWXlxcAwMHBAWVlZSguLtZcSiIJLmbn4ouR4/HN+k2wd3oTgXu24fm335Adi+i+7vuKav/+/YUQQmRnZwuVSiVUKpVwcnISPj4+wsfHp+a81atXi/z8fHHixAnRp0+fRr1Sy+Ho2nTp8ZSYk7RJhOYcExPCPxPtHzOTnonTPKee7tTJUByOzo2BoaEYOMFTfKY8LJb//I3o6/qu9Eyc5jeNetsiEf2f6jt3cHhLAkLeG4uis/kY/dFiTIuOxKNWj8uORgSAf/pP1GClvxdi3aQZ2PlRMKx794R/cjwGjB3Ni32RdPwKJHoAQggc+3I3Vrp44NwvmXBZMAez4qJg/mR32dGoGWOhEzXC1UsliJnhj4SFS2DW1QrzvozFYJ+JMDQykh2NmiEWOpEGZO77BsEuHsg5+D2cZk7FnO2bYd2rp+xY1Myw0Ik05PqVvxG/YAk2zQqASYcO8EuIxjtzZ8C4dSvZ0aiZYKETadi/Dv+EYJcxyNiditcnjcX8nVvx5Eu8pDRpHwudSAv+uV6Bncs+x7rJM9HCoAWmb16L94IC0bqtiexopMdY6ERalH/8V4SMGIvDsYl4+b3hCEhJRM8Br8iORXqKhU6kZbf/uYnUkEhEjpuKymvlmLI2FJ6fLYVJR1PZ0UjPsNCJHpLfc04ibNQEHFgTjefeGoTAlES8MGSw7FikR1joRA/RnaoqfLN+E8JGTcDlwiKMW/kxJq0KRvvOj8mORnqAhU4kQXH+eUSOm4o9KyNg+7ICgSmJeNnNuc7NYojUxUInkkRUV+PHuCSEjBiLwpOnMXLJQkzbGIlO1layo1ETxUInkuxy4R9YP2UWdixdAcueT8M/eSscvcbwYl/UYPyKIdIRGcl7Eezigbx0JYYH+MEvPhoWTz0hOxY1IfUWekxMDC5duoScnJw6jzs6OuLq1atQqVRQqVQICgrSeEii5uJayV/Y5BeIrQFBeNSyC+bu2IK3fCfzYl+ktvvujjFgwABhb28vcnJy6jzu6OgoUlNTNbrrBofDgTAx7SA8ViwRoTnHhP+ueGHd2056Jo78adSORUeOHMGVK1fqO42INKziahkSFy3Dxunz0aZdW/jFb8DwAD+0bNNadjTSURp5Dr1fv37IyspCWloa7Ozs7nmet7c3lEollEolzMzMNPHQRHrv1JGjCHbxQPrOPXD0GoP5yVvxVN8+smORjqr3R3wbG5t7PuXSrl07YWJiIgAIJycncfbs2Ub/2sDhcOqeJ16yFwu/2iFCc46JkUsWitbt2krPxHm4o9VNosvLy1FRUQEA2L9/P4yNjdGpU6fG3i0R1eH8LyqEuo3D95vi0df1HQTuTkSvga/KjkU6otGFbm5uXvNvhUIBAwMDXL58ubF3S0T3cPufm/gqbA0iPKagoqwMkyJXYmzwR2j7aEfZ0Uiyet8LlZiYiIEDB8LMzAwFBQVYsmQJjI2NAQBRUVFwc3ODr68vqqqqUFlZCXd3d62HJiKg8ORphI+eiNcnjcWbPhPR42UFUj4PQ+a+b2RHI4l07nkgDofTsDF/opuYFb9BhOYcE5PXhAhT887SM3G0M1p9Dp2I5Lt0/jes9pqGlM/C8ORLLyIgJRH9RrnyYl/NDAudSE+I6mocSdiBkBGe+D3nX3ALCoTvpjUw68qLfTUXLHQiPXPljz8RNXU2tgd9gsd7PAX/5Hi8PtETBoaGsqORlrHQifTU8ZSvEOzigdM/p+OdeTPhlxCNLj2ekh2LtIiFTqTHrv1Vii1zFiJ2/vswtTDH3KTNGDJzKgz//U410i8sdKJm4MQ3hxDsPAaZad/gTZ+JmPdlLGye7y07FmkYC52ombhRdg1JH3yMDdPmomWb1pgZFwXnwDlo2aaN7GikISx0ombmzM/pCHEdi6Pbd+G1caPhvysePfopZMciDWChEzVDN2/cwO5PQ7F6/DTcuX0bPhtWYdSyxWjTvp3saNQILHSiZuxCZjZC3bzw3cY4vDTcCYEpieg9yFF2LHpALHSiZq7q1i2kRaxDhMdklJdewcSIzzAuZDnaduLFvpoaFjoRAQD+OHUW4R6TsC98HXoNfBUL9iShz7tOsmNRA7DQiahGddUdHIqJwxcjx+PS+d/g8emH8F4Xho5dLGRHIzWw0InoLiUXLmLN+GnY9Wkour/4HPx3x6O/+3u82JeOY6ETUZ2EEPh5206sdPXExawcjHjfH9M3r8Vj3brKjkb3UG+hx8TE4NKlS8jJybnnOREREcjLy0N2djbs7e01GpCI5Pq7qBgbps3Ftvc/hsVTT2D+zjgMmjwOBka82JeuqbfQt2zZgiFDhtzzuJOTE2xtbWFra4upU6di3bp1Gg1IRLrhl71pCHYeg5M//Ixhc6ZjdkIMLJ/pITsW/Zd6C/3IkSO4cuXKPY87OzsjLi4OAJCRkQFTU1NYWPAFFCJ9VH75CuLmv48tcxaifWczzN4WAye/aTBq2VJ2NIIGnkO3tLREQUFBze3CwkJYWlrWea63tzeUSiWUSiXMzMwa+9BEJEnOdz8g2HkMfk39GoO9x2P+zjh0e+E52bGavUYXel2vegsh6jw3OjoaCoUCCoUCpaWljX1oIpKo8lo5tn/4CaKmzoZRy5aYEbsOrovmodUjj8iO1mw1utALCwthbW1dc9vKygpFRUWNvVsiaiLOHjuOla6e+CnxS7zi/h78d8fj6VccZMdqlhpd6Hv37oWXlxcAwMHBAWVlZSguLm50MCJqOm5VVmLP5+FYM94Xt/+5ialR4XBf/gHatG8vO1qzI+43iYmJoqioSNy6dUsUFBSISZMmCR8fH+Hj41NzzurVq0V+fr44ceKE6NOnz33v7z+jVCrVOo/D4TStMWrZUgyZNVUEZx4RS77/Sjw7eKD0TPo09XSnTobicDhNfB5/2lbM2b5ZhOYcE+O/+FS0M+skPZM+zP26k38pSkRaUXQmD6s8puCrsDXo+dorCNyTCIXLMNmx9BoLnYi0pvrOHXy/KR4h743Dn3nn4P7xB5gaFY6Oj/NvVbSBhU5EWld6sQDrJs5A8vKVsHm+NwJ2J+BVj5FoYcAK0iSuJhE9FEIIHN2+CytdPHH+1yy4LpqHmbHr0bm7jexoeoOFTkQP1dXiS9g4fT4SFi3FY926Yv7OOLzhPZ4X+9IAFjoRSZH51QEEO49B7qEfMdRvGuYmbYaV3dOyYzVpLHQikub6lb+xNSAIm2cvgElHU/glbMSwOb4watVKdrQmiYVORNLlHvoRwS4e+GVPGgZN9oL/zjg80ecF2bGaHBY6EemEf8qvY8fSFVg/ZRYMjAwxY8s6jHjfH61MeLEvdbHQiUin5GX8gpARY/FD3Db0G+WKgN0JeGZAP9mxmgQWOhHpnFuV/2DvylWIHDcVNytuwHvtFxjz6YcwMe0gO5pOY6ETkc76/cS/8MWoCfhmXQzsh7yJgJREPP/2G7Jj6SwWOhHptDu3b+PA2o0Ic5+Av/8shlfIckyM+AztH+OuZ/+LhU5ETcKfZ88hcuxUpIZE4ulXXkZgSiL6ur4rO5ZOYaETUZNRfecODscmYuWIsfjjTB5Gf7QY06Ij8ajV47Kj6QQWOhE1OZcLCrF+8kx8uewzWPfuCf/keLw2zr3ZX+xLrf/1b7/9Nk6fPo28vDwsWLDgruOOjo64evUqVCoVVCoVgoKCNB6UiOi/CSGQvnMPgl3G4JwyE86BszErLgrmT3aXHU2q++6OYWBgIPLz80X37t2FsbGxyMrKEj179qx1jqOjo0hNTdXYrhscDofT0LF3elMs+yFNfJ75o3hz2iRhaGQkPZM2plE7FvXt2xf5+fm4cOECbt++jaSkJDg7O9f3aURED5Vq/0EEu3jgxDeHMGSGN+Zs3wzrXj1lx3qo6i10S0tLFBQU1NwuLCyEpaXlXef169cPWVlZSEtLg52dXZ335e3tDaVSCaVSCTMzvuWIiDSr4u+rSFi4FDEzA/BIh/bwS4jGO/Nmwrh187jYV72F3qJFi7s+JoSodTszMxM2NjZ44YUXEBkZiZSUlDrvKzo6GgqFAgqFAqWlpQ+WmIioHid/+AkrXTyQnrwXr0/0hH9yPJ58yV52LK2rt9ALCwthbW1dc9vKygpFRUW1zikvL0dFRQUAYP/+/TA2NkanTp00HJWISH3/XK9A8sfBWDtpBgBg+ua1cPtwAVq3NZGcTLvu+wS8oaGhOHfunOjWrVvNi6J2dna1zjE3N6/5t0KhEBcvXmzUE/scDoejyTFu3Uq8M2+mWJn1kwj6do/o+Vp/6ZkedOrpzvrvwMnJSZw5c0bk5+eLxYsXCwDCx8dH+Pj4CABixowZIjc3V2RlZYljx46Jfv36NTYUh8PhaHyse9sJ/13xIjTnmPD8fJkw6WgqPVNDp9GFLiEUh8PhaGUMjYzEm9Mmic8zfxTLfkgT9k5vSs/UkGnU2xaJiPTJnaoqHFy/CV+MHI/LBX9gbPBHmBS5Eh3MH5MdrdFY6ETULF06dwGRXj7YExwBW4eXELA7ES+7Odf5zr6mgoVORM2WqK7Gj1uTsHKEJwr/dRojlyzEtI2R6GRtJTvaA2GhE1Gzd6WwCOu9Z2HHkk9h2fNpBOyKx8DxHjAwNJQdrUFY6ERE/5axKxXBLh44cywD7/rPwqytG2Bh+6TsWGpjoRMR/ZdrJX9hs98CxPl/gI6PW2De9i14e/oUGBoby45WLxY6EVEdsg98h2DnMVB9fRBv+U7G3O2b0fXZuq9TpStY6ERE93Cj7Bq2Lf4I0dPnoU27tpgVH43hAX5o2aa17Gh1YqETEdXj9JFjCHbxwLEdu+HoNQb+u+Jh6/CS7Fh3YaETEanhZsUN7PokBGsm+KK66g6mbYzEyCUL0bpdW9nRarDQiYga4PyvWQhx88KhmDgoXIYhMCURvV4fIDsWABY6EVGDVd28iX3h67DKcwquX/kbk1YFY2zwR2j7aEepuVjoREQPqPDkGYSPmYS0Vevx7BuOCNyzDS++87a0PCx0IqJGqK66g++iYxHq5oW/fvsdniuWYsraUJhamD/0LCx0IiINKLlwEavHT8PuFV/giT72CEhJQL9Rrg/1Yl8sdCIiDRHV1fgp8UuEjPDE7yf+BbegQPhuXgMzG+v6P1kD1Cr0t99+G6dPn0ZeXh4WLFhQ5zkRERHIy8tDdnY27O31fzNWIqJ7ufLHn4iaOhtJQcvRxfZJ+O/citcnej6Ui33dd3cMAwMDkZ+fL7p3716zp2jPnj1rnePk5CTS0tIEAOHg4CDS09MbtesGh8Ph6Mu0M+skxoetEKE5x8Sc7ZtFlx5PNer+GrVjUd++fZGfn48LFy7g9u3bSEpKgrOzc61znJ2dERcXBwDIyMiAqakpLCws6rtrIiK9V156GbFzF2HL3EXo0PkxzE3ajAFjR2vlseotdEtLSxQUFNTcLiwshKWlZYPPAQBvb28olUoolUqYmZk1JjcRUZOS8+1hBDt7IDPtAC4X/KGVxzCq74S6XqEVQjT4HACIjo5GdHQ0AECpVKodkohIH1Reu4akD5Zr7f7r/Qm9sLAQ1tb//xVaKysrFBUVNfgcIiLSrnoLXalUwtbWFt26dYOxsTHc3d2xd+/eWufs3bsXXl5eAAAHBweUlZWhuLhYO4mJiKhO9T7lcufOHcycORMHDhyAoaEhNm3ahJMnT8LHxwcAEBUVhbS0NAwdOhT5+fm4ceMGJk6cqPXgRERUWwv839tdHjqlUgmFQiHjoYmImqz7dSf/UpSISE+w0ImI9AQLnYhIT7DQiYj0hLQXRUtKSnDx4sUH+lwzMzOUlpZqOFHj6WouQHezMVfDMFfD6GMuGxsbdO7c+Z7HpV+8pqGjqxf20tVcupyNuZiLuTQ3fMqFiEhPsNCJiPREkyz0DRs2yI5QJ13NBehuNuZqGOZqmOaWS9qLokREpFlN8id0IiK6GwudiEhP6HSh6+rm1PXlcnR0xNWrV6FSqaBSqRAUFPRQcsXExODSpUvIycm55zky1qu+XDLWy8rKCocOHcLJkyeRm5sLPz+/Os972OulTi4Z69WqVStkZGQgKysLubm5WLp0aZ3nPez1UieXrO9HADAwMEBmZiZSU1PrPK6N9ZL+nsy6RlubUz+MXI6OjiI1NfWhr9mAAQOEvb29yMnJqfO4jPVSJ5eM9bKwsBD29vYCgGjbtq04c+aMTnx9qZNL1teXiYmJACCMjIxEenq6cHBwkL5e6uSStV4AxNy5c0VCQkKdj6+N9dLZn9B1dXNqdXLJcuTIEVy5cuWex2Vt5l1fLhmKi4uhUqkAANevX8epU6fu2gdXxnqpk0uWiooKAICxsTGMjY3v2mZS1tdXfblksbS0xLBhw7Bx48Y6j2tjvXS20DW5OfXDzgUA/fr1Q1ZWFtLS0mBnZ6fVTOqSsV7qkrleNjY2sLe3R0ZGRq2Py16ve+UC5KyXgYEBVCoVSkpKcPDgQRw/frzWcVnrVV8uQM56hYeHIzAwENXV1XUe18Z66Wyha3Jzak1S5zEzMzNhY2ODF154AZGRkUhJSdFqJnXJWC91yFwvExMTJCcnY86cOSgvL691TOZ63S+XrPWqrq6Gvb09rKys0LdvX/Tq1avWcVnrVV8uGes1bNgwlJSUIDMz857naGO9dLbQdXVzanUes7y8vObXwP3798PY2BidOnXSai516Opm3rLWy8jICMnJyUhISMDu3bvvOi5rverLJfvrq6ysDIcPH8aQIUNqfVz219e9cslYr/79+2P48OG4cOECkpKSMGjQIGzdurXWOdpaLykvFtQ3hoaG4ty5c6Jbt241Lz7a2dnVOmfo0KG1XlTIyMjQiVzm5uY1/1YoFOLixYsPbd1sbGzu+eKjjPVSJ5es9YqNjRVhYWH3PC5rverLJWO9zMzMRIcOHQQA0bp1a/Hjjz+KYcOGSV8vdXLJ/H4E7v2irDbWq95NomXR1c2p1cnl5uYGX19fVFVVobKyEu7u7lrPBQCJiYkYOHAgzMzMUFBQgCVLlsDY2Lgml6zNvOvLJWO9+vfvDy8vL5w4caLmRcjFixeja9euNblkrJc6uWSsV5cuXRAbGwtDQ0MYGBhgx44d2Ldvn/TvR3Vyyfp+rIu214t/+k9EpCd09jl0IiJqGBY6EZGeYKETEekJFjoRkZ5goRMR6QkWOhGRnmChExHpif8H/pOuuXP4jlIAAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.plot(range(5)[::-1])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "!figure --ref=reverse Reverse plot" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Code and Cell capture" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "연구노트에 코드 혹은 셀(결과 포함)을 첨부하고 싶을 수 있다. 그런 경우 *해당 셀의 위*에 마크다운 셀을 만들고 `!code` 혹은 `!cell`을 이용해 코드를 노트할수 있다." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Code" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "!code code caption here" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([0, 1, 2, 3, 4])" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import numpy as np\n", + "np.arange(5)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Cell" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "!cell cell caption here" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n", + "1\n", + "2\n", + "3\n", + "4\n", + "5\n", + "6\n", + "7\n", + "8\n", + "9\n" + ] + } + ], + "source": [ + "for i in range(10):\n", + " print(i)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "!cell cell with figure" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.plot(np.sin(np.linspace(0,4*np.pi,100)))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "code 는 단순히 코드만을 cell은 코드와 결과를 모두 저장한다." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Table capture" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Python을 이용해 데이터를 분석하다 보면 자연스럽게 `Pandas` 의 `DataFrame`을 이용하게 된다." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "코드보다 `DataFrame`의 표를 넣고 싶은 경우 해당 셀의 아래에 markdown cell을 만들고 `!table ` 이라고 입력해주면 된다." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
LibraryVersion
0Pandas1.3.1
1Numpy1.20.3
\n", + "
" + ], + "text/plain": [ + " Library Version\n", + "0 Pandas 1.3.1\n", + "1 Numpy 1.20.3" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import pandas as pd\n", + "\n", + "pd.DataFrame({\"Library\" : [\"Pandas\",\"Numpy\"], \"Version\" : [pd.__version__, np.__version__]})" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "!table Pandas와 Numpy 버전 비교" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Daily note" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "일일 연구노트 작성을 위해 어떤 헤더가 추가되었는지를 `daily/daily.md`에 지속적으로 업데이트 한다. 따라서 연구일지를 따로 작성할 필요없이 `daily.md` 파일을 수정함으로써 연구일지를 자동으로 작성할 수 있다." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![데일리노트](daily/daily.md)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 마치며" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "이외에 혹시 문의사항이나 건의가 있다면 알려주기 바람. (jhjung@uos.ac.kr)" + ] + } + ], + "metadata": { + "interpreter": { + "hash": "32faf49e23dade3da949dac38cd82415b4f92fc275f42257c9249d3d26f5392a" + }, + "kernelspec": { + "display_name": "Python 3.7.11 ('complex')", + "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.11" + }, + "orig_nbformat": 4 + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/example/example.md b/example/example.md new file mode 100644 index 0000000000000000000000000000000000000000..4f54132aa438bbab1e56a7ae4c2292bd31d31bae --- /dev/null +++ b/example/example.md @@ -0,0 +1,169 @@ +# Auto Research Note Example + +## Table of Contents + +Table of Contents(TOC)는 해당 마크다운에 등장하는 모든 헤더의 참조를 달아서 리스트로 정리한 것을 말한다. 여기서는 단순히 `!TOC`를 이용해 구현할 수 있다. + + - [Auto Research Note Example](#auto-research-note-example) + - [Table of Contents](#table-of-contents) + - [Cell with no caption will be ignored](#cell-with-no-caption-will-be-ignored) + - [Every hearder will be recorded by nbresnote](#every-hearder-will-be-recorded-by-nbresnote) + - [H3 header](#h3-header) + - [Second H3 header](#second-h3-header) + - [Figure capture](#figure-capture) + - [Code and Cell capture](#code-and-cell-capture) + - [Code](#code) + - [Cell](#cell) + - [Table capture](#table-capture) + - [Daily note](#daily-note) + - [마치며](#마치며) +## Cell with no caption will be ignored + +`nbresnote`는 기본적으로 모든 코드 셀을 무시한다. 오직 마크다운 셀만이 남겨진다. + +## Every hearder will be recorded by `nbresnote` + +### H3 header + +### Second H3 header + +## Figure capture + +연구노트에는 그림만 이용하여 표현하는것이 편리하다. +기본적으로 모든 셀을 무시하기 때문에 특정 그림을 남기고 싶다면 *해당 셀 밑*에 마크다운셀을 만들고 다음과 같이 입력하면 된다. +``` +!figure
+``` + +![fig. 1](fig1.png) +**Fig. 1.** Figure caption here + +Not Implemented yet : +>if you want reference, `--ref=` will capture the title of figure + +![fig. 2](fig2.png) +**Fig. 2.** Reverse plot + +## Code and Cell capture + +연구노트에 코드 혹은 셀(결과 포함)을 첨부하고 싶을 수 있다. 그런 경우 *해당 셀의 위*에 마크다운 셀을 만들고 `!code` 혹은 `!cell`을 이용해 코드를 노트할수 있다. + +### Code + +**Code 1.** : code caption here + + +```python +import numpy as np +np.arange(5) +``` + +### Cell + +**Code 2.** : cell caption here + + +--- + +```python +for i in range(10): + print(i) +``` + +*Outputs :* + + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + + +--- + + +**Code 3.** : cell with figure + + +--- + +```python +plt.plot(np.sin(np.linspace(0,4*np.pi,100))) +``` + +*Outputs :* + + + [] + +![png](outputs3_0.png) + +
+ +--- + + +code 는 단순히 코드만을 cell은 코드와 결과를 모두 저장한다. + +## Table capture + +Python을 이용해 데이터를 분석하다 보면 자연스럽게 `Pandas` 의 `DataFrame`을 이용하게 된다. + +코드보다 `DataFrame`의 표를 넣고 싶은 경우 해당 셀의 아래에 markdown cell을 만들고 `!table ` 이라고 입력해주면 된다. + +
+ + + + + + + + + + + + + + + + + + + + + +
LibraryVersion
0Pandas1.3.1
1Numpy1.20.3
+
+ +**Table 1** Pandas와 Numpy 버전 비교 + + +## Daily note + +일일 연구노트 작성을 위해 어떤 헤더가 추가되었는지를 `daily/daily.md`에 지속적으로 업데이트 한다. 따라서 연구일지를 따로 작성할 필요없이 `daily.md` 파일을 수정함으로써 연구일지를 자동으로 작성할 수 있다. + +![데일리노트](daily/daily.md) + +## 마치며 + +이외에 혹시 문의사항이나 건의가 있다면 알려주기 바람. (jhjung@uos.ac.kr) + diff --git a/example/fig1.png b/example/fig1.png new file mode 100644 index 0000000000000000000000000000000000000000..6b819f65fffdca1430d95db252ab092a47527e51 Binary files /dev/null and b/example/fig1.png differ diff --git a/example/fig2.png b/example/fig2.png new file mode 100644 index 0000000000000000000000000000000000000000..159f6f6e8116d6bcd55271c1fa69d0922574fbee Binary files /dev/null and b/example/fig2.png differ diff --git a/example/outputs3_0.png b/example/outputs3_0.png new file mode 100644 index 0000000000000000000000000000000000000000..fb30b1d7d33810e8054c7c021a8ac7cc2df19585 Binary files /dev/null and b/example/outputs3_0.png differ diff --git a/nbresnote.py b/nbresnote.py new file mode 100644 index 0000000000000000000000000000000000000000..379992cd222fbd4339513bcba511d4ab0e977016 --- /dev/null +++ b/nbresnote.py @@ -0,0 +1,312 @@ +import json, base64, os, pickle, datetime, string + +__version__ = "0.1" +### from ipynb extract markdown and noted output for document organization + +class nbparser: + def __init__(self, path, output_root = "wiki"): + """ipynb notebook parser. from .ipynb file, generating the markdown file. + + Args: + path (`os.Pathlike`): path of .ipynb file + """ + + self.path = path + self.folder, self.basename = os.path.dirname(path), os.path.splitext(os.path.basename(path))[0] + self.notebook = json.loads("\n".join(open(path).readlines())) + self.outroot = output_root + self.outputpath = os.path.join(self.outroot, self.folder, self.basename) + os.makedirs(self.outputpath, exist_ok = True) + self.TOC, self.source = [],[] + self.fig, self.code = [], [] + self.table = [] + self.ref = {} + + def conversion(self): + self.markdown_parsing() + self.write_markdown() + + + def markdown_parsing(self): + """from notebook json instance, generating and parsing the markdown syntax. + + Args: + notebook (_type_): jupyter notebook(.ipynb) file or json parser. + + Return: + source : markdown source. + fig : figure + code : code + """ + notebook = self.notebook + + fig = self.fig + source = self.source + code = self.code + + #### Markdown parsing + for i, cell in enumerate(notebook['cells']): + if not cell["source"]:continue + if cell["cell_type"] == 'markdown': #markdown + a = cell["source"][0].lstrip() + #header parsing + if a[0]== "#": + header = a.split()[0] + title = " ".join(a.split()[1:]) + for character in string.punctuation: + if character=="-":continue + title = title.replace(character, '') + self.TOC.append((header, title)) + #command parsing + elif a[0] == "!": + command = a.split()[0][1:] + if command =="code": #code + self.parse_code(cell, notebook['cells'][i+1]) + continue + if command =="cell": #cell + self.parse_code(cell, notebook['cells'][i+1], True) + continue + if command in ["figure","fig"]: #figure + #figure parsing + self.parse_figure(cell,notebook['cells'][i-1]) + continue + if command == "table":#Dataframe table + self.parse_table(cell, self.notebook["cells"][i-1]) + continue + if command in ["toc","TOC"]: + source.append("!TOC") + continue + + source.append("".join(cell["source"])) + + def parse_figure(self, mdcell, figcell): + """From markdown cell and figure cell, extract figure and extension and markdown. + + Args: + mdcell : markdown cell + figcell : equivalent figure cell + """ + captions = mdcell["source"][0].lstrip().split() + if captions[1][:6] == "--ref=": + self.ref[captions[1][6:]] = len(self.fig)+1 + captions = " ".join(captions[2:]) + else: + captions = " ".join(captions[1:]) + + for data in figcell['outputs']: + if not 'data' in data: continue + for key in data['data']: + if key.split("/")[0] == "image": + ext = key.split("/")[1] # PNG, JPEG, etc + self.fig.append((data['data'][key],captions)) + self.source.append(f"![fig. {len(self.fig)}](fig{len(self.fig)}.{ext}) \n**Fig. {len(self.fig)}.** {captions}") + self.save_fig(f"{self.outputpath}/fig{len(self.fig)}.{ext}", data['data'][key]) + + def save_fig(self, fname, base64fig): + with open(fname,"wb") as f: + f.write(base64.b64decode(base64fig)) + + def parse_code(self, mdcell, codecell, output = False): + """From markdwon and code cell, extract code and/or text outputs. + + Parameters + ---------- + mdcell : json dict + markdown cell dict. + codecell : json dict + code cell dict + + """ + captions = mdcell["source"][0].lstrip().split() + if captions[1][:6] == "--ref=": + self.ref[captions[1][6:]] = len(self.code)+1 + captions = " ".join(captions[2:]) + else: + captions = " ".join(captions[1:]) + + self.code.append(0) #number counting + self.source.append(f"**Code {len(self.code)}.** : {captions} \n") + if output: + self.source.append("---") + self.source.append(f"```python\n{''.join(codecell['source'])}\n```") + if output: + self.source.append(f"*Outputs :* \n") + i = 0 + for out in codecell["outputs"]: + if "data" in out: # display output or execute result + for data in out["data"]: + if data.split("/")[0] == "text": + self.source.append(" "+" ".join(out["data"][data])) + elif data.split("/")[0] == "image": + ext = data.split("/")[1] + fname = f'outputs{len(self.code)}_{i}.{ext}' + + self.source.append(f"![{ext}]({fname})") + self.save_fig(f"{self.outputpath}/{fname}", out['data'][data]) + i+=1 + + else: #stream output + if out["name"] =="stdout": + self.source.append(" "+" ".join(out["text"])) + else: # std err is ignored. + continue + + self.source.append("---\n") + + + def parse_table(self, mdcell, tablecell): + """From markdwon and table cell, extract table contents. + + Parameters + ---------- + mdcell : json dict + markdown cell dict. + tablecell : json dict + table cell dict + + + """ + captions = mdcell["source"][0].lstrip().split() + if captions[1][:6] == "--ref=": + self.ref[captions[1][6:]] = len(self.table)+1 + captions = " ".join(captions[2:]) + else: + captions = " ".join(captions[1:]) + + self.table.append(0) + table = [out["data"]["text/html"] for out in tablecell["outputs"] if out["output_type"]=="execute_result"][0] + self.source.append("".join(table)) + self.source.append(f"**Table {len(self.table)}** {captions} \n") + + def toc_source(self): + """Generate markdown source of `Table of Contents` from header in `self.TOC`. + """ + s = "" + for content in self.TOC: + s += (" "*len(content[0])+"- ["+content[1]+"](#"+"-".join(content[1].lower().split())+") \n") + return s + + def write_markdown(self): + ### Write markdown + with open(os.path.join(self.outputpath, self.basename)+".md","w") as f: + for line in self.source: + if line == "!TOC": + f.write(self.toc_source()) + else: + f.write(line+" \n\n") + + +def toc_source(TOC): + """Generate markdown source of `Table of Contents` from header in `self.TOC`. + """ + s = "" + for content in TOC: + s += ("> "*len(content[0])+"- ["+content[1]+"](#"+"-".join(content[1].lower().split())+") \n") + return s + +def daily_note(note_path, check): + if not os.path.exists(note_path): + os.makedirs(os.path.dirname(note_path),exist_ok=True) + with open(note_path, "w") as f: + f.write("# Daily notes \n---\n") + write_daily(note_path, check, check) + return + p = os.path.join(os.path.dirname(note_path),"data.pickle") + with open(p, "rb") as f: + source = pickle.load(f) + + mod, record = modified_check(source, check) + write_daily(note_path, mod, record) + +def modified_check(source, check): + mod = {} + new = {} + for i in check: + if i in source: + diff = check[i] - source[i] + if diff: + mod[i] = diff + new[i] = check[i] | source[i] + else: + mod[i] = check[i] + new[i] = check[i] + return mod, new + +def write_daily(note_path, mod, record): + p = os.path.join(os.path.dirname(note_path),"data.pickle") + with open(p, "wb") as f: + pickle.dump(record, f) + + if not mod: + return + #print(mod, record) + today = False + for line in open(note_path): + if line[0] != "#": continue + line = line.rstrip() + if line.split()[1] == str(datetime.date.today()): + today = True + + with open(note_path, "a") as f: + f.write("\n\n") + if not today: + f.write(f"## {datetime.date.today()} \n") + for file in mod: + f.write(f"### File : [{os.path.splitext(os.path.basename(file))[0]}](../{file}) \n") + f.write("#### Added headers: \n") + for header in mod[file]: + f.write(f"- {header} \n") + f.write("\n") + + +shellsource = """#!/bin/bash + +git diff --name-only --cached >> __tmp__files + +python -m notation git-pre-commit + +rm __tmp__files +""" + +if __name__ =="__main__": + import sys + #path config + wikipath = "wiki/" + daily_path = os.path.join(wikipath, "daily", "daily.md") + + if not len(sys.argv)>1: + print("Error : There is no target file.") + exit(1) + else: + if sys.argv[1] =="git-pre-commit": + targets = open("__tmp__files").readlines() + print(targets) + elif sys.argv[1] == "install": + if not os.path.exists(".git"): + raise OSError("Please run on the base folder of git repository.") + if not os.path.exists(".git/hooks/pre-commit"): + print("Creating 'pre-commit' file on '.git/hooks/'.") + with open(".git/hooks/pre-commit","a") as f: + f.write(shellsource) + print("Change mod of 'pre-commit' file on '.git/hooks/' into 755(rwxr-xr-x).") + os.chmod(".git/hooks/pre-commit", 755) + print("Done.") + else: + print("Warning : Already exists 'pre-commit' file on '.git/hooks/'.") + exit(0) + else: + targets = sys.argv[1:] + + check = {} + for file in targets: + file = file.rstrip() + if os.path.splitext(file)[1] == ".ipynb": + notebook = nbparser(file) + notebook.conversion() + check[file] = set(map(lambda x:x[1],notebook.TOC)) + + daily_note(daily_path, check) + + + + diff --git a/setup.py b/setup.py new file mode 100644 index 0000000000000000000000000000000000000000..6bb824bc0ce9edb6bd228e9356057eed39ecf711 --- /dev/null +++ b/setup.py @@ -0,0 +1,14 @@ +from setuptools import find_packages, setup + +from nbresnote import __version__ + +setup( + name="nbresnote", + version = __version__, + py_modules=["nbresnote"], + author="jhjung", + author_email="jhjung@uos.ac.kr", + description="auto research note conversion", + scripts=['bin/nbresnote'], + #url="https://yheom.sscc.uos.ac.kr/gitlab/csns-lab/auto-research-note" +) \ No newline at end of file