playbooks/roles/ood-applications/files/bc_jupyter/template/OFLogView.ipynb (161 lines of code) (raw):

{ "cells": [ { "cell_type": "markdown", "id": "216e3b46-0087-466d-8590-dee86353ee7f", "metadata": {}, "source": [ "# OpenFOAM Log Viewer" ] }, { "cell_type": "code", "execution_count": null, "id": "9079f2de-46ff-4756-86a7-eeed4f534707", "metadata": { "tags": [] }, "outputs": [], "source": [ "import numpy as np\n", "import os\n", "import requests\n", "import subprocess\n", "import tempfile\n", "\n", "import ipywidgets as widgets\n", "import matplotlib.pyplot as plt\n", "from ipyfilechooser import FileChooser\n", "\n", "class FoamLogWidget:\n", " def __init__(self):\n", " self.logfile = None\n", " self.foamlog_cmd = \"foamlog\"\n", " self.data = {}\n", " self.install_foamlog(os.path.join(os.environ[\"HOME\"], \"bin\"))\n", " self.file_selector_widget = None\n", " self.metrics_widget = None\n", " self.output_widget = None\n", " self.limit_residuals_widget = None\n", " self.separate_plots_widget = None\n", " self.width_widget = None\n", " self.height_widget = None\n", "\n", " def install_foamlog(self, install_dir):\n", " foamlog = \"https://raw.githubusercontent.com/OpenFOAM/OpenFOAM-dev/master/bin/foamLog\"\n", " foamlog_db = \"https://raw.githubusercontent.com/OpenFOAM/OpenFOAM-dev/master/bin/tools/foamLog.db\"\n", " os.makedirs(os.path.join(install_dir, \"tools\"), exist_ok = True)\n", " r = requests.get(foamlog)\n", " self.foamlog_cmd = os.path.join(install_dir, \"foamlog\")\n", " with open(self.foamlog_cmd, \"w\") as f:\n", " f.write(r.text)\n", " os.chmod(self.foamlog_cmd, 0o755)\n", " r = requests.get(foamlog_db)\n", " with open(os.path.join(install_dir, \"tools\", \"foamlog.db\"), \"w\") as f:\n", " f.write(r.text)\n", " \n", " def read(self):\n", " cwd = os.getcwd()\n", " fname = os.path.abspath(self.logfile)\n", " self.data = {}\n", " with tempfile.TemporaryDirectory() as tmpdir:\n", " os.chdir(tmpdir)\n", " subprocess.call([self.foamlog_cmd, fname], stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)\n", " logdir = os.path.join(tmpdir, \"logs\")\n", " os.chdir(logdir)\n", " for f in os.listdir(logdir):\n", " if f == \"foamLog.awk\" or f == \"foamlog.awk\":\n", " continue\n", " self.data[f] = np.genfromtxt(f, delimiter=\"\\t\", skip_header=0, filling_values=0)\n", " os.chdir(cwd)\n", " \n", " def _plot_residuals(self, w):\n", " self.output_widget.clear_output(wait=True)\n", " if len(self.metrics_widget.value) == 0:\n", " return\n", " with self.output_widget:\n", " lim = self.limit_residuals_widget.value\n", " if self.separate_plots_widget.value == True and len(self.metrics_widget.value) > 1:\n", " fig, ax = plt.subplots(nrows=len(self.metrics_widget.value), ncols=1, figsize=(self.width_widget.value, self.height_widget.value))\n", " for i, m in enumerate(self.metrics_widget.value):\n", " ax[i].plot(self.data[m][-lim:,0], self.data[m][-lim:,1], label=m)\n", " ax[i].set(xlabel=\"Iteration\")\n", " ax[i].legend()\n", " ax[i].grid()\n", " else:\n", " fig, ax = plt.subplots(figsize=(self.width_widget.value, self.height_widget.value))\n", " for m in self.metrics_widget.value:\n", " ax.plot(self.data[m][-lim:,0], self.data[m][-lim:,1], label=m)\n", " ax.legend()\n", " ax.grid()\n", " plt.show()\n", " \n", " def _open_logfile(self, w):\n", " self.logfile = self.file_selector_widget.selected\n", " self._refresh(w)\n", " \n", " def _refresh(self, w):\n", " self.read() \n", " with self.metrics_widget.hold_trait_notifications():\n", " old_values = self.metrics_widget.value\n", " self.metrics_widget.options = self.data.keys()\n", " new_values = list(set(old_values) & set(self.data.keys()))\n", " self.metrics_widget.value = list(set(old_values) & set(self.data.keys()))\n", " \n", " def display(self):\n", " self.file_selector_widget = FileChooser(os.environ[\"HOME\"])\n", " self.file_selector_widget.title = \"Select OpenFOAM log file\"\n", " self.file_selector_widget.show_hidden = False\n", " self.file_selector_widget.filter_patter = \"log.*\"\n", " self.file_selector_widget.dir_icon = \"/\"\n", " self.file_selector_widget.dir_icon_append = True\n", " self.file_selector_widget.show_only_dirs = False\n", " self.file_selector_widget.register_callback(self._open_logfile)\n", " \n", " self.separate_plots_widget = widgets.Checkbox(description=\"Separate plots\", value=False)\n", " self.width_widget = widgets.IntSlider(description=\"Width\", min=4, max=20, value=10)\n", " self.height_widget = widgets.IntSlider(description=\"Height\", min=2, max=20, value=6)\n", " self.limit_residuals_widget = widgets.IntSlider(description=\"Iterations\", min=100, max=10000, value=1000, step=50)\n", " self.metrics_widget = widgets.SelectMultiple(options=self.data.keys(), value=[], rows=10, description='Metrics')\n", " self.output_widget = widgets.Output()\n", " refresh_button = widgets.Button(description=\"Refresh\")\n", " refresh_button.on_click(self._refresh)\n", "\n", " vbox = widgets.VBox([self.separate_plots_widget, self.width_widget, self.height_widget, self.limit_residuals_widget])\n", " hbox = widgets.HBox([self.metrics_widget, vbox])\n", " vbox_main = widgets.VBox([self.file_selector_widget, hbox, refresh_button, self.output_widget])\n", " display(vbox_main)\n", " \n", " self.separate_plots_widget.observe(self._plot_residuals, names=\"value\")\n", " self.width_widget.observe(self._plot_residuals, names=\"value\")\n", " self.height_widget.observe(self._plot_residuals, names=\"value\")\n", " self.limit_residuals_widget.observe(self._plot_residuals, names=\"value\")\n", " self.metrics_widget.observe(self._plot_residuals, names=\"value\")\n", "\n", "w = FoamLogWidget()\n", "w.display()" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.9" } }, "nbformat": 4, "nbformat_minor": 5 }