diff --git a/talks/Freva_Workshop_2024/day 1/Day 1 - Freva Overview.ipynb b/talks/Freva_Workshop_2024/day 1/Day 1 - Freva Overview.ipynb new file mode 100644 index 0000000..dd22d9d --- /dev/null +++ b/talks/Freva_Workshop_2024/day 1/Day 1 - Freva Overview.ipynb @@ -0,0 +1,559 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "\"freva\n", + "\n", + "# Introduction to Freva \"freva\n", + "\n", + "\n", + "**Martin Bergemann, Bijan Fallah, Andrej Fast, Mostafa Hadizadeh, \n", + "Christopher Kadow, Etor E. Lucio-Eceiza, Felix Oertel, Manuel Reis, and many others…**\n", + "\n", + "Deutsches Klimarechenzentrum @ CLINT in Data Analysis Dpt. (+ Data Management Dpt.*)\n", + "\n", + "\"freva" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## Common Problem I: Finding Data\n", + "\"data\"" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Common Problem II: Using code of others\n", + "\"code\"" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Common Problem III: Reproducing your results\n", + "\"reproduce\"" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "* How can we search and access various datasets efficiently?\n", + "* How can we streamline user data analysis tools (reusable and reproducible)?" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "source": [ + "## Yet another solution: The Freva framework \"freva\n", + "\n", + "
\n", + "
\n", + " \n", + "
\n", + "
\n", + " \n", + "
\n", + "
\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## Let's get an overview...\n", + "\n", + "\"freva" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Flexible access \"freva\n", + "
\n", + "
\n", + "

Freva is a (mainly) Python3 framework

\n", + "

Running at DKRZ's HPC, it comes in 3 flavours

\n", + " \n", + "

Each interface offers similar and interconnected features

