{
 "cells": [
  {
   "attachments": {
    "09375636-629b-4ee2-9011-455f6157ab16.png": {
     "image/png": "iVBORw0KGgoAAAANSUhEUgAAAgsAAABgCAMAAACkLcFMAAAAwFBMVEX///8AO2EAOF8ANV0dVXddfZQAMlv7/P0ALlkAOWAALFgAJ1UAMFrp7vKttsDI1NxBaIRPbIbc5OkAIlIyUnGltsNSeJJxg5ePp7jFz9cAQmllhp2Woq/w9PYAAEQAB0gbTG8AFU4AGk42Y4K/xs41XHpYcIhzj6OwwMuZq7k9XXoASG7W4OaBkqPl6OsAHlGTqbldgJgAEUsAAD+dsb+LmqouVXR9maxofZJti6BYfJQnS2yeqbWAkKEQT3JAbYmctWnXAAAXrElEQVR4nO2dC3uiOhOAuVTuFIFiBUuX1hsqou1BrLXt/v9/9WWSgDdAPeuxflvnnKerGCCQl8lkMhMY5ipXucpVrnKVq1zllCKKvqX7IpLvrsnliBF/dw3OLWLUGSwaN7Ji2/bEtpvfXZ/LkVHjZz0YUbOXCpLAc7LMggjRd9focuSm9t01OJ/40UJTNZ5jV8LXzvMo+KuPol9e7HvlB7HQqXmazG4KH57jzNH47TOhn8PPt8+znPR4+Sks+GEqC9sksNxQP8O5HU8TNKmFP0859Fmbn+Gsx8sPYcEwFW4bBCRnaZQ45dGpZAG0gTWCanAj4wznPVp+BAv+fCQUkMCy6jksx0jB+kiboc+hgs8r3Z7hvEfLD2BBDANlp3cg1sLvc5w/UokO6iMzNaEsfJzjxMfKD2ChzxV1DyCKc47zWxImUYH2NyaEi4u0Hv96FvSGUkICshzP4mgTZwCDkFros9+QQC2YFzmu/NtZiIbFlgKI0D9PHfSFYtttF3+O321balymg+svZ8ENylFglSpr3j9h/yGKkS8WfL4w2ctCHCTMNL1MkPdKGPDlKHBflbtOBueq5aXIfhbqCeOY1lkqc2qJvTKrEUSaVu3bEPizWJYXJPv7CKTRLteFXilWt0IrsFxQZTkarMx5R1v7UQfE2N6wpVV9A29dc3laZL/SviMu/V03Bovf7W7jZWDsuFBFo+js5ecqZ8HvIAIilx62E8Of1ekMcsGie+u45J4aUVb0HH7dA0SsVaHACvdV3fYA7cuxR3aNUaBJkqRwOUPuSAIJNg2TuaxAMTNnMeqqUKyUPbELPyvyjiLTZ3VPEXie4wXJq0+3Lihh8W7djfYQU7yRK1CK5SxEzx2GWUjkiy89IKJ+5ZUVez04sfU2eXqcpHCp4u823W9yGYNnsVU6mCRSVU0dqxT+7rhBZ6JiT4Lwlm140eC7rDxsFPvCPZfMu9mGW+ILE95LjmvY5Petoag/4CU+96LJvMQNNmhoE7t5s6+jx+LN3Se2ggUb3ay+Qr7oHLDwnLtOCQu64IU++PoRNaJ5Q/dTL4MFp8pWQA99WtXxueQ2aseNOpsS1TjZhhY9zCYLHmk/eY0F0miNkuMaxHO51X5+Tdpyp3L8Yh2GOtGLnLP/WFj+iIU+18GV4rqXx4IVVLMgVQY01ehQVDrqWs7KgnVT0AVq9TUYzsmCn9IuN3mML46FRoVjARqCrRoa6dnOXHCM8XNOFnxTK7ourbWCoc6dj4UooM+WnuiXxoJbaTei9qoMaEqkvFz/CMfQOVnor6IxOH4tVktK8iLn1AuGtzrvhbEQD/ewIFdV0jdXeyudw896RhbCSVZBjR2+9VItq7Gs5nbQOVlwN1hoKE9YVOECWGjyxbPU+aOUVnURBrvam68fcdazsSBmtHJq34h934raasZGbgids49wt/RCeIsknB1nb/0nIu5BYU9AU2u9K1bdqqIbcj4WwozpIL/ZA9pP8Pns6yn0go61DGFBpZsq+wjwS15UHxFmD0mZqFXTUiK7TtLKW7BXzsaC+ElpXYvAEN+pwZsf9wQs6O9Yy1jAgvOLmE4RHLDUdoxM67JYWFQPIlgYBJeLs+Gkkr2DFcPZWNCJu2ozMEu3t/g4QR/h90z4x32M0J9nYjqFbKfAvzDsEVLmT+JFsaAPq30LrFQ57dTbtDsPdzidjYWIepn4DUwpIHlYxin6iFkAhtVC8eGuDqHD0E1walvPuU1NWHAm2KttaLXL6iPc0Z9YjtFykyRZOHRYeTYWaB/IpRsNOlcFECU7DGFB/iMWYrYbGnMVm1ehVE8MZ6jggG77PsHSEel8RF3pd4xmAOENKxbsb2fhds9MhDCu2nsmbRU/2Ho8GwvT7EQblOqzT5BxNqN2knGEawrqaOrTz57t9bCppQcjD0vdZ+7foBr+IOXV4A0OK7Zo32UFR4zI/xt5KHTJrbFQ1bh+d7uDEQ6N/TobC3163FlldbI+YuPZjI4dU/qRYa19jqj7IqKCfovpwMVCJQmceraH9e3RDuNqFribqp13xyDc8MArOhsLL+S4e0LrKQuyOe+v5IU/koX/bxH3DCOqp6UaBR7LA3u9s7FA66jtYYEqOA6bERr8rwn06n4MC/1KvSB7lZYju2t37tHFuVwaCxV++J/Cwh7bsTqgaVqgU4S3wzqJKwuXJ2GlXuAqA5rMAtcE1929cUVyaSxUeFl+DAtGUOFf4CstQbfI1JC9/08WrnphbRavSJRKy/Gl0OxUD8sJuFAWZG5N5B/GAuOUz01xX1XWgl+844FJuGdj4f2oPiJI14SqzJ/DgiiXdpVCUrVjUmx1Hrhmxw4LdHArnZqFYsa2hfqg5aYV5WLRibefw0K59bgdV74pfknnUpyF6zvN+XyerA64w8KcVGNrTEpdQF4+b340C8XHZXwimeIr9EEf73cMf3eHLWxvGw16rU3IL5w3kLSa2Ok4bVCJGXGBt8+pC9KfNtKGQ6sUT9tpK8RfrMYqMrMFycY62W8Kx/P71L5HZxTn2bEbLZ+ZwwyYk9VjTi4tatWHrVJfcpm7ifMq019cr9jo1BZF56jZGhJ1Ffi0w8KgaN5AJHPLXJBX5WgWaDzm1ljXCFRFUdQ8N/AkMW6+qdRms54NcZ/OP3Sn4ZvI+MtlzzRN7xlSdF54E76YZsT4wh3eTuYtoxuu9mk+k7OFHl97qz/hOYtwksc8uaqNqhh5ac/s1XkcHRHQG578isWxiTZzXXRQtGP7Bp3tfUI5+oKoVdHRvPvPrl2qu/WbIhi4Peu2zUvUidAqKGyRmErZzrfssJAr5PU2M7JJxn/PQjZPebPRoDNFBuFp0tJpWBioHXS//eTJhWiWNRbE5ScoIb0FU3cvNxbRSaioMMPbG5IBOUdBJIp+R4JL04Oh64t+ooI666jSJz3FWFMwC00R7Rf10ONqpVQRJ88x1naul5Cjt7siZCzQyfobYMFQ3y10joen0rb167sw7MuQ9MtycQtZ0GmHYud3lfo7hewimZjceHlDG1Hg+F4OyPGxLNQ5uhmHMaLxC5kSO8k8Zb2Oq+l7/R0W6Gwv9wIs5IfzBWLF+BzaY26TRhto6N8ZS3rFOSyT1VH7MrkrVtqC1K6IJfrM4JNNFvBGj14EYeGmR3IVMAs3N1hJiG9B6ahAb6hbcQhSsGdewSnzVwqFfcQbYUHJj0rhWEWf+jS8RFrTXz59XNdskKNZyOwaLl0rFdHaK9liASfRCw2SXybChGQhC2K7vckCtWj9Lrqcxg2Ni9OmjF+jvan12EEsTAybVDScuMoaC773UMQCNfkJC18RiajALLxSC9qpClycLdcW8pP5UX9fdmSpc0Z4KSp+T/MVTcpjSK2N1WpM4iKLS1wphhndtBYifHzs6weNsViLucoYk3M75CQsOM/TXH8VszBqAAt5oYwF3UMPkLyWuqN3X7IS6JfOU1wbkWq+x+oaCxb7sZeFETPAozBgIfp1UIxENPtSNQFnIatef++aimWWY9mYMtEoZeTXKCXkycpaGgPtqPghrbDYzOa+hFWpjIXS3Nqd9stjr/g+dYNZNS7zHGTNcpI+Qnx/7iX01hWyYDwjNdgaOSESaJ+MhSZEwWlrCZ65Qeh7L8CC7tpAbTwJY3uNBYcLD2BBTOEygQXj6cB4GT+atxp1NPI5ZGGcWek0hlLolBCzLoUbOrE7X2bTwe1VET/L2eHZl6lrhfNuFq2/HkWZzaV5jU3JGrGg/fKwfT7th3Hk9JeZebTSN6fJlRGd1POWTbh9Bbaj5QQQMNgSIMaJHcIlc3U00u63+YW/hwW9C/dgnsaEBa8JJmciIzW7nwXGgHFKzoLfXywW/dOtGBOXZ+PaxSPRVYMotqple2/kuA9yRybSTaoiZD5gLlireD6vym+I8ERPW9B+Vp42x2mqrSqrs69IPFXelGgkb/Zyx164Ux+RqCYojZcgdJFAfX056Ha7SoqR1PrlLMRMM9XR0zJjLMxCYMPx+DeLOYQFZJbGayx06/X0hIt7z7fjHFfCFVsaUdG4Q+itDyDFbrGjg1/XNGVz7Jnru6j9khIHCrvyuZwub4oRXYhv7jyS+yAO70Ev3BtISBTbur0gjHXdb8n4+GyWtiquswA6EViIUTfi8gZlwZtHcDy8rkfGwsAuZSFevq31EUilhN7Jgiv1Uala4L5K5ikL3Jvc1jpnZDXobZE2Bib/hgXmQS2wbjhu7X6cQi9YbXpAyKCLXsmTp9/NmNWYEmRnHBF5eBjebmfjiCbjvw1JCf0pISwwqSkuugxlgV0tlub3euTDfESOW8ACEz6FXUDtVzaOkE/GQrM8MI4vdVw3J1sNwivbvlCD2zmwrPQ2WuJfsSCO7R14+Q2HwylY8CXa4n0WAuRJiQ6X7GOBGWOfymxCngzsXxhT/8IM+xeAhdA2WCdnYW3ZoE86GOrSO1/EAtNYjoCFEQlfFRfcqViIKtbu0MalhueA3Xjste6uW9wytY1Dy7w82zzev2IB3cnlZq/GSZtnp30E/0d9RN/G8weGDJrsQ3FgEa8heA02WfiKRZG8vYv6miwZHO96mkaoO3E9GC7HXh2SJ0IejAjMQpzeQIrHLguWeq/Dmu4Cbd5CFqxUAhZctYYGBv5MYk/FwqIiFqoqQd/tKsiMk+E/ThBaRZ2J/+FBGTyYRIUkc/twtypXKDa9OOsJf9V6W+op6msajEvwgXlpNNs0pBsS7MVvmlTWa/GxmNL5CLs2+/jku3Bsvfbce/j0sM/O9z5XpV742j0IMvx8lcyY9W3QAq7Hvc3ulTauWSh744ea2gAbIMS2x/gZgLKegYWN5cQSKR2P60/ZQ2OwGQt4PsIjXxwbz0c0J+l4Vlfej193r1g6FSGS1WlWYlhfsrzAy95dKyrRH/G0vvQ4XuBYL110dgrptbtCWWTtNV7C13RH54jGfBiw6MAyG9Tn2wZu1IW9li+b5ys7VvmY8j1dtqnDSXR+L7sLcqLWmvmb1ImgNhffqVHxG7tf9X53Wc/mcuM5+jIgqdu/4bGJGlAPHf7q7xtVMtBZa25WdatBXRxz8OUkmSOmhYe6jNu6W7Yj/eU0K9IWW3hU+H3z+n7oDJywfHlGXMZ1cKGTVHddotBJBmF4gvvwl8YvHCliv2oZl2JP098nVxZAksr1GpSSEeXfJlcWkBjlrgXoIroXuq77qeXKQvVwEkzHb88VPpNcWWD0EjdxphYKRuJ/p1xZsOrVWdnVrxb4m+THsxCl1UnZHPvtSwicS346C0Z1B8HKP0ct/HAWxJCtciyAtdD4MWqhlAXfirJkB4sK+hpnZlQsMqKVi0+/xOS+6Wt7XLTo89JXV+YsVPu49eOv1L/Y21LCglsPhOAeu+FvAyoh47/TGQ3xK2RC2Jam6M/ogYlxiW4PJ8g8ZHtc5FubcxGNrz3LQLKsUr2en77kcATSMR3JrVq5ctifyR+9DaqYhalSb4bNpQCN+SHMm1giNPpSScyS/zpgYrRpOlzCLy4Tvy7Qv3MT37sxOyV7XPRgTF+UJ13mWqFbfW/9pdxtgxzxmrIP+z9koVM7fMXiHSlkweBqcA+iYYD+fqwMab0daPhc/jONQfmkixnE9PVDY8hOHy//fX3OJXozFaoXgWThffR77qy/ZKONFMYD5HAWROdou/Xh+Q/epFjIQmtEJmlvJy6wkD/eevfFxGEEOQv3Q/JjxgKOObh8FqIBp+xVCqys7nvckV5YTWfrbseg6yAajIVnLfXV6+bQRxf/+mHP/A6d1NRd/GLjDv7rWmJ+BPQNlb9ZZh/xLKTYcbGQS8jed4f2QyXw7K4fmlofB6DGHR9nt/guPhEuKhqRb0AloKJF8BaykEUWxeNwi4V+xEKkQikLeInoC2dBdBeptlcnwHBy//sa11gw6prN1uGrqLadO8iidofqRBnidnTris3V4GZ9qI2eonoP0BohflVJqMJ8vOs1WsLEq5HZ/brwPAm8OzhHTbbVEVBpTAQBWTh4ufYkkGwP52W4Srsl2TIEn4e2wHIS+Ennalgb1eDZhBQ4y4YwsOim22Jtvq+bvO0VXVohC95nFr0qbvYR3QWz4KIKFkIIqLpgFvQo7HuqsF8nsJDBsFfz+0vO1ZEwEOXL952aBPdDnHBqYFqMXufn7pS7Q5t0np8nbzYsSf4h8b2k701glsNRYMlUx4ZlUkNW6ybNQMXWalvpG0ZDAxbGSi1MUhUnAYzH864AQT2hkDYTU4VoEVflzWS2VGEh/7HJm2OIFVloPD+cQ2gaVCiawCt6o0AbTqeppNaT5tIuUHmFLLDr8X0fWq3Var1ABAmwwNy0xQIWXh0f3ZNOkKJiY+4F9ki+f+wUh6s3eMZROB2bI+UQlYC1wh67EcRf8t36cNiNcbwVpFhK8Eq+Cd+A5VGtdInOPn1HD890gppYDB4N0AvkwYX4wVC6X2NhZICOCBiIIoaTRxJ6qMR7yNd0f1PLxUrhaRNrkBGjLyFY0FVhjcJEwgrlQyWxFn1BCeHVDwaLWbDxQQOI1Usk24K0jfvdqzmABekLBEKSMAshQmqXBTut1+tdoQsd01i4gT3eL8BL46CG9/DI18PxiPveMbISvnVA9ZFeWCKBkN8WftKm9gOwYOOew+8p7SnxudzjNaVjR89sx9CGnJYNFmTomXUW1LDF3ljQypCMOlCDRU60XseBNfoXG8UxGtZBKaxtIhZHIj+opGH6dIHwTRYgXD+yOfS5IxW8FaOEhbUvG/YCwDwOLHGHhefGvN/iSMbUJfURjsSTpatkuWARz3KtoCwOIRmNI1wrwl65Nl4SfQCDbnFC38ZjmZOJ1AYK3lah8oQFA3fhjrLGAgfOG32Eb/dYMW8fAhvGEX5fmkwCEiTI1Cb4FussB69zUl6jFQtfGyyQPORtFiAlyYY+piMcGvsavFGXo2MUsKDzC39SaC8sSGLYJbHAdIK9DqVd4bj+QUptzXZs2PDATgkLHN0oGs02Dy63N6wXRBh7rrMQasBCohIWzBULicDx8nJOFhbQnZpHhjSJWsf3G5XCOWsweihmwSbByLssREeyUG/TsZHgFLDAhJNQLWTB4HENLooFJjIPtBBWwo8OjK5eY8EBiwD1BQ62F/CmuA/vXrm3byH5D27Y73+MTRZcFtq/r2yzYPAmzSZj/GnThy4FDzhYert9E5a69wcQnbzJgk2SiDIWIuz8dYgR8q9YcJ6xBSIuINJvaxzB4JeGC8XjiBoPt+ayWGD8ubpnAmpLKUjdQ53n+oqFiPUSq8kuoxULlsc7ojGEfI/4l+dEc0Xa0gv+nTa3HE/YZiH2htNkGsK9Fd/suW71J6ht/ZG0CB0HNMRA7bpRy25sszBQhk3IbVlQFsSeUovcLk/GEWssHJ4f0QOF4JNOZ1cvIDNXKWYhmmCDYgljUeb7hxGZOMMjVIMQHLaAH4jvKbl/oRM8PU3wuzPER4Vcezh6fX2SsOURwq84KeHjEbPw+IVL8ParVn8GGzFUMQsyD6PSvsp7nvIEY8Z4OHl9nZhgJf5SbGQl/AM7zgRkLuCIK/cRFmeJNJx5qJvqKyxYvPhFl3gzPPtpYk48EVoNcqWtRxkqOzmUBUa/Vx61XzKs0MV8PD0SSRg9pSmhg8eMBfqWG+sfolVnYM2M6R6/LmZuSp8q+z3OpHtQzGMyDTrh6pZGtzOH7BuG+ab5jJZAH28xN9YtFBJvqaN2NnDjW5wwEkLvL3bgsXakNyOKwhELRa1wPoMBCON3brHgHd2HGdYbjH+L84xpTeJOCLk40W2urwaDDvoRiuBfyIn18OBcGXSq2xnN67A6VGJGdOl9Ejs0RyeimS0+dbXG4E6Nsj0uaG7KevMO0A08v5Pf9i0yI2tAjavfkXZq+TmxLO7Mq56DgExH5zI6toGK9ULKnVWz/hwWkNJqpmyZt4kTuOUiugDvGBZ4ib3nyXx19MSp5SexgMT4MEfb0xEyJyh8dxxeCghYwsH0ITlNrujB8sNYgKg0t3/zbKuKJEmaJimqqnZfHGPfcn8/Qb7K1hT8u0U0wiRJmk0nNC42/PDsMrgIu/kqV7nKVa5ylatc5SpXucpVvkP+B7U7jCp8UStyAAAAAElFTkSuQmCC"
    }
   },
   "cell_type": "markdown",
   "metadata": {
    "toc-hr-collapsed": false
   },
   "source": [
    "<img src=attachment:09375636-629b-4ee2-9011-455f6157ab16.png title=\"Python Logo\" width=\"360\" align=\"left\" style=\"float:right\"/>\n",
    "<H1>Create your own Jupyter Kernel</H1>\n",
    "<HR>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Building your own Jupyter kernel is a three step process\n",
    "1. Create/Pimp new virtual Python environment\n",
    "   * venv\n",
    "2. Create/Edit launch script for the Jupyter kernel\n",
    "   * kernel.sh\n",
    "3. Create/Edit Jupyter kernel configuration\n",
    "   * kernel.json"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Settings"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* Set kernel name\n",
    "  - must be lower case\n",
    "  - change if you like"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# INPUT NEEDED:\n",
    "KERNEL_NAME=${USER}_kernel\n",
    "\n",
    "export KERNEL_NAME=$(echo \"${KERNEL_NAME}\" | awk '{print tolower($0)}')\n",
    "echo ${KERNEL_NAME} # double check"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* List directories where JupyterLab will search for kernels"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# JUPYTER SEARCH PATH (for kernels-directory)\n",
    "echo \"jupyter search paths for kernels-directories\"\n",
    "if [ -z $JUPYTER_PATH ]; then\n",
    "  echo \"$HOME/.local/share/jupyter\"\n",
    "else\n",
    "  tr ':' '\\n' <<< \"$JUPYTER_PATH\"\n",
    "fi"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* Set kernel type\n",
    "    - private kernel = \"\\${HOME}/.local/\"  \n",
    "    - project kernel = \"\\${PROJECT}/.local/\"  \n",
    "    - other kernel    = \"\\<your-path\\>\" (ensure it is part of $JUPYTER_PATH or your kernel will not be found by JuypterLab)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# INPUT NEEDED:\n",
    "export KERNEL_TYPE=private # private, project or other\n",
    "export KERNEL_SPECS_PREFIX=/p/home/jusers/$USER/jureca/.local\n",
    "\n",
    "###################\n",
    "# project kernel\n",
    "if [ \"${KERNEL_TYPE}\" == \"project\" ]; then\n",
    "  export KERNEL_SPECS_PREFIX=${PROJECT}/.local\n",
    "  echo \"project kernel\"\n",
    "# private kernel\n",
    "elif [ \"${KERNEL_TYPE}\" == \"private\" ]; then\n",
    "  export KERNEL_SPECS_PREFIX=${HOME}/.local\n",
    "  echo \"private kernel\"\n",
    "else\n",
    "  if [ ! -d \"$KERNEL_SPECS_PREFIX\" ]; then\n",
    "    echo \"ERROR: please create directory $KERNEL_SPECS_PREFIX\"\n",
    "  fi\n",
    "  echo \"other kernel\"\n",
    "fi\n",
    "export KERNEL_SPECS_DIR=${KERNEL_SPECS_PREFIX}/share/jupyter/kernels\n",
    "\n",
    "# check if kernel name is unique\n",
    "if [ -d \"${KERNEL_SPECS_DIR}/${KERNEL_NAME}\" ]; then\n",
    "  echo \"ERROR: Kernel already exists in ${KERNEL_SPECS_DIR}/${KERNEL_NAME}\"\n",
    "  echo \"       Rename kernel name or remove directory.\"\n",
    "fi\n",
    "\n",
    "echo ${KERNEL_SPECS_DIR}/${KERNEL_NAME} # double check"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* Set directory for kernels virtual environment\n",
    "  - change if you like"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# INPUT NEEDED:\n",
    "export KERNEL_VENVS_DIR=${PROJECT}/${USER}/jupyter/kernels\n",
    "\n",
    "###################\n",
    "mkdir -p ${KERNEL_VENVS_DIR}\n",
    "if [ \"${KERNEL_TYPE}\" != \"private\" ] && [ \"${KERNEL_TYPE}\" != \"other\" ]; then\n",
    "  echo \"Please check the permissions and ensure your project partners have read/execute permissions:\"\n",
    "  namei -l ${KERNEL_VENVS_DIR}\n",
    "fi\n",
    "\n",
    "echo ${KERNEL_VENVS_DIR} # double check\n",
    "ls -lt ${KERNEL_VENVS_DIR}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1. Create/Pimp new virtual Python environment"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 1.1 - Load required modules"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "module -q purge\n",
    "module -q use $OTHERSTAGES        \n",
    "module -q load Stages/Devel-2019a 2> /dev/null # any stage can be used\n",
    "module -q load GCCcore/.8.3.0     2> /dev/null\n",
    "module -q load Python/3.6.8                    # only Python is required\n",
    "module list # double check"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 1.2 - Load extra modules you need for your kernel"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# module load <module you need>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 1.3 - Create and activate a virtual environment for the kernel  \n",
    "and ensure python packages installed in the virtual environment are always prefered"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "if [ -d \"${KERNEL_VENVS_DIR}/${KERNEL_NAME}\" ]; then\n",
    "  echo \"ERROR: Directory for virtual environment already ${KERNEL_VENVS_DIR}/${KERNEL_NAME}\"\n",
    "  echo \"       Rename kernel name or remove directory.\"\n",
    "else\n",
    "  python -m venv --system-site-packages ${KERNEL_VENVS_DIR}/${KERNEL_NAME}\n",
    "  source ${KERNEL_VENVS_DIR}/${KERNEL_NAME}/bin/activate\n",
    "  export PYTHONPATH=${VIRTUAL_ENV}/lib/python3.6/site-packages:${PYTHONPATH}\n",
    "  echo ${VIRTUAL_ENV} # double check\n",
    "fi"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 1.4 - Install Python libraries required for communication with Jupyter"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "which pip\n",
    "pip install --ignore-installed ipykernel\n",
    "ls ${VIRTUAL_ENV}/lib/python3.6/site-packages/ # double check"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 1.5 - Install whatever else you need in your Python virtual environment (using pip)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#pip install <python-package you need>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2. Create/Edit launch script for the Jupyter kernel"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 2.1 - Create launch script, which loads your Python virtual environment and starts the ipykernel process inside:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "echo '#!/bin/bash'\"\n",
    "\n",
    "# Load required modules\n",
    "module purge\n",
    "module use \"'$OTHERSTAGES'\"\n",
    "module load Stages/Devel-2019a\n",
    "module load GCCcore/.8.3.0\n",
    "module load Python/3.6.8\n",
    "\n",
    "# Load extra modules you need for your kernel (as you did in step 1.2)\n",
    "#module load <module you need>\n",
    "    \n",
    "# Activate your Python virtual environment\n",
    "source ${KERNEL_VENVS_DIR}/${KERNEL_NAME}/bin/activate\n",
    "    \n",
    "# Ensure python packages installed in the virtual environment are always prefered\n",
    "export PYTHONPATH=${VIRTUAL_ENV}/lib/python3.6/site-packages:\"'${PYTHONPATH}'\"\n",
    "    \n",
    "exec python -m ipykernel \"'$@' > ${VIRTUAL_ENV}/kernel.sh\n",
    "chmod +x ${VIRTUAL_ENV}/kernel.sh\n",
    "\n",
    "cat ${VIRTUAL_ENV}/kernel.sh # double check"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3. Create/Edit Jupyter kernel configuration"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 3.1 - Create Jupyter kernel configuration directory and files"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "python -m ipykernel install --name=${KERNEL_NAME} --prefix ${VIRTUAL_ENV}\n",
    "export VIRTUAL_ENV_KERNELS=${VIRTUAL_ENV}/share/jupyter/kernels"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 3.2 - Adjust kernel.json file"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "mv ${VIRTUAL_ENV_KERNELS}/${KERNEL_NAME}/kernel.json ${VIRTUAL_ENV_KERNELS}/${KERNEL_NAME}/kernel.json.orig\n",
    "\n",
    "echo '{\n",
    "  \"argv\": [\n",
    "    \"'${KERNEL_VENVS_DIR}/${KERNEL_NAME}/kernel.sh'\",\n",
    "    \"-m\",\n",
    "    \"ipykernel_launcher\",\n",
    "    \"-f\",\n",
    "    \"{connection_file}\"\n",
    "  ],\n",
    "  \"display_name\": \"'${KERNEL_NAME}'\",\n",
    "  \"language\": \"python\"\n",
    "}' > ${VIRTUAL_ENV_KERNELS}/${KERNEL_NAME}/kernel.json\n",
    "\n",
    "cat ${VIRTUAL_ENV_KERNELS}/${KERNEL_NAME}/kernel.json # double check"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 3.3 - Create link to kernel specs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "cd ${KERNEL_SPECS_DIR}\n",
    "ln -s ${VIRTUAL_ENV_KERNELS}/${KERNEL_NAME} .\n",
    "\n",
    "ls ${KERNEL_SPECS_DIR} # double check"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 4. Cleanup"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "deactivate"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Bash",
   "language": "bash",
   "name": "bash"
  },
  "language_info": {
   "codemirror_mode": "shell",
   "file_extension": ".sh",
   "mimetype": "text/x-sh",
   "name": "bash"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}