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
}