\n", + "
\n", + "
\n", + " \"parts\" \n", + "
\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Standardized data \"freva\n", + "
\n", + "
\n", + " \n", + "
\n", + "
\n", + " \"parts\" \n", + " \"parts\"\n", + " \"parts\" \n", + "
\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Easy incorporation of tools \"freva\n", + "\n", + "* Flexible programming language: NO specific language (only free software!)\n", + "* Standardised API in python 3: no need to know all the code environments\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "source": [ + "1. **Tool**: ANY language (python, R, C, FORTRAN, a mix...)\n", + "\n", + "
\n",
+    "./movie_plotter.sh /path/2/INPUT /path/2/OUTPUT
\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "source": [ + "2. Plugin API (**Wrapper**): in python\n", + "\n", + "
\n",
+    "from evaluation_system.api import plugin\n",
+    "from evaluation_system.api.parameters import (ParameterDictionary as ParamDict, String)\n",
+    "\n",
+    "class MoviePlotter(plugin.PluginAbstract):\n",
+    "    __short_description__ = \"Plots 2D lon/lat movies in GIF format\"\n",
+    "    __version__ = (0,0,1)\n",
+    "    __parameters__ = ParamDict(\n",
+    "      String(name='input', default=None, mandatory=True, help='File to plot'), \n",
+    "      String(name='outputdir', default=None, mandatory=True, help='default output dir')\n",
+    "    )\n",
+    "    def run_tool(self, config_dict=None):\n",
+    "        input  = config_dict['input']\n",
+    "        outputdir = config_dict['outputdir']\n",
+    "        self.call(f'{self.class_basedir}/movie_plotter.sh {input} {outputdir}')\n",
+    "        return self.prepare_output(config_dict['outputdir'])\n",
+    "
" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "source": [ + "3. **Freva command**:\n", + "\n", + "
\n",
+    "freva plugin MoviePlotter input=/foo/bar.nc outputdir=/path/2/OUTPUT\n",
+    "
" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "source": [ + "\"parts\" " + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Transparency & reproducibility \"freva\n", + "
\n", + "
\n", + " \n", + "

Additionally:

\n", + " \n", + "
\n", + "
\n", + " \"parts\" \n", + "
\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## ... And there is more\n", + "\n", + "\"freva\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## A development environment \"freva \n", + "\n", + "
\n", + "
\n", + "

One can test a plugin without interference:

\n", + " \n", + "

Similar behaviour with the cli:

\n", + " \n", + "
\n", + "
\n", + " \"parts\" \n", + " \"parts\"\n", + " \"parts\" \n", + "
\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "

Plugin → Database → Plugin \"freva

\n", + "1. Special Freva function in the plugin wrapper to add outputs in databrowser:\n", + "
\n", + "
\n", + "
\n",
+    "    \n",
+    "if config_dict[\"link2database\"] is True:\n",
+    "    self.add_output_to_databrowser(outputdir, project=config_dict[\"project\"], product=config_dict[\"product\"],)\n",
+    "    \n",
+    "
\n", + "
\"freva
" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "source": [ + "
\n", + "
\n", + "2. Result now is part of the users database:

\n", + "
\n", + "
\n", + "
\n", + "\"freva
" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "source": [ + "
\n", + "
\n", + "3. Ready as input for new plugin:

\n", + "
\n", + "
\n", + "
\n", + "\"freva
" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " Freva Docu\n", + " \n", + "\n", + "\n", + "

How to use Freva? \"freva

\n", + "
\n", + "
\n", + " Freva framework:\n", + "
    \n", + "
  • Extensive documentation, updated regularly
  • \n", + "
  • Accessible from every Freva web interface
  • \n", + "
\n", + "
\n", + "
\n", + " \"parts\"\n", + "
\n", + "
\n", + "\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "source": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " Freva Docu\n", + " \n", + "\n", + "\n", + "
\n", + "
\n", + " Freva plugins:\n", + " \n", + "
\n", + "
\n", + " \"parts\"\n", + "
\n", + "
\n", + "\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " Freva Usage\n", + " \n", + "\n", + "\n", + "

What's next? \"freva

\n", + "
\n", + "
\n", + "
    \n", + "
  • Freva RestAPI: allows connection with solr to search for data in many languages (working!)
  • \n", + "
  • Freva Client: freva library for data search, for python and cli (working!)
  • \n", + "
  • Data streaming: allows to stream data in zarr from anywhere (filesystem, cloud, tape archive) (WIP)
  • \n", + "
  • Freva Futures: registering a dataset that will exist in the future (WIP)
  • \n", + "
  • Freva workflows: an efficient way to connect plugins (e.g. via CWL, concept)
  • \n", + "
  • ...
  • \n", + "
\n", + "
\n", + "
\n", + " \"parts\"\n", + "
\n", + "
\n", + "\n", + "" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "\n", + "\n", + "\"freva\n", + "\n", + "
Thanks for your attention!
\n", + "\n", + "Contact: freva@dkrz.de\n", + "\n", + "Documentation: https://freva-clint.github.io/freva/\n", + "\n", + "Workshop GitLab Repository: https://gitlab.dkrz.de/freva/freva_workshop\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Bash", + "language": "bash", + "name": "bash" + }, + "language_info": { + "name": "bash" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/talks/Freva_Workshop_2024/day 1/index.slides.html b/talks/Freva_Workshop_2024/day 1/index.slides.html new file mode 100644 index 0000000..10236f1 --- /dev/null +++ b/talks/Freva_Workshop_2024/day 1/index.slides.html @@ -0,0 +1,8027 @@ + + + + + + + +Day 1 - Freva Overview slides + + + + + + + + + + + + + + + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+ + + diff --git a/talks/Freva_Workshop_2024/day 1/media/freva_overview/3-way-access.jpg b/talks/Freva_Workshop_2024/day 1/media/freva_overview/3-way-access.jpg new file mode 100644 index 0000000..1e49ef3 Binary files /dev/null and b/talks/Freva_Workshop_2024/day 1/media/freva_overview/3-way-access.jpg differ diff --git a/talks/Freva_Workshop_2024/day 1/media/freva_overview/blank-plot.jpg b/talks/Freva_Workshop_2024/day 1/media/freva_overview/blank-plot.jpg new file mode 100644 index 0000000..c7f3fa6 Binary files /dev/null and b/talks/Freva_Workshop_2024/day 1/media/freva_overview/blank-plot.jpg differ diff --git a/talks/Freva_Workshop_2024/day 1/media/freva_overview/freva-accessibility.png b/talks/Freva_Workshop_2024/day 1/media/freva_overview/freva-accessibility.png new file mode 100644 index 0000000..9ae52a4 Binary files /dev/null and b/talks/Freva_Workshop_2024/day 1/media/freva_overview/freva-accessibility.png differ diff --git a/talks/Freva_Workshop_2024/day 1/media/freva_overview/freva-data.png b/talks/Freva_Workshop_2024/day 1/media/freva_overview/freva-data.png new file mode 100644 index 0000000..93d0e76 Binary files /dev/null and b/talks/Freva_Workshop_2024/day 1/media/freva_overview/freva-data.png differ diff --git a/talks/Freva_Workshop_2024/day 1/media/freva_overview/freva-docu.png b/talks/Freva_Workshop_2024/day 1/media/freva_overview/freva-docu.png new file mode 100644 index 0000000..6c5910d Binary files /dev/null and b/talks/Freva_Workshop_2024/day 1/media/freva_overview/freva-docu.png differ diff --git a/talks/Freva_Workshop_2024/day 1/media/freva_overview/freva-flowchart_basic.png b/talks/Freva_Workshop_2024/day 1/media/freva_overview/freva-flowchart_basic.png new file mode 100644 index 0000000..c8758ec Binary files /dev/null and b/talks/Freva_Workshop_2024/day 1/media/freva_overview/freva-flowchart_basic.png differ diff --git a/talks/Freva_Workshop_2024/day 1/media/freva_overview/freva-flowchart_plus.png b/talks/Freva_Workshop_2024/day 1/media/freva_overview/freva-flowchart_plus.png new file mode 100644 index 0000000..eb6df2c Binary files /dev/null and b/talks/Freva_Workshop_2024/day 1/media/freva_overview/freva-flowchart_plus.png differ diff --git a/talks/Freva_Workshop_2024/day 1/media/freva_overview/freva-how-to-plug.png b/talks/Freva_Workshop_2024/day 1/media/freva_overview/freva-how-to-plug.png new file mode 100644 index 0000000..678efa5 Binary files /dev/null and b/talks/Freva_Workshop_2024/day 1/media/freva_overview/freva-how-to-plug.png differ diff --git a/talks/Freva_Workshop_2024/day 1/media/freva_overview/freva-link-my-data.png b/talks/Freva_Workshop_2024/day 1/media/freva_overview/freva-link-my-data.png new file mode 100644 index 0000000..746f420 Binary files /dev/null and b/talks/Freva_Workshop_2024/day 1/media/freva_overview/freva-link-my-data.png differ diff --git a/talks/Freva_Workshop_2024/day 1/media/freva_overview/freva-logo.png b/talks/Freva_Workshop_2024/day 1/media/freva_overview/freva-logo.png new file mode 100644 index 0000000..da1ce09 Binary files /dev/null and b/talks/Freva_Workshop_2024/day 1/media/freva_overview/freva-logo.png differ diff --git a/talks/Freva_Workshop_2024/day 1/media/freva_overview/freva-next.png b/talks/Freva_Workshop_2024/day 1/media/freva_overview/freva-next.png new file mode 100644 index 0000000..efefd94 Binary files /dev/null and b/talks/Freva_Workshop_2024/day 1/media/freva_overview/freva-next.png differ diff --git a/talks/Freva_Workshop_2024/day 1/media/freva_overview/freva-people.jpg b/talks/Freva_Workshop_2024/day 1/media/freva_overview/freva-people.jpg new file mode 100644 index 0000000..ad62b1d Binary files /dev/null and b/talks/Freva_Workshop_2024/day 1/media/freva_overview/freva-people.jpg differ diff --git a/talks/Freva_Workshop_2024/day 1/media/freva_overview/freva-plugins.png b/talks/Freva_Workshop_2024/day 1/media/freva_overview/freva-plugins.png new file mode 100644 index 0000000..dd24a0c Binary files /dev/null and b/talks/Freva_Workshop_2024/day 1/media/freva_overview/freva-plugins.png differ diff --git a/talks/Freva_Workshop_2024/day 1/media/freva_overview/freva-transparency.png b/talks/Freva_Workshop_2024/day 1/media/freva_overview/freva-transparency.png new file mode 100644 index 0000000..40cf065 Binary files /dev/null and b/talks/Freva_Workshop_2024/day 1/media/freva_overview/freva-transparency.png differ diff --git a/talks/Freva_Workshop_2024/day 1/media/freva_overview/freva-whatisnext.jpg b/talks/Freva_Workshop_2024/day 1/media/freva_overview/freva-whatisnext.jpg new file mode 100644 index 0000000..146d1ce Binary files /dev/null and b/talks/Freva_Workshop_2024/day 1/media/freva_overview/freva-whatisnext.jpg differ diff --git a/talks/Freva_Workshop_2024/day 1/media/freva_overview/frevacode-docu.jpg b/talks/Freva_Workshop_2024/day 1/media/freva_overview/frevacode-docu.jpg new file mode 100644 index 0000000..e064b56 Binary files /dev/null and b/talks/Freva_Workshop_2024/day 1/media/freva_overview/frevacode-docu.jpg differ diff --git a/talks/Freva_Workshop_2024/day 1/media/freva_overview/link2database.jpg b/talks/Freva_Workshop_2024/day 1/media/freva_overview/link2database.jpg new file mode 100644 index 0000000..cbbdc19 Binary files /dev/null and b/talks/Freva_Workshop_2024/day 1/media/freva_overview/link2database.jpg differ diff --git a/talks/Freva_Workshop_2024/day 1/media/freva_overview/logo-fona-dkrz.jpg b/talks/Freva_Workshop_2024/day 1/media/freva_overview/logo-fona-dkrz.jpg new file mode 100644 index 0000000..ca9ea89 Binary files /dev/null and b/talks/Freva_Workshop_2024/day 1/media/freva_overview/logo-fona-dkrz.jpg differ diff --git a/talks/Freva_Workshop_2024/day 1/media/freva_overview/plugin-docu.jpg b/talks/Freva_Workshop_2024/day 1/media/freva_overview/plugin-docu.jpg new file mode 100644 index 0000000..442bb31 Binary files /dev/null and b/talks/Freva_Workshop_2024/day 1/media/freva_overview/plugin-docu.jpg differ diff --git a/talks/Freva_Workshop_2024/day 1/media/freva_overview/plugin-examples.jpg b/talks/Freva_Workshop_2024/day 1/media/freva_overview/plugin-examples.jpg new file mode 100644 index 0000000..c3c1e2f Binary files /dev/null and b/talks/Freva_Workshop_2024/day 1/media/freva_overview/plugin-examples.jpg differ diff --git a/talks/Freva_Workshop_2024/day 1/media/freva_overview/problem-data.png b/talks/Freva_Workshop_2024/day 1/media/freva_overview/problem-data.png new file mode 100644 index 0000000..c6d31e7 Binary files /dev/null and b/talks/Freva_Workshop_2024/day 1/media/freva_overview/problem-data.png differ diff --git a/talks/Freva_Workshop_2024/day 1/media/freva_overview/problem-reproducibility.png b/talks/Freva_Workshop_2024/day 1/media/freva_overview/problem-reproducibility.png new file mode 100644 index 0000000..85edcb5 Binary files /dev/null and b/talks/Freva_Workshop_2024/day 1/media/freva_overview/problem-reproducibility.png differ diff --git a/talks/Freva_Workshop_2024/day 1/media/freva_overview/problem-usability.png b/talks/Freva_Workshop_2024/day 1/media/freva_overview/problem-usability.png new file mode 100644 index 0000000..9025db9 Binary files /dev/null and b/talks/Freva_Workshop_2024/day 1/media/freva_overview/problem-usability.png differ diff --git a/talks/Freva_Workshop_2024/day 1/media/freva_overview/user-data.jpg b/talks/Freva_Workshop_2024/day 1/media/freva_overview/user-data.jpg new file mode 100644 index 0000000..3bf1236 Binary files /dev/null and b/talks/Freva_Workshop_2024/day 1/media/freva_overview/user-data.jpg differ diff --git a/talks/Freva_Workshop_2024/day 1/media/freva_overview/user-indata-plugin.jpg b/talks/Freva_Workshop_2024/day 1/media/freva_overview/user-indata-plugin.jpg new file mode 100644 index 0000000..26b814d Binary files /dev/null and b/talks/Freva_Workshop_2024/day 1/media/freva_overview/user-indata-plugin.jpg differ diff --git a/talks/Freva_Workshop_2024/day 2/Day 2 - Introduction to Freva Plugins.ipynb b/talks/Freva_Workshop_2024/day 2/Day 2 - Introduction to Freva Plugins.ipynb new file mode 100644 index 0000000..687f8fc --- /dev/null +++ b/talks/Freva_Workshop_2024/day 2/Day 2 - Introduction to Freva Plugins.ipynb @@ -0,0 +1,3327 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# Freva: Plugin Development\n", + "\n", + "\"freva\n", + "\n", + "**Martin Bergemann, Bijan Fallah, Andrej Fast, Mostafa Hadizadeh, \n", + "Christopher Kadow, Etor E. Lucio-Eceiza, Felix Örtel, Manuel Reis, and many others…**\n", + "\n", + "Deutsches Klimarechenzentrum @ CLINT in Data Analysis Dpt. (+ Data Management Dpt.*)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# Overview of a Freva plugin\n", + "\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Why should I build a Freva plugin?\n", + "It allows you to be part of \"The Freva Cycle\"\n", + "\n", + "\"parts\"\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Structure of a Plugin\n", + "
\n", + "
\n", + "

There are 3 main building blocks in a plugin:

\n", + "
    \n", + "
  • Wrapper: connects the tool to Freva
  • \n", + "
  • Tool: scientific code
  • \n", + "
  • Installer: they install the necessary libraries
  • \n", + "
\n", + "
\n", + "
\n", + " \"parts\"\n", + "
\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Structure of a Plugin: The Wrapper\n", + "
\n", + "
\n", + "

The connection to Freva:

\n", + "
    \n", + "
  • Written in python 3
  • \n", + "
  • Needs to follow a series of standards
  • \n", + "
\n", + "
\n", + "
\n", + " \"parts\"\n", + "
\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Structure of a Plugin: The tool\n", + "
\n", + "
\n", + "

The scientific code:

\n", + "
    \n", + "
  • Written in any* language (python, R, C, FORTRAN, a mix...)
  • \n", + "
  • A single script or multiple scripts and/or folders (subroutines, libraries, etc.).
  • \n", + "
\n", + "
\n", + "
\n", + " \"parts\"\n", + "
\n", + "
\n", + "*caveat: we encourage free software" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Structure of a Plugin: Installer\n", + "
\n", + "
\n", + "

Installs the plugin environment:

\n", + "
    \n", + "
  • Usually: Makefile (instructions) + .yaml file (libraries)
  • \n", + "
  • It can also be more elaborated: e.g. binary compilation, installation of subroutines...
  • \n", + "
\n", + "
\n", + "
\n", + " \"parts\"\n", + "
\n", + "
\n", + "\n", + "**NOTE:** It replaces the dependencies on the HPC (e.g. `modules`) and makes it more transferable to other e.g. institutions" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# Git and Gitlab" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## What is git? \"freva\n", + "Is a free and open source *Distributed* **Version Control System**:\n", + "- **Version Control System**: a system that tracks and provides control over changes to source code, documentation and configuration files.\n", + "- *Distributed*: a form of version control in which the complete codebase, including its full history, is mirrored on every developer's computer\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## What is gitlab? \"freva\n", + "\n", + "
\n", + "
\n", + "
  • GitLab is a web-based tool: provides version control, issue tracking, CI/CD etc.
  • \n", + "
  • DKRZ hosts its own framework at https://gitlab.dkrz.de
  • \n", + "
    \n", + "
    \n", + " \"freva\n", + "
    \n", + "
    \n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Gitlab and Freva:\n", + "\n", + "- One central local repository for the plugged plugins\n", + "- Other local repositories for different developers\n", + "- One remote repository for the plugin at gitlab\n", + "\"freva\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Gitlab and Freva: location of the plugins\n", + "\n", + "- Under [https://gitlab.dkrz.de/freva/plugins4freva](https://gitlab.dkrz.de/freva/plugins4freva) project:\n", + "\"freva\n", + "- Other projects have also their own, e.g.: \n", + " - climxtreme: https://gitlab.dkrz.de/bm1159/plugins4freva\n", + " - regiklim-nukleus: https://gitlab.dkrz.de/ch1187/plugins4freva\n", + "- some plugins can be found in different projects (see [forks](https://docs.gitlab.com/ee/user/project/repository/forking_workflow.html)).\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Gitlab and Freva: cloning a repository\n", + "To download a repository there are 2 ways: via `https` and via `ssh`:\n", + "\"freva\n", + "- `https`: straightforward, requires to enter (dkrz) username and password (usually). \n", + "- `ssh`: convenient, requires to provide a ssh key previously.\n", + "\n", + "In both cases:\n", + "\n", + "```\n", + "$ ssh @levante.dkrz.de\n", + "> cd /path/to/my/work/\n", + "> git clone https://gitlab.dkrz.de/freva/plugins4freva/plugin_workshop/example_plugin.git\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Gitlab and Freva: setting your SSH key\n", + "1. generate a ssh a private and public (`.pub`) key locally (e.g. laptop or levante):\n", + "```\n", + "$ ssh-keygen -t ed25519\n", + "$ cd ~/.ssh/\n", + "$ ls\n", + "id_ed25519 id_ed25519.pub\n", + "```\n", + "2. copy the **public** key: \n", + "```\n", + "$ cat id_ed25519.pub\n", + "ssh-ed25519 AAAAC3NzaC1lFDI1YTE5AAAAICUqpXx8AyrNH7HQgPSq9LuB7sTEmXP4ODqOnaHVPPQ6 username@levante\n", + "```\n", + "3. add the public key in gitlab (`user>preferences>ssh keys`): \"freva" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Gitlab and Freva: creating a new project\n", + "- If we already had an existing Git repository:\n", + "```shell\n", + "$ cd NEW_PLUGIN # for example\n", + "$ git remote rename origin old-origin\n", + "$ git remote add origin git@gitlab.dkrz.de:freva/plugins4freva/new_plugin.git\n", + "$ git push -u origin --all\n", + "$ git push -u origin --tags\n", + "```\n", + "\n", + "- If we did not already have an existing Git repository:\n", + "```shell\n", + "$ cd NEW_PLUGIN # for example\n", + "$ git init\n", + "$ git remote add origin git@gitlab.dkrz.de:freva/plugins4freva/new_plugin.git\n", + "# create your new files and folders\n", + "$ git add .\n", + "$ git commit -m \"Initial commit of my new project\"\n", + "$ git push -u origin master\n", + "```\n", + "\n", + "Now you could (hypothetically) go to https://gitlab.dkrz.de/freva/plugins4freva/new_plugin" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# License of Plugins" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## What kind of License should I follow?\n", + "\n", + "[The Freva code](https://github.com/FREVA-CLINT/freva/blob/main/LICENSE.md) follows a [BSD3 license](https://opensource.org/license/bsd-3-clause), a permissive open-source license with minimal restrictions:\n", + "- It allows for wide usage, including in proprietary software.\n", + "- it imposes very few restrictions on how the software can be redistributed.\n", + "\n", + "In principle, any derived product from Freva (i.e. plugins), should follow this license. *Unless* stated otherwise by the developer.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## What kind of License should I follow?\n", + "\n", + "- We encourage open-source software to foster collaboration within and outside your projects.\n", + "- That said, common courtesy should be expected, e.g.:\n", + " - reference to the first manuscript where the developer used the plugin (the plugin documentation is useful for this!).\n", + " - contacting him/her in case there is no such manuscript." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# Connecting your IDE / Code Editor to a remote session using SSH" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## 1. VS-Code \"freva\n", + "\n", + "Open a new window in VS Code. There are several ways to connect to a remote session, as indicated in the picture below:\n", + "\n", + "![Image depicting multiple ways to start a remote session in VS Code](media/vscode/01_connect_to_remote.png)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "\n", + "\"freva\n", + "
    \n", + "
    \n", + "
    \n", + "\n", + "Clicking either of the buttons opens a prompt at the top of the window, giving you several options to start a remote session:\n", + "\n", + "![Image depicting the prompt that opens when clicking one of the \"Connect to...\" buttons in the new VS Code window](media/vscode/02_remote_connection_options.jpg)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "\"freva\n", + "
    \n", + "
    \n", + "
    \n", + "\n", + "Click \"Connect Current Window to Host...\" (\"Connect to Host...\" opens a new window for the connection).\n", + "\n", + "You can type in the address of the remote host that you want to connect to or, in case the host is specified in your ssh config file (.ssh/config or ssh_config), select them from the list of hosts. To connect to levante, enter [k-number@]levante.dkrz.de :\n", + "\n", + "![Image depicting the prompt to enter a remote SSH host, with k202195@levante.dkrz.de manually entered](media/vscode/03_remote_host_entered.jpg)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "\"freva\n", + "
    \n", + "
    \n", + "
    \n", + "\n", + "The first time connecting to a host, you will be prompted to specify the OS of the remote host (i.e. Linux / Windows / macOS).\n", + "\n", + "Depending on the authentication set up for the remote host, you might be prompted to type in a password. Once the connection has been established, your can open a folder on the remote host, like you would do on your local machine (by pressing Ctrl + K, Ctrl + O or by pressing \"Open Folder\"):\n", + "\n", + "![Image depicting how to open a folder once connected to the remote host, similar to opening a local folder](media/vscode/04_opening_remote_folder.jpg)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "\"freva\n", + "
    \n", + "
    \n", + "
    \n", + "\n", + "You may be prompted again to type in the password at this point. The window should refresh and give you access to the remote folder that you selected in the previous step, similar to what can be seen in the following image:\n", + "\n", + "\"freva" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "\"freva\n", + "
    \n", + "
    \n", + "
    \n", + "\n", + "From here you can use the editor to work with remote files basically as you would with files on your local machine. Any terminals opened in this window will also connect to the remote host.\n", + "\n", + "For detailed documentation on remote development using VS Code, including development on dev containers or WSL, click [here](https://code.visualstudio.com/docs/remote/remote-overview)." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## 2. PyCharm \"freva\n", + "\n", + "\n", + "> 😱\n", + ">Remote Development is currently in beta and only supported for the Professional Version of PyCharm!\n", + "\n", + "Open your Plugins (Ctrl+Alt+S) and confirm that \"Remote Development Gateway\" is installed and that it is enabled:\n", + "\n", + "![Image depicting a list of installed PyCharm plugins, with the \"Remote Development Gateway\" being installed and enabled.](media/pycharm/01_remote_development_gateway.jpg)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "\"freva\n", + "
    \n", + "
    \n", + "
    \n", + "\n", + "To open a remote session in PyCharm, go to the welcome screen and click on the \"Remote Development\" Tab in the left side bar. This should give you a number of options, including the option to connect to a remote session using SSH:\n", + "\n", + "![Image depiciting the welcome screen of PyCharm Professional, with the \"Remote Development\" Tab highlighted using red arrows.](media/pycharm/02_remote_development_tab.png)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "\"freva\n", + "
    \n", + "
    \n", + "
    \n", + "\n", + "To establish a new SSH Connection, click \"New Connection\" below the SSH Connection option. This should open the following dialogue:\n", + "\n", + "![Image depicting the dialogue that opens when creating a new SSH connection on PyCharm. Includes fields for the username, the host name or address, and the port that should be used connected to.](media/pycharm/03_ssh_connection_dialogue.jpg)\n", + ">⚠\n", + ">Note that PyCharm currently only supports connecting to remote hosts running Linux." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "\"freva\n", + "
    \n", + "
    \n", + "
    \n", + "\n", + "Again, depending on the type of authentication set up by the remote host, you may be prompted to enter a password to establish the remote connection.\n", + "\n", + "In the next step (pending the successful connection to the remote host), you will be asked to set the IDE version (i.e. the version of the IDE that will be installed on the remote host) and the project directory (i.e. the directory on the remote host that contains the project files that you will be working with):\n", + "\n", + "![Image depicting the PyCharm window that prompts you to set the IDE Version to be installed on the remote host, as well as the project directory that you will be working in](media/pycharm/04_choose_ide_and_project.jpg)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "\"freva\n", + "
    \n", + "
    \n", + "
    \n", + "\n", + "Click \"Download IDE and Connect\". The installation of the selected IDE on the remote host might take a while. Once the installation is complete, a window containing the remote IDE should open.\n", + "\n", + "![Image depicting the remote IDE window, after successfully installing it to the remote host](media/pycharm/05_remote_IDE_successfully_opened.jpg)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "\"freva\n", + "
    \n", + "
    \n", + "
    \n", + "\n", + "The remote IDE gives you the ability to work with project files, much like you would with local project files. Any terminal sessions started in this IDE will also be connected to the remote host.\n", + "\n", + "For detailed documentation on remote development using PyCharm, click [here](https://www.jetbrains.com/help/pycharm/remote-development-starting-page.html)." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## 3. R Studio \"freva\n", + "\n", + "There is currently only one method of using R Studio on a remote host that is officially supported by R, namely by connecting to an instance of R Studio Server running on the remote host. The previously available alternative, by creating a remote connection in [R Studio Desktop Pro](https://docs.posit.co/ide/desktop-pro/2022.02.1+461.pro1/remote-desktop.html), has been removed since version [2023.06.2](https://docs.posit.co/ide/desktop-pro/remote_desktop/remote_desktop.html).\n", + "\n", + "However, R Studio Server is not available on Levante, so creating a remote development environment instance this way is not possible. However, it is possible to remotely develop and execute R-code by using the [VS Code R Extension](https://code.visualstudio.com/docs/languages/r). " + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "\"freva\n", + "
    \n", + "
    \n", + "
    \n", + "\n", + "First, connect to Levante as outlined in the VS Code section of this guide. Once the connection is established, you will want to install the R (`REditorSupport.r`) and R Debugger (`RDebugger.r-debugger`) Extensions, as shown below:\n", + "![Image depicting R VS Code Plugins](media/rstudio/01_rstudio_vscode_extensions.jpg)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "\"freva\n", + "
    \n", + "
    \n", + "
    \n", + "\n", + "Make sure that you have installed the extensions to the remote host, and not your local machine, by going to Extensions (Ctrl+Shift+X):\n", + "\n", + "![Image showing that R VS Code Plugins where installed on Levante](media/rstudio/02_rstudio_extensions_on_remote.jpg)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "\"freva\n", + "
    \n", + "
    \n", + "
    \n", + "\n", + "In a terminal that is connected to levante via ssh (e.g. in the VS Code window connected to levante), type in the following command:\n", + "```bash\n", + "$ module load r\n", + "```\n", + "The result should be something along the lines of:\n", + "```bash\n", + "[k202195@levante3 ~]$ module load r\n", + "Autoloading openjdk/17.0.0_35-gcc-11.2.0\n", + "\n", + "Loading r/4.1.2-gcc-11.2.0\n", + " Loading requirement: openjdk/17.0.0_35-gcc-11.2.0\n", + "[k202195@levante3 ~]$\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "\"freva\n", + "
    \n", + "
    \n", + "
    \n", + "\n", + "We'll need to find out, where R is located on the remote host. We do this by using the command:\n", + "```bash\n", + "$ which R\n", + "```\n", + "The output should be something like:\n", + "```bash\n", + "[k202195@levante3 ~]$ which R\n", + "/sw/spack-levante/r-4.1.2-eprwea/bin/R\n", + "[k202195@levante3 ~]$\n", + "```\n", + "Copy this path to your clipboard." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "\"freva\n", + "
    \n", + "
    \n", + "
    \n", + "\n", + "Install the [httpgd](https://github.com/nx10/httpgd) package to embed live R graphics into the VS Code environment. You can do this by running the following commands in a terminal on the remote host:\n", + "```bash\n", + "# Start and R command line session\n", + "$ R\n", + "```\n", + "The following command is executed in the R command line session\n", + "```R\n", + "install.packages(\"httpgd\")\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "\"freva\n", + "
    \n", + "
    \n", + "
    \n", + "\n", + "Open the settings (Ctrl + ,) and type `r.rterm.linux` in the search bar as shown in the image below. Make sure that you paste the previously copied path into the field, as depicted:\n", + "\n", + "![Image depicting how to set the path for the R Terminal in VS Code](media/rstudio/03_rterm_linux_settings.jpg)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "\"freva\n", + "
    \n", + "
    \n", + "
    \n", + "\n", + "Once that is done, open any R file on the remote host. Once an R terminal is ready, you could either select the code or put the cursor at the beginning or ending of the code you want to run, press (Ctrl+Enter), and then code will be sent to the active R terminal.\n", + "\n", + "If you want to run an entire R file, open the file in the editor, and press Ctrl+Shift+S and the file will be sourced in the active R terminal:\n", + "\n", + "![Image depicting some R code being run remotely on Levante and the resulting interactive plots](media/rstudio/04_opening_and_running_r_file_in_vscode.jpg)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "\"freva\n", + "
    \n", + "
    \n", + "
    \n", + "\n", + "For more information on working with R in VS Code, click [here](https://code.visualstudio.com/docs/languages/r)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# What is a Freva Wrapper?" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "

    Freva Wrapper Main Classes

    \n", + "\n", + "
    \n", + "
    \n", + "
      \n", + "
    • PluginAbstract Class Functions
    • \n", + "
      \n", + "
    • parameters.py Classes
    • \n", + "
      \n", + "
    • _ConfigWrapper Class
    • \n", + "
    \n", + "
    \n", + "
    \n", + " \"What\n", + "
    \n", + "
    " + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Special Variables:\n", + "\n", + "| Variables | Description |\n", + "|--------------------|------------------------------------------------------------------------|\n", + "| USER_BASE_DIR | Absolute path to the central directory for this user. |\n", + "| USER_OUTPUT_DIR | Absolute path to where the plugin outputs for this user are stored. |\n", + "| USER_PLOTS_DIR | Absolute path to where the plugin plots for this user are stored. |\n", + "| USER_CACHE_DIR | Absolute path to the cached data (temp data) for this user. |\n", + "| USER_UID | The users’ User Identifier. |\n", + "| SYSTEM_DATE | Current date in the form YYYYMMDD (e.g. 20120130). |\n", + "| SYSTEM_DATETIME | Current date in the form YYYYMMDD_HHmmSS (e.g. 20120130_101123). |\n", + "| SYSTEM_TIMESTAMP | Milliseconds since epoch (i.e. e.g. 1358929581838). |\n", + "| SYSTEM_RANDOM_UUID | A random Universal Unique Identifier (e.g. 912cca21-6364-4f46-9b03-4263410c9899). |\n", + "\n", + "Example: \n", + "\n", + "```bash\n", + "output_file='$USER_OUTPUT_DIR/myfile_${SYSTEM_DATETIME}blah.nc'\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "# PluginAbstract Class\n", + "## Function: class_basedir\n", + "```python\n", + "class PluginAbstract(abc.ABC):\n", + " \"\"\"Base class that is used as a template for all Freva plugins.\n", + " Any api wrapper class defining Freva plugins must inherit from this class.\"\"\"\n", + "\n", + " @deprecated_method(\"PluginAbstract\", \"class_basedir\")\n", + " def getClassBaseDir(self) -> Optional[str]:\n", + " \"\"\"Deprecated method for class_basedir.\"\"\"\n", + "\n", + " def class_basedir(self) -> str:\n", + " \"\"\"Get absolute path to the module defining the plugin class.\"\"\"\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "# PluginAbstract Class\n", + "## Function: call\n", + "```python\n", + "class PluginAbstract(abc.ABC):\n", + " \"\"\"Base class that is used as a template for all Freva plugins.\n", + " Any api wrapper class defining Freva plugins must inherit from this class.\"\"\"\n", + "\n", + " def call(\n", + " self,\n", + " cmd_string: Union[str, list[str]],\n", + " check: bool = True,\n", + " **kwargs,\n", + " ) -> sub.Popen[Any]:\n", + " \"\"\"Run command with arguments and return a CompletedProcess instance.\"\"\"\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "# PluginAbstract Class\n", + "## Function: call and class_basedir - Example\n", + "```python\n", + "from evaluation_system.api import plugin\n", + "class TemplatePlugin(plugin.PluginAbstract):\n", + " def run_tool(self, config_dict=None)\n", + " self.call(\n", + " f\"{self.class_basedir}/main_code.sh {config_dict}\"\n", + " )\n", + " # or\n", + " self.call(\n", + " f\"{Path(__file__).parent}/main_code.sh {config_dict}\"\n", + " )\n", + " # or\n", + " self.call(\n", + " f\"{os.getenv(USER_BASE_DIR)}/main_code.sh {config_dict}\"\n", + " ) \n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "# PluginAbstract Class\n", + "## Function: add_output_to_databrowser\n", + "```python\n", + "class PluginAbstract(abc.ABC):\n", + " @deprecated_method(\"PluginAbstract\", \"add_output_to_databrowser\")\n", + " def linkmydata(self, *args, **kwargs): # pragma: no cover\n", + "\n", + " def add_output_to_databrowser(\n", + " self,\n", + " plugin_output: os.PathLike,\n", + " project: str, # user-\n", + " product: str, # project.product\n", + " *,\n", + " model: str = \"freva\",\n", + " institute: Optional[str] = None,\n", + " ensemble: str = \"r1i1p1\",\n", + " time_frequency: Optional[str] = None,\n", + " variable: Optional[str] = None,\n", + " experiment: Optional[str] = None,\n", + " index_data: bool = True,\n", + " ) -> Path:\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "# PluginAbstract Class\n", + "## Function: add_output_to_databrowser - Example\n", + "```python\n", + "from evaluation_system.api import plugin\n", + "class TemplatePlugin(plugin.PluginAbstract):\n", + " def run_tool(self, config_dict=None)\n", + " self.add_output_to_databrowser(\n", + " plugin_output=config_dict[\"outputdir\"],\n", + " project=config_dict.get(\"project\", \"default_project\"),\n", + " product=config_dict.get(\"product\", \"default_product\"),\n", + " model=config_dict.get(\"model\", \"default_model\"),\n", + " institute=config_dict.get(\"institute\", \"default_institute\"),\n", + " time_frequency=\"mon\",\n", + " )\n", + "```\n", + "\n", + "### How to find it in Freva:\n", + "\n", + "```bash\n", + "freva databrowser product=project.product project=user-\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "# PluginAbstract Class\n", + "## Function: prepare_output\n", + "```python\n", + "class PluginAbstract(abc.ABC):\n", + " \"\"\"Base class that is used as a template for all Freva plugins.\n", + " Any api wrapper class defining Freva plugins must inherit from this class.\"\"\"\n", + "\n", + " @deprecated_method(\"PluginAbstract\", \"prepare_output\")\n", + " def prepareOutput(self, *args) -> dict[str, dict[str, str]]:\n", + " \"\"\"Deprecated method for :class:`prepare_output`. \"\"\"\n", + "\n", + " def prepare_output(\n", + " self, output_files: Union[str, list[str], dict[str, dict[str, str]]]\n", + " ) -> dict[str, dict[str, str]]:\n", + " \"\"\"Prepare output for files supposedly created.\"\"\"\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "# PluginAbstract Class\n", + "## Function: prepare_output - Example\n", + "```python\n", + "from evaluation_system.api import plugin\n", + "class TemplatePlugin(plugin.PluginAbstract):\n", + " def run_tool(self, config_dict=None)\n", + " return self.prepare_output(config_dict[\"outputdir\"])\n", + "```\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "# ParameterType Class\n", + "```python\n", + "class ParameterType(initOrder):\n", + " \"\"\"Base class for all parameter types.\n", + " All available parameter types inherit from this class. The class creates\n", + " a parameter object holding the following user defined information.\n", + " \"\"\"\n", + " def __init__(\n", + " self,\n", + " name=None,\n", + " default=None,\n", + " mandatory=False,\n", + " max_items=1,\n", + " item_separator=\",\",\n", + " regex=None,\n", + " version=1,\n", + " help=\"No help available.\",\n", + " print_format=\"%s\",\n", + " impact=Parameter.Impact.affects_values,\n", + " ):\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "# ParameterDictionary Class\n", + "```python\n", + "class ParameterDictionary(dict):\n", + " \"\"\"Directory holding all plugin parameters for a ``Freva`` plugin.\n", + " This class behaves like a built-in ``dict`` with additional features.\n", + " The most prominent feature is that the order of added items is preserved,\n", + " as opposed to a normal build-in ``dict``.\n", + " \"\"\"\n", + " def __init__(self, *parameters: ParameterType) -> None:\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "# _ConfigWrapper class\n", + "```python\n", + "class _ConfigWrapper:\n", + " \"\"\"Convenience class that helps to dynamically set the location of the\n", + " evaluation system config file.\"\"\"\n", + " _env: str = \"EVALUATION_SYSTEM_CONFIG_FILE\"\n", + " def __init__(\n", + " self,\n", + " default_file: str,\n", + " ):\n", + " self.default_file = default_file\n", + " def __fspath__(self) -> str:\n", + " return os.environ.get(self._env, self.default_file)\n", + " def __repr__(self) -> str:\n", + " return self.__fspath__()\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "

    Freva Wrapper Structure

    \n", + "\n", + "
    \n", + "
    \n", + "
      \n", + "
    • Plugin Details
    • \n", + "
      \n", + "
    • Plugin Parameters
    • \n", + "
      \n", + "
    • Plugin Methods
    • \n", + "
    \n", + "
    \n", + "
    \n", + " \"wrapper's\n", + "
    \n", + "
    " + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Freva Wrapper Structure: 1. Details\n", + "```python\n", + "from evaluation_system.api import plugin\n", + "class TemplatePlugin(plugin.PluginAbstract):\n", + " __version__ = (0, 0, 0)\n", + " \"\"\"\n", + " def __version__(self) -> tuple[int, int, int]:\n", + " # 3-value tuple representing the plugin version.\n", + " \"\"\"\n", + " __short_description__: str = \"template plugin\"\n", + " __category__ = \"something\"\n", + " \"\"\"\n", + " def __category__(self) -> str:\n", + " # Optional category this plugin belongs to.\n", + " return \"\"\n", + " \"\"\"\n", + " __tags__ = [\"something\", \"somethingelse\"]\n", + " \"\"\"\n", + " def __tags__(self) -> list[str]:\n", + " # Optional tags, that are the plugin can be described with.\n", + " return [\"\"]\n", + " \"\"\"\n", + " tool_developer: Optional[str] = \"someonename someonefamily\"\n", + " __long_description__: Optional[str] = \"template plugin long\"\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Freva Wrapper Structure: 2. Parameters\n", + "```python\n", + "from evaluation_system.api.parameters import ParameterDictionary, String, Bool\n", + "class TemplatePlugin(plugin.PluginAbstract):\n", + " __parameters__ = ParameterDictionary(\n", + " String(ParameterType),\n", + " \"\"\"\n", + " Example:\n", + " String(\n", + " name=\"string\",\n", + " default=\"None\",\n", + " help=(\n", + " \"some helps\"\n", + " ),\n", + " )\n", + " \"\"\"\n", + " Bool(ParameterType),\n", + " \"\"\"\n", + " Example:\n", + " Bool(\n", + " name=\"checkbox\",\n", + " default=True,\n", + " )\n", + " \"\"\"\n", + " )\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Freva Wrapper Structure: 2. Parameters\n", + "```python\n", + "from evaluation_system.api.parameters import ParameterDictionary, SolrField, InputDirectory, String\n", + "class TemplatePlugin(plugin.PluginAbstract):\n", + " __parameters__ = ParameterDictionary( \n", + " InputDirectory(String),\n", + " \"\"\"\n", + " Example:\n", + " InputDirectory(\n", + " name=\"inputdirectory\",\n", + " ),\n", + " \"\"\"\n", + " SolrField(String),\n", + " \"\"\"\n", + " class SolrField(String):\n", + " # A parameter using solr for finding valid values.\n", + " def __init__(\n", + " self,\n", + " *args,\n", + " facet: str,\n", + " group: int = 1,\n", + " multiple: bool = False,\n", + " predefined_facets: Optional[list[str]] = None,\n", + " editable: bool = True,\n", + " **kwargs,\n", + " ): \n", + " \"\"\"\n", + " )\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Freva Wrapper Structure: 2. Parameters\n", + "```python\n", + "from evaluation_system.api.parameters import ParameterDictionary, String, CacheDirectory, SelectField, Directory\n", + "class TemplatePlugin(plugin.PluginAbstract):\n", + " __parameters__ = ParameterDictionary(\n", + " Directory(String),\n", + " CacheDirectory(Directory),\n", + " SelectField(String),\n", + " \"\"\"\n", + " class SelectField(String):\n", + " # Select field to select parameter from predefined values.\n", + " def __init__(self, options: dict[str, str], *args, **kwargs):\n", + " Example:\n", + " SelectField(\n", + " options={\"first\": \"1st\", \"second\": \"2nd\"},\n", + " ),\n", + " \"\"\"\n", + " Integer(ParameterType),\n", + " \"\"\"\n", + " Example:\n", + " Integer(\n", + " name=\"integer\",\n", + " default=1,\n", + " )\n", + " \"\"\"\n", + " )\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Freva Wrapper Structure: 3. Methods\n", + "```python\n", + "from evaluation_system.api import plugin\n", + "class TemplatePlugin(plugin.PluginAbstract):\n", + " def run_tool(self, config_dict=None):\n", + " self.call(f\"python template_plugin.py arg1 arg2 {config_dict}\")\n", + " self.call(f\"template_runner.sh {config_dict}\")\n", + " self.add_output_to_databrowser(\n", + " output_dir,\n", + " project=config_dict[\"project\"], # user-\n", + " product=config_dict[\"product\"], # f\"{config_dict[\"project\"]}.{config_dict[\"project\"]}\"\n", + " institute=config_dict[\"institute\"],\n", + " model=config_dict[\"model\"],\n", + " experiment=config_dict[\"experiment\"],\n", + " time_frequency=config_dict[\"time_frequency\"],\n", + " variable=config_dict[\"variable\"],\n", + " ensemble=config_dict[\"ensemble\"],\n", + " )\n", + " return self.prepare_output(config_dict[\"outputdir\"])\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Recommended: Keep track of errors\n", + "\n", + "```python\n", + "from evaluation_system.api import plugin\n", + "import json\n", + "class TemplatePlugin(plugin.PluginAbstract):\n", + " def run_tool(self, config_dict=None):\n", + " json_file = Path(config_dict[\"cache\"]) / \"out.json\"\n", + " with json_file.open(\"w\") as json_f:\n", + " json.dump(config_dict, json_f, indent=4)\n", + " with errorfile.open(\"w\") as error_f:\n", + " self.call(\n", + " f\"{self.class_basedir}/main_runner.sh {json_file}\",\n", + " stderr=error_f,\n", + " )\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### Additional: How to deal with JSON files in the main script of plugin\n", + "#### Python:\n", + "```python\n", + "import json\n", + "import sys\n", + "with open(sys.argv[1]) as f:\n", + " config_dict = json.load(f)\n", + "```\n", + "#### Bash\n", + "```bash\n", + "_jq(){\n", + " jq -r ${1} ${2} | sed \"s/null/None/g;s/true/True/g;s/false/False/g\"\n", + "\n", + "}\n", + "export CACHE=\"$(_jq .cache $1)\"\n", + "export OUTPUTDIR=\"$(_jq .outputdir $1)\"\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### Wrapper Illustration\n", + "\n", + "![First Wrapper](media/wrapper/First_wrapper.png)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### Wrapper Illustration\n", + "\n", + "![Second Wrapper](media/wrapper/Second_wrapper.png)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### Wrapper Illustration\n", + "\n", + "![Third Wrapper](media/wrapper/Third_wrapper.png)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### Wrapper Illustration\n", + "\n", + "![Fourth Wrapper](media/wrapper/Fourth_wrapper.png)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# How To Install All Needed Libraries Of A Plugin" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Why the need?\n", + "\n", + "- Formerly, we relied on HPC modules to run plugins' software.\n", + "- Less than ideal when migrating to newer HPC/other institutions!\n", + "- Now, all necessary software installed in a `conda/mamba` environment at **each** repo folder." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "

    Steps to Install Necessary Packages

    \n", + "\n", + "
    \n", + "
    \n", + "
      \n", + "
    • Define an Env YAML file
    • \n", + "
      \n", + "
    • Install env via Conda
    • \n", + "
      \n", + "
    • Activate Environment
    • \n", + "
      \n", + "
    • Alternative: Makefile
    • \n", + "
    \n", + "
    \n", + "
    \n", + " \"install\n", + "
    \n", + "
    " + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Define an Env YAML file\n", + "e.g. `plugin-env.yml`:\n", + "```yaml\n", + "channels:\n", + " - conda-forge\n", + "dependencies:\n", + " - r-base\n", + " - pip\n", + "```\n", + "## Install env via Conda\n", + "- The environment **must** be located at the same level as the wrapper file!\n", + "- The environment **must** be located named `plugin_env/` so Freva recognizes it!\n", + "```bash\n", + "mamba env create --prefix ./plugin_env -f plugin-env.yml \n", + "```\n", + "## Activate Environment\n", + "```bash\n", + "conda activate plugin_env/bin/activate\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## More flexible approach via Makefile\n", + "\n", + "We can define a `Makefile` as below and then after definition of `environment.yml`, install all the dependencies listed above via `make` commands. But first and foremost, we need to ensure, we have `make` installed on our machine.\n", + "\n", + "```Makefile\n", + "env:\n", + "\t@# Installs a conda environment with R and the IDF package\n", + "\t@if [ -d \"./plugin_env\" ]; then \\\n", + "\t\trm -rf ./plugin_env; \\\n", + "\tfi\n", + "\tconda env create --prefix ./plugin_env -f environment.yml --force\n", + "\tRscript -e 'install.packages(\"IDF\", repos=\"https://CRAN.R-project.org/\")'\n", + "cartopy:\n", + "\t@# Download various cartopy shape-files\n", + "\t@if [ -d \"./cartopy\" ]; then \\\n", + "\t\trm -rf ./cartopy; \\\n", + "\tfi\n", + "\t./plugin_env/bin/python3 assets/cartopy_download.py physical cultural\n", + ".PHONY: env cartopy\n", + "```\n", + "\n", + "* Using `mamba` instead of using `conda` can make the way of installation faster.\n", + "\n", + "You can take a look at a plugin template [here](https://gitlab.dkrz.de/freva/plugins4freva/plugintemplate)." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# How To Plug a Tool into Freva" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "

    Plug a Tool into Freva

    \n", + "\n", + "
    \n", + "
    \n", + "
      \n", + "
    • Plug into Freva via CLI
    • \n", + "
      \n", + "
    • Plug into Freva via Freva-Web
    • \n", + "
      \n", + "
    \n", + "
    \n", + "
    \n", + " \"plug\n", + "
    \n", + "
    " + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Plug a tool into Freva\n", + "\n", + "\n", + "
    \n", + "
    \n", + " \"plug\n", + "
    \n", + "
    \n", + " \"plug\n", + "
    \n", + "
    " + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Plug a tool into Freva\n", + "\n", + "In this step we need to clone a plugin in the user directory of freva-dev and replace `` with your `k-number` or `b-number` username:\n", + "\n", + "```sh\n", + "ssh @levante.dkrz.de\n", + "#After login to Levante\n", + "cd work/ch1187/clint/freva-dev/share/work//freva-dev/\n", + "git clone https://gitlab.dkrz.de/freva/plugins4freva/plugin_workshop/example_plugin.git\n", + "```\n", + "In this step you need to install the dependencies. Have a look at the previous section (How To Install All Needed Libraries Of A Plugin)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Plug a tool into Freva\n", + "\n", + "\n", + "
    \n", + "
    \n", + " \"plug\n", + "
    \n", + "
    \n", + " \"plug\n", + "
    \n", + "
    " + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Plug a tool into Freva\n", + "\n", + "\n", + "
    \n", + "
    \n", + " \"plug\n", + "
    \n", + "
    \n", + " \"plug\n", + "
    \n", + "
    " + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# Freva: Plugin Development\n", + "\n", + "\"freva\n", + "\n", + "**Martin Bergemann, Bijan Fallah, Andrej Fast, Mostafa Hadizadeh, \n", + "Christopher Kadow, Etor E. Lucio-Eceiza, Felix Örtel, Manuel Reis, and many others…**\n", + "\n", + "Deutsches Klimarechenzentrum @ CLINT in Data Analysis Dpt. (+ Data Management Dpt.*)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# Overview of a Freva plugin\n", + "\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Why should I build a Freva plugin?\n", + "It allows you to be part of \"The Freva Cycle\"\n", + "\n", + "\"parts\"\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Structure of a Plugin\n", + "
    \n", + "
    \n", + "

    There are 3 main building blocks in a plugin:

    \n", + "
      \n", + "
    • Wrapper: connects the tool to Freva
    • \n", + "
    • Tool: scientific code
    • \n", + "
    • Installer: they install the necessary libraries
    • \n", + "
    \n", + "
    \n", + "
    \n", + " \"parts\"\n", + "
    \n", + "
    " + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Structure of a Plugin: The Wrapper\n", + "
    \n", + "
    \n", + "

    The connection to Freva:

    \n", + "
      \n", + "
    • Written in python 3
    • \n", + "
    • Needs to follow a series of standards
    • \n", + "
    \n", + "
    \n", + "
    \n", + " \"parts\"\n", + "
    \n", + "
    " + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Structure of a Plugin: The tool\n", + "
    \n", + "
    \n", + "

    The scientific code:

    \n", + "
      \n", + "
    • Written in any* language (python, R, C, FORTRAN, a mix...)
    • \n", + "
    • A single script or multiple scripts and/or folders (subroutines, libraries, etc.).
    • \n", + "
    \n", + "
    \n", + "
    \n", + " \"parts\"\n", + "
    \n", + "
    \n", + "*caveat: we encourage free software" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Structure of a Plugin: Installer\n", + "
    \n", + "
    \n", + "

    Installs the plugin environment:

    \n", + "
      \n", + "
    • Usually: Makefile (instructions) + .yaml file (libraries)
    • \n", + "
    • It can also be more elaborated: e.g. binary compilation, installation of subroutines...
    • \n", + "
    \n", + "
    \n", + "
    \n", + " \"parts\"\n", + "
    \n", + "
    \n", + "\n", + "**NOTE:** It replaces the dependencies on the HPC (e.g. `modules`) and makes it more transferable to other e.g. institutions" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# Git and Gitlab" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## What is git? \"freva\n", + "Is a free and open source *Distributed* **Version Control System**:\n", + "- **Version Control System**: a system that tracks and provides control over changes to source code, documentation and configuration files.\n", + "- *Distributed*: a form of version control in which the complete codebase, including its full history, is mirrored on every developer's computer\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## What is gitlab? \"freva\n", + "\n", + "
    \n", + "
    \n", + "
  • GitLab is a web-based tool: provides version control, issue tracking, CI/CD etc.
  • \n", + "
  • DKRZ hosts its own framework at https://gitlab.dkrz.de
  • \n", + "
    \n", + "
    \n", + " \"freva\n", + "
    \n", + "
    \n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Gitlab and Freva:\n", + "\n", + "- One central local repository for the plugged plugins\n", + "- Other local repositories for different developers\n", + "- One remote repository for the plugin at gitlab\n", + "\"freva\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Gitlab and Freva: location of the plugins\n", + "\n", + "- Under [https://gitlab.dkrz.de/freva/plugins4freva](https://gitlab.dkrz.de/freva/plugins4freva) project:\n", + "\"freva\n", + "- Other projects have also their own, e.g.: \n", + " - climxtreme: https://gitlab.dkrz.de/bm1159/plugins4freva\n", + " - regiklim-nukleus: https://gitlab.dkrz.de/ch1187/plugins4freva\n", + "- some plugins can be found in different projects (see [forks](https://docs.gitlab.com/ee/user/project/repository/forking_workflow.html)).\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Gitlab and Freva: cloning a repository\n", + "To download a repository there are 2 ways: via `https` and via `ssh`:\n", + "\"freva\n", + "- `https`: straightforward, requires to enter (dkrz) username and password (usually). \n", + "- `ssh`: convenient, requires to provide a ssh key previously.\n", + "\n", + "In both cases:\n", + "\n", + "```\n", + "$ ssh @levante.dkrz.de\n", + "> cd /path/to/my/work/\n", + "> git clone https://gitlab.dkrz.de/freva/plugins4freva/plugin_workshop/example_plugin.git\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Gitlab and Freva: setting your SSH key\n", + "1. generate a ssh a private and public (`.pub`) key locally (e.g. laptop or levante):\n", + "```\n", + "$ ssh-keygen -t ed25519\n", + "$ cd ~/.ssh/\n", + "$ ls\n", + "id_ed25519 id_ed25519.pub\n", + "```\n", + "2. copy the **public** key: \n", + "```\n", + "$ cat id_ed25519.pub\n", + "ssh-ed25519 AAAAC3NzaC1lFDI1YTE5AAAAICUqpXx8AyrNH7HQgPSq9LuB7sTEmXP4ODqOnaHVPPQ6 username@levante\n", + "```\n", + "3. add the public key in gitlab (`user>preferences>ssh keys`): \"freva" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Gitlab and Freva: creating a new project\n", + "- If we already had an existing Git repository:\n", + "```shell\n", + "$ cd NEW_PLUGIN # for example\n", + "$ git remote rename origin old-origin\n", + "$ git remote add origin git@gitlab.dkrz.de:freva/plugins4freva/new_plugin.git\n", + "$ git push -u origin --all\n", + "$ git push -u origin --tags\n", + "```\n", + "\n", + "- If we did not already have an existing Git repository:\n", + "```shell\n", + "$ cd NEW_PLUGIN # for example\n", + "$ git init\n", + "$ git remote add origin git@gitlab.dkrz.de:freva/plugins4freva/new_plugin.git\n", + "# create your new files and folders\n", + "$ git add .\n", + "$ git commit -m \"Initial commit of my new project\"\n", + "$ git push -u origin master\n", + "```\n", + "\n", + "Now you could (hypothetically) go to https://gitlab.dkrz.de/freva/plugins4freva/new_plugin" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# License of Plugins" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## What kind of License should I follow?\n", + "\n", + "[The Freva code](https://github.com/FREVA-CLINT/freva/blob/main/LICENSE.md) follows a [BSD3 license](https://opensource.org/license/bsd-3-clause), a permissive open-source license with minimal restrictions:\n", + "- It allows for wide usage, including in proprietary software.\n", + "- it imposes very few restrictions on how the software can be redistributed.\n", + "\n", + "In principle, any derived product from Freva (i.e. plugins), should follow this license. *Unless* stated otherwise by the developer.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## What kind of License should I follow?\n", + "\n", + "- We encourage open-source software to foster collaboration within and outside your projects.\n", + "- That said, common courtesy should be expected, e.g.:\n", + " - reference to the first manuscript where the developer used the plugin (the plugin documentation is useful for this!).\n", + " - contacting him/her in case there is no such manuscript." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# Connecting your IDE / Code Editor to a remote session using SSH" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## 1. VS-Code \"freva\n", + "\n", + "Open a new window in VS Code. There are several ways to connect to a remote session, as indicated in the picture below:\n", + "\n", + "![Image depicting multiple ways to start a remote session in VS Code](media/vscode/01_connect_to_remote.png)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "\n", + "\"freva\n", + "
    \n", + "
    \n", + "
    \n", + "\n", + "Clicking either of the buttons opens a prompt at the top of the window, giving you several options to start a remote session:\n", + "\n", + "![Image depicting the prompt that opens when clicking one of the \"Connect to...\" buttons in the new VS Code window](media/vscode/02_remote_connection_options.jpg)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "\"freva\n", + "
    \n", + "
    \n", + "
    \n", + "\n", + "Click \"Connect Current Window to Host...\" (\"Connect to Host...\" opens a new window for the connection).\n", + "\n", + "You can type in the address of the remote host that you want to connect to or, in case the host is specified in your ssh config file (.ssh/config or ssh_config), select them from the list of hosts. To connect to levante, enter [k-number@]levante.dkrz.de :\n", + "\n", + "![Image depicting the prompt to enter a remote SSH host, with k202195@levante.dkrz.de manually entered](media/vscode/03_remote_host_entered.jpg)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "\"freva\n", + "
    \n", + "
    \n", + "
    \n", + "\n", + "The first time connecting to a host, you will be prompted to specify the OS of the remote host (i.e. Linux / Windows / macOS).\n", + "\n", + "Depending on the authentication set up for the remote host, you might be prompted to type in a password. Once the connection has been established, your can open a folder on the remote host, like you would do on your local machine (by pressing Ctrl + K, Ctrl + O or by pressing \"Open Folder\"):\n", + "\n", + "![Image depicting how to open a folder once connected to the remote host, similar to opening a local folder](media/vscode/04_opening_remote_folder.jpg)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "\"freva\n", + "
    \n", + "
    \n", + "
    \n", + "\n", + "You may be prompted again to type in the password at this point. The window should refresh and give you access to the remote folder that you selected in the previous step, similar to what can be seen in the following image:\n", + "\n", + "\"freva" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "\"freva\n", + "
    \n", + "
    \n", + "
    \n", + "\n", + "From here you can use the editor to work with remote files basically as you would with files on your local machine. Any terminals opened in this window will also connect to the remote host.\n", + "\n", + "For detailed documentation on remote development using VS Code, including development on dev containers or WSL, click [here](https://code.visualstudio.com/docs/remote/remote-overview)." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## 2. PyCharm \"freva\n", + "\n", + "\n", + "> 😱\n", + ">Remote Development is currently in beta and only supported for the Professional Version of PyCharm!\n", + "\n", + "Open your Plugins (Ctrl+Alt+S) and confirm that \"Remote Development Gateway\" is installed and that it is enabled:\n", + "\n", + "![Image depicting a list of installed PyCharm plugins, with the \"Remote Development Gateway\" being installed and enabled.](media/pycharm/01_remote_development_gateway.jpg)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "\"freva\n", + "
    \n", + "
    \n", + "
    \n", + "\n", + "To open a remote session in PyCharm, go to the welcome screen and click on the \"Remote Development\" Tab in the left side bar. This should give you a number of options, including the option to connect to a remote session using SSH:\n", + "\n", + "![Image depiciting the welcome screen of PyCharm Professional, with the \"Remote Development\" Tab highlighted using red arrows.](media/pycharm/02_remote_development_tab.png)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "\"freva\n", + "
    \n", + "
    \n", + "
    \n", + "\n", + "To establish a new SSH Connection, click \"New Connection\" below the SSH Connection option. This should open the following dialogue:\n", + "\n", + "![Image depicting the dialogue that opens when creating a new SSH connection on PyCharm. Includes fields for the username, the host name or address, and the port that should be used connected to.](media/pycharm/03_ssh_connection_dialogue.jpg)\n", + ">⚠\n", + ">Note that PyCharm currently only supports connecting to remote hosts running Linux." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "\"freva\n", + "
    \n", + "
    \n", + "
    \n", + "\n", + "Again, depending on the type of authentication set up by the remote host, you may be prompted to enter a password to establish the remote connection.\n", + "\n", + "In the next step (pending the successful connection to the remote host), you will be asked to set the IDE version (i.e. the version of the IDE that will be installed on the remote host) and the project directory (i.e. the directory on the remote host that contains the project files that you will be working with):\n", + "\n", + "![Image depicting the PyCharm window that prompts you to set the IDE Version to be installed on the remote host, as well as the project directory that you will be working in](media/pycharm/04_choose_ide_and_project.jpg)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "\"freva\n", + "
    \n", + "
    \n", + "
    \n", + "\n", + "Click \"Download IDE and Connect\". The installation of the selected IDE on the remote host might take a while. Once the installation is complete, a window containing the remote IDE should open.\n", + "\n", + "![Image depicting the remote IDE window, after successfully installing it to the remote host](media/pycharm/05_remote_IDE_successfully_opened.jpg)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "\"freva\n", + "
    \n", + "
    \n", + "
    \n", + "\n", + "The remote IDE gives you the ability to work with project files, much like you would with local project files. Any terminal sessions started in this IDE will also be connected to the remote host.\n", + "\n", + "For detailed documentation on remote development using PyCharm, click [here](https://www.jetbrains.com/help/pycharm/remote-development-starting-page.html)." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## 3. R Studio \"freva\n", + "\n", + "There is currently only one method of using R Studio on a remote host that is officially supported by R, namely by connecting to an instance of R Studio Server running on the remote host. The previously available alternative, by creating a remote connection in [R Studio Desktop Pro](https://docs.posit.co/ide/desktop-pro/2022.02.1+461.pro1/remote-desktop.html), has been removed since version [2023.06.2](https://docs.posit.co/ide/desktop-pro/remote_desktop/remote_desktop.html).\n", + "\n", + "However, R Studio Server is not available on Levante, so creating a remote development environment instance this way is not possible. However, it is possible to remotely develop and execute R-code by using the [VS Code R Extension](https://code.visualstudio.com/docs/languages/r). " + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "\"freva\n", + "
    \n", + "
    \n", + "
    \n", + "\n", + "First, connect to Levante as outlined in the VS Code section of this guide. Once the connection is established, you will want to install the R (`REditorSupport.r`) and R Debugger (`RDebugger.r-debugger`) Extensions, as shown below:\n", + "![Image depicting R VS Code Plugins](media/rstudio/01_rstudio_vscode_extensions.jpg)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "\"freva\n", + "
    \n", + "
    \n", + "
    \n", + "\n", + "Make sure that you have installed the extensions to the remote host, and not your local machine, by going to Extensions (Ctrl+Shift+X):\n", + "\n", + "![Image showing that R VS Code Plugins where installed on Levante](media/rstudio/02_rstudio_extensions_on_remote.jpg)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "\"freva\n", + "
    \n", + "
    \n", + "
    \n", + "\n", + "In a terminal that is connected to levante via ssh (e.g. in the VS Code window connected to levante), type in the following command:\n", + "```bash\n", + "$ module load r\n", + "```\n", + "The result should be something along the lines of:\n", + "```bash\n", + "[k202195@levante3 ~]$ module load r\n", + "Autoloading openjdk/17.0.0_35-gcc-11.2.0\n", + "\n", + "Loading r/4.1.2-gcc-11.2.0\n", + " Loading requirement: openjdk/17.0.0_35-gcc-11.2.0\n", + "[k202195@levante3 ~]$\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "\"freva\n", + "
    \n", + "
    \n", + "
    \n", + "\n", + "We'll need to find out, where R is located on the remote host. We do this by using the command:\n", + "```bash\n", + "$ which R\n", + "```\n", + "The output should be something like:\n", + "```bash\n", + "[k202195@levante3 ~]$ which R\n", + "/sw/spack-levante/r-4.1.2-eprwea/bin/R\n", + "[k202195@levante3 ~]$\n", + "```\n", + "Copy this path to your clipboard." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "\"freva\n", + "
    \n", + "
    \n", + "
    \n", + "\n", + "Install the [httpgd](https://github.com/nx10/httpgd) package to embed live R graphics into the VS Code environment. You can do this by running the following commands in a terminal on the remote host:\n", + "```bash\n", + "# Start and R command line session\n", + "$ R\n", + "```\n", + "The following command is executed in the R command line session\n", + "```R\n", + "install.packages(\"httpgd\")\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "\"freva\n", + "
    \n", + "
    \n", + "
    \n", + "\n", + "Open the settings (Ctrl + ,) and type `r.rterm.linux` in the search bar as shown in the image below. Make sure that you paste the previously copied path into the field, as depicted:\n", + "\n", + "![Image depicting how to set the path for the R Terminal in VS Code](media/rstudio/03_rterm_linux_settings.jpg)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "\"freva\n", + "
    \n", + "
    \n", + "
    \n", + "\n", + "Once that is done, open any R file on the remote host. Once an R terminal is ready, you could either select the code or put the cursor at the beginning or ending of the code you want to run, press (Ctrl+Enter), and then code will be sent to the active R terminal.\n", + "\n", + "If you want to run an entire R file, open the file in the editor, and press Ctrl+Shift+S and the file will be sourced in the active R terminal:\n", + "\n", + "![Image depicting some R code being run remotely on Levante and the resulting interactive plots](media/rstudio/04_opening_and_running_r_file_in_vscode.jpg)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "\"freva\n", + "
    \n", + "
    \n", + "
    \n", + "\n", + "For more information on working with R in VS Code, click [here](https://code.visualstudio.com/docs/languages/r)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# What is a Freva Wrapper?" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "

    Freva Wrapper Main Classes

    \n", + "\n", + "
    \n", + "
    \n", + "
      \n", + "
    • PluginAbstract Class Functions
    • \n", + "
      \n", + "
    • parameters.py Classes
    • \n", + "
      \n", + "
    • _ConfigWrapper Class
    • \n", + "
    \n", + "
    \n", + "
    \n", + " \"What\n", + "
    \n", + "
    " + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Special Variables:\n", + "\n", + "| Variables | Description |\n", + "|--------------------|------------------------------------------------------------------------|\n", + "| USER_BASE_DIR | Absolute path to the central directory for this user. |\n", + "| USER_OUTPUT_DIR | Absolute path to where the plugin outputs for this user are stored. |\n", + "| USER_PLOTS_DIR | Absolute path to where the plugin plots for this user are stored. |\n", + "| USER_CACHE_DIR | Absolute path to the cached data (temp data) for this user. |\n", + "| USER_UID | The users’ User Identifier. |\n", + "| SYSTEM_DATE | Current date in the form YYYYMMDD (e.g. 20120130). |\n", + "| SYSTEM_DATETIME | Current date in the form YYYYMMDD_HHmmSS (e.g. 20120130_101123). |\n", + "| SYSTEM_TIMESTAMP | Milliseconds since epoch (i.e. e.g. 1358929581838). |\n", + "| SYSTEM_RANDOM_UUID | A random Universal Unique Identifier (e.g. 912cca21-6364-4f46-9b03-4263410c9899). |\n", + "\n", + "Example: \n", + "\n", + "```bash\n", + "output_file='$USER_OUTPUT_DIR/myfile_${SYSTEM_DATETIME}blah.nc'\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "# PluginAbstract Class\n", + "## Function: class_basedir\n", + "```python\n", + "class PluginAbstract(abc.ABC):\n", + " \"\"\"Base class that is used as a template for all Freva plugins.\n", + " Any api wrapper class defining Freva plugins must inherit from this class.\"\"\"\n", + "\n", + " @deprecated_method(\"PluginAbstract\", \"class_basedir\")\n", + " def getClassBaseDir(self) -> Optional[str]:\n", + " \"\"\"Deprecated method for class_basedir.\"\"\"\n", + "\n", + " def class_basedir(self) -> str:\n", + " \"\"\"Get absolute path to the module defining the plugin class.\"\"\"\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "# PluginAbstract Class\n", + "## Function: call\n", + "```python\n", + "class PluginAbstract(abc.ABC):\n", + " \"\"\"Base class that is used as a template for all Freva plugins.\n", + " Any api wrapper class defining Freva plugins must inherit from this class.\"\"\"\n", + "\n", + " def call(\n", + " self,\n", + " cmd_string: Union[str, list[str]],\n", + " check: bool = True,\n", + " **kwargs,\n", + " ) -> sub.Popen[Any]:\n", + " \"\"\"Run command with arguments and return a CompletedProcess instance.\"\"\"\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "# PluginAbstract Class\n", + "## Function: call and class_basedir - Example\n", + "```python\n", + "from evaluation_system.api import plugin\n", + "class TemplatePlugin(plugin.PluginAbstract):\n", + " def run_tool(self, config_dict=None)\n", + " self.call(\n", + " f\"{self.class_basedir}/main_code.sh {config_dict}\"\n", + " )\n", + " # or\n", + " self.call(\n", + " f\"{Path(__file__).parent}/main_code.sh {config_dict}\"\n", + " )\n", + " # or\n", + " self.call(\n", + " f\"{os.getenv(USER_BASE_DIR)}/main_code.sh {config_dict}\"\n", + " ) \n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "# PluginAbstract Class\n", + "## Function: add_output_to_databrowser\n", + "```python\n", + "class PluginAbstract(abc.ABC):\n", + " @deprecated_method(\"PluginAbstract\", \"add_output_to_databrowser\")\n", + " def linkmydata(self, *args, **kwargs): # pragma: no cover\n", + "\n", + " def add_output_to_databrowser(\n", + " self,\n", + " plugin_output: os.PathLike,\n", + " project: str, # user-\n", + " product: str, # project.product\n", + " *,\n", + " model: str = \"freva\",\n", + " institute: Optional[str] = None,\n", + " ensemble: str = \"r1i1p1\",\n", + " time_frequency: Optional[str] = None,\n", + " variable: Optional[str] = None,\n", + " experiment: Optional[str] = None,\n", + " index_data: bool = True,\n", + " ) -> Path:\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "# PluginAbstract Class\n", + "## Function: add_output_to_databrowser - Example\n", + "```python\n", + "from evaluation_system.api import plugin\n", + "class TemplatePlugin(plugin.PluginAbstract):\n", + " def run_tool(self, config_dict=None)\n", + " self.add_output_to_databrowser(\n", + " plugin_output=config_dict[\"outputdir\"],\n", + " project=config_dict.get(\"project\", \"default_project\"),\n", + " product=config_dict.get(\"product\", \"default_product\"),\n", + " model=config_dict.get(\"model\", \"default_model\"),\n", + " institute=config_dict.get(\"institute\", \"default_institute\"),\n", + " time_frequency=\"mon\",\n", + " )\n", + "```\n", + "\n", + "### How to find it in Freva:\n", + "\n", + "```bash\n", + "freva databrowser product=project.product project=user-\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "# PluginAbstract Class\n", + "## Function: prepare_output\n", + "```python\n", + "class PluginAbstract(abc.ABC):\n", + " \"\"\"Base class that is used as a template for all Freva plugins.\n", + " Any api wrapper class defining Freva plugins must inherit from this class.\"\"\"\n", + "\n", + " @deprecated_method(\"PluginAbstract\", \"prepare_output\")\n", + " def prepareOutput(self, *args) -> dict[str, dict[str, str]]:\n", + " \"\"\"Deprecated method for :class:`prepare_output`. \"\"\"\n", + "\n", + " def prepare_output(\n", + " self, output_files: Union[str, list[str], dict[str, dict[str, str]]]\n", + " ) -> dict[str, dict[str, str]]:\n", + " \"\"\"Prepare output for files supposedly created.\"\"\"\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "# PluginAbstract Class\n", + "## Function: prepare_output - Example\n", + "```python\n", + "from evaluation_system.api import plugin\n", + "class TemplatePlugin(plugin.PluginAbstract):\n", + " def run_tool(self, config_dict=None)\n", + " return self.prepare_output(config_dict[\"outputdir\"])\n", + "```\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "# ParameterType Class\n", + "```python\n", + "class ParameterType(initOrder):\n", + " \"\"\"Base class for all parameter types.\n", + " All available parameter types inherit from this class. The class creates\n", + " a parameter object holding the following user defined information.\n", + " \"\"\"\n", + " def __init__(\n", + " self,\n", + " name=None,\n", + " default=None,\n", + " mandatory=False,\n", + " max_items=1,\n", + " item_separator=\",\",\n", + " regex=None,\n", + " version=1,\n", + " help=\"No help available.\",\n", + " print_format=\"%s\",\n", + " impact=Parameter.Impact.affects_values,\n", + " ):\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "# ParameterDictionary Class\n", + "```python\n", + "class ParameterDictionary(dict):\n", + " \"\"\"Directory holding all plugin parameters for a ``Freva`` plugin.\n", + " This class behaves like a built-in ``dict`` with additional features.\n", + " The most prominent feature is that the order of added items is preserved,\n", + " as opposed to a normal build-in ``dict``.\n", + " \"\"\"\n", + " def __init__(self, *parameters: ParameterType) -> None:\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "# _ConfigWrapper class\n", + "```python\n", + "class _ConfigWrapper:\n", + " \"\"\"Convenience class that helps to dynamically set the location of the\n", + " evaluation system config file.\"\"\"\n", + " _env: str = \"EVALUATION_SYSTEM_CONFIG_FILE\"\n", + " def __init__(\n", + " self,\n", + " default_file: str,\n", + " ):\n", + " self.default_file = default_file\n", + " def __fspath__(self) -> str:\n", + " return os.environ.get(self._env, self.default_file)\n", + " def __repr__(self) -> str:\n", + " return self.__fspath__()\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "

    Freva Wrapper Structure

    \n", + "\n", + "
    \n", + "
    \n", + "
      \n", + "
    • Plugin Details
    • \n", + "
      \n", + "
    • Plugin Parameters
    • \n", + "
      \n", + "
    • Plugin Methods
    • \n", + "
    \n", + "
    \n", + "
    \n", + " \"wrapper's\n", + "
    \n", + "
    " + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Freva Wrapper Structure: 1. Details\n", + "```python\n", + "from evaluation_system.api import plugin\n", + "class TemplatePlugin(plugin.PluginAbstract):\n", + " __version__ = (0, 0, 0)\n", + " \"\"\"\n", + " def __version__(self) -> tuple[int, int, int]:\n", + " # 3-value tuple representing the plugin version.\n", + " \"\"\"\n", + " __short_description__: str = \"template plugin\"\n", + " __category__ = \"something\"\n", + " \"\"\"\n", + " def __category__(self) -> str:\n", + " # Optional category this plugin belongs to.\n", + " return \"\"\n", + " \"\"\"\n", + " __tags__ = [\"something\", \"somethingelse\"]\n", + " \"\"\"\n", + " def __tags__(self) -> list[str]:\n", + " # Optional tags, that are the plugin can be described with.\n", + " return [\"\"]\n", + " \"\"\"\n", + " tool_developer: Optional[str] = \"someonename someonefamily\"\n", + " __long_description__: Optional[str] = \"template plugin long\"\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Freva Wrapper Structure: 2. Parameters\n", + "```python\n", + "from evaluation_system.api.parameters import ParameterDictionary, String, Bool\n", + "class TemplatePlugin(plugin.PluginAbstract):\n", + " __parameters__ = ParameterDictionary(\n", + " String(ParameterType),\n", + " \"\"\"\n", + " Example:\n", + " String(\n", + " name=\"string\",\n", + " default=\"None\",\n", + " help=(\n", + " \"some helps\"\n", + " ),\n", + " )\n", + " \"\"\"\n", + " Bool(ParameterType),\n", + " \"\"\"\n", + " Example:\n", + " Bool(\n", + " name=\"checkbox\",\n", + " default=True,\n", + " )\n", + " \"\"\"\n", + " )\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Freva Wrapper Structure: 2. Parameters\n", + "```python\n", + "from evaluation_system.api.parameters import ParameterDictionary, SolrField, InputDirectory, String\n", + "class TemplatePlugin(plugin.PluginAbstract):\n", + " __parameters__ = ParameterDictionary( \n", + " InputDirectory(String),\n", + " \"\"\"\n", + " Example:\n", + " InputDirectory(\n", + " name=\"inputdirectory\",\n", + " ),\n", + " \"\"\"\n", + " SolrField(String),\n", + " \"\"\"\n", + " class SolrField(String):\n", + " # A parameter using solr for finding valid values.\n", + " def __init__(\n", + " self,\n", + " *args,\n", + " facet: str,\n", + " group: int = 1,\n", + " multiple: bool = False,\n", + " predefined_facets: Optional[list[str]] = None,\n", + " editable: bool = True,\n", + " **kwargs,\n", + " ): \n", + " \"\"\"\n", + " )\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Freva Wrapper Structure: 2. Parameters\n", + "```python\n", + "from evaluation_system.api.parameters import ParameterDictionary, String, CacheDirectory, SelectField, Directory\n", + "class TemplatePlugin(plugin.PluginAbstract):\n", + " __parameters__ = ParameterDictionary(\n", + " Directory(String),\n", + " CacheDirectory(Directory),\n", + " SelectField(String),\n", + " \"\"\"\n", + " class SelectField(String):\n", + " # Select field to select parameter from predefined values.\n", + " def __init__(self, options: dict[str, str], *args, **kwargs):\n", + " Example:\n", + " SelectField(\n", + " options={\"first\": \"1st\", \"second\": \"2nd\"},\n", + " ),\n", + " \"\"\"\n", + " Integer(ParameterType),\n", + " \"\"\"\n", + " Example:\n", + " Integer(\n", + " name=\"integer\",\n", + " default=1,\n", + " )\n", + " \"\"\"\n", + " )\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Freva Wrapper Structure: 3. Methods\n", + "```python\n", + "from evaluation_system.api import plugin\n", + "class TemplatePlugin(plugin.PluginAbstract):\n", + " def run_tool(self, config_dict=None):\n", + " self.call(f\"python template_plugin.py arg1 arg2 {config_dict}\")\n", + " self.call(f\"template_runner.sh {config_dict}\")\n", + " self.add_output_to_databrowser(\n", + " output_dir,\n", + " project=config_dict[\"project\"], # user-\n", + " product=config_dict[\"product\"], # f\"{config_dict[\"project\"]}.{config_dict[\"project\"]}\"\n", + " institute=config_dict[\"institute\"],\n", + " model=config_dict[\"model\"],\n", + " experiment=config_dict[\"experiment\"],\n", + " time_frequency=config_dict[\"time_frequency\"],\n", + " variable=config_dict[\"variable\"],\n", + " ensemble=config_dict[\"ensemble\"],\n", + " )\n", + " return self.prepare_output(config_dict[\"outputdir\"])\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Recommended: Keep track of errors\n", + "\n", + "```python\n", + "from evaluation_system.api import plugin\n", + "import json\n", + "class TemplatePlugin(plugin.PluginAbstract):\n", + " def run_tool(self, config_dict=None):\n", + " json_file = Path(config_dict[\"cache\"]) / \"out.json\"\n", + " with json_file.open(\"w\") as json_f:\n", + " json.dump(config_dict, json_f, indent=4)\n", + " with errorfile.open(\"w\") as error_f:\n", + " self.call(\n", + " f\"{self.class_basedir}/main_runner.sh {json_file}\",\n", + " stderr=error_f,\n", + " )\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### Additional: How to deal with JSON files in the main script of plugin\n", + "#### Python:\n", + "```python\n", + "import json\n", + "import sys\n", + "with open(sys.argv[1]) as f:\n", + " config_dict = json.load(f)\n", + "```\n", + "#### Bash\n", + "```bash\n", + "_jq(){\n", + " jq -r ${1} ${2} | sed \"s/null/None/g;s/true/True/g;s/false/False/g\"\n", + "\n", + "}\n", + "export CACHE=\"$(_jq .cache $1)\"\n", + "export OUTPUTDIR=\"$(_jq .outputdir $1)\"\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### Wrapper Illustration\n", + "\n", + "![First Wrapper](media/wrapper/First_wrapper.png)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### Wrapper Illustration\n", + "\n", + "![Second Wrapper](media/wrapper/Second_wrapper.png)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### Wrapper Illustration\n", + "\n", + "![Third Wrapper](media/wrapper/Third_wrapper.png)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### Wrapper Illustration\n", + "\n", + "![Fourth Wrapper](media/wrapper/Fourth_wrapper.png)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# How To Install All Needed Libraries Of A Plugin" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Why the need?\n", + "\n", + "- Formerly, we relied on HPC modules to run plugins' software.\n", + "- Less than ideal when migrating to newer HPC/other institutions!\n", + "- Now, all necessary software installed in a `conda/mamba` environment at **each** repo folder." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "

    Steps to Install Necessary Packages

    \n", + "\n", + "
    \n", + "
    \n", + "
      \n", + "
    • Define an Env YAML file
    • \n", + "
      \n", + "
    • Install env via Conda
    • \n", + "
      \n", + "
    • Activate Environment
    • \n", + "
      \n", + "
    • Alternative: Makefile
    • \n", + "
    \n", + "
    \n", + "
    \n", + " \"install\n", + "
    \n", + "
    " + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Define an Env YAML file\n", + "e.g. `plugin-env.yml`:\n", + "```yaml\n", + "channels:\n", + " - conda-forge\n", + "dependencies:\n", + " - r-base\n", + " - pip\n", + "```\n", + "## Install env via Conda\n", + "- The environment **must** be located at the same level as the wrapper file!\n", + "- The environment **must** be located named `plugin_env/` so Freva recognizes it!\n", + "```bash\n", + "mamba env create --prefix ./plugin_env -f plugin-env.yml \n", + "```\n", + "## Activate Environment\n", + "```bash\n", + "conda activate plugin_env/bin/activate\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## More flexible approach via Makefile\n", + "\n", + "We can define a `Makefile` as below and then after definition of `environment.yml`, install all the dependencies listed above via `make` commands. But first and foremost, we need to ensure, we have `make` installed on our machine.\n", + "\n", + "```Makefile\n", + "env:\n", + "\t@# Installs a conda environment with R and the IDF package\n", + "\t@if [ -d \"./plugin_env\" ]; then \\\n", + "\t\trm -rf ./plugin_env; \\\n", + "\tfi\n", + "\tconda env create --prefix ./plugin_env -f environment.yml --force\n", + "\tRscript -e 'install.packages(\"IDF\", repos=\"https://CRAN.R-project.org/\")'\n", + "cartopy:\n", + "\t@# Download various cartopy shape-files\n", + "\t@if [ -d \"./cartopy\" ]; then \\\n", + "\t\trm -rf ./cartopy; \\\n", + "\tfi\n", + "\t./plugin_env/bin/python3 assets/cartopy_download.py physical cultural\n", + ".PHONY: env cartopy\n", + "```\n", + "\n", + "* Using `mamba` instead of using `conda` can make the way of installation faster.\n", + "\n", + "You can take a look at a plugin template [here](https://gitlab.dkrz.de/freva/plugins4freva/plugintemplate)." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# How To Plug a Tool into Freva" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "

    Plug a Tool into Freva

    \n", + "\n", + "
    \n", + "
    \n", + "
      \n", + "
    • Plug into Freva via CLI
    • \n", + "
      \n", + "
    • Plug into Freva via Freva-Web
    • \n", + "
      \n", + "
    \n", + "
    \n", + "
    \n", + " \"plug\n", + "
    \n", + "
    " + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Plug a tool into Freva\n", + "\n", + "\n", + "
    \n", + "
    \n", + " \"plug\n", + "
    \n", + "
    \n", + " \"plug\n", + "
    \n", + "
    " + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Plug a tool into Freva\n", + "\n", + "In this step we need to clone a plugin in the user directory of freva-dev and replace `` with your `k-number` or `b-number` username:\n", + "\n", + "```sh\n", + "ssh @levante.dkrz.de\n", + "#After login to Levante\n", + "cd work/ch1187/clint/freva-dev/share/work//freva-dev/\n", + "git clone https://gitlab.dkrz.de/freva/plugins4freva/plugin_workshop/example_plugin.git\n", + "```\n", + "In this step you need to install the dependencies. Have a look at the previous section (How To Install All Needed Libraries Of A Plugin)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Plug a tool into Freva\n", + "\n", + "\n", + "
    \n", + "
    \n", + " \"plug\n", + "
    \n", + "
    \n", + " \"plug\n", + "
    \n", + "
    " + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Plug a tool into Freva\n", + "\n", + "\n", + "
    \n", + "
    \n", + " \"plug\n", + "
    \n", + "
    \n", + " \"plug\n", + "
    \n", + "
    " + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "\n", + "\n", + "\"freva\n", + "\n", + "
    Thanks for your attention!
    \n", + "\n", + "Contact: freva@dkrz.de\n", + "\n", + "Plugin Developer Guide: https://freva-clint.github.io/freva/developers_guide.html\n", + "\n", + "Workshop GitLab Repository: https://gitlab.dkrz.de/freva/freva_workshop\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Bash", + "language": "bash", + "name": "bash" + }, + "language_info": { + "name": "bash" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/talks/Freva_Workshop_2024/day 2/index.slides.html b/talks/Freva_Workshop_2024/day 2/index.slides.html new file mode 100644 index 0000000..d0e1c36 --- /dev/null +++ b/talks/Freva_Workshop_2024/day 2/index.slides.html @@ -0,0 +1,10594 @@ + + + + + + + +Day 2 - Introduction to Freva Plugins slides + + + + + + + + + + + + + + + + + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + diff --git a/talks/Freva_Workshop_2024/day 2/media/freva-people.jpg b/talks/Freva_Workshop_2024/day 2/media/freva-people.jpg new file mode 100644 index 0000000..ad62b1d Binary files /dev/null and b/talks/Freva_Workshop_2024/day 2/media/freva-people.jpg differ diff --git a/talks/Freva_Workshop_2024/day 2/media/gitlab/clone-repo.jpg b/talks/Freva_Workshop_2024/day 2/media/gitlab/clone-repo.jpg new file mode 100644 index 0000000..c9944c0 Binary files /dev/null and b/talks/Freva_Workshop_2024/day 2/media/gitlab/clone-repo.jpg differ diff --git a/talks/Freva_Workshop_2024/day 2/media/gitlab/freva-gitlab-flow.jpg b/talks/Freva_Workshop_2024/day 2/media/gitlab/freva-gitlab-flow.jpg new file mode 100644 index 0000000..7e8d8ae Binary files /dev/null and b/talks/Freva_Workshop_2024/day 2/media/gitlab/freva-gitlab-flow.jpg differ diff --git a/talks/Freva_Workshop_2024/day 2/media/gitlab/freva-gitlab.jpg b/talks/Freva_Workshop_2024/day 2/media/gitlab/freva-gitlab.jpg new file mode 100644 index 0000000..c69b4c6 Binary files /dev/null and b/talks/Freva_Workshop_2024/day 2/media/gitlab/freva-gitlab.jpg differ diff --git a/talks/Freva_Workshop_2024/day 2/media/gitlab/git-logo.jpg b/talks/Freva_Workshop_2024/day 2/media/gitlab/git-logo.jpg new file mode 100644 index 0000000..b0f97d5 Binary files /dev/null and b/talks/Freva_Workshop_2024/day 2/media/gitlab/git-logo.jpg differ diff --git a/talks/Freva_Workshop_2024/day 2/media/gitlab/gitlab-flow.jpg b/talks/Freva_Workshop_2024/day 2/media/gitlab/gitlab-flow.jpg new file mode 100644 index 0000000..2ffbb21 Binary files /dev/null and b/talks/Freva_Workshop_2024/day 2/media/gitlab/gitlab-flow.jpg differ diff --git a/talks/Freva_Workshop_2024/day 2/media/gitlab/gitlab-logo.jpg b/talks/Freva_Workshop_2024/day 2/media/gitlab/gitlab-logo.jpg new file mode 100644 index 0000000..e370dd3 Binary files /dev/null and b/talks/Freva_Workshop_2024/day 2/media/gitlab/gitlab-logo.jpg differ diff --git a/talks/Freva_Workshop_2024/day 2/media/gitlab/ssh-keyadd.jpg b/talks/Freva_Workshop_2024/day 2/media/gitlab/ssh-keyadd.jpg new file mode 100644 index 0000000..3433705 Binary files /dev/null and b/talks/Freva_Workshop_2024/day 2/media/gitlab/ssh-keyadd.jpg differ diff --git a/talks/Freva_Workshop_2024/day 2/media/plugin_general/env.gif b/talks/Freva_Workshop_2024/day 2/media/plugin_general/env.gif new file mode 100644 index 0000000..aea16b4 Binary files /dev/null and b/talks/Freva_Workshop_2024/day 2/media/plugin_general/env.gif differ diff --git a/talks/Freva_Workshop_2024/day 2/media/plugin_general/freva.png b/talks/Freva_Workshop_2024/day 2/media/plugin_general/freva.png new file mode 100644 index 0000000..401cc4c Binary files /dev/null and b/talks/Freva_Workshop_2024/day 2/media/plugin_general/freva.png differ diff --git a/talks/Freva_Workshop_2024/day 2/media/plugin_general/gnu-make.jpg b/talks/Freva_Workshop_2024/day 2/media/plugin_general/gnu-make.jpg new file mode 100644 index 0000000..2bc9458 Binary files /dev/null and b/talks/Freva_Workshop_2024/day 2/media/plugin_general/gnu-make.jpg differ diff --git a/talks/Freva_Workshop_2024/day 2/media/plugin_general/module_load.png b/talks/Freva_Workshop_2024/day 2/media/plugin_general/module_load.png new file mode 100644 index 0000000..55b695a Binary files /dev/null and b/talks/Freva_Workshop_2024/day 2/media/plugin_general/module_load.png differ diff --git a/talks/Freva_Workshop_2024/day 2/media/plugin_general/module_load_code.png b/talks/Freva_Workshop_2024/day 2/media/plugin_general/module_load_code.png new file mode 100644 index 0000000..6e2cc41 Binary files /dev/null and b/talks/Freva_Workshop_2024/day 2/media/plugin_general/module_load_code.png differ diff --git a/talks/Freva_Workshop_2024/day 2/media/plugin_general/plug_in_code.png b/talks/Freva_Workshop_2024/day 2/media/plugin_general/plug_in_code.png new file mode 100644 index 0000000..4bd63fa Binary files /dev/null and b/talks/Freva_Workshop_2024/day 2/media/plugin_general/plug_in_code.png differ diff --git a/talks/Freva_Workshop_2024/day 2/media/plugin_general/plug_in_web.png b/talks/Freva_Workshop_2024/day 2/media/plugin_general/plug_in_web.png new file mode 100644 index 0000000..8fd69e8 Binary files /dev/null and b/talks/Freva_Workshop_2024/day 2/media/plugin_general/plug_in_web.png differ diff --git a/talks/Freva_Workshop_2024/day 2/media/plugin_general/plugin_general.png b/talks/Freva_Workshop_2024/day 2/media/plugin_general/plugin_general.png new file mode 100644 index 0000000..6496665 Binary files /dev/null and b/talks/Freva_Workshop_2024/day 2/media/plugin_general/plugin_general.png differ diff --git a/talks/Freva_Workshop_2024/day 2/media/plugin_general/plugin_list_code.png b/talks/Freva_Workshop_2024/day 2/media/plugin_general/plugin_list_code.png new file mode 100644 index 0000000..d635fd2 Binary files /dev/null and b/talks/Freva_Workshop_2024/day 2/media/plugin_general/plugin_list_code.png differ diff --git a/talks/Freva_Workshop_2024/day 2/media/plugin_general/plugin_list_web.png b/talks/Freva_Workshop_2024/day 2/media/plugin_general/plugin_list_web.png new file mode 100644 index 0000000..352c7d5 Binary files /dev/null and b/talks/Freva_Workshop_2024/day 2/media/plugin_general/plugin_list_web.png differ diff --git a/talks/Freva_Workshop_2024/day 2/media/plugin_general/python-logo.jpg b/talks/Freva_Workshop_2024/day 2/media/plugin_general/python-logo.jpg new file mode 100644 index 0000000..4812b89 Binary files /dev/null and b/talks/Freva_Workshop_2024/day 2/media/plugin_general/python-logo.jpg differ diff --git a/talks/Freva_Workshop_2024/day 2/media/plugin_general/python-logo.png b/talks/Freva_Workshop_2024/day 2/media/plugin_general/python-logo.png new file mode 100644 index 0000000..02574c6 Binary files /dev/null and b/talks/Freva_Workshop_2024/day 2/media/plugin_general/python-logo.png differ diff --git a/talks/Freva_Workshop_2024/day 2/media/plugin_general/structure.gif b/talks/Freva_Workshop_2024/day 2/media/plugin_general/structure.gif new file mode 100644 index 0000000..53ea7ba Binary files /dev/null and b/talks/Freva_Workshop_2024/day 2/media/plugin_general/structure.gif differ diff --git a/talks/Freva_Workshop_2024/day 2/media/plugin_general/wrapper.gif b/talks/Freva_Workshop_2024/day 2/media/plugin_general/wrapper.gif new file mode 100644 index 0000000..5dafb74 Binary files /dev/null and b/talks/Freva_Workshop_2024/day 2/media/plugin_general/wrapper.gif differ diff --git a/talks/Freva_Workshop_2024/day 2/media/plugin_general/yaml.png b/talks/Freva_Workshop_2024/day 2/media/plugin_general/yaml.png new file mode 100644 index 0000000..afd1c0a Binary files /dev/null and b/talks/Freva_Workshop_2024/day 2/media/plugin_general/yaml.png differ diff --git a/talks/Freva_Workshop_2024/day 2/media/plugin_intro/code.jpg b/talks/Freva_Workshop_2024/day 2/media/plugin_intro/code.jpg new file mode 100644 index 0000000..7335452 Binary files /dev/null and b/talks/Freva_Workshop_2024/day 2/media/plugin_intro/code.jpg differ diff --git a/talks/Freva_Workshop_2024/day 2/media/plugin_intro/freva-plugindev.png b/talks/Freva_Workshop_2024/day 2/media/plugin_intro/freva-plugindev.png new file mode 100644 index 0000000..0586f1e Binary files /dev/null and b/talks/Freva_Workshop_2024/day 2/media/plugin_intro/freva-plugindev.png differ diff --git a/talks/Freva_Workshop_2024/day 2/media/plugin_intro/make-yaml.jpg b/talks/Freva_Workshop_2024/day 2/media/plugin_intro/make-yaml.jpg new file mode 100644 index 0000000..2d3ed9c Binary files /dev/null and b/talks/Freva_Workshop_2024/day 2/media/plugin_intro/make-yaml.jpg differ diff --git a/talks/Freva_Workshop_2024/day 2/media/plugin_intro/plugin-livecycle.png b/talks/Freva_Workshop_2024/day 2/media/plugin_intro/plugin-livecycle.png new file mode 100644 index 0000000..eb7ac8b Binary files /dev/null and b/talks/Freva_Workshop_2024/day 2/media/plugin_intro/plugin-livecycle.png differ diff --git a/talks/Freva_Workshop_2024/day 2/media/plugin_intro/plugin-parts.png b/talks/Freva_Workshop_2024/day 2/media/plugin_intro/plugin-parts.png new file mode 100644 index 0000000..7798209 Binary files /dev/null and b/talks/Freva_Workshop_2024/day 2/media/plugin_intro/plugin-parts.png differ diff --git a/talks/Freva_Workshop_2024/day 2/media/plugin_intro/wrapper.jpg b/talks/Freva_Workshop_2024/day 2/media/plugin_intro/wrapper.jpg new file mode 100644 index 0000000..f5a4994 Binary files /dev/null and b/talks/Freva_Workshop_2024/day 2/media/plugin_intro/wrapper.jpg differ diff --git a/talks/Freva_Workshop_2024/day 2/media/pycharm/01_remote_development_gateway.jpg b/talks/Freva_Workshop_2024/day 2/media/pycharm/01_remote_development_gateway.jpg new file mode 100644 index 0000000..bb5df77 Binary files /dev/null and b/talks/Freva_Workshop_2024/day 2/media/pycharm/01_remote_development_gateway.jpg differ diff --git a/talks/Freva_Workshop_2024/day 2/media/pycharm/02_remote_development_tab.jpg b/talks/Freva_Workshop_2024/day 2/media/pycharm/02_remote_development_tab.jpg new file mode 100644 index 0000000..e0c559e Binary files /dev/null and b/talks/Freva_Workshop_2024/day 2/media/pycharm/02_remote_development_tab.jpg differ diff --git a/talks/Freva_Workshop_2024/day 2/media/pycharm/02_remote_development_tab.png b/talks/Freva_Workshop_2024/day 2/media/pycharm/02_remote_development_tab.png new file mode 100644 index 0000000..d4a39de Binary files /dev/null and b/talks/Freva_Workshop_2024/day 2/media/pycharm/02_remote_development_tab.png differ diff --git a/talks/Freva_Workshop_2024/day 2/media/pycharm/03_ssh_connection_dialogue.jpg b/talks/Freva_Workshop_2024/day 2/media/pycharm/03_ssh_connection_dialogue.jpg new file mode 100644 index 0000000..d71b15a Binary files /dev/null and b/talks/Freva_Workshop_2024/day 2/media/pycharm/03_ssh_connection_dialogue.jpg differ diff --git a/talks/Freva_Workshop_2024/day 2/media/pycharm/04_choose_ide_and_project.jpg b/talks/Freva_Workshop_2024/day 2/media/pycharm/04_choose_ide_and_project.jpg new file mode 100644 index 0000000..1bc90ae Binary files /dev/null and b/talks/Freva_Workshop_2024/day 2/media/pycharm/04_choose_ide_and_project.jpg differ diff --git a/talks/Freva_Workshop_2024/day 2/media/pycharm/05_remote_IDE_successfully_opened.jpg b/talks/Freva_Workshop_2024/day 2/media/pycharm/05_remote_IDE_successfully_opened.jpg new file mode 100644 index 0000000..2f96cac Binary files /dev/null and b/talks/Freva_Workshop_2024/day 2/media/pycharm/05_remote_IDE_successfully_opened.jpg differ diff --git a/talks/Freva_Workshop_2024/day 2/media/pycharm/pycharm_logo.svg b/talks/Freva_Workshop_2024/day 2/media/pycharm/pycharm_logo.svg new file mode 100644 index 0000000..cc5869d --- /dev/null +++ b/talks/Freva_Workshop_2024/day 2/media/pycharm/pycharm_logo.svg @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/talks/Freva_Workshop_2024/day 2/media/rstudio/01_rstudio_vscode_extensions.jpg b/talks/Freva_Workshop_2024/day 2/media/rstudio/01_rstudio_vscode_extensions.jpg new file mode 100644 index 0000000..b2e9f19 Binary files /dev/null and b/talks/Freva_Workshop_2024/day 2/media/rstudio/01_rstudio_vscode_extensions.jpg differ diff --git a/talks/Freva_Workshop_2024/day 2/media/rstudio/02_rstudio_extensions_on_remote.jpg b/talks/Freva_Workshop_2024/day 2/media/rstudio/02_rstudio_extensions_on_remote.jpg new file mode 100644 index 0000000..816eda9 Binary files /dev/null and b/talks/Freva_Workshop_2024/day 2/media/rstudio/02_rstudio_extensions_on_remote.jpg differ diff --git a/talks/Freva_Workshop_2024/day 2/media/rstudio/03_rterm_linux_settings.jpg b/talks/Freva_Workshop_2024/day 2/media/rstudio/03_rterm_linux_settings.jpg new file mode 100644 index 0000000..cab0813 Binary files /dev/null and b/talks/Freva_Workshop_2024/day 2/media/rstudio/03_rterm_linux_settings.jpg differ diff --git a/talks/Freva_Workshop_2024/day 2/media/rstudio/04_opening_and_running_r_file_in_vscode.jpg b/talks/Freva_Workshop_2024/day 2/media/rstudio/04_opening_and_running_r_file_in_vscode.jpg new file mode 100644 index 0000000..534a6c2 Binary files /dev/null and b/talks/Freva_Workshop_2024/day 2/media/rstudio/04_opening_and_running_r_file_in_vscode.jpg differ diff --git a/talks/Freva_Workshop_2024/day 2/media/rstudio/RStudio_logo.svg b/talks/Freva_Workshop_2024/day 2/media/rstudio/RStudio_logo.svg new file mode 100644 index 0000000..15a1d2a --- /dev/null +++ b/talks/Freva_Workshop_2024/day 2/media/rstudio/RStudio_logo.svg @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/talks/Freva_Workshop_2024/day 2/media/vscode/01_connect_to.jpg b/talks/Freva_Workshop_2024/day 2/media/vscode/01_connect_to.jpg new file mode 100644 index 0000000..b13bbef Binary files /dev/null and b/talks/Freva_Workshop_2024/day 2/media/vscode/01_connect_to.jpg differ diff --git a/talks/Freva_Workshop_2024/day 2/media/vscode/01_connect_to_remote.png b/talks/Freva_Workshop_2024/day 2/media/vscode/01_connect_to_remote.png new file mode 100644 index 0000000..707e980 Binary files /dev/null and b/talks/Freva_Workshop_2024/day 2/media/vscode/01_connect_to_remote.png differ diff --git a/talks/Freva_Workshop_2024/day 2/media/vscode/02_remote_connection_options.jpg b/talks/Freva_Workshop_2024/day 2/media/vscode/02_remote_connection_options.jpg new file mode 100644 index 0000000..4d32c6f Binary files /dev/null and b/talks/Freva_Workshop_2024/day 2/media/vscode/02_remote_connection_options.jpg differ diff --git a/talks/Freva_Workshop_2024/day 2/media/vscode/03_remote_host_entered.jpg b/talks/Freva_Workshop_2024/day 2/media/vscode/03_remote_host_entered.jpg new file mode 100644 index 0000000..645afac Binary files /dev/null and b/talks/Freva_Workshop_2024/day 2/media/vscode/03_remote_host_entered.jpg differ diff --git a/talks/Freva_Workshop_2024/day 2/media/vscode/04_opening_remote_folder.jpg b/talks/Freva_Workshop_2024/day 2/media/vscode/04_opening_remote_folder.jpg new file mode 100644 index 0000000..bd3b1f5 Binary files /dev/null and b/talks/Freva_Workshop_2024/day 2/media/vscode/04_opening_remote_folder.jpg differ diff --git a/talks/Freva_Workshop_2024/day 2/media/vscode/05_remote_folder_success.jpg b/talks/Freva_Workshop_2024/day 2/media/vscode/05_remote_folder_success.jpg new file mode 100644 index 0000000..530e83c Binary files /dev/null and b/talks/Freva_Workshop_2024/day 2/media/vscode/05_remote_folder_success.jpg differ diff --git a/talks/Freva_Workshop_2024/day 2/media/vscode/vscode_logo.svg b/talks/Freva_Workshop_2024/day 2/media/vscode/vscode_logo.svg new file mode 100644 index 0000000..ae09fa1 --- /dev/null +++ b/talks/Freva_Workshop_2024/day 2/media/vscode/vscode_logo.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/talks/Freva_Workshop_2024/day 2/media/wrapper/First_wrapper.png b/talks/Freva_Workshop_2024/day 2/media/wrapper/First_wrapper.png new file mode 100644 index 0000000..706cb95 Binary files /dev/null and b/talks/Freva_Workshop_2024/day 2/media/wrapper/First_wrapper.png differ diff --git a/talks/Freva_Workshop_2024/day 2/media/wrapper/Fourth_wrapper.png b/talks/Freva_Workshop_2024/day 2/media/wrapper/Fourth_wrapper.png new file mode 100644 index 0000000..bedbb9d Binary files /dev/null and b/talks/Freva_Workshop_2024/day 2/media/wrapper/Fourth_wrapper.png differ diff --git a/talks/Freva_Workshop_2024/day 2/media/wrapper/Second_wrapper.png b/talks/Freva_Workshop_2024/day 2/media/wrapper/Second_wrapper.png new file mode 100644 index 0000000..d923fc3 Binary files /dev/null and b/talks/Freva_Workshop_2024/day 2/media/wrapper/Second_wrapper.png differ diff --git a/talks/Freva_Workshop_2024/day 2/media/wrapper/Third_wrapper.png b/talks/Freva_Workshop_2024/day 2/media/wrapper/Third_wrapper.png new file mode 100644 index 0000000..59c7cc8 Binary files /dev/null and b/talks/Freva_Workshop_2024/day 2/media/wrapper/Third_wrapper.png differ diff --git a/talks/Freva_Workshop_2024/index.slides.html b/talks/Freva_Workshop_2024/index.slides.html new file mode 100644 index 0000000..b495dcd --- /dev/null +++ b/talks/Freva_Workshop_2024/index.slides.html @@ -0,0 +1,18 @@ + + + + + + + +

    Select a presentation:

    + + + \ No newline at end of file